Configuration
Fluenti uses a fluenti.config.ts file at your project root. It is auto-loaded via jiti — no build step needed.
Example
Section titled “Example”import { defineConfig } from '@fluenti/cli'
export default defineConfig({ sourceLocale: 'en', locales: ['en', 'zh-CN', 'ja'], catalogDir: './locales', format: 'po', include: ['./src/**/*.vue', './src/**/*.tsx', './src/**/*.jsx', './src/**/*.ts'], exclude: ['./src/**/*.test.*'], compileOutDir: './src/locales/compiled', fallbackChain: { 'zh-TW': ['zh-CN', 'en'], '*': ['en'] }, splitting: 'dynamic', defaultBuildLocale: 'en',})defineConfig is an identity function that provides full type inference and IDE autocompletion for all config options.
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
sourceLocale | string | 'en' | The locale used in source code |
locales | LocaleDefinition[] | ['en'] | All target locales. Each entry can be a string ('en') or an object ({ code: 'en', name: 'English' }) |
catalogDir | string | './locales' | Directory for translation catalogs |
format | 'json' | 'po' | 'po' | Catalog file format. PO is recommended — compatible with Poedit, Weblate, Crowdin and other translation tools |
include | string[] | ['./src/**/*.vue', './src/**/*.tsx', './src/**/*.jsx'] | Glob patterns for source files |
exclude | string[] | ['./src/**/*.test.*'] | Glob patterns to exclude |
compileOutDir | string | './src/locales/compiled' | Output directory for compiled messages |
fallbackChain | Record<string, string[]> | {} | Locale fallback chains |
splitting | 'dynamic' | 'static' | false | false | Code-splitting strategy |
defaultBuildLocale | string? | — | Default locale embedded in the bundle |
devWarnings | boolean? | — | Enable development-mode warnings for missing translations and format errors |
extends | string? | — | Path to parent config file for monorepo inheritance |
defaultLocale | string? | — | Default locale for routing/detection (defaults to sourceLocale) |
parallelCompile | boolean? | false | Enable parallel compilation using worker threads |
idGenerator | (message: string, context?: string) => string | — | Custom message ID hash function |
catalogExtension | string? | '.js' | File extension for compiled catalog output files |
devAutoCompile | boolean? | true | Auto extract+compile in dev mode |
buildAutoCompile | boolean? | true | Auto extract+compile before production build |
devAutoCompileDelay | number? | 500 | Debounce delay in ms for dev auto-compile |
onBeforeCompile | () => boolean | void | Promise<...> | — | Lifecycle hook called before auto-compile |
onAfterCompile | () => void | Promise<void> | — | Lifecycle hook called after auto-compile |
PO vs JSON
Section titled “PO vs JSON”| PO | JSON | |
|---|---|---|
| Best for | Teams with translators, Crowdin/Weblate | Solo devs, programmatic manipulation |
| Tooling | Poedit, Crowdin, Weblate, Lokalise | Any text editor, jq |
| Comments | First-class #. translator comment | Not supported |
| Recommendation | Default choice for production | Quick prototyping |
Compiled output
Section titled “Compiled output”Compiled catalogs are build artifacts. Regenerate them in CI instead of committing:
locales/compiled/For the full API reference, see @fluenti/cli and @fluenti/vite-plugin.
Monorepo Configuration
Section titled “Monorepo Configuration”Use the extends option to inherit from a shared base config:
export default defineConfig({ extends: '../../fluenti.config.ts', include: ['./src/**/*.tsx', './src/**/*.ts'], splitting: 'dynamic',})Child configs inherit all options from the parent and can override any field. Relative paths in the parent are automatically rebased to the child’s directory.
See Scaling & Enterprise for a full monorepo setup guide.
Performance Options
Section titled “Performance Options”Enable parallel compilation and incremental caching for large projects:
export default defineConfig({ // ... parallelCompile: true, // Worker threads for 5+ locales devAutoCompileDelay: 1000, // Increase debounce for large codebases})Use --no-cache flags on extract and compile to force full rebuilds when needed. See Scaling & Enterprise for details.
Lifecycle Hooks
Section titled “Lifecycle Hooks”Hook into the auto-compile process for custom build integration:
export default defineConfig({ // ... onBeforeCompile: () => { // Return false to skip compilation console.log('Compiling translations...') }, onAfterCompile: async () => { // Post-compile: notifications, uploads, validation },})See Scaling & Enterprise for details.
Common Configurations
Section titled “Common Configurations”Vue SPA
Section titled “Vue SPA”export default defineConfig({ sourceLocale: 'en', locales: ['en', 'ja', 'zh-CN'], catalogDir: './locales', format: 'po', include: ['./src/**/*.vue', './src/**/*.ts'], compileOutDir: './src/locales/compiled',})React / SolidJS SPA
Section titled “React / SolidJS SPA”export default defineConfig({ sourceLocale: 'en', locales: ['en', 'es', 'fr'], catalogDir: './locales', format: 'po', include: ['./src/**/*.tsx', './src/**/*.jsx', './src/**/*.ts'], compileOutDir: './src/locales/compiled', splitting: 'dynamic',})Next.js
Section titled “Next.js”export default defineConfig({ sourceLocale: 'en', locales: ['en', 'ja'], catalogDir: './locales', format: 'po', include: ['./app/**/*.tsx', './components/**/*.tsx'], compileOutDir: './src/locales/compiled',})export default defineConfig({ sourceLocale: 'en', locales: ['en', 'fr', 'de'], catalogDir: './locales', format: 'po', include: ['./components/**/*.vue', './pages/**/*.vue', './layouts/**/*.vue'], compileOutDir: './locales/compiled',})TypeScript Integration
Section titled “TypeScript Integration”Fluenti provides strict type safety for translation calls via the FluentiTypeConfig interface and auto-generated type declarations.
Auto-generated types
Section titled “Auto-generated types”When you run fluenti compile, Fluenti generates a messages.d.ts file alongside your compiled catalogs. This file narrows the t() function signature to only accept valid message IDs and their expected interpolation values:
// locales/compiled/messages.d.ts (auto-generated)declare module '@fluenti/core' { interface FluentiTypeConfig { messageIds: 'greeting' | 'item_count' | 'welcome_back' messageValues: { greeting: { name: string } item_count: { count: number } welcome_back: Record<string, never> } }}After compilation, your IDE will autocomplete message IDs and flag missing or incorrect interpolation values:
const { t } = useI18n()
t('greeting', { name: 'Alice' }) // ✅ Validt('greeting', {}) // ❌ Missing required 'name't('unknown_key') // ❌ Not a valid message ID- Run
fluenti compileto generate the type declarations - Ensure
compileOutDiris included in yourtsconfig.json:
{ "compilerOptions": { "strict": true, "verbatimModuleSyntax": true }, "include": ["src", "locales/compiled"]}The types update automatically on each fluenti compile run. In dev mode with devAutoCompile: true (the default), types stay in sync as you edit messages.
FluentiTypeConfig interface
Section titled “FluentiTypeConfig interface”The FluentiTypeConfig interface has three fields you can augment:
| Field | Default | Purpose |
|---|---|---|
localizedString | LocalizedString (branded) | The return type of t(). Override to string to disable the branded type |
messageIds | string | Union of all valid message IDs (auto-narrowed by messages.d.ts) |
messageValues | Record<string, Record<string, unknown>> | Map of message ID → interpolation values (auto-narrowed by messages.d.ts) |
Disabling the branded type
Section titled “Disabling the branded type”By default, t() returns a LocalizedString branded type — a string that has been marked as translated. This prevents accidentally passing untranslated strings where translated ones are expected.
If this is too strict for your project, disable it:
declare module '@fluenti/core' { interface FluentiTypeConfig { localizedString: string }}For more on type safety at scale, see Scaling & Enterprise. For type-safe message authoring patterns, see Best Practices.