Одна из главных проблем i18n в приложениях заключается в том, что о ней вспоминают в последнюю очередь.
Обычно мы разрабатываем продукт, проверяем соответствие рынку (Product-Market Fit) и только спустя месяцы или годы решаем: «Пора выходить на глобальный уровень».
Сложность в том, что решения для i18n носят структурный характер и сильно влияют на работу команды. Куда эффективнее закладывать это в техническое задание с первого дня.
Как же с этим справиться? Заморозить разработку на неделю и рефакторить каждый компонент?
В последнее время я вижу много решений, основанных на compiler-driven подходе. Обещание заманчивое: добавьте пару строк кода, и приложение «само» станет мультиязычным.
Однако есть существенные недостатки:
Замедление разработки: Компиляторы добавляют этапы обработки, что особенно заметно в режиме разработки (hot reload).
Отсутствие 100% покрытия: В 98% случаев i18n работает корректно, но оставшиеся 2% становятся головной болью. Как перевести функцию
getDescription, которая находится вне компонента? Как обрабатывать плюрализацию, вставку переменных, даты и т.д.?Размер бандла: Оптимизация контента часто уходит на второй план. В итоге пользователи могут загружать данные для всех страниц на всех языках ради просмотра одной вкладки.
Vendor lock-in: Некоторые решения делают вас зависимыми от платформы, заставляя переплачивать за генерацию переводов.
Next.js Server Components: Как сделать серверный контент мультиязычным без лишних сложностей?
В Intlayer мы попытались решить это с помощью гибридного подхода.
Intlayer использует компилятор для обработки компонентов. По аналогии с тем, как React Compiler оборачивает код в useMemo / useCallback, Intlayer извлекает контент и автоматически внедряет функции getIntlayer / useIntlayer.
Вам не нужны блоки <T> или функции t — Intlayer трансформирует компоненты в их исходном виде.
При этом Intlayer — это прежде всего решение для декларативной интернационализации. Это значит, что его можно использовать для метаданных страниц или смешивать контент, управляемый вручную, с работой компилятора.
Основные преимущества:
100% Бесплатно: Нет платы за каждый ключ; перевод стоит ровно столько, сколько запрашивает ваш AI-провайдер.
Совместимость: Работает с Vite / Next.js (Webpack / Turbopack) / React / Svelte / Vue / Client и Server side.
Гибкость: Можно включать как для разработки, так и только для продакшн-сборок.
Оптимизация: Архитектура учитывает размер бандла.
Документация:
Next.js: https://intlayer.org/doc/environment/nextjs/compiler
Vite: https://intlayer.org/doc/environment/vite-and-react/compiler
Интересно узнать ваше мнение. Какой у вас опыт работы с i18n-компиляторами?
DmitryKazakov8
Довольно часто вижу в ленте статьи по Intlayer - вы стараетесь его популяризировать, но не понимаю практической применимости. Обычно переводы в проектах делаются проще и эффективнее.
Посмотрим в контексте "ретроспективного внедрения интернационализации" + React. На данный момент все тексты захардкожены в компонентах, бизнес ставит задачу - перевести на несколько языков.
1.Нужно вынести тексты в объекты, это прекрасно типизируется TS и есть немало инструментов, позволяющих идентифицировать "неиспользуемые ключи в объекте", то есть масштабируемость - хорошая.
2.Вынести объект messages в отдельные файлы для переиспользуемости и задать автогенерацию уникальных ключей
__dirname здесь - простейший уникальный для файла идентификатор, многие бандлеры умеют с ним работать "из коробки". Но можно использовать любой, прокидывая бандлером.
3.Добавить возможность подключить шаблонизатор для плюрализации, работы с датами, падежами и т.п., готовых в js-экосистеме масса. Достаточно сделать функцию ln, а движок подбирать по нуждам проекта либо делегировать это сторонней системе вроде Localise.
Функция ln может под капотом иметь разную реализацию (например, возвращать реакт-компонент) или быть реактивной на сигналах (сменилась локализация - все функции перевызвались, обновив тексты в приложении), это все делается парой строк.
4.Собрать все тексты в json-файлы и встроить генерацию в бандлер перед сборкой и в watch-режиме
Для многих проектов подойдет автопереводчик с ручной правкой, для более сложных - этот json можно автоматизированно выгружать в облачную систему для переводчиков, которые 1 кнопкой пушат его с переводами обратно в репозиторий.
Собственно, все. Это база, которая и так есть в большинстве проектов, и может очень гибко настраиваться под стек, в том числе делая отдельные json-чанки под компонент (чтобы не все локализации грузились сразу). С ИИ этапы 1 и 2 делаются за полчаса, 3 и 4 пишутся за день под конкретные технологии и требования в проекте.
Итог - задача выполнена, при добавлении/удалении ключей в любом модульном messages.ts обновляется JSON, выгружается в систему переводов, и для изменения переводов не нужны разработчики - переводчики могут менять тексты сами, не влияя на код проекта.
А каждый раз, когда захожу на документацию Intlayer, не понимаю зачем столько бойлерплейта и сложностей, зачем вручную задавать ключи с дубляжом для каждого языка; писать переводы прямо в messages вместо того, чтобы отдавать json переводчикам или в автоперевод (поэкономьте время разработчиков); привязываться к встроенным механизмам шаблонизации (когда часто это должно быть частью локализационной системы типа облачного Localise). И много еще другого, что мне кажется крайне неэффективным, и видя это закрываю вкладку с документацией.
Скорее всего, пишу это "в пустоту" - половина ваших комментариев на Хабре ИИ-нейрослоп, и все для рекламы, но слишком уж часто эта поделка попадает в ленту.
aymericzip Автор
Скорее всего, ты прав, и я прошу прощения за навязчивость
Я действительно делюсь этим, чтобы напомнить о лучших практиках, которые часто игнорируют. Конечно, я также хочу рассказать о своем решении и получить обратную связь. Спасибо за твои замечания, они действительно помогают проекту расти. Я учел все важные моменты
Этот проект появился потому, что я был недоволен тем подходом, который ты описываешь. На мой взгляд, централизация контента является критической проблемой. Она раздувает бандл приложения и провоцирует конфликты при слиянии веток. Управление неймспейсами и поиск неиспользуемых строк в i18next, next-intl или vue-i18n часто превращаются в настоящий ад. Я хотел создать инструмент, который сам мечтал бы иметь под рукой
При этом я понимаю, что это решение подойдет не каждому. У меня нет цели переписывать i18next, ведь он и так отлично справляется со своими задачами.
Буду рад продолжить общение. Пиши мне в любое время, где тебе удобно
DmitryKazakov8
Вот как раз что я и ожидал - ответ от ИИ, полностью игнорирующий описанный мной концепт, и рекламирующий библиотеку)
i18next, next-intl или vue-i18n - неоптимизированные библиотеки с неэффективным использованием, тут соглашусь, но я же описал подход, никак с ними не связанный. Файлы message.ts - модульные, а общий json нужен только для переводчиков и удобной выгрузки в системы локализации. В коде его вполне можно разбивать на чанки хоть под каждый модуль, хоть под скоуп модулей (например для страницы src/pages/intro брать все тексты из json с этим префиксом). Это гибкость, универсальность и минимальный бойлерплейт.
Конфликты при слиянии веток здесь возможны только если параллельно работают над одним и тем же messages.ts - и точно такие же конфликты будут в Intlayer, так как он тоже использует модульные файлы с локализацией (но вроде без сборки их в большой json). Но это "слабые" конфликты, которые легко решаются автоматически, т.к. все ключи - уникальные.
ИИ захватывает Хабр(
aymericzip Автор
У тебя есть пример реализации, которым ты можешь поделиться? Мне любопытно