Skip to content
F fluenti

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.

<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.

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>

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.

<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>
<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.

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>
PropWhen used
value(required) The numeric value to pluralize on
zeroExact zero match
oneCLDR “one” category (e.g., 1 in English)
twoCLDR “two” category (e.g., Arabic dual)
fewCLDR “few” category (e.g., Russian 2-4)
manyCLDR “many” category (e.g., Arabic 11-99)
other(required) Fallback for all other values
tagWrapper element (default: 'span')

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.

You can also write ICU plural patterns directly in t() calls:

{count, plural,
=0 {No items}
one {# item}
other {# items}
}

Exact matches (=0, =1, =2) are checked before CLDR categories:

{count, plural, =0 {Nobody} =1 {Just you} one {# person} other {# people}}
{count, plural, offset:1
=0 {Nobody}
=1 {Just {name}}
one {# other and {name}}
other {# others and {name}}
}
LanguageCategories
Englishone, other
Chineseother (no plural forms)
Arabiczero, one, two, few, many, other
Russianone, few, many, other
Frenchone, other

ICU select patterns for choosing text based on a string value (e.g., gender, status).

Pass each option as a separate prop:

<template>
<Select :value="gender" male="He liked this" female="She liked this" other="They liked this" />
</template>

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>

Props: value (required), other (required), options (optional object), plus any string keys as individual props. tag optional.