Skip to content

Переводы

Виджет Shoutbox, его право доступа и его ссылка навигации прямо сейчас показывают захардкоженный английский. На этой странице мы переносим этот текст в файлы локалей, чтобы Shoutbox говорил на каждом языке, на котором говорит ваш сервер — и чтобы заголовок его права доступа и строки журнала активности показывали настоящие слова вместо сырых ключей.

Полный справочник: Локализация.

А это вообще обязательно?

Да, хотя бы немного. Вы можете захардкодить английский в своих Svelte-компонентах — но двум видам текста больше негде жить: заголовки прав доступа (страница «Права доступа» в панели) и строки журнала активности (страница «Активность») могут браться только из файлов локалей. Так что даже англоязычному аддону нужен en-US.json.

Шаг 1 — настройте файлы локалей

Текст живёт в JSON-файлах в папке src/main/resources/locales/, по одному файлу на язык, а имя файла — это код языка:

src/main/resources/locales/
├─ en-US.json   ← required; also the fallback
├─ tr.json
└─ ru.json

Обязателен только en-US.json. Создайте его сейчас, содержащим просто {}, если его ещё нет.

en-US — это подстраховка

Если ключ отсутствует для языка посетителя, Pano откатывается к en-US.json. Если его нет и там тоже, посетитель видит на экране сырой путь ключа (вроде plugins.pano-plugin-shoutbox.widget.title). Держите en-US.json полным — сырой ключ на экране это ваш первый признак, что это не так. Также сохраняйте каждый файл в UTF-8, иначе турецкие/русские символы превратятся в кашу вроде ö.

Шаг 2 — пространство имён, в одном предложении

Pano отдаёт каждый написанный вами ключ под plugins.<pluginId>.<key>. Для Shoutbox этот префикс — plugins.pano-plugin-shoutbox.. Вы никогда не пишете этот префикс — в вашем JSON ключи остаются короткими (widget.title), а Pano добавляет префикс автоматически. Именно это удерживает ваши ключи от столкновений с ключами ядра платформы или другого аддона.

Единственное место, где префикс действительно написан, — маленький хелпер, который шаблон уже поставляет в main.js:

js
export const _ = derived(i18n, ($t) => (key, options) => $t(`plugins.${pluginId}.${key}`, options));

Скопируйте его как есть; чтобы им пользоваться, понимать его не нужно.

Шаг 3 — определите первые ключи

Поместите текст вашего UI в en-US.json, вложенный как вам угодно. Вложенные объекты становятся путями через точку, а {...} отмечает плейсхолдер, который вы заполните позже:

json
{
  "widget": {
    "title": "Latest shouts",
    "empty": "No shouts yet — be the first!"
  },
  "nav": {
    "shoutbox": "Shoutbox"
  }
}

Шаг 4 — используйте ключи в компоненте

Импортируйте хелпер _ из вашего main.js и читайте его с префиксом $:

svelte
<script>
  import { _ } from '../main.js';
</script>

<h2>{$_('widget.title')}</h2>

{$_('widget.title')} ищет для вас plugins.pano-plugin-shoutbox.widget.title. Чтобы заполнить плейсхолдер, передайте значения вторым аргументом: $_('welcome-message', { values: { username: 'Ada' } }).

Исправьте ../ под глубину вашего файла

import { _ } from '../main.js' предполагает, что ваш компонент лежит ровно на одну папку ниже main.js. В более глубоко вложенном маршруте добавьте больше ../ (вроде ../../main.js), иначе импорт отдаст 404.

Контрольная точка: живая перезагрузка доказывает себя

При включённом режиме разработки и запущенном bun run dev виджет теперь отрисовывает Latest shouts. Теперь отредактируйте строку в en-US.json, сохраните и нажмите F5 — новый текст появляется без пересборки. В этом и выгода режима разработки: Pano читает ваши locales/*.json вживую с диска на каждый запрос. (При выключенном режиме разработки, или в выпущенном jar, локали читаются изнутри jar — чтобы увидеть изменение, пришлось бы пересобирать и перезапускать.)

Шаг 5 — переведите право доступа и журнал активности

Эти два раздела приходят не из ваших компонентов — Pano читает их напрямую, чтобы заполнить страницы «Права доступа» и «Активность» в панели. Оба лежат в корне файла, рядом с вашими собственными ключами.

Имена ключей выводятся из имён ваших Kotlin-классов, так что вы их не выбираете:

  • Право доступа ManageShoutboxPermission → отбросьте Permission, UPPER_SNAKE → MANAGE_SHOUTBOX.
  • Журнал активности CreatedShoutLog → отбросьте Log, UPPER_SNAKE → CREATED_SHOUT.
json
{
  "permissions": {
    "MANAGE_SHOUTBOX": {
      "title": "Manage Shoutbox",
      "description": "Allows managing shouts shown on the home page."
    }
  },
  "activity-logs": {
    "CREATED_SHOUT": "<b>{username}</b> posted a shout: {target}."
  }
}

Плейсхолдеры {username} и {target} заполняются из полезной нагрузки details записи журнала (собранной в Kotlin-классе). HTML вроде <b> работает только в строках журнала активности — страница «Активность» отрисовывает их как HTML; обычные ключи, показанные через {$_(...)}, его экранируют.

Контрольная точка

Откройте Панель → Права доступа — ваша запись теперь читается как Manage Shoutbox вместо сырого MANAGE_SHOUTBOX. Опубликуйте выкрик, затем откройте Панель → Активность — предложение появляется с именем пользователя жирным.

Шаг 6 — добавьте ещё один язык

Вы не ограничены английским. Добавьте файл, имя которого — код локали — турецкий в tr.json, русский в ru.json — с теми же ключами, переведёнными:

json
{
  "widget": {
    "title": "Son bağırışlar",
    "empty": "Henüz bağırış yok — ilk sen ol!"
  }
}

Любой ключ, который вы не перевели, откатывается к en-US.json, так что частичный перевод никогда не показывает сырой ключ. Чтобы протестировать ваш tr.json, переключите собственный язык на турецкий в Панель → Настройки → Платформа → Предпочтения (или через селектор языка сайта) и обновите.

Администраторы могут переводить за вас

Администраторы могут переопределить любой ключ или добавить целый новый язык прямо из панели, не трогая ваш jar — и их правки переживают обновления аддона. Переопределение администратора всегда побеждает текст из вашего jar, так что кастомная формулировка владельца сайта никогда не будет молча перезаписана обновлением.

Один полный en-US.json

Вот как фрагменты складываются вместе — собственные ключи, permissions и activity-logs, все в корне:

json
{
  "widget": {
    "title": "Latest shouts",
    "empty": "No shouts yet — be the first!"
  },
  "nav": { "shoutbox": "Shoutbox" },
  "permissions": {
    "MANAGE_SHOUTBOX": {
      "title": "Manage Shoutbox",
      "description": "Allows managing shouts shown on the home page."
    }
  },
  "activity-logs": {
    "CREATED_SHOUT": "<b>{username}</b> posted a shout: {target}."
  }
}

Сломанный JSON-файл ломает все свои ключи

JSON строг: одна лишняя запятая, случайный комментарий или незакрытая скобка делают весь файл невалидным, и тогда ни один его ключ не разрешается — вы увидите сырые пути ключей сразу по всей странице. Если такое случилось, в первую очередь подозревайте синтаксическую ошибку JSON и прогоните файл через любой валидатор.

Shoutbox теперь и выглядит как надо, и говорит на языке. Осталось только упаковать его и поделиться с миром.

Далее: Выпуск →