vscode-flutter-i18n-json
VS Code extension to create a binding between your translations from .json files and your Flutter app. You can also automagically generate translations for all your locales, based on Google Translate.
Installation
To install the extension just execute the following command:
ext install vscode-flutter-i18n-json
You may also install the extension from the visual studio code marketplace.
Getting started
- Install the extension
- Open your project, open the command palette and find the
Flutter I18n Json: Initialize
command.
- Enter a default locale, or press enter to use
en-US
.
Commands
Flutter I18n Json: Initialize
Creates the inital binding between translations from .json files and your Flutter app.
The command will ask you for the default locale, the locale that will be used when no other locale can be matched.
The following files will be created:
i18n/<default-locale>.json
lib/generated/i18n.dart
i18nconfig.json
Flutter I18n Json: Add locale
Adds another locale to your Flutter app.
The command will ask you for a new locale.
The following files will be created:
i18n/<new-locale>.json
and updated:
lib/generated/i18n.dart
i18nconfig.json
Flutter I18n Json: Update
After you change or add any translations, run the update command to update
lib/generated/i18n.dart
to reflect your translation changes.
Flutter I18n Json: Remove locale
Removes an existing locale from your Flutter app.
The command will ask you to pick a locale from the list of existing locales.
The following files will be removed:
i18n/<existing-locale>.json
and updated:
lib/generated/i18n.dart
i18nconfig.json
Flutter I18n Json: Set Google Translate API Code
Sets the API code for the Google Translate API.
To obtain an API key, you need to have an account with the Google Cloud Platform:
- Go to: https://console.developers.google.com/apis/dashboard
- Select (or create) a project
- Click button "Enable API's and services" (on top)
- Search for "Cloud Translation API"
- Click "Enable"
- Once enabled, go to the "Credentials" (left side) section on your API overview
- Click "Create credential" (top bar)
- In de text "We'll help you set up the correct credentials.
If you want you can skip this step and create an API key, client ID or service account.", choose the link "API key".
- Give it a name and click "Create"
You can copy the key now.
The following file will be updated:
i18nconfig.json
Flutter I18n Json: Create automagic translations from default locale
Generates and adds missing translations to i18n/<locale>.json
files, based on the translation keys and values in i18n/<default-locale>.json
.
When using this command, you don't have to manually add every translation key and translated value to all i18n/<locale>.json
files.
Usage
JSON
Use a simple key-value pair JSON format to define your translations.
{
"hello": "Hello"
}
In the above example "hello"
is the key for the translation value "Hello!"
.
Placeholders are automatically detected and are enclosed in curly brackets ({}
):
{
"greetTo": "Hello {name}"
}
Here, {name}
is a placeholder within the translation value for "greetTo"
.
Dart
Let's add some translations in i18n/en-US.json
:
{
"hello": "Hello!",
"greetTo": "Nice to meet you, {name}!"
}
After you run the update command, you will see that in lib/generated/i18n.dart
, a getter hello
and a method greetTo
were created:
class I18n implements WidgetsLocalizations {
const I18n();
static const GeneratedLocalizationsDelegate delegate =
const GeneratedLocalizationsDelegate();
static I18n of(BuildContext context) =>
Localizations.of<I18n>(context, WidgetsLocalizations);
@override
TextDirection get textDirection => TextDirection.ltr;
String get hello => "Hello!";
String greetTo(String name) => "Nice to meet you, ${name}!";
}
Using the generated I18n
class is showcased in the example below:
@override
Widget build(BuildContext context) {
final i18n = I18n.delegate;
return new MaterialApp(
localizationsDelegates: [
i18n
],
supportedLocales: i18n.supportedLocales,
localeResolutionCallback: i18n.resolution(fallback: new Locale("en", "US"))
// .. any other properties supported and required by your application
);
When translating something, simply call your translation like this:
I18n.of(context).hello
This returns a string you can direcly use in e.g. a Text() widget
Nesting
Nesting is supported which allows you to hierarchically structure the translations.
{
"hello": "hello!",
"greeting": {
"formal": "Hello",
"informal": "Hi",
"placeholder": {
"formal": "Hello {name}",
"informal": "Hi {name}"
}
}
}
The above file will generate the following dart code
/// "hello!"
String get hello => "hello!";
/// "Hello"
String get greetingFormal => "Hello";
/// "Hi"
String get greetingInformal => "Hi";
/// "Hello ${name}"
String greetingPlaceholderFormal(String name) => "Hello ${name}";
/// "Hi ${name}"
String greetingPlaceholderInformal(String name) => "Hi ${name}";
Arrays
Arrays of strings is supported too.
{
"hello": "hello!",
"greetings": [
"Hello",
"Hi"
]
}
The above file will generate the following dart code
/// "hello!"
String get hello => "hello!";
/// ["Hello", "Hi"]
List<String> get greetings => ["Hello", "Hi"];
Changing locale manually
Locale can be changed manually using static locale
parameter. To make application reload from anywhere in the app you can use static onLocaleChanged
callback:
import 'package:flutter_localizations/flutter_localizations.dart';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final i18n = I18n.delegate;
@override
void initState() {
super.initState();
I18n.onLocaleChanged = onLocaleChange;
}
void onLocaleChange(Locale locale) {
setState(() {
I18n.locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: app,
localizationsDelegates: [
i18n,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate // <-- needed for iOS
],
supportedLocales: i18n.supportedLocales,
home: <your home widget>
);
}
}
Calling this anywhere in your app will now change the app's language
I18n.onLocaleChanged(newLocale);
Generate translations
After you run the Create automagic translations-command, all translation files will be supplemented with the new translations.
For instance, if you added the greetTo
key from above, with this command your i18n/es-ES.json
goes from
{
"hello": "¡Hola!"
}
to
{
"hello": "¡Hola!",
"greetTo": "Encantado de conocerte, {name}!"
}
The run the update command will run automatically after any successful automagic translation, so you'll see that the Spanish WidgetsLocalizations are updated as:
class _I18n_es_ES extends I18n {
const _I18n_es_ES();
@override
String get hello => "¡Hola!";
@override
String greetTo(String name) => "Encantado de conocerte, ${name}!";
}
Text direction
Starting form version 0.12.0 the module detects the text direction automatically - based on the language code.
If you want to change the automatic behaviour, you can change the text direction in the i18nconfig.json
file:
{
rtl: ["ar-AR"],
ltr: []
}
Troubleshooting
iOS
By default, your languages are not supported by iOS out of the box. To enable them, add the following to your your_project/ios/Runner/Info.plist
file:
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>es</string>
<string>ru</string>
</array>
(with en
, es
and ru
being examples for English, Spanish and Russian)
Your file should look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>es</string>
<string>ru</string>
</array>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
.
.
.
etc...
There are still some unresolved issues in Flutter when trying to use localization with the iOS simulators. For more information to address this issue check the flutter documentation.
No Material-/CupertinoLocalizations found.
Global widgets may throw exceptions informaing you that they cannot find any MaterialLocalizations (No MaterialLocalizations found.
). You need to install them manually and add their delegates to your localizationsDelegates.
in your pubspec.yaml:
dev_dependencies:
flutter_localizations:
sdk: flutter
in your app:
import 'package:flutter_localizations/flutter_localizations.dart';
return new MaterialApp(
localizationsDelegates: [
i18n,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate
...