Localization (i18n)
Finch has a built-in i18n system supporting multiple languages. Language strings can be stored in JSON files or defined directly in Dart.
Configuration
Set the language options in FinchConfigs:
FinchConfigs configs = FinchConfigs(
// Path to directory containing language JSON files
languagePath: pathTo(env['LANGUAGE_PATH'] ?? './lib/languages'),
// Use JSON files (LanguageSource.json) or Dart maps (LanguageSource.dart)
languageSource: LanguageSource.json,
// If using LanguageSource.dart, supply the map here:
// dartLanguages: languageDart,
);
Option 1: JSON Files
Create one JSON file per language in your languagePath directory. The file name is the language code:
lib/languages/en.json
{
"dir": "ltr",
"logo.title": "My App",
"greeting": "Hello, World!",
"example.params": "My name is {name}, my age is {age}",
"example.params.arr": "My name is {0}, my age is {1}"
}
lib/languages/fa.json
{
"dir": "rtl",
"logo.title": "برنامه من",
"greeting": "سلام دنیا!",
"example.params": "نام من {name} است، سن من {age} سال است"
}
The
dirkey (ltr/rtl) is used by{{ $e.dir }}in templates.
Option 2: Dart Map
Define languages as a Dart Map<String, Map<String, String>> and point FinchConfigs to it:
// lib/languages/language_dart.g.dart (or any name)
const languageDart = <String, Map<String, String>>{
'en': {
'dir': 'ltr',
'logo.title': 'My App',
'greeting': 'Hello, World!',
'example.params': 'My name is {name}, my age is {age}',
},
'fa': {
'dir': 'rtl',
'logo.title': 'برنامه من',
'greeting': 'سلام دنیا!',
'example.params': 'نام من {name} است، سن من {age} سال است',
},
};
FinchConfigs configs = FinchConfigs(
languageSource: LanguageSource.dart,
dartLanguages: languageDart,
);
The
finch servewatcher can convert JSON files to a Dart map automatically. The generated file is written tolanguage_dart.g.dart.
Translating in Controllers
Use the .tr extension on any key string. .write() renders the final translated string:
// Simple translation
String text = 'logo.title'.tr.write();
// With named parameters
String text = 'example.params'.tr.write({'name': 'Alice', 'age': 30});
// With positional parameters (array)
String text = 'example.params.arr'.tr.writeArr(['Alice', 30]);
Pass translated strings to templates:
rq.addParams({
'greeting': 'greeting'.tr.write(),
'userLine': 'example.params'.tr.write({'name': 'Alice', 'age': 30}),
});
return rq.renderView(path: 'pages/home');
Translating in Templates
Use {{ $t('key') }} for inline translation:
<h1>{{ $t('logo.title') }}</h1>
<p>{{ $t('example.params', {'name': user.name, 'age': user.age}) }}</p>
<p>{{ $t('example.params.arr', ['Alice', 30]) }}</p>
Language Switching
Language is determined in this order:
- First path segment if it matches a known language code (e.g.,
/fa/home) langdata field on API endpointslanguagecookielanguagesession key- Default from settings
Change language from a controller:
rq.changeLanguege('fa');
In a template, generate a URL that switches language:
<a href="{{ $e.urlToLanguage('fa') }}">فارسی</a>
<a href="{{ $e.urlToLanguage('en') }}">English</a>
Available Languages in Templates
{% for lang in $e.langs %}
<a href="{{ $e.urlToLanguage(lang.code) }}">{{ lang.label }}</a>
{% endfor %}
Each entry: { code: 'en', label: 'English', country: 'United States' }
TString — Translation Objects
TString wraps a key and lets you defer translation:
var ts = TString('example.params');
rq.addParam('exampleTString', ts.write());
// Or using the .tr shorthand:
rq.addParam('examplePathString', 'example.path'.tr.write());
## array parameters in i18n
You can use array parameters in your i18n text. For example, if you want to translate the `example.params` key, you can do it like this:
```dart
rq.renderString(text: 'example.params'.tr.writeArr(['Alexandre', 30]));
and in your template you can use it like this:
{
"example.params": "نام من {0} است، سن من {1} سال است",
}
<p>{{ $t('example.params', ['Alexandre', 30]) }}</p>