Локализация: языки консоли и документации
| Переключатель в шапке | apps/web/src/language-menu.ts: кнопка с флагом и двумя буквами, список-popover со всеми языками (флаг, своё название, галочка); стрелки, Home, End, буква, Enter, Escape. Флаги — apps/web/flags/<страна>.svg (flag-icons, MIT; лицензия там же и в THIRD-PARTY.txt), сервер отдаёт их через GET /console/flags/:file (два символа и .svg). Флаг — страна, не язык: английский показан флагом Великобритании, португальский — Бразилии, арабский — Саудовской Аравии (flag в languages.ts) |
Состояние: 2026-10-05. Языки: английский (исходный), русский, испанский, французский, немецкий, португальский (Бразилия), китайский (упрощённый), японский, корейский, хинди, арабский — справа налево. Решение: ADR 0068.
1. Где живут тексты
| Что | Где |
|---|---|
| Список языков: код, своё название, направление, локаль чисел | apps/web/src/languages.ts (LANGUAGES); сайт читает его же (wiki/.vitepress/languages.ts) |
| Тексты консоли, английский и русский | apps/web/src/*-messages.ts, сборка в messages-en.ts / messages-ru.ts; тип ключей — MessageKey |
| Тексты консоли на других языках | apps/web/locales/<code>.json: { "key": { "en": "<английский оригинал>", "text": "<перевод>" } } |
| Что получает браузер | apps/web/public/locales/<code>.json — только тексты; пишет scripts/build.mjs |
| Выбор и применение языка | apps/web/src/i18n.ts (setLanguage, initializeLanguage, documentationUrl), preferences.ts, appearance-init.ts (lang/dir до первой отрисовки) |
| Отдача словарей сервером | GET /console/locales/:file (apps/api/src/console.ts): только [a-z]{2}.json |
| Глоссарий терминов | wiki/i18n/terms/<code>.json; английский — с пояснениями |
| Страницы документации | wiki/<section>/<page>.md (английский), wiki/<code>/<section>/<page>.md (переводы) |
| Что говорит сам сайт | wiki/.vitepress/text/<code>.json: разделы, кнопки темы, поиск, слова справочника API |
| Тексты справочника API | wiki/i18n/api/<code>.json: operations, errors, fields |
Язык консоли — сохранённый выбор (localStorage, ключ language), иначе первый язык браузера (navigator.languages), который есть у консоли, по базовому коду (pt-BR → pt), иначе английский. Английский и русский в бандле; другой словарь загружается при выборе и кэшируется на время страницы. Переключение перерисовывает все узлы с data-i18n* и не сбрасывает формы и передачи. Если словарь не загрузился, переключатель возвращается к текущему языку.
Переключатель показывает каждый язык его собственным названием (Deutsch, 日本語) и в его направлении письма, на каком бы языке ни была страница.
Справа налево. Арабский ставит <html dir="rtl">: CSS консоли использует логические свойства (inline-start/end), поэтому раскладка зеркалится. Код, ключи, хэши и адреса остаются слева направо. Числа — латинскими цифрами (intl: "ar-u-nu-latn"), как размеры и порты рядом с ними.
Разрядка. Мелкие подписи капителью разрежены в латинице и кириллице; в арабском, деванагари и CJK разрядки нет (:lang() в CSS консоли и сайта).
2. Как писать текст
- Один ключ — одна вещь, которую читает человек; имя по экрану (
backup*,storage*,permission.*,error*). - Значения — плейсхолдеры
{name}, никогда не склейка строк. Множественного числа в консоли нет: формулируйте нейтрально («Файлов: {count}», «{count} / 32»). - Не переводятся: Arkvory, ProAnimaStudio, UPack, Git LFS, OCI, Docker, npm, Unity, PostgreSQL, SHA-256, HTTP(S), API, CLI, SDK; команды, флаги, переменные
ARKVORY_*, пути, заголовки HTTP, идентификаторы прав (artifact.read), значения стадий (release), примеры (*Example). - Кнопки, вкладки, заголовки колонок — коротко: ширины фиксированы, цель касания 44 px.
- Термины — по глоссарию языка (
wiki/i18n/terms/<code>.json), одинаково в консоли и в документации. - Новый текст добавляется в английский и русский словари, затем в каждый
apps/web/locales/*.json(en— текущий английский,text— перевод). Изменили английский — обновитеenиtextво всех файлах: тест покажет устаревшие.
3. Что проверяется
| Проверка | Где |
|---|---|
| У каждого языка есть словарь со всеми ключами, переведённый с текущего английского, с теми же плейсхолдерами | tests/web-locales.test.mjs |
| Выбор языка: сохранённый → браузер → английский; RTL; латинские цифры в арабском | tests/web-locales.test.mjs |
| Сервер отдаёт словарь по двум буквам и 404 на любое другое имя | tests/integration/sdk.test.mjs |
| Консоль на каждом языке: направление, ничего шире окна на 320 и 1440 px, нет пустых подписей, текст в своей письменности, ссылка на документацию того же языка | tests/browser/languages.mjs (гейт browser) |
В каждом языке все страницы документации, те же id заголовков, метки [[ui:]] и блоки кода | tests/wiki.test.mjs |
| Все тексты сайта, глоссарий, тексты операций API, ошибок и полей — у каждого языка, не устаревшие | tests/wiki.test.mjs |
Каждая [[ui:key]] — существующая подпись без плейсхолдеров | tests/wiki.test.mjs и сборка сайта |
| Сайт собирается без битых ссылок | гейт docs |
4. Как добавить язык
- Строка в
LANGUAGES(apps/web/src/languages.ts): код BCP 47, своё название,dir: 'rtl'для письма справа налево,intl— если числа нужно писать не по умолчанию. apps/web/locales/<code>.json: скопируйте файл другого языка, замените всеtext;enоставьте.wiki/i18n/terms/<code>.json— глоссарий;wiki/.vitepress/text/<code>.json— тексты сайта;wiki/i18n/api/<code>.json— тексты справочника.wiki/<code>/— страницы английской документации с теми же id заголовков, метками и блоками кода; недостающие показываются по-английски как заглушки (npm run wiki -- stubs, см. WIKI). ВCOMPLETEязык попадает, когда переведено всё.npm run gate -- quick, затем гейтыbrowserиdocs: тесты назовут каждый пропущенный текст и страницу.
5. Что не переводится намеренно
- Данные пользователя: имена артефактов, метки, метаданные, комментарии.
- Раздел документации для разработчиков — копия
docs/на русском. - Журналы сервера и ответы API:
messageошибки — английский текст для журнала; клиенты решают поcodeиreason, консоль показывает свой текст по коду. - Установщик Windows, мастер удалённой установки,
arkvoryctl— пока английский и русский. - Отзыв в хаб уходит с языком
ruилиen: другой язык консоли отправляется какen(контракт хаба). - Лицензия —
LICENSE.mdиLICENSE.ru.md; при расхождении действует русский текст.