Подключение через CDN используется в случаях, когда проект работает без системы сборки, без Node.js и без пакетных менеджеров. Такой способ подходит для статических сайтов, небольших веб-приложений, учебных проектов и быстрого прототипирования интерфейсов с поддержкой нескольких языков.
Библиотека загружается напрямую в браузер через тег
<script>, после чего становится доступной глобально
через объект i18next.
CDN (Content Delivery Network) — сеть серверов для распространения статических файлов. Вместо локальной установки библиотека загружается из внешнего источника.
Подключение через CDN позволяет:
Наиболее популярные CDN:
Минимальный пример подключения I18next:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>I18next CDN</title>
</head>
<body>
<h1 id="title"></h1>
<script src="https://unpkg.com/i18next@23.11.5/dist/umd/i18next.min.js"></script>
<script>
i18next.init({
lng: 'ru',
resources: {
ru: {
translation: {
title: 'Главная страница'
}
}
}
}, function(err, t) {
document.getElementById('title').textContent = t('title');
});
</script>
</body>
</html>
После загрузки файла:
<script src="https://unpkg.com/i18next/dist/umd/i18next.min.js"></script>
в глобальной области появляется объект:
i18next
Через него выполняются:
Главный метод настройки библиотеки:
i18next.init(options, callback)
| Параметр | Назначение |
|---|---|
lng |
текущий язык |
resources |
словари переводов |
fallbackLng |
резервный язык |
debug |
режим отладки |
ns |
namespaces |
defaultNS |
namespace по умолчанию |
Все переводы обычно описываются внутри объекта
resources.
Пример:
resources: {
en: {
translation: {
welcome: 'Welcome',
button: 'Save'
}
},
ru: {
translation: {
welcome: 'Добро пожаловать',
button: 'Сохранить'
}
}
}
Структура имеет несколько уровней:
resources
└── язык
└── namespace
└── ключи перевода
По умолчанию используется namespace:
translation
Поэтому запись:
t('welcome')
эквивалентна:
t('translation:welcome')
Для получения текста используется функция:
i18next.t()
Пример:
const text = i18next.t('welcome');
console.log(text);
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Languages</title>
</head>
<body>
<h1 id="title"></h1>
<script src="https://unpkg.com/i18next@23.11.5/dist/umd/i18next.min.js"></script>
<script>
i18next.init({
lng: 'en',
fallbackLng: 'en',
resources: {
en: {
translation: {
title: 'Home page'
}
},
ru: {
translation: {
title: 'Главная страница'
}
}
}
}, function () {
document.getElementById('title').textContent =
i18next.t('title');
});
</script>
</body>
</html>
Язык можно изменить динамически.
i18next.changeLanguage('ru');
Полный пример:
<button oncl ick="setRu()">RU</button>
<button oncl ick="setEn()">EN</button>
<h1 id="title"></h1>
<script>
function render() {
document.getElementById('title').textContent =
i18next.t('title');
}
i18next.init({
lng: 'en',
resources: {
en: {
translation: {
title: 'Settings'
}
},
ru: {
translation: {
title: 'Настройки'
}
}
}
}, render);
function setRu() {
i18next.changeLanguage('ru', render);
}
function setEn() {
i18next.changeLanguage('en', render);
}
</script>
Метод init() работает асинхронно.
Неправильно:
i18next.init({...});
console.log(i18next.t('title'));
Возможна ситуация, когда инициализация ещё не завершилась.
Правильно:
i18next.init({...}, function () {
console.log(i18next.t('title'));
});
Либо через Promise:
i18next.init({...}).then(() => {
console.log(i18next.t('title'));
});
Для корректного порядка загрузки рекомендуется использовать:
<script
defer
src="https://unpkg.com/i18next/dist/umd/i18next.min.js">
</script>
Преимущества:
Режим отладки помогает видеть работу библиотеки.
i18next.init({
debug: true
});
В консоли браузера будут отображаться:
Резервный язык используется при отсутствии перевода.
i18next.init({
lng: 'de',
fallbackLng: 'en',
resources: {
en: {
translation: {
hello: 'Hello'
}
}
}
});
Если немецкий перевод отсутствует:
i18next.t('hello')
вернёт:
Hello
Если перевод не найден:
i18next.t('unknown')
по умолчанию возвращается сам ключ:
unknown
Это удобно при разработке, поскольку сразу видно отсутствующие переводы.
I18next поддерживает вставку переменных в строки.
resources: {
ru: {
translation: {
welcome: 'Привет, {{name}}'
}
}
}
i18next.t('welcome', {
name: 'Алексей'
});
Результат:
Привет, Алексей
По умолчанию I18next экранирует HTML.
interpolation: {
escapeValue: true
}
Это защищает от XSS-атак.
Для браузерных приложений иногда используется:
interpolation: {
escapeValue: false
}
особенно при работе с React, где экранирование уже выполняется самим фреймворком.
Переводы можно группировать.
translation: {
menu: {
home: 'Главная',
profile: 'Профиль'
}
}
Получение значения:
i18next.t('menu.home');
translation: {
errors: [
'Ошибка сети',
'Ошибка сервера'
]
}
Получение:
i18next.t('errors.0');
Обычно переводы выносятся в отдельные файлы.
{
"title": "Главная",
"button": "Сохранить"
}
{
"title": "Home",
"button": "Save"
}
Для загрузки переводов из файлов используется дополнительный плагин:
<script src="https://unpkg.com/i18next-http-backend@2.5.2/i18nextHttpBackend.min.js"></script>
После этого можно загружать JSON автоматически.
<script src="https://unpkg.com/i18next@23.11.5/dist/umd/i18next.min.js"></script>
<script src="https://unpkg.com/i18next-http-backend@2.5.2/i18nextHttpBackend.min.js"></script>
<script>
i18next
.use(i18nextHttpBackend)
.init({
lng: 'ru',
backend: {
loadPath: '/locales/{{lng}}.json'
}
}, function () {
console.log(i18next.t('title'));
});
</script>
Пример организации проекта:
project/
│
├── index.html
│
├── locales/
│ ├── ru.json
│ └── en.json
│
└── js/
└── app.js
{
"title": "Главная страница",
"login": "Войти",
"logout": "Выйти"
}
{
"title": "Home page",
"login": "Login",
"logout": "Logout"
}
Для определения языка браузера существует плагин:
<script src="https://unpkg.com/i18next-browser-languagedetector@7.2.0/i18nextBrowserLanguageDetector.min.js"></script>
Использование:
i18next
.use(i18nextBrowserLanguageDetector)
.init({
fallbackLng: 'en'
});
Библиотека может определять язык:
Настраивается параметром:
detection: {
order: [
'querystring',
'cookie',
'localStorage',
'navigator'
]
}
detection: {
caches: ['localStorage']
}
После выбора языка значение сохраняется в браузере.
i18next
.use(i18nextHttpBackend)
.use(i18nextBrowserLanguageDetector)
.init({
fallbackLng: 'en'
});
Альтернативное подключение:
<script src="https://cdnjs.cloudflare.com/ajax/libs/i18next/23.11.5/i18next.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/i18next@23.11.5/dist/umd/i18next.min.js"></script>
После подключения можно проверить:
console.log(i18next);
Если библиотека загружена успешно, в консоли появится объект API.
Ошибка:
<script>
i18next.init();
</script>
<script src="i18next.min.js"></script>
Правильно:
<script src="i18next.min.js"></script>
<script>
i18next.init();
</script>
При загрузке JSON-файлов через file:// браузер может
блокировать запросы.
Неправильно:
file:///project/index.html
Правильно запускать через локальный сервер:
http://localhost:3000
Если сервер неправильно отдаёт JSON:
application/json
могут возникать ошибки загрузки переводов.
Если namespace не найден:
i18next.t('common:title')
но namespace common не подключён, перевод не будет
найден.
i18next.init({
ns: ['common', 'auth'],
defaultNS: 'common'
});
resources: {
ru: {
common: {
save: 'Сохранить'
},
auth: {
login: 'Вход'
}
}
}
Использование:
i18next.t('auth:login');
Обычно после смены языка требуется повторный рендер интерфейса.
Пример:
function updateContent() {
document.querySelector('#title').innerHTML =
i18next.t('title');
document.querySelector('#login').innerHTML =
i18next.t('login');
}
Удобный способ локализации HTML.
<h1 data-i18n="title"></h1>
<button data-i18n="save"></button>
function translatePage() {
document.querySelectorAll('[data-i18n]')
.forEach(element => {
const key = element.dataset.i18n;
element.textContent = i18next.t(key);
});
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>I18next App</title>
<script
src="https://unpkg.com/i18next@23.11.5/dist/umd/i18next.min.js">
</script>
<script
src="https://unpkg.com/i18next-http-backend@2.5.2/i18nextHttpBackend.min.js">
</script>
<script
src="https://unpkg.com/i18next-browser-languagedetector@7.2.0/i18nextBrowserLanguageDetector.min.js">
</script>
</head>
<body>
<button id="ru">RU</button>
<button id="en">EN</button>
<h1 data-i18n="title"></h1>
<p data-i18n="description"></p>
<script>
i18next
.use(i18nextHttpBackend)
.use(i18nextBrowserLanguageDetector)
.init({
fallbackLng: 'en',
debug: true,
backend: {
loadPath: '/locales/{{lng}}.json'
}
}, updateContent);
function updateContent() {
document.querySelectorAll('[data-i18n]')
.forEach(element => {
element.textContent =
i18next.t(element.dataset.i18n);
});
}
document
.getElementById('ru')
.addEventListener('click', () => {
i18next.changeLanguage('ru', updateContent);
});
document
.getElementById('en')
.addEventListener('click', () => {
i18next.changeLanguage('en', updateContent);
});
</script>
</body>
</html>