Блоки — это ключевая концепция архитектуры @feugene/fint-i18n. Они позволяют логически разделять переводы, изолировать модули приложения и оптимизировать производительность.
Блок — это именованный набор сообщений. Например, auth, admin, common, dashboard.
Преимущества использования блоков:
- Изоляция: Ключи в разных блоках не пересекаются.
- Ленивая загрузка: Вы можете подгружать переводы для конкретной страницы только тогда, когда пользователь на неё перешёл.
- Производительность: Движок ищет ключи сначала внутри целевого блока, что быстрее, чем поиск по гигантскому глобальному объекту.
Это самый удобный способ для Vue-компонентов. Он автоматически загружает указанные блоки и управляет их жизненным циклом (подсчёт ссылок).
<script setup>
import { useI18nScope } from '@feugene/fint-i18n/vue'
// Асинхронно загружаем блоки до рендера компонента
await useI18nScope(['auth', 'profile'])
</script>Tip
Используйте <Suspense> в корне вашего приложения для корректной работы асинхронных композаблов.
Метод loadBlock позволяет загрузить блок в любой момент.
const { loadBlock } = useFintI18n()
await loadBlock('admin')
console.log('Блок загружен!')Технически — да, но фактически вы всё равно используете хотя бы один блок.
Если вы хотите иметь плоскую структуру "как в классическом i18n", просто определите все ваши ключи в одном блоке, например, app.
// messages.ts
export const loaders = {
en: {
app: () => import('./locales/en.json')
}
}
// Использование
t('app.welcome')
t('app.buttons.save')Библиотека требует, чтобы первой частью ключа всегда было имя блока. Это залог высокой производительности при резолве (поиск по Flat Map кэшу O(1)).
Вы можете создавать вложенные блоки, используя точку в названии.
// В messages.ts
const loaders = {
en: {
'pages.articles': () => import('./articles.json'),
},
}
// В коде
await useI18nScope(['pages.articles'])
t('pages.articles.title')Если вы загружаете pages.articles, библиотека пометит этот путь как загруженный. При этом вы всё равно можете иметь отдельный лоадер для родительского блока pages.
При вызове loadBlock(blockName) библиотека использует следующие правила:
- Сначала ищет точное совпадение по
blockName. - Если точного совпадения нет и block вложенный, ищет ближайший parent block.
- Если для найденного блока зарегистрировано несколько loaders, они выполняются последовательно.
Пример:
const loaders = {
en: {
page: () => import('./page.json'),
},
}
await i18n.loadBlock('page.articles')В этом случае будет использован loader блока page.
createFintI18n() может принять несколько package collections:
const i18n = createFintI18n({
locale: 'en',
fallbackLocale: 'en',
loaders: [package1LocaleLoaders, package2LocaleLoaders],
})Правила merge:
- package collections мерджатся слева направо;
- одинаковые block keys не конфликтуют, а собираются в общий список loaders;
- если loader внутри package уже массив, он flatten-ится в этот общий список;
- при совпадении message keys побеждает последнее загруженное значение.
useI18nScope реализует механизм Reference Counting (подсчёт ссылок).
- Когда первый компонент запрашивает блок
auth, он загружается в память. - Когда другие компоненты запрашивают
auth, они используют уже загруженные данные. - (Опционально) Когда последний компонент, использующий
auth, размонтируется, данные могут быть очищены для экономии памяти (если настроено).