diff --git a/.claude/skills/template-add/scripts/add-template.ps1 b/.claude/skills/template-add/scripts/add-template.ps1
index 082ade526..cb87ca09c 100644
--- a/.claude/skills/template-add/scripts/add-template.ps1
+++ b/.claude/skills/template-add/scripts/add-template.ps1
@@ -1,4 +1,4 @@
-# template-add v1.25 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
+# template-add v1.26 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -201,6 +201,14 @@ $processorDir = Join-Path $SrcDir $ObjectName
$templatesDir = Join-Path $processorDir "Templates"
$templateMetaPath = Join-Path $templatesDir "$TemplateName.xml"
+# Код языка идёт и в текст XML, и в имя файла страницы, поэтому проверяем его до записи:
+# пустое значение дало бы файл «.html» и пустой , а разделитель пути —
+# запись мимо каталога Ext/Template. Оба отказа платформы были бы тихими.
+if ($Lang -notmatch '^[A-Za-z0-9_-]+$') {
+ Write-Error "Недопустимый код языка: '$Lang'`nОжидается код вида ru, en (буквы, цифры, дефис, подчёркивание)"
+ exit 1
+}
+
# Существующий HTML-макет — не всегда повод отказать: в один макет платформа кладёт
# несколько языков ( на каждый, страницы рядом), и повторный вызов с другим -Lang
# добавляет страницу. Для остальных типов поведение прежнее — отказ.
@@ -339,6 +347,12 @@ if ($addLangMode) {
$langs = @()
$descVersion = $formatVersion
+ # Сначала РАЗБОР состояния, и только в самом конце запись: иначе отказ на полпути
+ # оставляет макет разобранным (страница есть, дескриптора нет) — а такую раскладку
+ # платформа снова молча игнорирует.
+ $legacyPending = $false
+ $pagePath = Join-Path $pageDir "$Lang.html"
+
if (Test-Path $descPath) {
$descText = [System.IO.File]::ReadAllText((Resolve-Path $descPath).Path, [System.Text.Encoding]::UTF8)
# Версию берём из самого дескриптора: правка чужой выгрузки не должна менять формат.
@@ -347,23 +361,26 @@ if ($addLangMode) {
} elseif (Test-Path $legacyPagePath) {
# Раскладка до v1.24 — одиночный Ext/Template.html, который платформа молча игнорирует.
# Языка у него нет, но создать его могла только версия навыка без параметра -Lang,
- # то есть это страница на языке по умолчанию. Переносим и говорим об этом вслух.
- New-Item -ItemType Directory -Path $pageDir -Force | Out-Null
- Move-Item -LiteralPath $legacyPagePath -Destination (Join-Path $pageDir "ru.html") -Force
+ # то есть это страница на языке по умолчанию.
+ if (Test-Path (Join-Path $pageDir "ru.html")) {
+ Write-Error "Макет разобран: есть и старый Ext/Template.html, и Template/ru.html — что из них актуально, решать не навыку.`nОставьте один файл и повторите."
+ exit 1
+ }
+ $legacyPending = $true
$langs = @("ru")
- Write-Host "[WARN] Макет был в старой раскладке (Ext/Template.html) — платформа её игнорирует."
- Write-Host " Страница считана как ru и перенесена в Template/ru.html, создан дескриптор."
}
- $pagePath = Join-Path $pageDir "$Lang.html"
- if ($langs -contains $Lang) {
+ # Файл страницы НИКОГДА не перезаписываем: в нём может лежать текст макета.
+ # Ошибка — только когда добавлять нечего: язык уже в дескрипторе И страница на диске.
+ $pageExists = (Test-Path $pagePath) -or ($legacyPending -and $Lang -eq "ru")
+ if (($langs -contains $Lang) -and $pageExists -and -not $legacyPending) {
Write-Error "Страница макета на языке '$Lang' уже существует: $pagePath"
exit 1
}
# Порядок страниц — по коду языка (в выгрузке ERP так во всех 54 двуязычных макетах).
# Сравнение ordinal, а не культурное: иначе порты разойдутся на ровном месте.
- $langs = @($langs + $Lang)
+ if (-not ($langs -contains $Lang)) { $langs = @($langs + $Lang) }
[Array]::Sort($langs, [System.StringComparer]::Ordinal)
$pagesXml = ($langs | ForEach-Object { "`t$_" }) -join "`n"
@@ -373,11 +390,23 @@ if ($addLangMode) {
$pagesXml
"@
- Write-XmlFile $descPath $descXml $encBom
+ # --- запись ---
New-Item -ItemType Directory -Path $pageDir -Force | Out-Null
- $pageContent = ($htmlSkeleton -replace "`r`n", "`n")
- [System.IO.File]::WriteAllText($pagePath, $pageContent, $encBom)
+ if ($legacyPending) {
+ Move-Item -LiteralPath $legacyPagePath -Destination (Join-Path $pageDir "ru.html")
+ Write-Host "[WARN] Макет был в старой раскладке (Ext/Template.html) — платформа её игнорирует."
+ Write-Host " Страница считана как ru и перенесена в Template/ru.html."
+ }
+ Write-XmlFile $descPath $descXml $encBom
+ if (Test-Path $pagePath) {
+ # При миграции про сохранённое содержимое уже сказано выше — не повторяемся.
+ if (-not $legacyPending) {
+ Write-Host "[WARN] Страница $Lang.html уже лежала на диске — содержимое сохранено, дописан только ."
+ }
+ } else {
+ [System.IO.File]::WriteAllText($pagePath, ($htmlSkeleton -replace "`r`n", "`n"), $encBom)
+ }
Write-Host "[OK] Добавлена страница макета: $TemplateName ($Lang)"
Write-Host " Содержимое: $pagePath"
diff --git a/.claude/skills/template-add/scripts/add-template.py b/.claude/skills/template-add/scripts/add-template.py
index 9f9c6fcc8..277c84bdb 100644
--- a/.claude/skills/template-add/scripts/add-template.py
+++ b/.claude/skills/template-add/scripts/add-template.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# template-add v1.25 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
+# template-add v1.26 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -379,6 +379,14 @@ def main():
templates_dir = os.path.join(processor_dir, "Templates")
template_meta_path = os.path.join(templates_dir, f"{template_name}.xml")
+ # Код языка идёт и в текст XML, и в имя файла страницы, поэтому проверяем его до записи:
+ # пустое значение дало бы файл «.html» и пустой , а разделитель пути —
+ # запись мимо каталога Ext/Template. Оба отказа платформы были бы тихими.
+ if not re.match(r"^[A-Za-z0-9_-]+$", lang):
+ print(f"Недопустимый код языка: '{lang}'", file=sys.stderr)
+ print("Ожидается код вида ru, en (буквы, цифры, дефис, подчёркивание)", file=sys.stderr)
+ sys.exit(1)
+
# Существующий HTML-макет — не всегда повод отказать: в один макет платформа кладёт
# несколько языков ( на каждый, страницы рядом), и повторный вызов с другим -Lang
# добавляет страницу. Для остальных типов поведение прежнее — отказ.
@@ -469,6 +477,12 @@ def main():
langs = []
desc_version = format_version
+ # Сначала РАЗБОР состояния, и только в самом конце запись: иначе отказ на полпути
+ # оставляет макет разобранным (страница есть, дескриптора нет) — а такую раскладку
+ # платформа снова молча игнорирует.
+ legacy_pending = False
+ page_path = os.path.join(page_dir, f"{lang}.html")
+
if os.path.exists(desc_path):
with open(desc_path, "r", encoding="utf-8-sig") as f:
desc_text = f.read()
@@ -480,21 +494,27 @@ def main():
elif os.path.exists(legacy_page_path):
# Раскладка до v1.24 — одиночный Ext/Template.html, который платформа молча игнорирует.
# Языка у него нет, но создать его могла только версия навыка без параметра -Lang,
- # то есть это страница на языке по умолчанию. Переносим и говорим об этом вслух.
- os.makedirs(page_dir, exist_ok=True)
- os.replace(legacy_page_path, os.path.join(page_dir, "ru.html"))
+ # то есть это страница на языке по умолчанию.
+ if os.path.exists(os.path.join(page_dir, "ru.html")):
+ print("Макет разобран: есть и старый Ext/Template.html, и Template/ru.html — что из них актуально, решать не навыку.", file=sys.stderr)
+ print("Оставьте один файл и повторите.", file=sys.stderr)
+ sys.exit(1)
+ legacy_pending = True
langs = ["ru"]
- print("[WARN] Макет был в старой раскладке (Ext/Template.html) — платформа её игнорирует.")
- print(" Страница считана как ru и перенесена в Template/ru.html, создан дескриптор.")
- page_path = os.path.join(page_dir, f"{lang}.html")
+ # Файл страницы НИКОГДА не перезаписываем: в нём может лежать текст макета.
+ # Ошибка — только когда добавлять нечего: язык уже в дескрипторе И страница на диске.
# Сравнение без учёта регистра — зеркало -contains в PS, который регистр не различает.
- if lang.lower() in [x.lower() for x in langs]:
+ lang_known = lang.lower() in [x.lower() for x in langs]
+ page_exists = os.path.exists(page_path) or (legacy_pending and lang.lower() == "ru")
+ if lang_known and page_exists and not legacy_pending:
print(f"Страница макета на языке '{lang}' уже существует: {page_path}", file=sys.stderr)
sys.exit(1)
# Порядок страниц — по коду языка (в выгрузке ERP так во всех 54 двуязычных макетах).
- langs = sorted(langs + [lang])
+ if not lang_known:
+ langs = langs + [lang]
+ langs = sorted(langs)
pages_xml = '\n'.join(f"\t{x}" for x in langs)
desc_xml = (
@@ -506,10 +526,20 @@ def main():
f'{pages_xml}\n'
''
)
- write_xml_file(desc_path, desc_xml)
+ # --- запись ---
os.makedirs(page_dir, exist_ok=True)
- write_utf8_bom(page_path, html_skeleton)
+ if legacy_pending:
+ os.replace(legacy_page_path, os.path.join(page_dir, "ru.html"))
+ print("[WARN] Макет был в старой раскладке (Ext/Template.html) — платформа её игнорирует.")
+ print(" Страница считана как ru и перенесена в Template/ru.html.")
+ write_xml_file(desc_path, desc_xml)
+ if os.path.exists(page_path):
+ # При миграции про сохранённое содержимое уже сказано выше — не повторяемся.
+ if not legacy_pending:
+ print(f"[WARN] Страница {lang}.html уже лежала на диске — содержимое сохранено, дописан только .")
+ else:
+ write_utf8_bom(page_path, html_skeleton)
print(f"[OK] Добавлена страница макета: {template_name} ({lang})")
print(f" Содержимое: {page_path}")
diff --git a/tests/skills/cases/template-add/html-lang-invalid.json b/tests/skills/cases/template-add/html-lang-invalid.json
new file mode 100644
index 000000000..dcfe90f95
--- /dev/null
+++ b/tests/skills/cases/template-add/html-lang-invalid.json
@@ -0,0 +1,22 @@
+{
+ "name": "Недопустимый код языка отвергается до записи",
+ "preRun": [
+ {
+ "script": "epf-init/scripts/init",
+ "args": {
+ "-Name": "МояОбработка",
+ "-SrcDir": "{workDir}"
+ }
+ }
+ ],
+ "params": {
+ "objectName": "МояОбработка",
+ "templateName": "МакетHTML",
+ "templateType": "HTML"
+ },
+ "args_extra": [
+ "-Lang",
+ "../evil"
+ ],
+ "expectError": "Недопустимый код языка"
+}
diff --git a/tests/skills/cases/template-add/html-layout-ambiguous.json b/tests/skills/cases/template-add/html-layout-ambiguous.json
new file mode 100644
index 000000000..365c56ee7
--- /dev/null
+++ b/tests/skills/cases/template-add/html-layout-ambiguous.json
@@ -0,0 +1,45 @@
+{
+ "name": "Разобранный макет (и Template.html, и Template/ru.html): отказ без изменений",
+ "preRun": [
+ {
+ "script": "epf-init/scripts/init",
+ "args": {
+ "-Name": "МояОбработка",
+ "-SrcDir": "{workDir}"
+ }
+ },
+ {
+ "script": "template-add/scripts/add-template",
+ "args": {
+ "-ObjectName": "МояОбработка",
+ "-TemplateName": "МакетHTML",
+ "-TemplateType": "HTML",
+ "-SrcDir": "{workDir}"
+ }
+ },
+ {
+ "deletePath": "МояОбработка/Templates/МакетHTML/Ext/Template"
+ },
+ {
+ "deletePath": "МояОбработка/Templates/МакетHTML/Ext/Template.xml"
+ },
+ {
+ "writeFile": {
+ "path": "МояОбработка/Templates/МакетHTML/Ext/Template.html",
+ "content": "\n\nЦЕННОЕ_СОДЕРЖИМОЕ\n"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "МояОбработка/Templates/МакетHTML/Ext/Template/ru.html",
+ "content": "ДРУГАЯ_СТРАНИЦА"
+ }
+ }
+ ],
+ "params": {
+ "objectName": "МояОбработка",
+ "templateName": "МакетHTML",
+ "templateType": "HTML"
+ },
+ "expectError": "Макет разобран"
+}
diff --git a/tests/skills/cases/template-add/html-legacy-same-lang.json b/tests/skills/cases/template-add/html-legacy-same-lang.json
new file mode 100644
index 000000000..70f2c3934
--- /dev/null
+++ b/tests/skills/cases/template-add/html-legacy-same-lang.json
@@ -0,0 +1,52 @@
+{
+ "name": "Старая раскладка + язык по умолчанию: дескриптор создаётся, содержимое сохраняется",
+ "preRun": [
+ {
+ "script": "epf-init/scripts/init",
+ "args": {
+ "-Name": "МояОбработка",
+ "-SrcDir": "{workDir}"
+ }
+ },
+ {
+ "script": "template-add/scripts/add-template",
+ "args": {
+ "-ObjectName": "МояОбработка",
+ "-TemplateName": "МакетHTML",
+ "-TemplateType": "HTML",
+ "-SrcDir": "{workDir}"
+ }
+ },
+ {
+ "deletePath": "МояОбработка/Templates/МакетHTML/Ext/Template"
+ },
+ {
+ "deletePath": "МояОбработка/Templates/МакетHTML/Ext/Template.xml"
+ },
+ {
+ "writeFile": {
+ "path": "МояОбработка/Templates/МакетHTML/Ext/Template.html",
+ "content": "\n\nЦЕННОЕ_СОДЕРЖИМОЕ\n"
+ }
+ }
+ ],
+ "params": {
+ "objectName": "МояОбработка",
+ "templateName": "МакетHTML",
+ "templateType": "HTML"
+ },
+ "expect": {
+ "stdoutContains": [
+ "[WARN]",
+ "старой раскладке",
+ "Добавлена страница макета"
+ ],
+ "filesAbsent": [
+ "МояОбработка/Templates/МакетHTML/Ext/Template.html"
+ ],
+ "fileContains": {
+ "file": "МояОбработка/Templates/МакетHTML/Ext/Template/ru.html",
+ "text": "ЦЕННОЕ_СОДЕРЖИМОЕ"
+ }
+ }
+}
diff --git a/tests/skills/cases/template-add/html-page-not-in-descriptor.json b/tests/skills/cases/template-add/html-page-not-in-descriptor.json
new file mode 100644
index 000000000..155cbdf96
--- /dev/null
+++ b/tests/skills/cases/template-add/html-page-not-in-descriptor.json
@@ -0,0 +1,46 @@
+{
+ "name": "Страница есть на диске, но не в дескрипторе: содержимое не затирается",
+ "preRun": [
+ {
+ "script": "epf-init/scripts/init",
+ "args": {
+ "-Name": "МояОбработка",
+ "-SrcDir": "{workDir}"
+ }
+ },
+ {
+ "script": "template-add/scripts/add-template",
+ "args": {
+ "-ObjectName": "МояОбработка",
+ "-TemplateName": "МакетHTML",
+ "-TemplateType": "HTML",
+ "-SrcDir": "{workDir}"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "МояОбработка/Templates/МакетHTML/Ext/Template/en.html",
+ "content": "РУЧНАЯ_АНГЛИЙСКАЯ_СТРАНИЦА"
+ }
+ }
+ ],
+ "params": {
+ "objectName": "МояОбработка",
+ "templateName": "МакетHTML",
+ "templateType": "HTML"
+ },
+ "args_extra": [
+ "-Lang",
+ "en"
+ ],
+ "expect": {
+ "stdoutContains": [
+ "[WARN]",
+ "уже лежала на диске"
+ ],
+ "fileContains": {
+ "file": "МояОбработка/Templates/МакетHTML/Ext/Template/en.html",
+ "text": "РУЧНАЯ_АНГЛИЙСКАЯ_СТРАНИЦА"
+ }
+ }
+}
diff --git a/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка.xml b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка.xml
new file mode 100644
index 000000000..281f29338
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+
+ МояОбработка
+
+
+ ru
+ МояОбработка
+
+
+
+
+
+
+
+ МакетHTML
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Ext/ObjectModule.bsl b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Ext/ObjectModule.bsl
new file mode 100644
index 000000000..15543d277
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Ext/ObjectModule.bsl
@@ -0,0 +1,11 @@
+#Область ОписаниеПеременных
+
+#КонецОбласти
+
+#Область ПрограммныйИнтерфейс
+
+#КонецОбласти
+
+#Область СлужебныеПроцедурыИФункции
+
+#КонецОбласти
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML.xml b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML.xml
new file mode 100644
index 000000000..b05945a1a
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ МакетHTML
+
+
+ ru
+ МакетHTML
+
+
+
+ HTMLDocument
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML/Ext/Template.xml b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML/Ext/Template.xml
new file mode 100644
index 000000000..b9fbd0bc7
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML/Ext/Template.xml
@@ -0,0 +1,4 @@
+
+
+ ru
+
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html
new file mode 100644
index 000000000..f6a56afb1
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-legacy-same-lang/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html
@@ -0,0 +1,4 @@
+
+
+ЦЕННОЕ_СОДЕРЖИМОЕ
+
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка.xml b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка.xml
new file mode 100644
index 000000000..281f29338
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+
+ МояОбработка
+
+
+ ru
+ МояОбработка
+
+
+
+
+
+
+
+ МакетHTML
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Ext/ObjectModule.bsl b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Ext/ObjectModule.bsl
new file mode 100644
index 000000000..15543d277
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Ext/ObjectModule.bsl
@@ -0,0 +1,11 @@
+#Область ОписаниеПеременных
+
+#КонецОбласти
+
+#Область ПрограммныйИнтерфейс
+
+#КонецОбласти
+
+#Область СлужебныеПроцедурыИФункции
+
+#КонецОбласти
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML.xml b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML.xml
new file mode 100644
index 000000000..b05945a1a
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ МакетHTML
+
+
+ ru
+ МакетHTML
+
+
+
+ HTMLDocument
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template.xml b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template.xml
new file mode 100644
index 000000000..67df2f067
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template.xml
@@ -0,0 +1,5 @@
+
+
+ en
+ ru
+
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template/en.html b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template/en.html
new file mode 100644
index 000000000..0a704edeb
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template/en.html
@@ -0,0 +1 @@
+РУЧНАЯ_АНГЛИЙСКАЯ_СТРАНИЦА
\ No newline at end of file
diff --git a/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html
new file mode 100644
index 000000000..9433caa59
--- /dev/null
+++ b/tests/skills/cases/template-add/snapshots/html-page-not-in-descriptor/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file