Локализация Vue-приложения — не просто перевод строк. На одном из проектов с 8 языками мы получили вспухший бандл на 2 мегабайта только из-за статической загрузки всех переводов. Клиент жаловался на медленный TTFB и низкий LCP. Пришлось переписывать на ленивую загрузку — бандл уменьшился в 5 раз, метрики Core Web Vitals пришли в норму. Такая история повторяется часто: разработчики недооценивают влияние переводов на производительность.
Правильная настройка vue-i18n решает не только проблемы с размером бандла, но и типичные ошибки: неправильная плюрализация для русского языка, конфликты с SSR при гидратации, отсутствие типизации ключей. Наш опыт — 5+ лет работы с Vue и более 20 проектов по локализации — гарантирует надёжное решение, которое работает с первого раза.
Официальная документация vue-i18n рекомендует использовать Composition API и ленивую загрузку для крупных проектов. Мы придерживаемся этого подхода и адаптируем его под конкретные задачи.
Почему стоит использовать vue-i18n?
Vue I18n — официальное расширение, полностью интегрированное с Vue 3. Оно поддерживает Composition API, ленивую загрузку, форматирование дат/чисел и SSR через Nuxt. По сравнению с самодельными решениями, vue-i18n даёт готовые механизмы плюрализации и интерполяции, что сокращает время разработки в 2 раза. Кроме того, это отраслевой стандарт для экосистемы Vue.
Как решить проблему гидратации с SSR?
При SSR Vue I18n может вызывать ошибки гидратации из-за несовпадения локалей на сервере и клиенте. Решение — синхронизировать локаль через cookie или заголовок запроса, а также использовать sync: false в конфигурации. В Nuxt модуль @nuxtjs/i18n делает это автоматически, считывая локаль из accept-language и сохраняя в cookie.
Пример конфигурации с cookie
// nuxt.config.ts
export default defineNuxtConfig({
i18n: {
detectBrowserLanguage: {
useCookie: true,
cookieKey: 'i18n_redirected',
alwaysRedirect: true
}
}
}) Когда нужна ленивая загрузка переводов?
Для приложений с десятками локалей загружать все переводы сразу на старте — непозволительная роскошь. Начальный бандл может вырасти на мегабайты, что критично для LCP и TTI. Ленивая загрузка загружает только актуальный язык, а остальные — по требованию. Это уменьшает размер бандла в 4–10 раз в зависимости от числа языков.
| Подход | Размер бандла (10 языков) | Время загрузки | UX |
|---|---|---|---|
| Статическая загрузка | ~1 MB | 2 секунды | - |
| Ленивая загрузка | ~100 KB | 0.3 секунды | + |
Как мы настраиваем vue-i18n?
Установка и базовая конфигурация
npm install vue-i18n@9 // src/i18n/index.ts
import { createI18n } from 'vue-i18n'
import ru from './locales/ru.json'
import en from './locales/en.json'
export type MessageSchema = typeof ru
const i18n = createI18n<[MessageSchema], 'ru' | 'en'>({
legacy: false,
locale: 'ru',
fallbackLocale: 'en',
messages: {
ru,
en
},
datetimeFormats: {
ru: {
short: {
day: 'numeric',
month: 'short',
year: 'numeric'
}
},
en: {
short: {
month: 'short',
day: 'numeric',
year: 'numeric'
}
}
},
numberFormats: {
ru: {
currency: {
style: 'currency',
currency: 'USD'
}
},
en: {
currency: {
style: 'currency',
currency: 'USD'
}
}
}
})
export default i18n
Основные возможности
- Плюрализация: поддерживает до 4 форм для русского языка.
- Форматирование дат и чисел: встроенные форматеры с привязкой к локали.
- TypeScript: строгая типизация ключей через MessageSchema.
- Ленивая загрузка: загружаем переводы только для текущего языка.
Как организовать ленивую загрузку переводов?
Для больших приложений критично не грузить все переводы сразу. Реализуем через динамический импорт:
// src/i18n/index.ts
const i18n = createI18n({
legacy: false,
locale: 'ru',
messages: { ru }
})
const loaded = new Set(['ru'])
export async function loadLocale(locale: string) {
if (loaded.has(locale)) return
const msgs = await import(`./locales/${locale}.json`)
i18n.global.setLocaleMessage(locale, msgs.default)
loaded.add(locale)
}Используем в роутере:
router.beforeEach(async (to) => {
const locale = to.params.locale || 'ru'
await loadLocale(locale)
i18n.global.locale.value = locale
}) Чем отличается настройка для Nuxt?
Для Nuxt используем официальный модуль, который автоматически интегрируется с vue-i18n, поддерживает SSR и SEO. Конфигурация минимальна:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
locales: [
{
code: 'ru',
language: 'ru-RU',
file: 'ru.json',
name: 'Русский'
},
{
code: 'en',
language: 'en-US',
file: 'en.json',
name: 'English'
}
],
defaultLocale: 'ru',
lazy: true,
langDir: 'locales/',
strategy: 'prefix_except_default'
}
}) Что входит в настройку i18n?
| Этап | Длительность | Результат |
|---|---|---|
| Анализ требований | 0.5 дня | Список языков, ключи, формат |
| Конфигурация плагина | 0.5 дня | Работающая базовая локализация |
| Интеграция с роутером | 1 день | Локализованные маршруты |
| Настройка ленивой загрузки | 1 день | Минимальный бандл при старте |
| Тестирование | 0.5 дня | Проверка всех языков и плюрализации |
Сроки и стоимость
Базовая настройка vue-i18n для 2 языков занимает 1 день. Полная интеграция с Nuxt, ленивой загрузкой и локализованными маршрутами — 2–3 дня. Стоимость настройки vue-i18n под ключ — от $72–100 для базового Vue-приложения, от $160–230 при интеграции с SSR и кастомными маршрутами.
Мы сопровождаем внедрение: помогаем разобраться с нюансами плюрализации в русском языке (четыре формы против двух в английском), настраиваем строгую типизацию ключей через TypeScript и документируем правила добавления переводов для всей команды. Это исключает дублирующие ключи и хардкод строк в компонентах. В итоге добавление нового языка занимает 2–4 часа вместо нескольких дней.
Получите консультацию — свяжитесь с нами, чтобы обсудить детали. Мы гарантируем, что после настройки ваше Vue-приложение корректно отображается на всех целевых языках и не теряет в производительности.







