Фреймворк Fresh предоставляет мощные возможности для создания высокопроизводительных веб-приложений на базе Deno. Одной из ключевых задач при разработке многоязычных интерфейсов является корректная организация контекстных переводов. Контекстные переводы позволяют различать одинаковые строки в зависимости от ситуации, что предотвращает неоднозначности в отображении текста на разных языках.
Контекстный перевод отличается от стандартного тем, что каждая строка
сопровождается контекстной меткой, которая помогает
интернационализационной системе выбирать правильный вариант перевода.
Например, слово file в английском языке может означать как
«файл», так и «пилочка для ногтей». Контекст решает, какой вариант
использовать.
Пример структуры переводов в формате JSON:
{
"file": {
"noun": "Файл",
"tool": "Пилка"
},
"save": {
"button": "Сохранить",
"command": "Сохранить изменения"
}
}
Ключ noun или tool определяет контекст, в
котором используется конкретный перевод.
В Fresh для работы с локализацией рекомендуется использовать модули контекстных переводов и сервисные функции, которые динамически выбирают нужную строку на основе текущей локали и контекста.
Структура проекта может выглядеть следующим образом:
/locales
├─ en.json
├─ ru.json
└─ de.json
Каждый файл содержит переводы с контекстными ключами:
{
"greeting": {
"morning": "Доброе утро",
"evening": "Добрый вечер"
},
"file": {
"noun": "Файл",
"tool": "Пилка"
}
}
В Fresh перевод подключается через middleware, которое определяет текущую локаль пользователя:
import { MiddlewareHandlerContext } from "$fresh/server.ts";
import { getLocale } from "./i18n.ts";
export async function handler(req: Request, ctx: MiddlewareHandlerContext) {
const locale = getLocale(req);
ctx.state.locale = locale;
return ctx.next();
}
Для удобства работы с контекстными переводами создается функция
t (translate), которая принимает ключ
строки и контекст, возвращая корректный
вариант перевода:
import translations from "../locales/ru.json";
export function t(key: string, context?: string) {
const value = translations[key];
if (!value) return key;
if (context && value[context]) return value[context];
return typeof value === "string" ? value : Object.values(value)[0];
}
Использование:
const fileName = t("file", "noun"); // "Файл"
const nailTool = t("file", "tool"); // "Пилка"
const morningGreeting = t("greeting", "morning"); // "Доброе утро"
Такой подход позволяет централизованно управлять контекстными переводами, избегая дублирования и ошибок в интерфейсе.
Компоненты во Fresh используют JSX/TSX и получают локаль через пропсы
или глобальное состояние. Контекстные переводы удобно подключать с
помощью хелпера t:
import { t } from "../i18n.tsx";
export default function FileComponent() {
return (
<div>
<h1>{t("file", "noun")}</h1>
<button>{t("save", "button")}</button>
</div>
);
}
Такой подход обеспечивает чистоту кода и позволяет менять переводы без модификации логики компонентов.
Для работы с несколькими языками создается объект с
локалями, а функция t расширяется для
динамического выбора нужной локали:
import en from "../locales/en.json";
import ru from "../locales/ru.json";
const locales = { en, ru };
export function t(key: string, context?: string, locale: string = "ru") {
const translations = locales[locale];
const value = translations[key];
if (!value) return key;
if (context && value[context]) return value[context];
return typeof value === "string" ? value : Object.values(value)[0];
}
Выбор локали может выполняться через cookie, заголовок
Accept-Language или настройку пользователя. Такой механизм
позволяет масштабировать приложение и поддерживать любой набор
языков.
auth.json,
dashboard.json), что упрощает поддержку.Контекстные переводы во Fresh обеспечивают точное соответствие текста ситуации и позволяют создавать действительно профессиональные мультиязычные интерфейсы.