From 65c4fba47167f47124d5306207330898893dbe72 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 4 Jul 2026 14:07:53 +0300 Subject: [PATCH] =?UTF-8?q?feat(meta-compile,meta-decompile):=20object-?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B8=20InputByString/DataLockFi?= =?UTF-8?q?elds/BasedOn=20(v1.28/v0.19)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Три object-блока каталога компилятор хардкодил (InputByString={Descr,Code}, DataLockFields/BasedOn пустые), декомпилятор не захватывал. Class-2 фикс InputByString: хардкод → вывод из Code/DescriptionLength ([Descr при D>0]+[Code при C>0]) — покрывает 88.5% каталогов, убил каскад Field ADDED=80 (у 1057/1640 InputByString = только Наименование). Class-3 DSL: • inputByString — массив имён полей (авто-резолв через Expand-DataPath, как dataPath), [] = пусто; декомпилятор эмитит только при отличии от дефолта. • dataLockFields — поля блокировки, omit-on-empty. • basedOn — «ввод на основании», MDObjectRef verbatim, omit-on-empty. Хелперы Emit-FieldBlock/Emit-BasedOn (+py-порт); декомпилятор Short-Field (частичная форма StandardAttribute.X/Attribute.X для dogfood резолвера). Class-2 ловушка PS: пустой @() в позиц.параметр схлопывается в $null, а @($null) = массив из 1 null → пустой . Фикс — Where-Object фильтр. Роундтрип 120 объектов: match 20→94, TOTAL 305→183 (−122), DataLockFields 35→0, InputByString/BasedOn=0, новых diff не внесено. Override-кейсы (реверс, +реквизит, пустой, codeonly, dlf, basedOn) роундтрипятся чисто. Регресс 46/46 ps1+py, ps1↔py identical. spec §7.1.5, кейс catalog-inputbystring-datalock. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../meta-compile/scripts/meta-compile.ps1 | 43 ++- .../meta-compile/scripts/meta-compile.py | 43 ++- .../meta-decompile/scripts/meta-decompile.ps1 | 36 ++- docs/meta-dsl-spec.md | 29 ++ .../catalog-inputbystring-datalock.json | 20 ++ .../Catalogs/ДоговорыКонтрагентов.xml | 180 +++++++++++++ .../ДоговорыКонтрагентов/Ext/ObjectModule.bsl | 0 .../Configuration.xml | 252 ++++++++++++++++++ .../Ext/ClientApplicationInterface.xml | 18 ++ .../Languages/Русский.xml | 16 ++ 10 files changed, 622 insertions(+), 15 deletions(-) create mode 100644 tests/skills/cases/meta-compile/catalog-inputbystring-datalock.json create mode 100644 tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Catalogs/ДоговорыКонтрагентов.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Catalogs/ДоговорыКонтрагентов/Ext/ObjectModule.bsl create mode 100644 tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Configuration.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Ext/ClientApplicationInterface.xml create mode 100644 tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Languages/Русский.xml diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 9be0259c..0ae4cd34 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -1,4 +1,4 @@ -# meta-compile v1.27 — Compile 1C metadata object from JSON +# meta-compile v1.28 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -1202,6 +1202,29 @@ function Emit-LinkByType { X "$indent" } +# Есть ли ключ в $def (отличаем отсутствие от пустого массива [] = явно пусто). +function Test-DefKey { param([string]$name) return ($def.PSObject -and $def.PSObject.Properties -and ($def.PSObject.Properties.Name -contains $name)) } + +# со списком (InputByString/DataLockFields). $fields — готовые полные пути. Пусто → self-close. +function Emit-FieldBlock { + param([string]$indent, [string]$tag, $fields) + $arr = @($fields | Where-Object { "$_" -ne '' }) + if ($arr.Count -eq 0) { X "$indent<$tag/>"; return } + X "$indent<$tag>" + foreach ($f in $arr) { X "$indent`t$(Esc-Xml "$f")" } + X "$indent" +} + +# — «ввод на основании», список MDObjectRef ("Catalog.X"/"Document.Y"). Нет ключа/пусто → self-close. +function Emit-BasedOn { + param([string]$indent, $items) + $arr = @($items | Where-Object { $_ }) + if ($arr.Count -eq 0) { X "$indent"; return } + X "$indent" + foreach ($it in $arr) { X "$indent`t$(Esc-Xml "$it")" } + X "$indent" +} + # --- Параметры/связи выбора (порт из form-compile; структура реквизита ⟷ элемента формы совпадает) --- # Свойство из dict/PSCustomObject по списку синонимов (первый найденный, иначе $null). @@ -1879,10 +1902,15 @@ function Emit-CatalogProperties { $choiceMode = Get-EnumProp "ChoiceMode" "choiceMode" "BothWays" X "$i$quickChoice" X "$i$choiceMode" - X "$i" - X "$i`tCatalog.$objName.StandardAttribute.Description" - X "$i`tCatalog.$objName.StandardAttribute.Code" - X "$i" + # InputByString: override `inputByString` (массив имён, авто-резолв; [] = пусто) ЛИБО дефолт [Descr при D>0]+[Code при C>0]. + if (Test-DefKey 'inputByString') { + $ibFields = @($def.inputByString | ForEach-Object { Expand-DataPath "$_" }) + } else { + $ibFields = @() + if ([int]$descriptionLength -gt 0) { $ibFields += "Catalog.$objName.StandardAttribute.Description" } + if ([int]$codeLength -gt 0) { $ibFields += "Catalog.$objName.StandardAttribute.Code" } + } + Emit-FieldBlock $i "InputByString" $ibFields X "$i$(Get-EnumProp 'SearchStringModeOnInputByString' 'searchStringModeOnInputByString' 'Begin')" X "$iDontUse" X "$iDirectly" @@ -1898,8 +1926,9 @@ function Emit-CatalogProperties { Emit-FormRef $i "AuxiliaryFolderChoiceForm" $def.auxiliaryFolderChoiceForm $inclHelp = if (Get-BoolProp "includeHelpInContents" $false) { "true" } else { "false" } X "$i$inclHelp" - X "$i" - X "$i" + Emit-BasedOn $i $def.basedOn + $dlFields = if (Test-DefKey 'dataLockFields') { @($def.dataLockFields | ForEach-Object { Expand-DataPath "$_" }) } else { @() } + Emit-FieldBlock $i "DataLockFields" $dlFields $dataLockControlMode = Get-EnumProp "DataLockControlMode" "dataLockControlMode" "Automatic" X "$i$dataLockControlMode" diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 5d34320a..b3b594de 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-compile v1.27 — Compile 1C metadata object from JSON +# meta-compile v1.28 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -1269,6 +1269,28 @@ def emit_link_by_type(indent, spec): X(f'{indent}\t{li}') X(f'{indent}') +def emit_field_block(indent, tag, fields): + """ со списком (InputByString/DataLockFields). Пусто → self-close.""" + arr = [f for f in (fields or []) if str(f) != ''] + if not arr: + X(f'{indent}<{tag}/>') + return + X(f'{indent}<{tag}>') + for f in arr: + X(f'{indent}\t{esc_xml(str(f))}') + X(f'{indent}') + +def emit_based_on(indent, items): + """ — «ввод на основании», список MDObjectRef. Нет/пусто → self-close.""" + arr = [it for it in (items or []) if it] + if not arr: + X(f'{indent}') + return + X(f'{indent}') + for it in arr: + X(f'{indent}\t{esc_xml(str(it))}') + X(f'{indent}') + # --- Параметры/связи выбора (порт из form-compile) --- def ch_el_prop(obj, names): @@ -1879,10 +1901,16 @@ def emit_catalog_properties(indent): choice_mode = get_enum_prop('ChoiceMode', 'choiceMode', 'BothWays') X(f'{i}{quick_choice}') X(f'{i}{choice_mode}') - X(f'{i}') - X(f'{i}\tCatalog.{obj_name}.StandardAttribute.Description') - X(f'{i}\tCatalog.{obj_name}.StandardAttribute.Code') - X(f'{i}') + # InputByString: override `inputByString` (массив имён, авто-резолв; [] = пусто) ЛИБО дефолт [Descr при D>0]+[Code при C>0]. + if 'inputByString' in defn: + ib_fields = [expand_data_path(str(x)) for x in (defn.get('inputByString') or [])] + else: + ib_fields = [] + if int(description_length) > 0: + ib_fields.append(f'Catalog.{obj_name}.StandardAttribute.Description') + if int(code_length) > 0: + ib_fields.append(f'Catalog.{obj_name}.StandardAttribute.Code') + emit_field_block(i, 'InputByString', ib_fields) X(f'{i}{get_enum_prop("SearchStringModeOnInputByString", "searchStringModeOnInputByString", "Begin")}') X(f'{i}DontUse') X(f'{i}Directly') @@ -1898,8 +1926,9 @@ def emit_catalog_properties(indent): emit_form_ref(i, 'AuxiliaryFolderChoiceForm', defn.get('auxiliaryFolderChoiceForm')) incl_help = 'true' if get_bool_prop('includeHelpInContents', False) else 'false' X(f'{i}{incl_help}') - X(f'{i}') - X(f'{i}') + emit_based_on(i, defn.get('basedOn')) + dl_fields = [expand_data_path(str(x)) for x in defn.get('dataLockFields', [])] if 'dataLockFields' in defn else [] + emit_field_block(i, 'DataLockFields', dl_fields) data_lock_control_mode = get_enum_prop('DataLockControlMode', 'dataLockControlMode', 'Automatic') X(f'{i}{data_lock_control_mode}') full_text_search = get_enum_prop('FullTextSearch', 'fullTextSearch', 'Use') diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 index 92ae391a..f0bbdf4d 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.18 — XML объекта метаданных 1С → JSON-черновик формата meta-compile +# meta-decompile v0.19 — XML объекта метаданных 1С → JSON-черновик формата meta-compile # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # # Пилот: только Catalog. Инверс meta-compile (omit-on-default: ключ эмитим только @@ -387,6 +387,40 @@ Add-EnumProp 'choiceHistoryOnInput' 'ChoiceHistoryOnInput' 'Auto' Add-EnumProp 'predefinedDataUpdate' 'PredefinedDataUpdate' 'Auto' Add-EnumProp 'searchStringModeOnInputByString' 'SearchStringModeOnInputByString' 'Begin' +# Короткая форма поля: ..StandardAttribute.X / .Attribute.X → StandardAttribute.X / Attribute.X +# (Expand-DataPath компилятора разворачивает частичную форму обратно — dogfood резолвера). +function Short-Field { param([string]$full) if ($full -match '\.(StandardAttribute|Attribute)\.(.+)$') { return "$($Matches[1]).$($Matches[2])" } return $full } + +# InputByString — эмитим только при отличии от выведенного дефолта [Descr при D>0]+[Code при C>0]. +$ibNode = $props.SelectSingleNode('md:InputByString', $nsm) +if ($ibNode) { + $ibActual = @($ibNode.SelectNodes('xr:Field', $nsm) | ForEach-Object { $_.InnerText }) + $clv = P 'CodeLength'; $dlv = P 'DescriptionLength' + $cl = if ($clv -and $clv -ne '') { [int]$clv } else { 9 } + $dl = if ($dlv -and $dlv -ne '') { [int]$dlv } else { 25 } + $ibDef = @() + if ($dl -gt 0) { $ibDef += "StandardAttribute.Description" } + if ($cl -gt 0) { $ibDef += "StandardAttribute.Code" } + $ibShort = @($ibActual | ForEach-Object { Short-Field $_ }) + $same = ($ibShort.Count -eq $ibDef.Count) + if ($same) { for ($k = 0; $k -lt $ibShort.Count; $k++) { if ($ibShort[$k] -ne $ibDef[$k]) { $same = $false; break } } } + if (-not $same) { $dsl['inputByString'] = [System.Collections.ArrayList]@($ibShort) } +} + +# BasedOn — «ввод на основании», список MDObjectRef (omit-on-empty). +$boNode = $props.SelectSingleNode('md:BasedOn', $nsm) +if ($boNode) { + $boItems = @($boNode.SelectNodes('xr:Item', $nsm) | ForEach-Object { $_.InnerText }) + if ($boItems.Count -gt 0) { $dsl['basedOn'] = [System.Collections.ArrayList]@($boItems) } +} + +# DataLockFields — поля блокировки данных (omit-on-empty). +$dlfNode = $props.SelectSingleNode('md:DataLockFields', $nsm) +if ($dlfNode) { + $dlfFields = @($dlfNode.SelectNodes('xr:Field', $nsm) | ForEach-Object { Short-Field $_.InnerText }) + if ($dlfFields.Count -gt 0) { $dsl['dataLockFields'] = [System.Collections.ArrayList]@($dlfFields) } +} + # Формы по умолчанию (компилятор пишет пусто → omit-on-empty; значение = ссылка на форму verbatim). function Add-FormRef { param([string]$key, [string]$tag) $v = P $tag; if ($v) { $dsl[$key] = $v } } Add-FormRef 'defaultObjectForm' 'DefaultObjectForm' diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md index 2721d896..04344bda 100644 --- a/docs/meta-dsl-spec.md +++ b/docs/meta-dsl-spec.md @@ -347,6 +347,9 @@ JSON DSL для описания объектов метаданных конф | `extendedListPresentation` | пусто | ExtendedListPresentation (ML) | | `explanation` | пусто | Explanation (ML) | | `standardAttributes` | *(ключа нет → блок опущен)* | StandardAttributes | +| `inputByString` | *(ключа нет → авто-вывод)* | InputByString (поля ввода по строке, §7.1.5) | +| `dataLockFields` | `[]` | DataLockFields (поля блокировки данных, §7.1.5) | +| `basedOn` | `[]` | BasedOn (ввод на основании, §7.1.5) | | `characteristics` | `[]` | Characteristics (привязка ПВХ, §7.1.4) | | `attributes` | `[]` | → Attribute в ChildObjects | | `tabularSections` | `{}` | → TabularSection в ChildObjects | @@ -485,6 +488,32 @@ JSON DSL для описания объектов метаданных конф Декомпилятор пишет короткую форму (поля голые/частичные, `filterValue` без каталога, `from` полный). +#### 7.1.5 `inputByString` / `dataLockFields` / `basedOn` — object-списки полей + +Три списка object-уровня. Имена полей — прощающий ввод как `dataPath`: голое стандартное (`Наименование`/`Код`/ +`Владелец`, RU→EN) → `<Тип>.<Объект>.StandardAttribute.`; голое обычное → `Attribute.<имя>`; +частичное `StandardAttribute.X`/`Attribute.X` → + префикс; полный путь → как есть. + +- **`inputByString`** — поля быстрого ввода по строке (``). **Дефолт выводится** из наличия Кода/ + Наименования: `[Наименование при descriptionLength>0] + [Код при codeLength>0]` — покрывает ~88% каталогов, ключ не + нужен. Задавать только при отличии: другой порядок, подмножество, добавленные реквизиты, или **пустой список `[]`** + (быстрый ввод выключен). + ```json + "inputByString": ["Код", "Наименование", "Контрагент"] // порядок + реквизит + "inputByString": [] // явно пусто + ``` +- **`dataLockFields`** — поля управляемой блокировки данных (``). По умолчанию пусто; массив имён полей. + ```json + "dataLockFields": ["Организация", "Контрагент", "Владелец"] + ``` +- **`basedOn`** — «ввод на основании» (``), список ссылок на объекты метаданных (`MDObjectRef`) verbatim. + ```json + "basedOn": ["Catalog.Контрагенты", "Document.ЗаказПоставщику"] + ``` + +Декомпилятор: `inputByString` — только при отличии от выведенного дефолта (иначе опущен); `dataLockFields`/`basedOn` — +omit-on-empty. Поля пишутся частичной формой (`StandardAttribute.X`/`Attribute.X`). + ### 7.2 Document | Поле JSON | Умолчание | XML элемент | diff --git a/tests/skills/cases/meta-compile/catalog-inputbystring-datalock.json b/tests/skills/cases/meta-compile/catalog-inputbystring-datalock.json new file mode 100644 index 00000000..f08b91f5 --- /dev/null +++ b/tests/skills/cases/meta-compile/catalog-inputbystring-datalock.json @@ -0,0 +1,20 @@ +{ + "name": "InputByString / DataLockFields / BasedOn каталога", + "input": { + "type": "Catalog", + "name": "ДоговорыКонтрагентов", + "codeLength": 11, + "descriptionLength": 100, + "inputByString": ["Код", "Наименование", "Контрагент"], + "dataLockFields": ["Организация", "Контрагент", "Владелец"], + "basedOn": ["Catalog.Контрагенты", "Document.ЗаказПоставщику"], + "attributes": [ + "Организация: CatalogRef.Организации", + "Контрагент: CatalogRef.Контрагенты" + ] + }, + "validatePath": "Catalogs/ДоговорыКонтрагентов", + "expect": { + "files": ["Catalogs/ДоговорыКонтрагентов.xml"] + } +} diff --git a/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Catalogs/ДоговорыКонтрагентов.xml b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Catalogs/ДоговорыКонтрагентов.xml new file mode 100644 index 00000000..22c65ed5 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Catalogs/ДоговорыКонтрагентов.xml @@ -0,0 +1,180 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + + ДоговорыКонтрагентов + + + ru + Договоры контрагентов + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + ToItems + 11 + 100 + String + Variable + WholeCatalog + false + true + AsDescription + + Auto + InDialog + false + BothWays + + Catalog.ДоговорыКонтрагентов.StandardAttribute.Code + Catalog.ДоговорыКонтрагентов.StandardAttribute.Description + Catalog.ДоговорыКонтрагентов.Attribute.Контрагент + + Begin + DontUse + Directly + + + + + + + + + + + false + + Catalog.Контрагенты + Document.ЗаказПоставщику + + + Catalog.ДоговорыКонтрагентов.Attribute.Организация + Catalog.ДоговорыКонтрагентов.Attribute.Контрагент + Catalog.ДоговорыКонтрагентов.StandardAttribute.Owner + + Automatic + Use + + + + + + Use + Auto + DontUse + false + false + + + + + Организация + + + ru + Организация + + + + + d5p1:CatalogRef.Организации + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + ForItem + DontIndex + Use + Use + + + + + Контрагент + + + ru + Контрагент + + + + + d5p1:CatalogRef.Контрагенты + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + ForItem + DontIndex + Use + Use + + + + + diff --git a/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Catalogs/ДоговорыКонтрагентов/Ext/ObjectModule.bsl b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Catalogs/ДоговорыКонтрагентов/Ext/ObjectModule.bsl new file mode 100644 index 00000000..e69de29b diff --git a/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Configuration.xml b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Configuration.xml new file mode 100644 index 00000000..391de403 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Configuration.xml @@ -0,0 +1,252 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + UUID-012 + UUID-013 + + + UUID-014 + UUID-015 + + + + TestConfig + + + ru + TestConfig + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + ДоговорыКонтрагентов + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Ext/ClientApplicationInterface.xml new file mode 100644 index 00000000..3c1161b2 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Ext/ClientApplicationInterface.xml @@ -0,0 +1,18 @@ + + + + + UUID-002 + + + + + UUID-004 + + + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Languages/Русский.xml b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Languages/Русский.xml new file mode 100644 index 00000000..37c60d78 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/catalog-inputbystring-datalock/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + \ No newline at end of file