Flutter: i18n Made Easy
At the time of writing, the “basic” i18n approach in Flutter is complicated and heavyweight. That’s why I decided to start my own library: slang
Step 1: Add dependencies
Add slang
and slang_flutter
to your dependencies:
dependencies:
slang: 3.25.0
slang_flutter: 3.25.0
Step 2: Write JSON files
Now lets add some strings. Just make sure that they are inside the lib directory and all in one common package like lib/i18n/strings.i18n.json
Default Locale
File: strings.i18n.json{
"hello": "Hello $name",
"save": "Save",
"login": {
"success": "Logged in successfully",
"fail": "Logged in failed"
}
}
German Locale
File: strings_de.i18n.json{
"hello": "Hallo $name",
"save": "Speichern",
"login": {
"success": "Login erfolgreich",
"fail": "Login fehlgeschlagen"
}
}
Step 3: Generate the dart code
This will translate the .json files into .dart files.
dart run slang
Step 4: Initialize the right language
Users expect that your app shows the right language at the start of the app.
There are 2 methods to set the locale: LocaleSettings.useDeviceLocale()
and LocaleSettings.setLocaleRaw(String locale)
. It is up to you how you implement it.
a) use device locale
void main() {
WidgetsFlutterBinding.ensureInitialized();
LocaleSettings.useDeviceLocale();
runApp(MyApp());
}
b) use specific locale
@override
void initState() {
super.initState();
String storedLocale = loadFromStorage(); // your logic here
LocaleSettings.setLocaleRaw(storedLocale);
}
Step 4b: iOS-only
There is one small change needed for iOS users:
File: ios/Runner/Info.plist<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>de</string>
</array>
Step 5: Finally use your translations!
That’s all! In the generated dart file you will see the famous t
variable.
While most libraries goes for the t('somekey.anotherKey.blabla')
solution with a plain string, the approach of slang is 100% safe, and it has nice autocompletion. Let’s try this out:
import 'package:my_app/i18n/strings.g.dart'; // import
String a = t.login.success; // plain
String b = t.hello(name: 'Tom'); // with argument
String c = t.step[3]; // with index (for arrays)
String d = t.type['WARNING']; // with key (for maps)
// advanced
TranslationProvider(child: MyApp()); // wrap your app
// [...]
final t = Translations.of(context); // get translation instance
String translateAdvanced = t.hello(name: 'Tom');
Supported Features
- String Interpolation, e.g.
t.hello(name: 'Tom')
- Pluralization, e.g.
t.apples(count: 3)
- Gender, e.
t.greet(context: Gender.male)
- Arrays, e.g.
t.step[2]
- Maps, e.g.
t.group['LEADER']
- Fully Dynamic, e.g.
t['homeScreen.title']