main is production branch dev is development branch
Flutter Translate is a fully featured localization / internationalization (i18n) library for Flutter.
It lets you define translations for your content in different languages and switch between them easily.
- Very easy to use
Mobile
,Web
andDesktop
supportPluralization
andDuals
support- Supports both
languageCode (en)
andlanguageCode_countryCode (en_US)
locale formats - Automatically
save & restore
the selected locale with a simple implementation - Full support for
right-to-left
locales Fallback
locale support in case the system locale is unsupported- Supports both
inline or nested
JSON
Complete documentation is available on the wiki page.
To get started please see Installation, Configuration & Usage.
https://github.com/Windmillcode/flutter_translate/tree/master/example
Please file any issues, bugs or feature request here.
This project is licensed under the MIT License
To illustrate the use of the translate
function with a JSON structure that includes nested objects and lists, we'll expand our example to include a more complex structure. In this scenario, our localization files will have keys that point to nested objects and arrays, providing a more intricate example of how you might structure your localized content.
Here's an extended example of the JSON structure for English (en.json
) and Spanish (es.json
), including lists within the nested objects:
en.json:
{
"dashboard": {
"title": "Dashboard",
"notifications": [
"You have {count} new messages",
"Your subscription ends in {days} days",
"New features available!"
],
"menu": {
"home": "Home",
"profile": "Profile",
"settings": "Settings"
}
}
}
es.json:
{
"dashboard": {
"title": "Tablero",
"notifications": [
"Tienes {count} mensajes nuevos",
"Tu suscripciĂłn termina en {days} dĂas",
"¡Nuevas funciones disponibles!"
],
"menu": {
"home": "Inicio",
"profile": "Perfil",
"settings": "ConfiguraciĂłn"
}
}
}
Now, let's see how we can use the translate
function to access these nested and list-based translations:
To access translations within nested objects, you concatenate the keys using a dot (.
) notation.
String title = translate("dashboard.title");
print(title); // Outputs "Dashboard" in English or "Tablero" in Spanish.
To access a specific item in a list, you would also use the dot notation followed by the index of the item in the list.
String messageNotification = translate("dashboard.notifications.0", args: {"count": 5});
print(messageNotification); // Outputs "You have 5 new messages" in English or "Tienes 5 mensajes nuevos" in Spanish.
String subscriptionNotification = translate("dashboard.notifications.1", args: {"days": 3});
print(subscriptionNotification); // Outputs "Your subscription ends in 3 days" in English or "Tu suscripciĂłn termina en 3 dĂas" in Spanish.
If the JSON structure had nested objects within an array, you would access them similarly, using the index and then the key.
Assuming a structure (not shown in the above JSON) like "dashboard": { "alerts": [{ "type": "System", "message": "An update is available." }] }
, you would access the message like so:
String alertMessage = translate("dashboard.alerts.0.message");
print(alertMessage); // Assuming it's properly localized, it would output the message based on the current locale.
These examples demonstrate how you can retrieve localized strings from a complex JSON structure using the translate
function, accommodating dynamic values and accessing nested and array-based structures.
To illustrate how to use the translatePlural
function for handling pluralization based on the current locale, we'll need to expand our JSON structure to include plural forms. The Intl
package, which is often used in conjunction with localization in Flutter, supports different plural categories like zero, one, two, few, many, and other, depending on the language's rules.
Let's modify our en.json
and es.json
files to include a pluralized key for messages. Note that different languages have different pluralization rules, and the Intl
package expects you to provide translations for all these categories, even if they're not all used in every language.
en.json:
{
"dashboard": {
"title": "Dashboard",
"messages": {
"zero": "You have no new messages",
"one": "You have one new message",
"other": "You have {count} new messages"
},
"menu": {
"home": "Home",
"profile": "Profile",
"settings": "Settings"
}
}
}
es.json:
{
"dashboard": {
"title": "Tablero",
"messages": {
"zero": "No tienes mensajes nuevos",
"one": "Tienes un mensaje nuevo",
"other": "Tienes {count} mensajes nuevos"
},
"menu": {
"home": "Inicio",
"profile": "Perfil",
"settings": "ConfiguraciĂłn"
}
}
}
Now, here's how you can use the translatePlural
function to select the appropriate plural form based on the number of messages:
String noMessages = translatePlural("dashboard.messages", 0);
print(noMessages); // Outputs "You have no new messages" in English or "No tienes mensajes nuevos" in Spanish.
String oneMessage = translatePlural("dashboard.messages", 1);
print(oneMessage); // Outputs "You have one new message" in English or "Tienes un mensaje nuevo" in Spanish.
String multipleMessages = translatePlural("dashboard.messages", 5, args: {"count": 5});
print(multipleMessages); // Outputs "You have 5 new messages" in English or "Tienes 5 mensajes nuevos" in Spanish.
In this code, translatePlural
is used to get the correct translation based on the value
provided. The value
determines which plural form to use, and the optional args
map allows for dynamic values to be inserted into the translation string, similar to how you use translate
for non-pluralized strings.
Given a list in your localization files like this:
{
"options": ["Option 1", "Option 2", "Option 3"]
}
You can create a ListView
that dynamically translates each item:
Widget buildOptionList(BuildContext context) {
// Assuming the number of options is known
int optionCount = 3;
return ListView.builder(
itemCount: optionCount,
itemBuilder: (context, index) {
return ListTile(
title: Text(translate('options.$index')),
);
},
);
}
Consider a map in your localization files:
{
"settings": {
"volume": "Volume",
"brightness": "Brightness"
}
}
To display this in a UI component like ListView
, you can:
Widget buildSettingsList(BuildContext context) {
Map<String, String> settings = getValueAtKeyPath('settings');
return ListView.builder(
itemCount: settings.length,
itemBuilder: (context, index) {
String key = settings.keys.elementAt(index);
return ListTile(
title: Text(translate(key)),
subtitle: Text(translate("settings.$key")),
);
},
);
}
Assuming a combination of lists and maps:
{
"categories": ["books", "movies"],
"books": ["Fiction", "Non-fiction"],
"movies": ["Action", "Comedy"]
}
Displaying nested structures in a UI, such as ExpansionTile
:
Widget buildCategoryList(BuildContext context) {
List<String> categories = getValueAtKeyPath('categories');
return ListView.builder(
itemCount: categories.length,
itemBuilder: (context, index) {
String category = categories[index];
List<String> subcategories = getValueAtKeyPath(category);
return ExpansionTile(
title: Text(translate(category)),
children: subcategories.map((subcategory) {
return ListTile(
title: Text(translate('$category.$subcategory')),
);
}).toList(),
);
},
);
}
In these examples, the translate
function is used in a way that respects the dynamic nature of the list and map structures, ensuring that the localized strings are fetched correctly and dynamically based on the index or keys within the data structures.
To create examples that use getValueAtKeyPath
with translatePlural
, we'll leverage the dynamic nature of Dart's access to nested JSON structures. We'll assume the JSON localization files contain pluralized strings and demonstrate how to construct key paths dynamically to use with translatePlural
. Let's work through examples using Lists, Maps, and a combination of both.
Given a list with pluralized keys in your localization files like this:
{
"messages": [
{"key": "inbox_message", "zero": "No messages", "one": "One message", "other": "{} messages"},
{"key": "sent_message", "zero": "No messages sent", "one": "One message sent", "other": "{} messages sent"}
]
}
You can create a method to display the pluralized messages based on the count:
Widget buildMessageList(BuildContext context, List<int> messageCounts) {
return ListView.builder(
itemCount: messageCounts.length,
itemBuilder: (context, index) {
String keyPath = 'messages.$index.key';
int count = messageCounts[index];
return ListTile(
title: Text(translatePlural(keyPath, count)),
);
},
);
}
Consider a map in your localization files with pluralized values:
{
"notifications": {
"email": {"zero": "No emails", "one": "One email", "other": "{} emails"},
"alert": {"zero": "No alerts", "one": "One alert", "other": "{} alerts"}
}
}
Display these settings with pluralization:
Widget buildNotificationSettings(BuildContext context, Map<String, int> notificationCounts) {
return ListView.builder(
itemCount: notificationCounts.length,
itemBuilder: (context, index) {
String key = notificationCounts.keys.elementAt(index);
int count = notificationCounts[key];
return ListTile(
title: Text(translatePlural('notifications.$key', count)),
);
},
);
}
Assume a combination of lists and maps for categories and their items, with pluralization:
{
"categories": ["emails", "alerts"],
"emails": {"zero": "No emails", "one": "One email", "other": "{} emails"},
"alerts": {"zero": "No alerts", "one": "One alert", "other": "{} alerts"}
}
Displaying these in a UI, such as an ExpansionTile
, with counts:
Widget buildCategoryList(BuildContext context, Map<String, int> itemCounts) {
List<String> categories = getValueAtKeyPath('categories');
return ListView.builder(
itemCount: categories.length,
itemBuilder: (context, index) {
String category = categories[index];
int count = itemCounts[category] ?? 0;
return ExpansionTile(
title: Text(translatePlural(category, count)),
);
},
);
}
In these examples, translatePlural
is dynamically used with key paths constructed on the fly, similar to how translate
was used in your provided examples, enabling the handling of pluralized translations in a dynamic and nested data structure.