ESPN DeportesPachuca y Atlante femenil despiden a sus DTInquirerDefense, prosecution to present oral arguments on voting thresholdDaily MaverickGOING FOR A SONG OP-ED: AI and the future of creativity — can artists’ histories travel with their work?The Jerusalem PostErdogan calls Gaza suffering 'most embarrassing concentration camp' in UNGA speechPunchAnambra flood: Pupil missing as police rescue nine한겨레2연패 도전 여자 배드민턴, 안세영 승리에도 일본에 막혀 단체전 ‘동’SözcüTrafikte görünen H işaretli trafik levhası kafa karıştırıyor: Çoğu sürücü anlamını bilmiyorCNN TürkMenderes Belediyesi'ne ikinci dalga operasyon: 9 gözaltı경향신문용수 상수도 활용·전력망 지중화··· “호남 반도체 팹 2기 2028년 착공 목표”Het Laatste NieuwsDroomtransfer met een valse start: waarom de interlandbreak op het ideale moment komt voor Nathan De CatDaily MailAndy Burnham wobbles on Chagos as Trump hits out at 'terrible and ridiculous deal' during their first-ever meetingSportstarAsian Games 2026 Day 5, Live Updates: India wins bronze medals in skeet shooting; Mirabai Chanu confirms weightlifting medal; India takes on China in men's badminton
The Daily Newsstand · Free, Always
Wednesday, September 23, 2026

Проблема с vue-i18n и почему Intlayer ее решает

Translate

При разработке мультиязычных приложений на Vue 3 или Nuxt библиотека vue-i18n долгие годы оставалась безальтернативным стандартом. Кадзупон (Kazupon) и сообщество создали вокруг нее зрелую и богатую экосистему, на которой выросло не одно поколение Vue-проектов.

Однако чтобы понять, почему vue-i18n устроен именно так, стоит вспомнить контекст его создания: архитектура проектировалась в эпоху классических SPA (Single Page Applications), когда динамические импорты (import()) и разделение кода по маршрутам еще не были общепринятым стандартом. В той парадигме загрузить на старте приложения один монолитный объект со всеми переводами прямо в память было самым простым и разумным решением.

Но современный фронтенд живет жесткой оптимизацией размера бандлов, будь то Nuxt, статическая генерация (SSG) или динамическая загрузка страниц. В этих современных реалиях централизованная модель глобального провайдера превратилась в серьезное архитектурное бутылочное горлышко.

Почему сама библиотека vue-i18n так много весит в бандле? Пустой компонент, который просто импортирует vue-i18n, обходится в 24.3 КБ gzipped (83.2 КБ в минифицированном виде) еще до вывода первого слова. Причина в том, что библиотека тащит в браузер полноценный рантайм-движок для динамического парсинга форматирования: подстановку переменных вида {{number}} или {name}, вычисление правил плюрализации и списков. Кроме того, мультиязычный роутинг требует дополнительной клиентской логики: работы с cookie, автоматического определения языка и манипуляций с префиксами URL прямо на клиенте.

И всё это еще до того, как мы дойдем до главной архитектурной проблемы: масштабной утечки переводов между страницами (Copy Leakage).

В типичном проекте вызов createI18n({ messages }) инициализирует глобальное дерево сообщений, хранящее все ключи для всех языков сразу. Когда пользователь заходит на простую страницу контактов (/contact), браузер вынужден загружать тексты для панели управления (/dashboard), страницы цен (/pricing), настроек и всего остального приложения. В наших бенчмарках на стандартном приложении из 10 страниц и 10 языков на Vite + Vue 3 около 90% объема переводов, переданных на конкретную страницу, относились к совершенно другим маршрутам. А поскольку хук useI18n() жестко привязывает компоненты к этому глобальному экземпляру, один скомпилированный изолированный компонент в среднем весит 196 КБ JavaScript.

Кроме того, вызов вида t("key.path") опирается на динамическое вычисление строк во время выполнения. Сборщики (Vite, Rollup) не могут статически проанализировать, какие ключи действительно используются в коде. Неиспользуемые переводы невозможно вырезать через Tree-shaking, а опечатки в ключах тихо всплывают на проде в виде сломанных строк вместо того, чтобы завершаться ошибкой TypeScript на этапе сборки.

## Как эту проблему решает Intlayer?

Intlayer решает эту задачу, полностью устраняя лишнюю рантайм-логику на этапе сборки и связывая контент напрямую с компонентами через статические трансформации, а не через тяжелый рантайм-провайдер.

1. Предварительная компиляция на этапе сборки (ноль оверхеда на парсинг в рантайме)

Вместо того чтобы отправлять клиенту парсеры для вычисления вставок вроде {{number}} или заставлять браузер на лету разруливать префиксы URL и cookie, Intlayer оптимизирует и компилирует всю эту логику заранее при сборке проекта. Клиент получает предельно легкий код без лишних движков, а вес рантайма падает всего до 3.9 КБ (или 7.9 КБ при использовании слоя совместимости).

2. Прямая привязка контента к компонентам

Вместо того чтобы складывать тысячи строк в безразмерные файлы locales/en.json, Intlayer размещает словари рядом с компонентами, которые их используют (например, Footer.content.ts прямо рядом с Footer.vue). В результате неимпортированные компоненты никогда не подтягивают неиспользуемые переводы. Мертвый код больше не утяжеляет клиентский бандл чужими текстами.

3. Динамическая загрузка без сетевых «водопадов» через Vite

Помимо классического tree-shaking, Intlayer использует продвинутые трансформации модулей Vite. Даже при динамической загрузке страниц и code-splitting Intlayer вшивает нужный локализованный контент непосредственно в соответствующий чанк. Никаких дополнительных сетевых запросов и водопадов ожидания JSON-словарей перед рендерингом: компонент и его точные локализованные строки приходят вместе в одном файле.

4. Строгая типобезопасность на этапе компиляции

Intlayer генерирует строгие типы TypeScript непосредственно из ваших деклараций контента. Вы получаете автодополнение ключей в IDE и мгновенные ошибки сборки при пропущенных переводах или опечатках, что полностью исключает неприятные сюрпризы с фоллбэками на проде.

5. 0% утечек и бандлы в 3 раза меньше

Во время сборки компилятор Intlayer статически анализирует места вызовов и дробит словари так, чтобы каждый роут получал только те строки, которые он реально рендерит. В наших бенчмарках утечка текста между страницами упала с 90% до 0%, а средний вес JavaScript на страницу снизился со 134.9 КБ до 47.0 КБ gzipped (для сравнения, базовое приложение вообще без i18n весит 41.3 КБ).

6. Бесшовный переход через @intlayer/vue-i18n

Если у вас уже есть работающий проект на Vue, переписывать компоненты не придется. Адаптер совместимости @intlayer/vue-i18n предоставляет абсолютно тот же API vue-i18n (useI18n, t(), d(), n(), $t, v-t). Достаточно подключить Vite-плагин и убрать монолитный импорт messages, ваши существующие вызовы t("key") автоматически переключатся на скомпилированные и разделенные словари. Рантайм уменьшается в 3 раза, а вес компонентов снижается в 23 раза без изменения единой строчки в файлах .vue.

Если вы поддерживаете мультиязычный проект на Vue или Nuxt в проде, откройте вкладку Network в консоли браузера на любой второстепенной странице. Вы наверняка обнаружите, что солидную часть загруженного JavaScript составляют переводы, которые пользователь на этой странице никогда не увидит.

Полный разбор архитектуры, цифры бенчмарков и руководство по миграции читайте здесь:

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.