Localization
The library brings no i18n stack of its own: the locale, the dictionaries and where the choice is stored stay with the application. Three languages ship.
The package neither imposes a separate i18n stack on the application nor creates an instance of its own. The locale, the fallback locale, where the chosen language is stored and how the dictionaries are merged are the application’s job; the library only asks it for a translation by key.
How it works
- The component asks for a string by a key such as
gr.pagination.prev. - If a translation exists, it is used.
- If the layer is not wired up or returned the key itself, the component falls back to its built-in text.
The third step matters more than it looks: a missing translation does not break the interface. The package can be adopted gradually and some service strings moved into dictionaries later — the components keep working in English.
What ships
The library carries dictionaries for three languages: English, Spanish and Russian. All three are complete — the key sets are compared by one of the package’s gates rather than by eye.
The portal you are reading speaks two languages while the library speaks three. That is not an error: the Spanish dictionary of the core is complete and working, there is simply no Spanish documentation yet.
Wiring it up
The recommended layer is @feugene/fint-i18n: it is declared as an optional peer
dependency and sits well with an approach where the application owns everything.
If the project already has a mature i18n, the package fits into that one too.
import { createFintI18n } from '@feugene/fint-i18n/core'
import { installI18n } from '@feugene/fint-i18n/vue'
import { GRANULARITY_I18N_BLOCK, en, ru } from '@feugene/granularity/i18n'
const i18n = createFintI18n({
locale: 'ru',
fallbackLocale: 'en',
loaders: [en, ru],
})
i18n.registerBlocks([GRANULARITY_I18N_BLOCK])
await i18n.loadUsedBlocks('ru')
// Without this the package cannot find the instance through provide/inject
// and stays on its built-in texts.
installI18n(app, i18n)The subpath @feugene/granularity/i18n hands out the gr block, the lazy en,
es and ru loaders and the adapter key with its types. Per-locale loaders are
exactly what you want in production: the bundler shakes out the unused languages.
The aggregate of every locale at once lives separately, in
@feugene/granularity/i18n/all, and is meant for demos, e2e and tooling.
Companion packages
Every companion has a string block of its own — GR_CHRONO_I18N_BLOCK
(grChrono), GR_MEDIA_I18N_BLOCK (grMedia) and so on — and they are wired
into the same instance, next to the main one:
import { GRANULARITY_I18N_BLOCK, en as coreEn, ru as coreRu } from '@feugene/granularity/i18n'
import { GR_CHRONO_I18N_BLOCK, en, ru } from '@feugene/granularity-chrono/i18n'
const i18n = createFintI18n({ locale: 'ru', fallbackLocale: 'en', loaders: [coreEn, coreRu, en, ru] })
i18n.registerBlocks([GRANULARITY_I18N_BLOCK, GR_CHRONO_I18N_BLOCK])One i18n layer for the whole application — the product screens and the design system alike.
What does not come from dictionaries
The calendar, the time and relative dates take everything locale-dependent from
Intl: month and weekday names, the first day of the week, the parsing order of
a date, the 12- or 24-hour default. The dictionary carries interface strings
only — labels, aria-labels, panel titles.
The practical consequence: the date components speak every language the engine knows, not the three listed above.
Overriding strings
Labels, buttons, aria-labels and service messages are changed in the
application’s dictionary, not by forking the package. That keeps the
terminology under a single control and stops upgrades from turning into conflict
resolution.
Changing the language, and the provider
GrConfigProvider takes a locale prop, but that is a request for the adapter
to switch, not the source of truth: the provider neither stores the locale nor
substitutes it. An adapter of its own contract is asked through syncLocale; on a
fint-i18n instance, which has no such method, the provider calls setLocale() —
the same call that switches the language directly: i18n.setLocale('en'). An adapter passed in the i18n prop is handed down through a
facade rather than by value — so an adapter created asynchronously reaches the
components once it appears, and swapping the adapter re-renders the strings.
Without the prop the facade delegates to the adapter found higher up the tree,
including one installed through installI18n. See
configuration.