diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1
index 6db2c78d..aaecc5f4 100644
--- a/.claude/skills/meta-compile/scripts/meta-compile.ps1
+++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1
@@ -382,8 +382,8 @@ function Split-CamelCase {
return $result
}
-# Auto-synonym
-$synonym = if ($def.synonym) { "$($def.synonym)" } else { Split-CamelCase $objName }
+# Auto-synonym. Проброс без стрингификации (строка ИЛИ {ru,en} — мультиязычный синоним объекта).
+$synonym = if ($null -ne $def.synonym) { $def.synonym } else { Split-CamelCase $objName }
$comment = if ($def.comment) { "$($def.comment)" } else { "" }
# --- 4. Type system ---
@@ -1755,7 +1755,8 @@ function Emit-ScheduledJobProperties {
}
X "$i$(Esc-Xml $methodName)"
- $description = if ($def.description) { "$($def.description)" } else { $synonym }
+ # $synonym может быть {ru,en}; здесь Description — плоская строка, берём ru-текст.
+ $description = if ($def.description) { "$($def.description)" } elseif ($synonym -is [string]) { $synonym } else { "" }
X "$i$(Esc-Xml $description)"
$key = if ($def.key) { "$($def.key)" } else { "" }
diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py
index 424d2bf1..6bdb6ad0 100644
--- a/.claude/skills/meta-compile/scripts/meta-compile.py
+++ b/.claude/skills/meta-compile/scripts/meta-compile.py
@@ -426,7 +426,8 @@ if not defn.get('name'):
obj_name = str(defn['name'])
# Auto-synonym
-synonym = str(defn['synonym']) if defn.get('synonym') else split_camel_case(obj_name)
+# Проброс без стрингификации (строка ИЛИ {ru,en} — мультиязычный синоним объекта).
+synonym = defn['synonym'] if defn.get('synonym') is not None else split_camel_case(obj_name)
comment = str(defn['comment']) if defn.get('comment') else ''
# ---------------------------------------------------------------------------
@@ -1619,7 +1620,8 @@ def emit_scheduled_job_properties(indent):
if method_name and not method_name.startswith('CommonModule.'):
method_name = f'CommonModule.{method_name}'
X(f'{i}{esc_xml(method_name)}')
- description = str(defn['description']) if defn.get('description') else synonym
+ # synonym может быть {ru,en}; Description — плоская строка, берём ru-текст.
+ description = str(defn['description']) if defn.get('description') else (synonym if isinstance(synonym, str) else '')
X(f'{i}{esc_xml(description)}')
key = str(defn['key']) if defn.get('key') else ''
X(f'{i}{esc_xml(key)}')
diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
index cbf6e1ac..83d8a92a 100644
--- a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
+++ b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
@@ -1,4 +1,4 @@
-# meta-decompile v0.6 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
+# meta-decompile v0.7 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
#
# Пилот: только Catalog. Инверс meta-compile (omit-on-default: ключ эмитим только
@@ -237,8 +237,10 @@ function Attr-ToDsl {
# === Сборка DSL ===
$dsl = [ordered]@{ type = 'Catalog'; name = $objName }
-$syn = Get-MLru ($props.SelectSingleNode('md:Synonym', $nsm))
-if ($syn -and $syn -ne (Split-CamelWords $objName)) { $dsl['synonym'] = $syn }
+# Синоним объекта: строка ru-only ИЛИ {ru,en} (мультиязычно). Кастом → эмитим.
+$synVal = Get-MLValue ($props.SelectSingleNode('md:Synonym', $nsm))
+if ($synVal -is [string]) { if ($synVal -ne (Split-CamelWords $objName)) { $dsl['synonym'] = $synVal } }
+elseif ($null -ne $synVal) { $dsl['synonym'] = $synVal }
$cmt = P 'Comment'; if ($cmt) { $dsl['comment'] = $cmt }
# Свойства Catalog (omit-on-default). Порядок ключей — как удобно DSL.
diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md
index 87de4782..0b95aeaf 100644
--- a/docs/meta-dsl-spec.md
+++ b/docs/meta-dsl-spec.md
@@ -149,7 +149,7 @@ JSON DSL для описания объектов метаданных конф
| `createOnInput` | CreateOnInput | Auto | Auto/Use/DontUse |
| `quickChoice` | QuickChoice | Auto | Auto/Use/DontUse. Прощаем bool (форм-стиль): `true`→Use, `false`→DontUse |
| `dataHistory` | DataHistory | Use | Use/DontUse |
-| `use` | Use | ForItem | ForItem/ForFolderAndItem/ForFolder (иерарх. каталог) |
+| `use` | Use | ForItem | ForItem/ForFolderAndItem/ForFolder (иерарх. справочник) |
| `passwordMode` | PasswordMode | false | bool |
| `mask` | Mask | пусто | строка маски |
| `format` / `editFormat` | Format / EditFormat | пусто | строка/`{ru,en}` (ML, форматная строка 1С) |
@@ -268,7 +268,7 @@ JSON DSL для описания объектов метаданных конф
Блок `` платформа материализует **только когда пользователь кастомизировал хотя бы один стандартный реквизит** (Наименование/Код/Владелец/…). Ни иерархия, ни владелец, ни предопределённые сами по себе блок не создают. В DSL это выражается **наличием ключа `standardAttributes`**:
-- **Ключа нет** → блок не эмитится (обычный каталог: Наименование, Код, Владелец и т.д. остаются платформенными по умолчанию).
+- **Ключа нет** → блок не эмитится (обычный справочник: Наименование, Код, Владелец и т.д. остаются платформенными по умолчанию).
- **Ключ есть** (даже пустой `{}`) → эмитится полный блок из всех стандартных реквизитов с **профилем материализованного блока**, поверх которого накладываются заданные переопределения.
Формат: `standardAttributes` — объект `{ ИмяРеквизита: { переопределения } }`. Имена реквизитов — как в XML: `PredefinedDataName`, `Predefined`, `Ref`, `DeletionMark`, `IsFolder`, `Owner`, `Parent`, `Description`, `Code`.
@@ -334,7 +334,7 @@ JSON DSL для описания объектов метаданных конф
"childItems": [ "Факс", "(7) Скайп [Скайп]" ] }
```
-Тип кода в XML определяется свойством каталога `codeType`: `Number` → ``, `String` → `` (без типа); пустой код → ``.
+Тип кода в XML определяется свойством справочника `codeType`: `Number` → ``, `String` → `` (без типа); пустой код → ``.
> Пока поддержано для **Catalog** (`CatalogPredefinedItems`). ChartOf*/ПВХ — при их проработке.
diff --git a/tests/skills/cases/meta-compile/catalog-attr-ml.json b/tests/skills/cases/meta-compile/catalog-attr-ml.json
index 51bb479b..10f1a04d 100644
--- a/tests/skills/cases/meta-compile/catalog-attr-ml.json
+++ b/tests/skills/cases/meta-compile/catalog-attr-ml.json
@@ -2,6 +2,7 @@
"name": "Справочник с ML-синонимом и подсказкой реквизита",
"input": {
"type": "Catalog", "name": "Контрагенты",
+ "synonym": { "ru": "Контрагенты", "en": "Counterparties" },
"attributes": [
{ "name": "ИНН", "type": "String(12)", "synonym": { "ru": "ИНН", "en": "TIN" }, "tooltip": "Идентификационный номер налогоплательщика" },
{ "name": "Комментарий", "type": "String(200)", "tooltip": { "ru": "Произвольный комментарий", "en": "Free-form comment" } }
diff --git a/tests/skills/cases/meta-compile/snapshots/catalog-attr-ml/Catalogs/Контрагенты.xml b/tests/skills/cases/meta-compile/snapshots/catalog-attr-ml/Catalogs/Контрагенты.xml
index cf2a78f2..aabf9db8 100644
--- a/tests/skills/cases/meta-compile/snapshots/catalog-attr-ml/Catalogs/Контрагенты.xml
+++ b/tests/skills/cases/meta-compile/snapshots/catalog-attr-ml/Catalogs/Контрагенты.xml
@@ -30,6 +30,10 @@
ru
Контрагенты
+
+ en
+ Counterparties
+
false