Контекстные переводы

Фреймворк Fresh предоставляет мощные возможности для создания высокопроизводительных веб-приложений на базе Deno. Одной из ключевых задач при разработке многоязычных интерфейсов является корректная организация контекстных переводов. Контекстные переводы позволяют различать одинаковые строки в зависимости от ситуации, что предотвращает неоднозначности в отображении текста на разных языках.


Основы контекстных переводов

Контекстный перевод отличается от стандартного тем, что каждая строка сопровождается контекстной меткой, которая помогает интернационализационной системе выбирать правильный вариант перевода. Например, слово file в английском языке может означать как «файл», так и «пилочка для ногтей». Контекст решает, какой вариант использовать.

Пример структуры переводов в формате JSON:

{
  "file": {
    "noun": "Файл",
    "tool": "Пилка"
  },
  "save": {
    "button": "Сохранить",
    "command": "Сохранить изменения"
  }
}

Ключ noun или tool определяет контекст, в котором используется конкретный перевод.


Организация переводов во Fresh

В 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

Компоненты во 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), что упрощает поддержку.
  • Единообразие ключей: Контекстные ключи должны быть согласованы по всей системе, чтобы избежать конфликтов.
  • Fallback: Если перевод для текущей локали отсутствует, следует использовать fallback-значение на языке по умолчанию.

Преимущества контекстных переводов

  1. Уменьшение неоднозначностей в интерфейсе.
  2. Упрощение поддержки многоязычных приложений.
  3. Централизованное управление переводами.
  4. Гибкость при добавлении новых языков и контекстов.

Контекстные переводы во Fresh обеспечивают точное соответствие текста ситуации и позволяют создавать действительно профессиональные мультиязычные интерфейсы.