Components
Fluenti provides three components for complex translation patterns. All three are globally registered by the Fluenti plugin — no imports needed in Vue templates.
When translations contain HTML elements or framework components, use <Trans> with its default slot (Vue) or children (Solid). You write native HTML inside the component — no indexed placeholders.
Default Slot Pattern
Section titled “Default Slot Pattern”<template> <Trans>Read the <router-link to="/terms">terms</router-link> and <strong>conditions</strong></Trans></template>Trans, Plural, and Select are globally registered by the Fluenti plugin — no import needed.
<Trans> Read the <A href="/terms">terms</A> and <strong>conditions</strong></Trans>Nested Elements
Section titled “Nested Elements”You can nest elements naturally — no special syntax required:
<template> <Trans> Click <a href="/next">here</a> to <strong>sign up</strong> for the <em>beta program</em> </Trans></template><Trans> Click <a href="/next">here</a> to <strong>sign up</strong> for the <em>beta program</em></Trans>How it works
Section titled “How it works”The <Trans> component extracts the text content of its default slot (including HTML tags) as the source message. During compilation, translators see the tags as placeholders (e.g., <0>terms</0>), and at runtime the translated message is rendered with the original elements restored.
This is native HTML — unlike libraries that use indexed placeholders (e.g., {0} or <0>text</0> in source code), Fluenti lets you write real markup. The extraction step handles the mapping automatically.
Legacy API (deprecated)
The message prop pattern still works but is deprecated and will be removed in a future version.
Vue (legacy)
Section titled “Vue (legacy)”<Trans message="Read the <link>terms</link> and <bold>conditions</bold>"> <template #link="{ children }"> <router-link to="/terms">{{ children }}</router-link> </template> <template #bold="{ children }"> <strong>{{ children }}</strong> </template></Trans>Solid (legacy)
Section titled “Solid (legacy)”<Trans message="Read the <link>terms</link> and <bold>conditions</bold>" components={{ link: (props) => <A href="/terms">{props.children}</A>, bold: (props) => <strong>{props.children}</strong>, }}/>Migrate to the default slot pattern shown above. The message prop will be removed in v2.
Plural
Section titled “Plural”Fluenti uses Intl.PluralRules for locale-aware pluralization, supporting all CLDR plural categories. The <Plural> component is the simplest way to handle plurals. Pass the numeric value and provide a string for each plural category your source language needs. Use # as a placeholder for the numeric value.
<template> <Plural :value="count" one="# item" other="# items" /></template><Plural value={count()} one="# item" other="# items" />| Prop | When used |
|---|---|
value | (required) The numeric value to pluralize on |
zero | Exact zero match |
one | CLDR “one” category (e.g., 1 in English) |
two | CLDR “two” category (e.g., Arabic dual) |
few | CLDR “few” category (e.g., Russian 2-4) |
many | CLDR “many” category (e.g., Arabic 11-99) |
other | (required) Fallback for all other values |
tag | Wrapper element (default: 'span') |
Catalog extraction
Section titled “Catalog extraction”Plural forms are auto-extracted to catalogs by fluenti extract. Translators see the full ICU plural pattern in their PO/JSON file and provide locale-appropriate translations. You only write the source-language forms — Fluenti generates the correct ICU {count, plural, ...} pattern in the catalog.
For example, the English source:
<Plural :value="count" one="# item" other="# items" />Produces this catalog entry:
msgid "{count, plural, one {# item} other {# items}}"A Chinese translator simply provides the other form (Chinese has no plural distinction), while an Arabic translator provides all six categories.
ICU MessageFormat syntax
Section titled “ICU MessageFormat syntax”You can also write ICU plural patterns directly in t() calls:
{count, plural, =0 {No items} one {# item} other {# items}}Exact matches
Section titled “Exact matches”Exact matches (=0, =1, =2) are checked before CLDR categories:
{count, plural, =0 {Nobody} =1 {Just you} one {# person} other {# people}}Offset
Section titled “Offset”{count, plural, offset:1 =0 {Nobody} =1 {Just {name}} one {# other and {name}} other {# others and {name}}}Language-specific plural rules
Section titled “Language-specific plural rules”| Language | Categories |
|---|---|
| English | one, other |
| Chinese | other (no plural forms) |
| Arabic | zero, one, two, few, many, other |
| Russian | one, few, many, other |
| French | one, other |
Select
Section titled “Select”ICU select patterns for choosing text based on a string value (e.g., gender, status).
Attrs API
Section titled “Attrs API”Pass each option as a separate prop:
<template> <Select :value="gender" male="He liked this" female="She liked this" other="They liked this" /></template><Select value={gender()} male="He liked this" female="She liked this" other="They liked this" />options prop (type-safe)
Section titled “options prop (type-safe)”For programmatic usage or when you want explicit type checking, pass an options object:
<script setup lang="ts">import { ref } from 'vue'
const role = ref<'admin' | 'editor' | 'viewer'>('editor')
const roleOptions = { admin: 'Full access granted', editor: 'Can edit content', viewer: 'Read-only access', other: 'Unknown role',} as const</script>
<template> <Select :value="role" :options="roleOptions" /></template>const [role, setRole] = createSignal<'admin' | 'editor' | 'viewer'>('editor')
const roleOptions = { admin: 'Full access granted', editor: 'Can edit content', viewer: 'Read-only access', other: 'Unknown role',} as const
<Select value={role()} options={roleOptions} />Props: value (required), other (required), options (optional object), plus any string keys as individual props. tag optional.