Flutter ARB
AI translation for Flutter ARB files with Lingo.dev CLI
What is Flutter ARB?
Flutter ARB (Application Resource Bundle) is a JSON-based format used by Google's Flutter framework for managing localized strings. It supports metadata, placeholders, and ICU message formatting for building natively compiled applications.
What is Lingo.dev CLI?
Lingo.dev CLI is a free, open-source CLI for translating apps and content with AI. It's designed to replace traditional translation management software while integrating with existing pipelines.
To learn more, see Overview.
About this guide
This guide explains how to translate Flutter ARB files with Lingo.dev CLI.
You'll learn how to:
- Create a project from scratch
- Configure a translation pipeline
- Generate translations with AI
Prerequisites
To use Lingo.dev CLI, ensure that Node.js v18+ is installed:
❯ node -v
v22.17.0
Step 1. Set up a project
In your project's directory, create an i18n.json file:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
This file defines the behavior of the translation pipeline, including what languages to translate between and where the localizable content exists on the file system.
To learn more about the available properties, see i18n.json.
Step 2. Configure the source locale
The source locale is the original language and region that your content was written in. To configure the source locale, set the locale.source property in the i18n.json file:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
The source locale must be provided as a BCP 47 language tag.
For the complete list of the locale codes that Lingo.dev CLI supports, see Supported locale codes.
Step 3. Configure the target locales
The target locales are the languages and regions you want to translate your content into. To configure the target locales, set the locale.targets property in the i18n.json file:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
Step 4. Create the source content
If you haven't already, create one or more ARB files that contain the content to be translated. These files must be located at a path that includes the source locale somewhere in the path (e.g., as a directory name like en/ or as part of the filename like messages.en.arb).
For Flutter ARB files, the following requirements apply:
- Each message key must have a corresponding translation value
- Metadata entries (starting with
@) are preserved but not translated - The
@@localemetadata field identifies the locale - Placeholders (
{name}) are preserved during translation - ICU message format for plurals and selects is supported
For example:
{
"@@locale": "en",
"welcome_message": "Welcome to our Flutter app",
"@welcome_message": {
"description": "The main welcome message shown on the home screen"
},
"login_button": "Log In",
"greeting_with_name": "Hello {name}!",
"@greeting_with_name": {
"placeholders": {
"name": {
"type": "String"
}
}
}
}
Step 5. Create a bucket
-
In the
i18n.jsonfile, add a"flutter"object to thebucketsobject:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "flutter": {} } } -
In the
"flutter"object, define an array of one or moreincludepatterns:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "flutter": { "include": ["./[locale]/example.arb"] } } }These patterns define which files to translate.
The patterns themselves:
- must contain
[locale]as a placeholder for the configured locale - can point to file paths (e.g.,
"[locale]/config.arb") - can use asterisks as wildcard placeholders (e.g.,
"[locale]/*.arb")
Recursive glob patterns (e.g.,
**/*.arb) are not supported. - must contain
Step 6. Configure an LLM
Lingo.dev CLI uses large language models (LLMs) to translate content with AI. To use one of these models, you need an API key from a supported provider.
To get up and running as quickly as possible, we recommend using Lingo.dev Engine — our own, hosted platform that offers 10,000 tokens of free, monthly usage:
-
Run the following command:
npx lingo.dev@latest loginThis will open your default browser and ask you to authenticte.
-
Follow the prompts.
Step 7. Generate the translations
In the directory that contains the i18n.json file, run the following command:
npx lingo.dev@latest run
This command:
- Reads the
i18n.jsonfile. - Finds the files that need to be translated.
- Extracts the translatable content from the files.
- Uses the configured LLM to translate the extracted content.
- Writes the translated content back to the file system.
The first time translations are generated, an i18n.lock file is created. This file keeps track of what content has been translated, preventing unnecessary retranslations on subsequent runs.
Example
en/example.arb
{
"@@locale": "en",
"welcome_message": "Welcome to our Flutter app",
"@welcome_message": {
"description": "The main welcome message shown on the home screen",
"context": "greeting"
},
"login_button": "Log In",
"signup_button": "Sign Up",
"greeting_with_name": "Hello {name}!",
"@greeting_with_name": {
"description": "Greeting message with user's name",
"placeholders": {
"name": {
"type": "String",
"description": "The user's display name"
}
}
},
"item_count": "{count, plural, =0 {No items} one {# item} other {# items}}",
"@item_count": {
"description": "Message showing the number of items with proper pluralization",
"placeholders": {
"count": {
"type": "int",
"description": "The number of items"
}
}
}
}
es/example.arb
{
"@@locale": "es",
"welcome_message": "Bienvenido a nuestra aplicación Flutter",
"@welcome_message": {
"description": "The main welcome message shown on the home screen",
"context": "greeting"
},
"login_button": "Iniciar sesión",
"signup_button": "Registrarse",
"greeting_with_name": "¡Hola {name}!",
"@greeting_with_name": {
"description": "Greeting message with user's name",
"placeholders": {
"name": {
"type": "String",
"description": "The user's display name"
}
}
},
"item_count": "{count, plural, =0 {Sin elementos} one {# elemento} other {# elementos}}",
"@item_count": {
"description": "Message showing the number of items with proper pluralization",
"placeholders": {
"count": {
"type": "int",
"description": "The number of items"
}
}
}
}
i18n.json
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {
"flutter": {
"include": ["./[locale]/example.arb"]
}
}
}
i18n.lock
version: 1
checksums:
88559ecadc7cff52625bd3a47e51dd78:
welcome_message: 9c56d00796c3c7facba6a25275de5b7b
login_button: 0029e5a35676c0051e761fcd046ef9ee
signup_button: 0dd2ae69be4618c1f9e615774a4509ca
error_network: e0becd5fc88e85a97c6987b96c80fb11
success_message: e6dcd73052dc41dbe05d86af9887d2c4
user_profile_title: bee775ff7216747b2111e93cefa57ddc
settings_screen_title: 8df6777277469c1fd88cc18dde2f1cc3
cancel_action: 2e2a849c2223911717de8caa2c71bade
confirm_action: 90930b51154032f119fa75c1bd422d8b
greeting_with_name: 218521f06746e82ba44d68c8a5bb210c
item_count: d8d083b56bc155cf0997ea6ae989b83f
user_status: 903b5a6edde5368dd9089accdc1b1f9d