Skip to content
fluenti

Framework API Comparison

Fluenti provides a consistent API across Vue, React, and SolidJS. This page highlights what is identical and what differs due to framework-specific patterns.

VueReactSolid
Init functioncreateFluenti(options)
Providerapp.use(i18n) plugin<I18nProvider> component<I18nProvider> component
Access hookuseI18n() composableuseI18n() hookuseI18n() hook

Vue uses a plugin-based approach (app.use()), while React and Solid use a context provider component wrapping the tree.

All three frameworks return the same core translation functions with identical signatures:

PropertyVueReactSolidIdentical?
t(id, values?)LocalizedStringLocalizedStringLocalizedString
t`Hello ${name}`
d(value, style?)LocalizedStringLocalizedStringLocalizedString
n(value, style?)LocalizedStringLocalizedStringLocalizedString
format(message, values?)LocalizedStringLocalizedStringLocalizedString
setLocale(locale)Promise<void>Promise<void>Promise<void>
loadMessages(locale, msgs)
getLocales()string[]string[]string[]
preloadLocale(locale)Promise<void>Promise<void>Promise<void>
te(key, locale?)booleanbooleanboolean
tm(key, locale?)CompiledMessage?CompiledMessage?CompiledMessage?

These properties expose the same data but use framework-native reactivity types:

PropertyVueReactSolid
localeRef<string>stringAccessor<string>
isLoadingRef<boolean>booleanAccessor<boolean>
loadedLocalesRef<ReadonlySet<string>>ReadonlySet<string>Accessor<Set<string>>
  • Vue: Use .value to read (e.g., locale.value)
  • React: Plain values that trigger re-renders via useState
  • Solid: Call as functions (e.g., locale())

<Trans>, <Plural>, and <Select> share the same props across all frameworks:

PropTypeRequiredNotes
idstringNoOverride auto-generated hash ID
contextstringNoMessage context for disambiguation
commentstringNoTranslator-facing note
tagstringNoWrapper element. Default: no wrapper (Fragment)
childrenYesContent to translate
render(node) => nodeNoReact only — custom render wrapper
PropTypeRequiredNotes
valuenumberYesNumeric value for plural selection
otherstringYesRequired fallback form
zero / one / two / few / manystringNoCLDR plural category forms
offsetnumberNoOffset before selecting form
tagstringNoWrapper element. Default: Fragment
PropTypeRequiredNotes
valuestringYesValue to match against cases
otherstringYesRequired fallback case
optionsRecord<string, string>NoNamed case options
tagstringNoWrapper element. Default: Fragment

Each framework uses its native reactivity system internally:

AspectVueReactSolid
Stateref(), shallowReactive()useState(), useRef()createSignal()
TrackingAutomatic dependency tracking via ProxyRe-render on state changeFine-grained signal tracking
MemoizationAutomaticuseMemo(), useCallback()Not needed (fine-grained)
Race protectionNot needed (synchronous reactive graph)localeRequestRef counterNot needed (synchronous signals)
VueReactSolid
Loader propchunkLoaderloadMessageschunkLoader
Enable flaglazyLocaleLoading: trueAutomatic (when loadMessages provided)lazyLocaleLoading: true
Loader signature(locale) => Promise<Messages>(locale) => Promise<Messages>(locale) => Promise<Messages>

Vue and Solid use chunkLoader + explicit lazyLocaleLoading flag. React infers lazy loading automatically when loadMessages is provided.

Each framework has its own Vite plugin that wraps @fluenti/vite-plugin:

// Vue
import fluentiVue from '@fluenti/vue/vite-plugin'
// React
import fluentiReact from '@fluenti/react/vite-plugin'
// Solid
import fluentiSolid from '@fluenti/solid/vite-plugin'

All three accept the same FluentiPluginOptions (optional config field). The framework plugin handles scope transforms, virtual module generation, and component compilation automatically.

FeatureFluentivue-i18nreact-i18nextnext-intlLinguiJS
Compile-time transformsYesNoNoNoYes
Runtime parser neededNoYesYesYesNo
ICU MessageFormatFullPartialVia pluginFullFull
Plural/Select components<Plural>, <Select>$tc()<Trans>useTranslations<Plural>
SSR supportBuilt-inBuilt-inVia next-i18nextBuilt-inManual
Code splittingBuilt-in (static/dynamic)ManualManual namespace loadingPer-locale JSONManual
TypeScriptFull (branded types, message ID narrowing)PartialPartialFullPartial
PO catalog formatNativeNoNoNoNative
JSON catalog formatYesYesYesYesYes
Message extraction CLIBuilt-inNoi18next-parserNoBuilt-in
Multi-frameworkVue, React, Solid, Next.js, Nuxt, SolidStartVue onlyReact onlyNext.js onlyReact, Vue (experimental)

Because Fluenti compiles messages at build time, the runtime does not include a parser or compiler. This reduces the client-side footprint:

LibraryRuntime size (min+gzip)Includes parser?
@fluenti/core~3 kBNo
vue-i18n~14 kBYes
react-i18next + i18next~13 kBYes
next-intl~12 kBYes
@lingui/react + @lingui/core~5 kBNo

Sizes are approximate and vary by version. Fluenti and Lingui both use compile-time transforms to keep runtime size minimal.

Compile-time libraries (Fluenti, Lingui) perform message resolution via simple object lookups at runtime. Runtime libraries (vue-i18n, react-i18next, next-intl) parse ICU syntax on the fly or on first access, which adds CPU overhead on initial render and locale switches.

AspectCompile-time (Fluenti)Runtime (vue-i18n, react-i18next)
First renderHash lookupParse + interpolate
Locale switchSwap compiled catalogRe-parse all visible messages
MemoryPre-compiled functionsParser cache + AST cache
Cold start (SSR)MinimalParser initialization

Fluenti is a good fit when:

  • You need a single i18n solution across Vue, React, and Solid projects
  • Bundle size and runtime performance are priorities
  • You use PO-based translation workflows (gettext tooling, Weblate, Crowdin)
  • You want type-safe message IDs with compile-time checking
  • Your app uses SSR and needs built-in hydration support

Consider alternatives when:

  • You only use one framework and are already invested in its ecosystem library (e.g., vue-i18n for Vue-only projects)
  • You need runtime message loading from a CMS without a build step
  • Your team is already productive with react-i18next and migration cost outweighs the benefits

If you are migrating from an existing i18n library, see the dedicated migration guides:

  • From vue-i18n: Migration from vue-i18n covers the vue-i18n-compat bridge layer for incremental migration
  • From react-i18next: Replace useTranslation() with useI18n(), <Trans> with Fluenti’s <Trans>, and convert JSON namespaces to PO catalogs or flat JSON
  • From next-intl: Swap useTranslations() for useI18n() and adopt @fluenti/next with withFluenti() in next.config.ts
  • From LinguiJS: The APIs are similar — replace <Trans> and useLingui() with Fluenti equivalents; PO catalogs are compatible with minimal changes