Работа с пространствами имён (namespaces) в i18next является ключевым
механизмом организации переводов в крупных приложениях. Хук
useTranslation в связке с namespaces позволяет
структурировать словарь, изолировать доменные области интерфейса и
минимизировать избыточную загрузку переводов.
Namespaces в i18next представляют собой логические контейнеры для ключей локализации. Вместо единого плоского JSON-файла используется набор файлов или объектов, разделённых по функциональным областям:
Такой подход снижает связность и упрощает поддержку больших приложений.
Пример структуры:
locales/
en/
common.json
auth.json
dashboard.json
ru/
common.json
auth.json
dashboard.json
В экосистеме react-i18next хук useTranslation является
основным инструментом доступа к переводам внутри компонентов.
Базовый вариант без указания namespace:
import { useTranslation } from "react-i18next";
function Header() {
const { t } = useTranslation();
return <h1>{t("title")}</h1>;
}
В этом случае используется namespace по умолчанию
(defaultNS, чаще всего translation).
Передача namespace в useTranslation позволяет ограничить
область поиска ключей:
const { t } = useTranslation("auth");
Теперь все вызовы t будут искать ключи только в
auth.json.
Пример использования:
function LoginForm() {
const { t } = useTranslation("auth");
return (
<form>
<h2>{t("login.title")}</h2>
<button>{t("login.submit")}</button>
</form>
);
}
Структура auth.json:
{
"login": {
"title": "Вход в систему",
"submit": "Войти"
}
}
useTranslation поддерживает массив namespaces. Это
позволяет обращаться к нескольким словарям без повторной инициализации
хука.
const { t } = useTranslation(["common", "auth"]);
При таком подходе поиск ключей происходит в порядке приоритета: сначала в первом namespace, затем в следующих.
Пример:
function Navbar() {
const { t } = useTranslation(["common", "auth"]);
return (
<nav>
<span>{t("common:home")}</span>
<button>{t("auth:logout")}</button>
</nav>
);
}
При работе с несколькими namespaces часто используется явное префиксирование:
namespace:key
Пример:
t("common:cancel");
t("dashboard:stats.title");
Такой подход устраняет неоднозначность при совпадении ключей в разных namespaces.
Одной из оптимизационных возможностей является lazy loading переводов. При использовании конфигурации загрузчика (например, HTTP backend) namespaces подгружаются по требованию.
const { t } = useTranslation("dashboard");
При первом вызове компонента происходит загрузка
dashboard.json, если он ещё не был загружен.
Это снижает начальный размер бандла и ускоряет первичную загрузку приложения.
В конфигурации i18next можно заранее определить namespaces, которые должны быть доступны сразу:
i18next.init({
ns: ["common", "auth"],
defaultNS: "common"
});
При использовании useTranslation("dashboard") загрузка
произойдёт асинхронно, если namespace не был предзагружен.
Хук принимает дополнительные настройки:
useTranslation(ns, options);
Пример с keyPrefix:
const { t } = useTranslation("auth", {
keyPrefix: "login"
});
t("title"); // фактически auth:login.title
keyPrefix позволяет упростить доступ к глубоко вложенным ключам:
{
"login": {
"form": {
"title": "Вход",
"submit": "Отправить"
}
}
}
Без keyPrefix:
t("login.form.title");
t("login.form.submit");
С keyPrefix:
const { t } = useTranslation("auth", {
keyPrefix: "login.form"
});
t("title");
t("submit");
Если namespace не загружен, поведение зависит от конфигурации:
Пример fallback:
i18next.init({
fallbackLng: "en",
fallbackNS: "common"
});
В TypeScript-проектах namespaces часто типизируются через декларации ресурсов.
declare module "i18next" {
interface CustomTypeOptions {
defaultNS: "common";
resources: {
common: typeof common;
auth: typeof auth;
};
}
}
Это позволяет получать автодополнение ключей внутри
t.
При включённом Suspense компонент может ожидать загрузки
namespace:
const { t } = useTranslation("dashboard", { useSuspense: true });
В этом режиме компонент не рендерится до завершения загрузки переводов.
Namespaces особенно важны в компонентной архитектуре: каждый модуль приложения может иметь собственный словарь.
Пример модульной структуры:
Такое разделение минимизирует пересечения и упрощает масштабирование локализации.
Иногда требуется доступ к нескольким контекстам одновременно:
function Footer() {
const { t: tCommon } = useTranslation("common");
const { t: tAuth } = useTranslation("auth");
return (
<footer>
<span>{tCommon("copyright")}</span>
<button>{tAuth("logout")}</button>
</footer>
);
}
Разделение вызовов улучшает читаемость при сложных интерфейсах.
При использовании массива namespaces порядок имеет значение:
useTranslation(["common", "auth"]);
Алгоритм поиска:
При совпадении ключей используется первое найденное значение.
Эффективная организация namespaces влияет на производительность:
Разделение должно соответствовать границам бизнес-доменов, а не UI-структуре.
При изменении языка происходит перезагрузка активных namespaces:
i18next.changeLanguage("ru");
Компоненты, использующие useTranslation, автоматически
обновляют значения t без ручного обновления состояния.