Большинство разработчиков живут с одним любопытным парадоксом. Мы пишем API, настраиваем Docker, обсуждаем микросервисную архитектуру — но при этом напрямую вшиваем строки в UI:
h1.innerText = "Главная";
Потом клиент говорит: "Нам нужен английский язык."
И внезапно кодовая база трещит по швам.
Именно здесь на сцену выходит i18n.
Что означает i18n?
i18n — это сокращение слова "internationalization": между буквами "i" и "n" стоят 18 символов.
Но технически i18n — это не просто об этом.
i18n = Отделение текста от кода и управление языком на системном уровне.
Это не механизм перевода.
Это архитектурное решение.
Зачем нужен i18n?
Если вы хотите:
- Масштабировать продукт
- Делать SEO правильно
- Охватывать глобальную аудиторию
- Добавлять языки в будущем
то i18n уже не является опцией.
Проблема захардкоженных строк
Писать такой код легко:
if (lang === "ru") {
title.innerText = "Проекты";
} else {
title.innerText = "Projects";
}
Работает. Но структурно слабо.
- 10 строк → управляемо
- 100 строк → беспорядок
- 1000 строк → кошмар
Цель i18n — освободить код от языковых изменений.
Основная логика i18n
Принцип очень прост:
- UI-строкам присваиваются ключи
- Для каждого языка создаётся отдельный файл
- Система подставляет нужный перевод по ключу
Простая 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
Почему? Потому что:
- Google индексирует каждый URL как отдельную страницу
- Можно использовать
hreflang - У каждого языка может быть свой meta title
Это уже не просто перевод. Это 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 — это не только текст. Сюда входят:
- Формат даты
- Формат валюты
- Формат времени
- RTL-языки (например, арабский)
- Правила множественного числа
Форматирование валюты:
new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB'
}).format(1200);
Вот здесь и начинается настоящая интернационализация.
Самая большая ошибка
Добавлять i18n постфактум.
Если вы разрабатываете проект для одного языка и добавляете i18n позже, вам придётся рефакторить весь код.
Правильный подход: Разделяйте строки с самого начала.
Почему за это платят?
Потому что люди воспринимают это как "перевод". Но i18n — это:
- Структурный дизайн
- Компонентная архитектура
- Масштабируемость
- Предотвращение технического долга
Это показатель качества кода.
i18n = Мышление на уровне продукта
Если продукт написан для одного языка — это локальный проект.
Если продукт написан с i18n:
- Он может масштабироваться
- Он готов к инвестициям
- Он готов к выходу на международный рынок
Это уже не "замена строк". Это системный дизайн.
Заключение
i18n не сложен. Он просто требует системного мышления. Каждый разработчик с этим справится.
Ключевые моменты:
- Выносите строки из кода
- Стройте правильную структуру
- Планируйте роутинг
- Учитывайте SEO
- Думайте о добавлении новых языков в будущем
Всё остальное — реализация.
Программирование — это зачастую не про алгоритмы. Это про правильную структуру.
i18n — одна из таких структур.