В системах интернационализации на базе JavaScript поддержка грамматического рода становится критически важной при работе с языками, где формы слов зависят от пола субъекта. В i18next этот механизм реализуется через контекст (context) и расширенные правила выбора ключей перевода, позволяющие разделять строки по признаку мужского и женского рода без дублирования логики в коде приложения.
Грамматический род в переводах затрагивает не только местоимения, но и глагольные формы, существительные и прилагательные. В русском языке различие особенно выражено, поэтому система перевода должна уметь адаптировать сообщения динамически, исходя из переданных параметров.
В i18next механизм контекста реализуется через добавление суффикса к
ключу перевода. По умолчанию используется разделитель _,
формируя составные ключи:
user_maleuser_femaleПри этом логический ключ остаётся единым — user, а
различие определяется параметром context.
{
"user_male": "Пользователь вошёл в систему",
"user_female": "Пользовательница вошла в систему"
}
i18next.t('user', { context: 'male' });
// "Пользователь вошёл в систему"
i18next.t('user', { context: 'female' });
// "Пользовательница вошла в систему"
Контекст работает как механизм подстановки варианта перевода без изменения базового ключа.
В реальных приложениях род часто определяется на основе данных
пользователя. Обычно в объект пользователя добавляется поле
gender, которое затем передаётся в функцию перевода.
const user = {
name: 'Анна',
gender: 'female'
};
i18next.t('welcome', { context: user.gender });
{
"welcome_male": "Добро пожаловать, пользователь",
"welcome_female": "Добро пожаловать, пользовательница"
}
Такой подход позволяет полностью отделить логику определения пола от текстовых шаблонов.
В сложных системах переводов часто требуется комбинировать несколько параметров: род, число, состояние объекта. i18next поддерживает многоуровневую структуру ключей.
{
"friend_male_singular": "Друг онлайн",
"friend_female_singular": "Подруга онлайн",
"friend_male_plural": "Друзья онлайн",
"friend_female_plural": "Подруги онлайн"
}
i18next.t('friend', {
context: user.gender,
count: 1
});
Однако базовый механизм i18next не автоматически объединяет
context и count в единый ключ без
дополнительной настройки. Поэтому часто используется ручное построение
ключа или middleware-логика.
В языках с развитой морфологией, таких как русский, необходимо учитывать одновременно два фактора:
{
"message_male_one": "1 новый друг",
"message_male_other": "{{count}} новых друзей",
"message_female_one": "1 новая подруга",
"message_female_other": "{{count}} новых подруг"
}
const key = `message_${user.gender}`;
i18next.t(key, { count: 5 });
Такой подход сохраняет прозрачность структуры и упрощает масштабирование переводов при росте проекта.
По умолчанию i18next использует _ как разделитель
контекста:
i18next.init({
contextSeparator: '_'
});
Это означает, что ключ profile_male интерпретируется
как:
profilemalei18next.init({
contextSeparator: '-'
});
В этом случае ресурсы должны быть переименованы:
{
"profile-male": "Профиль пользователя",
"profile-female": "Профиль пользовательницы"
}
Контекст в i18next передаётся через объект опций:
t('key', { context: 'male' });
Дополнительно можно комбинировать с интерполяцией:
t('greeting', {
context: user.gender,
name: user.name
});
{
"greeting_male": "Здравствуйте, {{name}}",
"greeting_female": "Здравствуйте, {{name}}"
}
Интерполяция остаётся общей, а различие создаётся только по контексту.
В реальных архитектурах значение gender часто
хранится:
async function loadUser() {
const response = await fetch('/api/user');
const user = await response.json();
i18next.changeLanguage(user.language);
return user;
}
Использование:
const user = await loadUser();
i18next.t('dashboard', {
context: user.gender
});
Если контекстный ключ отсутствует, i18next использует базовый ключ без суффикса:
{
"notification": "Уведомление",
"notification_male": "Уведомление для мужчины"
}
При отсутствии notification_female система вернёт:
notificationЭто поведение важно учитывать при проектировании структуры ресурсов, чтобы избежать неожиданного падения качества локализации.
Дублирование ключей быстро приводит к росту словаря переводов. Для уменьшения избыточности применяются стратегии:
{
"user_online": "Пользователь онлайн"
}
При этом род игнорируется, если текст нейтрален.
{
"user_online": "{{name}} онлайн"
}
В этом случае род влияет только на имя или отдельные слова.
function getGenderKey(base, gender) {
return `${base}_${gender}`;
}
i18next.t(getGenderKey('profile', user.gender));
В некоторых ситуациях род влияет не только на отдельное слово, но и на структуру предложения:
{
"invite_male": "{{name}} пригласил вас",
"invite_female": "{{name}} пригласила вас"
}
i18next.t('invite', {
context: user.gender,
name: user.name
});
Такие конструкции часто становятся необходимыми при высокой точности языковой локализации.
Контекстный механизм i18next не является полноценной грамматической системой. Он опирается на статическое сопоставление ключей, поэтому:
По этой причине в крупных системах часто комбинируются:
context i18nextПри использовании ICU-подхода род может выражаться через выбор:
{
"invite": "{gender, select, male {Он пригласил вас} female {Она пригласила вас} other {Пользователь пригласил вас}}"
}
Этот формат переносит логику выбора внутрь строки перевода, уменьшая количество ключей, но увеличивая сложность самих сообщений.
При проектировании структуры переводов с учётом рода часто используется следующая организация:
locales/
ru/
common.json
user.json
notifications.json
user.json{
"profile_male": "Профиль пользователя",
"profile_female": "Профиль пользовательницы",
"status_male": "Активен",
"status_female": "Активна"
}
Такое разделение уменьшает конфликт ключей и облегчает масштабирование.
В серверных и клиентских рендерах важно синхронизировать контекст:
i18next.init({
lng: user.language,
resources
});
Контекст передаётся в момент рендеринга:
t('welcome', { context: user.gender });
Несогласованность между сервером и клиентом может приводить к различиям в отображении текста.
Такие ошибки приводят к росту сложности словаря и ухудшению поддерживаемости локализации.