💡 Flutter adds Vietnamese in under two hours: add
flutter_localizationsandintl: any, createlib/l10n/app_vi.arb, declareLocale('vi'), and runflutter gen-l10n. Vietnamese nouns never inflect for number, so a singleother{...}category usually covers all counts. Format VND withdecimalDigits: 0and usedd/MM/yyyyfor dates.
Key takeaways
- Add
flutter_localizations(Flutter SDK) andintl: anytopubspec.yaml; setgenerate: trueand createl10n.yamlat project root. - Create
lib/l10n/app_vi.arbwith the same ICU message keys as your English template - only the string values change. - Vietnamese has two CLDR plural categories (
onefor n=0 or n=1,otherfor n≥2), but nouns never inflect:=0{...}plusother{...}is usually enough. - VND currency: use
NumberFormat.currency(locale: 'vi_VN', symbol: '₫', decimalDigits: 0)- no decimal places, period as thousands separator. - Date format is day-first:
DateFormat('dd/MM/yyyy', 'vi_VN'). Test on a device set to Vietnamese before submitting to the app stores.
How do you add Vietnamese to Flutter's gen-l10n pipeline?
Flutter's official i18n solution uses ARB (Application Resource Bundle) files processed by the gen-l10n tool. Setup involves three files: updated dependencies, a config file, and a locale declaration in MaterialApp.
In pubspec.yaml, add flutter_localizations from the Flutter SDK, intl: any, and set generate: true under the flutter: key. Then create l10n.yaml at the project root:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
In your MaterialApp, pass AppLocalizations.delegate and ...GlobalMaterialLocalizations.delegates to localizationsDelegates. Add Locale('vi') to supportedLocales. Run flutter gen-l10n to produce the typed Dart class. The class is regenerated on every flutter pub get as long as generate: true is set.
What does app_vi.arb look like?
The ARB file is JSON where every key maps to an ICU message string. Vietnamese keys mirror the English template exactly - only the content changes. Here is a minimal example covering a plain string, a placeholder, and a plural:
{
"appTitle": "Ứng dụng của tôi",
"greeting": "Xin chào, {name}!",
"@greeting": {
"placeholders": {
"name": { "type": "String" }
}
},
"itemCount": "{count, plural, =0{Không có mục nào} other{{count} mục}}"
}
Descriptive @key metadata from the English template is optional in translation ARBs. Include @key objects only when you need to define new placeholders or add locale-specific notes.
Store ARB files in UTF-8 without BOM. Vietnamese diacritics must be real Unicode code points, not escape sequences. Most editors handle this automatically, but verify if your CI pipeline runs on Windows and touches these files.
How do plural rules work for Vietnamese?
The Unicode CLDR plural rules define two cardinal categories for Vietnamese: one (when n = 0 or n = 1) and other (n ≥ 2). Unlike English, Vietnamese nouns carry no singular or plural inflection. "1 cuốn sách" and "5 cuốn sách" use the same word "sách" (book). The noun form never changes based on count.
This simplifies ARB strings considerably. For most UI copy, a single other{...} branch suffices with an explicit =0{...} match for the empty state:
"cartItems": "{count, plural, =0{Giỏ hàng trống} other{{count} sản phẩm}}"
You do not need a one{...} branch to handle "1 item" vs "2 items" as in English. This reduces Vietnamese ARB maintenance by roughly one third compared to inflected languages like French or German.
Classifier words (cái, con, chiếc, cuốn, tờ) pair with specific noun categories in Vietnamese. A machine-translation tool will sometimes pick the wrong classifier - "con" is for animals, "cái" for objects. This is one place where automated checks miss errors that a native reviewer catches immediately.
Number, currency, and date formatting for Vietnamese
Vietnam's currency (₫, ISO code VND) has no sub-units. All prices are whole numbers. Showing "1.250.000,00 ₫" is incorrect and will confuse Vietnamese buyers at checkout.
Vietnamese number formatting follows the convention inherited from French: a period (.) groups thousands and a comma (,) marks the decimal point - the reverse of US English. Use Dart's intl package and pass decimalDigits: 0 explicitly:
import 'package:intl/intl.dart';
final vndFormat = NumberFormat.currency(
locale: 'vi_VN',
symbol: '₫',
decimalDigits: 0,
);
print(vndFormat.format(1250000)); // "1.250.000 ₫"
Without decimalDigits: 0, the formatter defaults to two decimal places for currency types, producing the incorrect "1.250.000,00 ₫".
Vietnamese date order is little-endian: day, then month, then year. October 11, 2026 is "11/10/2026". A user who sees "10/11" reads November 10, not October 11. Use DateFormat('dd/MM/yyyy', 'vi_VN'). For full written dates, the CLDR pattern produces "Chủ Nhật, 11 tháng 10, 2026". Vietnamese business contexts use 24-hour time: use DateFormat('HH:mm', 'vi_VN') rather than jm to avoid 12-hour output on some devices.
Why do Vietnamese strings run longer than English on screen?
Vietnamese uses stacked diacritics. A single character like "ộ" (o + circumflex + dot below) renders visibly wider than a plain ASCII letter in most system fonts. Vietnamese strings typically need 20-30% more horizontal space than their English equivalents. "Add to cart" (11 characters) becomes "Thêm vào giỏ hàng" (18 characters with diacritics).
Build layouts with flexible constraints. Use Expanded, FittedBox, or percentage-based widths for buttons, chips, and tab labels rather than hard-coded pixel values. The flutter_localizations package provides Vietnamese translations for built-in Material widget strings such as "OK", "Hủy" (Cancel), and date picker headers.
Test your app with the device locale set to Vietnamese before submitting to Google Play or the App Store. DataReportal's 2025 Vietnam report counts 127 million mobile connections across 101 million people. Meeting users' expectations on first launch determines whether they stay or uninstall.
What you can do in-house vs when a native Vietnamese reviewer pays off
The technical pipeline - ARB files, gen-l10n, number and date formatting - is entirely within a developer's reach and takes a few hours to wire up. The resulting strings will be syntactically valid and structurally correct.
Where non-native Vietnamese translation typically falls short:
- Register mismatch: B2B software uses Sino-Vietnamese (Hán Việt) vocabulary; consumer apps use everyday Vietnamese. A fintech dashboard that mixes the two feels inconsistent to native speakers.
- Classifier errors: Vietnamese uses noun classifiers (cái, con, chiếc, cuốn) that vary by object category. Machine translation picks the wrong classifier often enough to be noticed immediately by Vietnamese users.
- UI edge-case phrasing: Error messages, empty states, and confirmation dialogs need natural Vietnamese. Awkward phrasing damages user trust at the worst point in the flow.
A single review pass by a native Vietnamese localization specialist after a machine-translation first pass catches most of these issues at a fraction of full translation cost. For fintech, medical, or legal apps, build a terminology glossary before the first translation pass to keep register consistent across all screens.
FAQ
Does Flutter ship Vietnamese translations for Material widgets out of the box?
Yes. Adding GlobalMaterialLocalizations.delegate and GlobalCupertinoLocalizations.delegate to localizationsDelegates gives you Vietnamese strings for the date picker, back button, alert dialog buttons, and similar standard widgets. You still supply translations for your own app strings via ARB files.
Can I omit a key from app_vi.arb if the Vietnamese string is identical to English?
Yes. If a string such as a brand name or technical term is unchanged in Vietnamese, omit it from app_vi.arb and Flutter falls back to the template locale value. Add a note in the English @key description to flag intentional non-translations for future reviewers.
What font works best for Vietnamese diacritics in Flutter?
Noto Sans is the most reliable choice. Its Vietnamese coverage includes all 134 precomposed diacritic combinations. Add it via the google_fonts package and use GoogleFonts.notoSans(). If you bundle a custom font, test every tone-mark combination: ắ ặ ể ị ộ ụ ướ ự - these are most likely to render as boxes with incomplete font subsets.
How do I test Vietnamese locale in the simulator without changing system language?
Wrap MaterialApp in a Localizations.override during development: Localizations.override(context: context, locale: const Locale('vi'), child: MaterialApp(...)). This forces Vietnamese for the wrapped subtree without changing the device language. Remove the wrapper before releasing to production.
When should I use a human Vietnamese translator instead of machine translation for ARB files?
Use human translation when the app handles money, medical data, legal terms, or sensitive user data - incorrect phrasing in these areas carries trust and legal risk. For general consumer apps, a machine-translation first pass with a native Vietnamese review pass is cost-effective. Budget 15-20 minutes per screen of UI strings for a human reviewer.
Official Sources
- Flutter Internationalization documentation - gen-l10n pipeline, ARB format, supportedLocales setup. Verified Nov 2026.
- Unicode CLDR Plural Rules - Vietnamese plural categories: one (n=0 or n=1) and other. Verified Nov 2026.
- DataReportal Digital 2025: Vietnam - 127 million mobile connections, 79.8 million internet users. Verified Nov 2026.

Written by Dao Huy (Lucas), Vietnamese translator and localization specialist (English, Chinese and French into Vietnamese). See translation services →
