Локализация пользовательского интерфейса не ограничивается переводом текстовых строк на другой язык. Пользователи из разных стран воспринимают информацию через призму собственных культурных норм, традиций, привычек и ожиданий. Интерфейс, удобный для одной аудитории, может вызывать непонимание или даже негативную реакцию у другой.
В контексте международных приложений библиотека I18next выступает не только инструментом перевода, но и механизмом управления культурно-зависимым контентом. Она позволяет учитывать особенности форматирования данных, региональные различия, варианты написания текстов и специфику пользовательского опыта.
При разработке многоязычных приложений необходимо учитывать несколько уровней адаптации:
| Уровень | Описание |
|---|---|
| Язык | Перевод текста на другой язык |
| Регион | Различия внутри одного языка |
| Форматы данных | Даты, время, числа, валюты |
| Символика | Иконки, изображения, цвета |
| Поведение интерфейса | Направление текста, расположение элементов |
| Контекст общения | Формальный или неформальный стиль |
Например:
I18next позволяет разделять такие варианты через систему региональных локалей.
i18next.init({
lng: "en-US",
resources: {
"en-US": {
translation: {
favoriteColor: "Favorite color"
}
},
"en-GB": {
translation: {
favoriteColor: "Favourite colour"
}
}
}
});
Стандарт ISO определяет язык и регион через составной код:
en-US
en-GB
fr-FR
fr-CA
es-ES
es-MX
pt-PT
pt-BR
ru-RU
kk-KZ
Структура:
язык-страна
Например:
i18next.changeLanguage("pt-BR");
или
i18next.changeLanguage("pt-PT");
Хотя оба варианта используют португальский язык, словарный запас и некоторые формулировки отличаются.
Одним из важных механизмов I18next является автоматический поиск подходящего перевода.
Настройка:
i18next.init({
lng: "en-AU",
fallbackLng: "en"
});
Структура ресурсов:
resources: {
en: {
translation: {
welcome: "Welcome"
}
}
}
Поиск выполняется следующим образом:
Это позволяет создавать общие переводы для языка и переопределять только необходимые строки для отдельных регионов.
Формат даты существенно зависит от страны.
Примеры:
| Регион | Формат |
|---|---|
| США | MM/DD/YYYY |
| Россия | DD.MM.YYYY |
| Германия | DD.MM.YYYY |
| Япония | YYYY/MM/DD |
Дата:
04/05/2025
может означать:
Поэтому отображение даты должно учитывать локаль пользователя.
Современный JavaScript предоставляет API Intl.
Пример:
const date = new Date();
new Intl.DateTimeFormat("ru-RU").format(date);
new Intl.DateTimeFormat("en-US").format(date);
new Intl.DateTimeFormat("ja-JP").format(date);
Совместно с I18next локаль обычно определяется через текущий язык:
const locale = i18next.language;
const formatter = new Intl.DateTimeFormat(locale);
formatter.format(new Date());
Существуют два основных стандарта отображения времени:
14:30
18:45
23:10
Используется во многих странах Европы и Азии.
2:30 PM
6:45 PM
11:10 PM
Наиболее распространён в США.
Пример:
new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric"
}).format(new Date());
Для России:
new Intl.DateTimeFormat("ru-RU", {
hour: "numeric",
minute: "numeric"
}).format(new Date());
Стоимость товара должна отображаться привычным для пользователя образом.
Пример одной и той же суммы:
| Страна | Отображение |
|---|---|
| США | $1,250.50 |
| Германия | 1.250,50 € |
| Россия | 1 250,50 ₽ |
| Казахстан | 1 250,50 ₸ |
Использование:
new Intl.NumberFormat("ru-RU", {
style: "currency",
currency: "RUB"
}).format(1250.5);
Для США:
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
}).format(1250.5);
Текущая локаль может определяться через I18next:
const locale = i18next.language;
new Intl.NumberFormat(locale, {
style: "currency",
currency: "EUR"
}).format(1250.5);
Даже запись чисел отличается между регионами.
Число:
1234567.89
может отображаться как:
1,234,567.89
или
1 234 567,89
Пример:
new Intl.NumberFormat("en-US").format(1234567.89);
new Intl.NumberFormat("ru-RU").format(1234567.89);
Некоторые страны используют метрическую систему:
км
кг
°C
Другие предпочитают имперскую:
mile
lb
°F
Пример переводов:
{
"distance": "Расстояние: {{value}} км"
}
Английская версия:
{
"distance": "Distance: {{value}} miles"
}
Использование:
t("distance", {
value: 12
});
При необходимости могут использоваться разные наборы переводов для различных регионов.
Многие языки имеют несколько уровней вежливости.
Например:
Формально:
Sie
Неформально:
du
Формально:
vous
Неформально:
tu
В переводах это может выглядеть так:
{
"welcomeFormal": "Bienvenue",
"welcomeInformal": "Salut"
}
Выбор строки зависит от контекста приложения.
Цвета воспринимаются по-разному в разных культурах.
Примеры:
| Цвет | Возможное восприятие |
|---|---|
| Белый | Чистота, траур |
| Красный | Опасность, удача |
| Зелёный | Экология, религия |
| Чёрный | Элегантность, траур |
Хотя I18next не управляет цветами напрямую, через него можно переключать тематические настройки.
Пример:
{
"theme": "dark"
}
или
{
"theme": "light"
}
Получение значения:
const theme = t("theme");
Изображения также могут требовать локализации.
Например:
Через переводы можно хранить пути к изображениям.
{
"banner": "/images/us-banner.jpg"
}
Для другой локали:
{
"banner": "/images/japan-banner.jpg"
}
Использование:
<img src={t("banner")} />
Некоторые символы интерпретируются по-разному.
Например:
Вместо жёстко заданных иконок можно использовать локализованные ресурсы:
{
"supportIcon": "support-us.svg"
}
{
"supportIcon": "support-eu.svg"
}
Многие языки используют направление слева направо:
LTR
Примеры:
Некоторые языки используют направление справа налево:
RTL
Примеры:
I18next содержит встроенную функцию определения направления.
i18next.dir();
Результат:
ltr
или
rtl
Применение:
document.documentElement.dir = i18next.dir();
Для RTL-интерфейсов часто требуется:
Рекламные тексты редко переводятся буквально.
Пример английского слогана:
Save big today!
Для разных рынков могут использоваться совершенно разные формулировки.
Словарь:
{
"promoText": "Экономьте уже сегодня"
}
Другая локаль:
{
"promoText": "Получите специальные предложения"
}
В данном случае перевод является адаптацией, а не буквальной заменой текста.
Для культурно-зависимых сообщений удобно применять контексты.
Переводы:
{
"welcome_male": "Добро пожаловать",
"welcome_female": "Добро пожаловать"
}
Использование:
t("welcome", {
context: "male"
});
или
t("welcome", {
context: "female"
});
Подобный механизм особенно востребован в языках со сложной грамматикой.
Контент приложения может меняться в зависимости от региона.
Пример:
{
"holiday": "День независимости"
}
Для другой страны:
{
"holiday": "День благодарения"
}
Использование:
t("holiday");
Это позволяет строить регионально ориентированные интерфейсы без дополнительной логики внутри приложения.
Практикой крупных проектов является разделение переводов на несколько уровней:
locales/
├─ en/
│ ├─ common.json
│ ├─ marketing.json
│ └─ regional.json
│
├─ en-US/
│ └─ regional.json
│
├─ en-GB/
│ └─ regional.json
│
└─ ru/
├─ common.json
├─ marketing.json
└─ regional.json
Подобная структура позволяет:
Предпочтительно использовать:
en-US
en-GB
fr-CA
pt-BR
kk-KZ
вместо только языковых кодов:
en
fr
pt
если приложение работает на нескольких рынках.
Вместо:
"01.05.2025"
следует использовать:
Intl.DateTimeFormat
Перевод:
Buy now
не всегда должен иметь одинаковый смысл во всех странах.
При добавлении арабского или иврита необходимо тестировать:
Настройка:
fallbackLng: "en"
позволяет избежать отсутствующих переводов и обеспечивает корректную работу интерфейса даже при неполной локализации.