Что такое i18n и почему каждый разработчик должен это знать

Что такое i18n и почему каждый разработчик должен это знать

Большинство разработчиков живут с одним любопытным парадоксом. Мы пишем API, настраиваем Docker, обсуждаем микросервисную архитектуру — но при этом напрямую вшиваем строки в UI:

h1.innerText = "Главная";

Потом клиент говорит: "Нам нужен английский язык."

И внезапно кодовая база трещит по швам.

Именно здесь на сцену выходит i18n.

Что означает i18n?

i18n — это сокращение слова "internationalization": между буквами "i" и "n" стоят 18 символов.

Но технически i18n — это не просто об этом.

i18n = Отделение текста от кода и управление языком на системном уровне.

Это не механизм перевода.

Это архитектурное решение.

Зачем нужен i18n?

Если вы хотите:

то i18n уже не является опцией.

Проблема захардкоженных строк

Писать такой код легко:

if (lang === "ru") {
    title.innerText = "Проекты";
} else {
    title.innerText = "Projects";
}

Работает. Но структурно слабо.

Цель i18n — освободить код от языковых изменений.

Основная логика i18n

Принцип очень прост:

  1. UI-строкам присваиваются ключи
  2. Для каждого языка создаётся отдельный файл
  3. Система подставляет нужный перевод по ключу

Простая i18n-система на JS

1. Языковые файлы

/lang/ru.json

{
  "nav.home": "Главная",
  "nav.projects": "Проекты",
  "hero.title": "Privacy & AI Solutions",
  "hero.subtitle": "Scalable digital infrastructure"
}

/lang/en.json

{
  "nav.home": "Home",
  "nav.projects": "Projects",
  "hero.title": "Privacy & AI Solutions",
  "hero.subtitle": "Scalable digital infrastructure"
}

2. HTML

data-i18n="hero.title">h1> 
data-i18n="hero.subtitle">p>

3. JS Loader

let currentLang = localStorage.getItem("lang") || "ru";
let translations = {};

async function loadLanguage(lang) {
    const response = await fetch(`/lang/${lang}.json`);
    translations = await response.json();
    applyTranslations();
}

function applyTranslations() {
    document.querySelectorAll("[data-i18n]").forEach(el => {
        const key = el.getAttribute("data-i18n");
        el.innerText = translations[key] || key;
    });
}

function changeLanguage(lang) {
    localStorage.setItem("lang", lang);
    loadLanguage(lang);
}

loadLanguage(currentLang);

Вот и всё. Никакого фреймворка. Никаких платных плагинов.

Server-Side i18n на PHP

Если бэкенд на PHP, можно реализовать это на стороне сервера.

/lang/ru.php

 "Главная",
    "nav.projects" => "Проекты",
    "hero.title" => "Privacy & AI Solutions"
];

index.php

$lang = $_GET['lang'] ?? 'az';
$translations = require "lang/$lang.php";

function t($key) {
global $translations;
return $translations[$key] ?? $key;
}
?>

Рендеринг на сервере. Лучше для SEO.

SEO и Multi-language Routing

Правильный подход:

site.com/az
site.com/en
site.com/ru

Почему? Потому что:

Это уже не просто перевод. Это SEO-архитектура.

Сложная часть: Динамические строки

Простые строки — не проблема. Сложность — в интерполяции и множественных числах.

{"cart.items": "В корзине {count} товаров"
}

JS-интерполяция:

function translate(key, vars = {}) {
    let text = translations[key] || key;
    Object.keys(vars).forEach(v => {
        text = text.replace(`{${v}}`, vars[v]);
    });
    return text;
}

translate("cart.items", { count: 3 });

Более глубокие проблемы

i18n — это не только текст. Сюда входят:

Форматирование валюты:

new Intl.NumberFormat('ru-RU', {
    style: 'currency',
    currency: 'RUB'
}).format(1200);

Вот здесь и начинается настоящая интернационализация.

Самая большая ошибка

Добавлять i18n постфактум.

Если вы разрабатываете проект для одного языка и добавляете i18n позже, вам придётся рефакторить весь код.

Правильный подход: Разделяйте строки с самого начала.

Почему за это платят?

Потому что люди воспринимают это как "перевод". Но i18n — это:

Это показатель качества кода.

i18n = Мышление на уровне продукта

Если продукт написан для одного языка — это локальный проект.

Если продукт написан с i18n:

Это уже не "замена строк". Это системный дизайн.

Заключение

i18n не сложен. Он просто требует системного мышления. Каждый разработчик с этим справится.

Ключевые моменты:

Всё остальное — реализация.

Программирование — это зачастую не про алгоритмы. Это про правильную структуру.

i18n — одна из таких структур.

Вернуться к блогам