Локализация 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: 'RUB' } }, 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 под ключ — от 8 000 ₽ для базового Vue-приложения, от 18 000 ₽ при интеграции с SSR и кастомными маршрутами.
Мы сопровождаем внедрение: помогаем разобраться с нюансами плюрализации в русском языке (четыре формы против двух в английском), настраиваем строгую типизацию ключей через TypeScript и документируем правила добавления переводов для всей команды. Это исключает дублирующие ключи и хардкод строк в компонентах. В итоге добавление нового языка занимает 2–4 часа вместо нескольких дней.
Получите консультацию — свяжитесь с нами, чтобы обсудить детали. Мы гарантируем, что после настройки ваше Vue-приложение корректно отображается на всех целевых языках и не теряет в производительности.







