Last reviewed: 4 October 2026
Short answer
Define complete messages in ARB, keep stable identifiers, and supply metadata for context and typed placeholders. Use Flutter's generation workflow to produce the application's localization accessors, then test language selection, message branches and layout. Validate the JSON container and the message syntax separately. Vietnamese wording, dates and customer journeys still need review in the running product; generating code is not the final acceptance check.
Key takeaways
- Keep messages, metadata and generator configuration connected.
- Preserve placeholder names and explain their values.
- Test zero, one and several rather than copying plural patterns blindly.
- Use select branches only for information the application actually knows.
- Check generated source paths against the project's SDK version.
- Review built-in widgets and custom messages as separate scopes.

What does ARB contribute to a Flutter project?
ARB gives the project a JSON-based resource bundle with associated attributes. The ARB specification describes message resources and optional attribute entries.[1] In a Flutter workflow, those attributes can help explain messages and define the inputs used by generation.
Separate the application catalog from built-in widget translations. Flutter's Material localization API lists Vietnamese support.[2] That does not translate the product's custom screens, errors or business terms automatically. Inventory those messages and identify which team owns them.
Include accessibility labels, empty states, validation messages and notifications in the inventory. A translated home screen with English error text is still an incomplete journey. Identify text embedded in images or supplied by a backend, because ARB generation will not discover every external source of content for you.
What configuration should developers agree first?
Agree the source template, ARB directory, output location, class name and supported locales. Flutter documents generate: true, l10n.yaml and the gen-l10n workflow.[3] Confirm the configuration in the SDK used by the project rather than copying an old tutorial without checking its assumptions.
This illustrative l10n.yaml expects resource files in lib/l10n and the English template named app_en.arb:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
The project's pubspec.yaml also needs the appropriate dependencies and generation setting. The example is not a complete dependency file and does not pin a tested SDK. Record the actual SDK and package versions with the release.
Flutter's migration guidance describes moving generated localization imports away from the synthetic package:flutter_gen location into application source.[4] Check the output your current project produces and import that file. Do not add obsolete migration options merely because they appear in a historical configuration.
What should the source and Vietnamese files contain?
Keep identifiers and placeholder definitions coherent while translating complete messages. The following original fixture has a greeting, a document count and a select message. It is designed to illustrate resource decisions rather than a complete customer-support application.
The English template, app_en.arb, is:
{
"@@locale": "en",
"welcome": "Welcome, {name}.",
"@welcome": {
"description": "Greeting using the supplied display name.",
"placeholders": {"name": {"type": "String"}}
},
"documents": "{count, plural, =0{No documents attached} =1{1 document attached} other{{count} documents attached}}",
"@documents": {
"description": "Number of documents attached to this request.",
"placeholders": {"count": {"type": "num"}}
},
"agentUpdate": "{gender, select, female{She will review your request.} male{He will review your request.} other{Our team will review your request.}}",
"@agentUpdate": {
"description": "Use only an explicitly known staff value; otherwise other.",
"placeholders": {"gender": {"type": "String"}}
}
}
The corresponding app_vi.arb is:
{
"@@locale": "vi",
"welcome": "Chào {name}.",
"@welcome": {
"description": "Greeting using the supplied display name.",
"placeholders": {"name": {"type": "String"}}
},
"documents": "{count, plural, =0{Chưa đính kèm tài liệu} =1{Đã đính kèm 1 tài liệu} other{Đã đính kèm {count} tài liệu}}",
"@documents": {
"description": "Number of documents attached to this request.",
"placeholders": {"count": {"type": "num"}}
},
"agentUpdate": "{gender, select, female{Nhân viên tư vấn sẽ xem xét yêu cầu.} male{Nhân viên tư vấn sẽ xem xét yêu cầu.} other{Đội ngũ sẽ xem xét yêu cầu.}}",
"@agentUpdate": {
"description": "Use only an explicitly known staff value; otherwise other.",
"placeholders": {"gender": {"type": "String"}}
}
}
The metadata remains a shared technical contract in this fixture. In a real translation platform, confirm whether target metadata is retained, copied from the template or maintained separately. The customer's visible language and the team's metadata language are different decisions.
How should placeholders and descriptions be reviewed?
Protect the placeholder name and type, while letting the sentence place it naturally. Flutter documents how placeholders become inputs to generated localization methods.[3] A resource reviewer should understand the data behind each name, not just count braces.
For name, define whether the value is a person, organization or another display label. The sample uses a supplied display name, without inferring an honorific. For count, confirm it represents attached documents rather than total uploads, pages or completed translations.
Descriptions should resolve actual ambiguity. Explain the screen, the confirmed event and the customer's next action. A note stating “button text” is less useful than one explaining whether activation sends the request or opens a preview. Keep source defects visible instead of asking the translator to guess which business state is true.
| Resource field | Review question | What should remain stable |
|---|---|---|
| Message identifier | Which product task does it represent? | Callers and generation reference |
| Description | Does it resolve an ambiguity? | Essential context across handoffs |
| Placeholder name | What value does the app supply? | Identifier expected by generation |
| Placeholder type | Is the supplied value compatible? | Technical input contract |
| Branch selector | What state is explicitly known? | Branch keys and fallback meaning |
| Visible message | Does it match the confirmed event? | Accurate business meaning |
How should plurals and selects work for Vietnamese?
Use a full message with the branches required by the configured generator, and review each meaningful state. The official Flutter guide describes plural and select expressions.[3] In the fixture, explicit zero and one branches are product wording choices; they are not a claim that Vietnamese grammar always requires those separate forms.
Zero explains that nothing is attached. One and other report the same completed attachment event with a different count. Keep this event distinct from server receipt or successful quotation processing. A locally selected file is not necessarily uploaded unless the application has confirmed that state.
The select example demonstrates gender branches because a multilingual source may use them. Vietnamese can use neutral staff wording for both named branches. Do not infer gender from a customer's name, email or appearance. If the product does not need the distinction, a neutral message may be a better design than collecting extra data.
Test the fallback branch with an unknown value. Review case-sensitive selectors under the actual generator and calling code. Do not assume a capitalized value such as Female will match a lowercase branch key. Keep the allowed values in the application's data contract.
How should the generated code be used?
Use the generated class for both delegates and supported locales, then access messages below the initialized localization context. The file path in the following example assumes output at lib/l10n/app_localizations.dart. The resource identifiers above supply the method names.
import 'package:flutter/material.dart';
import 'l10n/app_localizations.dart';
void main() => runApp(const LocalizationDemo());
class LocalizationDemo extends StatelessWidget {
const LocalizationDemo({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Builder(builder: (context) {
final text = AppLocalizations.of(context)!;
return Scaffold(
body: SafeArea(child: Column(children: [
Text(text.welcome('Lan')),
Text(text.documents(3)),
Text(text.agentUpdate('other')),
])),
);
}),
);
}
This is an integration example to validate in a configured Flutter project, not an SDK build performed for this article. Run generation and analysis in the actual environment. Do not edit the generated translation methods as a substitute for updating the ARB source, because later generation can replace those edits.
What Vietnamese issues need interface testing?
Test diacritics, line wrapping, dynamic values and the full customer journey. Resource correctness alone cannot establish that a font or narrow widget displays the message properly. Use the approved Vietnamese terminology consistently across screens and support material.
Keep language, country and currency separate. A Vietnamese interface does not prove the customer is in Vietnam or paying in VND. Format dates and amounts using the intended product rules, and preserve the underlying data. Review localized instructions alongside validation and error recovery.
Do not add familiar pronouns mechanically to every message. Choose the product's tone and keep it consistent. Account forms, transactional errors and friendly onboarding can have different constraints, but the same event should not acquire conflicting meanings in different screens.

What should the release QA checklist include?
Check the container, generated resources and product behavior as separate layers. Record which checks were actually performed and keep unresolved issues visible. This original matrix gives the team specific cases rather than a generic “translation complete” checkbox.
| Check | Test case | Acceptance evidence |
|---|---|---|
| JSON container | Parse source and target ARB | No syntax error or lost message |
| Metadata | Compare identifiers and placeholder definitions | Compatible names and types |
| Message syntax | Run the project's generator | Expressions accepted by the actual SDK |
| Counts | Render 0, 1 and several attachments | Correct event wording and value |
| Select | Render known and unknown selector values | Intended branch or meaningful fallback |
| Language selection | Change app language and revisit screens | Custom and built-in text follow policy |
| Layout | Use long names and larger text settings | Readable text and operable controls |
| Journey | Attach, remove and submit documents | Messages follow the actual state |
Include failures and interruptions: a rejected attachment, removed file, network error and resumed app. Verify that the visible count does not describe stale state. A translation can be linguistically correct but still mislead when the application chooses the wrong message.
For automation, compare required message identifiers and placeholder metadata before generation, then exercise representative messages in widget or integration tests. Review rendered screens for issues that data checks cannot catch. Keep screenshots tied to the tested build and language setting.
How should LocalizeZone scope an ARB project?
Share the ARB template, target bundles, SDK details and screenshots when requesting software localization. LocalizeZone recommends a representative pilot covering a static label, typed value, plural, select and error before assigning the whole catalog.
Use the quotation page to describe target languages, source revision, release timing and review layers. State who will generate and integrate the files. Translation, resource validation and in-app testing are related tasks with different inputs and evidence.
Keep later updates connected to the same process. When a source identifier, placeholder type or branch changes, review the corresponding target and calling code. New strings should not silently inherit approval from an earlier release.
FAQ
Does Flutter's Vietnamese support translate custom screens?
No. Built-in component resources and product-specific messages have separate scopes.[2] Maintain the custom catalog and test both in the intended journey.
Can translators rename a placeholder?
Not without an agreed technical change. Preserve names and types expected by the generator; adjust sentence order instead of changing the contract.
Why are there explicit zero and one branches?
They illustrate product-specific attachment messages. Test their meaning and the other branch; do not treat them as a universal Vietnamese grammar rule.
Must Vietnamese messages use gendered pronouns?
No. Neutral wording can be appropriate. Only use known, necessary distinctions, and provide a useful fallback rather than inferring identity.
Does valid JSON prove flutter gen-l10n will succeed?
No. The generator also interprets message expressions, metadata and project configuration. Validate in the actual SDK before claiming generation success.
What should we send first for a quotation?
Send representative ARB, source revision, screenshots, SDK information and required languages. Explain whether the scope includes generation review and testing in the application.
Sources and methodology
Official ARB and Flutter documentation was checked on 4 October 2026. The resource pair, Dart example and review matrices are original constructions. JSON parsing and metadata comparisons can be verified locally; no Flutter SDK generation, Dart analysis, device rendering or production app test was performed for this article. Migration documentation is read in its release context, not treated as a permanent configuration prescription.
References
[1] Google app-resource-bundle project. Application Resource Bundle Specification.
[2] Flutter API documentation. GlobalMaterialLocalizations class.
[3] Flutter documentation. Internationalizing Flutter apps.
[4] Flutter breaking-change documentation. Localized messages are generated into source, not a synthetic package.
Related guides
- How to Localize a Mobile App for Vietnam
- XLIFF vs JSON vs PO vs ARB: Localization File Formats Compared
- JSON Localization Guide: Strings, Variables and Common Mistakes
- XLIFF Localization Guide for Developers and Localization Managers
- GNU PO Localization Guide: msgid, msgstr, Plurals and Context
- Vietnamese Localization Style Guide for Software and SaaS
