Перейти к содержанию

Интернационализация

Metabase — приложение с большим количеством пользователей по всему миру. Чтобы помочь им использовать Metabase на своём родном языке, все строки помечены как i18n.

Краткое пособие

Если вам нужно добавить новые тексты (постарайтесь быть разумными при добавлении), сделайте следующее:

  1. Пометьте строки во внешнем интерфейсе, используя литералы шаблонов t и jt ES6 подробнее см.
const someString = t`Hello ${name}!`;
const someJSX = <div>{jt`Hello ${name}`}</div>;

и в бэкенде с помощью trs (для использования текущего языка сайта) или tru (для использования текущего языка пользователя):

(trs "Hello {0}!" name)

Ошибки перевода или отсутствующие строки

Если вы видите неправильные или отсутствующие строки для вашего языка, посетите наш проект POEditor и отправьте туда свои исправления.

Руководство по переводу серверной части

Glarus BI позволяет выполнять переводы на многие языки. Официальный список можно найти в resources/locales.clj.

На стороне Glarus BI

Glarus BI заботится о локализации в двух различных локалях: переводе в локали сервера и переводе в локали пользователя. Разница в значительной степени заключается в том, будет ли это зарегистрировано на сервере или отправлено по сети обратно пользователю.

Чтобы перевести строку для сервера, используйте metabase.util.i18n/trs, а для локали пользователя используйте аналогичную metabase.util.i18n/tru. Подумайте о tr-server и tr-user.

Как это работает

Грубо говоря, переводимая строка рассматривается как ключ поиска в словаре исходная строка -> локализованная строка. Эта переведённая строка используется так:

;; from source of `translate` in `metabase.util.i18n`

(.format (MessageFormat. looked-up-string) (to-array args))

При этом используется класс java.text.MessageFormat для объединения в аргументах формата.

Функции trs и tru создают экземпляры двух записей, SiteLocalizedString и UserLocalizedString соответственно с переопределением метода toString. Этот метод выполняет поиск текущей локали (пользователь или сайт в зависимости от ситуации), ищет строку для перевода в соответствующую переведенную строку, а затем вызывает метод .format для MessageFormat.

Соответствие исходной строки переведённой строке

На определённом шаге нашей сборки Glarus BI создаёт файл edn маппинга из исходной строки в переведённую строку для каждой поддерживаемой локали. Они расположены в resources/i18n. Если у вас нет этих файлов, вы можете запустить bin/build-translation-resources, чтобы сгенерировать их.

У нас есть много участников, которые помогают нам поддерживать качество перевода строк на множество разных языков. Мы используем POEditor, чтобы вести актуальный список. Мы экспортируем из него файлы .po, которые по сути являются словарём перевода из исходного кода в переведённую строку. В рамках нашего процесса сборки мы форматируем эти файлы как файлы edn и сопоставляем исходный текст с переведённой строкой для каждой локали.

Форматирование

Помимо строковых литералов, мы также хотим переводить строки, аргументы которых вставлены в середину строки. Мы используем синтаксис из упомянутого ранее класса java.text.MessageFormat. Это аргументы с нулевым индексом формы {0}, {1}.

например,

(trs "{0} accepted their {1} invite" (:common_name new-user) (app-name-trs))
(tru "{0}th percentile of {1}" p (aggregation-arg-display-name inner-query arg))
(tru "{0} driver does not support foreign keys." driver/*driver*)

Экранирование

Каждый строковый язык нуждается в escape-символе. Поскольку {0} — это аргумент, который должен быть вставлен, то возникает запрос: каким образом вы можете использовать точную подстроку "{0}" в строке? Специально для таких случаев используется апостроф, это описано в MessageFormat javadocs.

Однако у этого способа есть неприятный побочный эффект. Поскольку апостроф является распространённой частью речи (особенно во французском языке), мы часто можем использовать escape-символы как обычную часть строки, а не escape-символ. В этом случае строки формата должны использовать двойные апострофы, такие как (deferred-tru "SAML attribute for the user''s email address), чтобы избежать апострофа.

Во многих переводах на французский язык один апостроф используется неправильно. (например, "l'URL" вместо "l''URL"). У нас есть ручное исправление для этого в bin/i18n/src/i18n/create_artifacts/backend.clj, где мы пытаемся идентифицировать эти апострофы, которые не являются escape-символами, и заменяем их двойными кавычками.