Laravel localization in Vietnamese Tiếng Việt
Everything you need to ship Vietnamese in a Laravel app: the right locale codes,
the exact plural forms trans_choice() expects,
real localized Carbon output and Latin-script considerations.
Every value on this page was generated by running ICU, CLDR and Carbon — not copied from another article.
ISO 639-1
vi
Script / Direction
Latin · LTR
Plural forms (Laravel)
1
Text vs English
Expands
Locale codes
Set the base locale in config/app.php. For regional variants,
Vietnamese commonly uses:
vi_VN
// config/app.php
'locale' => 'vi',
'fallback_locale' => 'en',
// Or switch at runtime
App::setLocale('vi');
Plural rules: what Vietnamese actually needs
CLDR defines 1 cardinal category for Vietnamese. The sample numbers below were computed by ICU for this exact locale:
| CLDR category | Numbers that select it |
|---|---|
| other | 0–130, 200, 1000, 1000000, 1.5 |
Laravel's trans_choice() maps numbers to
1 pipe-separated
form for this locale:
| Form index | Numbers that select it |
|---|---|
| 0 | 0–130, 200, 1000 |
// lang/vi/messages.php
'items' => ':count'
// Usage
trans_choice('messages.items', $count, ['count' => $count]);
This language has no grammatical plural, so a single form covers every number.
Try any number live in the pluralization tester.
Localized dates with Carbon
Real output for Vietnamese (vi locale),
generated by Carbon for March 21, 2026:
$date = now()->locale('vi');
$date->translatedFormat('l, j F Y');
// "thứ bảy, 21 tháng 3 2026"
$date->isoFormat('LLLL');
// "thứ bảy, 21 tháng 3 năm 2026 14:30"
$date->isoFormat('L');
// "21/03/2026"
$date->subDays(3)->diffForHumans();
// "3 tháng trước"
What to watch out for in Vietnamese
- Latin script with stacked tone and vowel diacritics (ệ, ở, ữ); verify font support, as missing marks change meaning.
- No inflection: plurality, tense, and possession are expressed with separate words and classifiers.
- Pronouns depend on relative age and relationship; the neutral bạn is common in UI copy.
- Decimal comma with dot as thousands separator (1.234,56); dates are dd/mm/yyyy.
Diacritics that stack, and why they break normalisation
Vietnamese is written in the Latin alphabet, which makes it look approachable, and then attaches up to two marks to a single vowel: one modifying the vowel quality and one marking tone. The result is a character set far larger than any other Latin-script language.
| Character | Composition | Meaning of the word |
|---|---|---|
| ma | bare | ghost |
| má | acute tone | mother |
| mà | grave tone | but |
| mả | hook tone | grave |
| mã | tilde tone | horse |
| mạ | dot-below tone | rice seedling |
Every one of those is a different word. Stripping tone marks does not produce a less precise version of the text; it produces a different word or no word at all, so accent folding is acceptable for slugs and search normalisation and never for display.
The technical hazard is Unicode normalisation. Vietnamese characters exist in both precomposed form, as a single code point, and decomposed form, as a base vowel plus one or two combining marks. Both render identically and compare unequal, and different input methods, operating systems and applications favour different forms — macOS tends to produce decomposed text where Windows produces precomposed.
Normalise Vietnamese at the boundary
<?php
// Same visible word, different byte sequences
$a = "ti\u{1EBF}ng"; // precomposed
$b = "tie\u{0302}\u{0301}ng"; // decomposed
$a === $b; // false
Normalizer::normalize($a, Normalizer::FORM_C)
=== Normalizer::normalize($b, Normalizer::FORM_C); // true
Normalise to NFC on input and store the normalised form. Doing it later means a search index and a database holding two representations of the same word, which is very hard to reconcile once several years of records carry both.
Syllables are separate words
Vietnamese writes each syllable as a separate token with spaces between them, even when several syllables form one concept. Điện thoại (telephone) is two words in writing and one word in meaning; Việt Nam is two syllables.
This inverts the assumption behind most word-handling code. Splitting on whitespace does not give you words, it gives you syllables, so word counts are inflated, keyword extraction produces fragments, and truncating at a word boundary can cut a concept in half — leaving text that is grammatically valid and semantically wrong.
Line breaking is affected in the same way. A browser will happily break between the two syllables of a single concept because there is a space there, which reads as awkward rather than as broken but is worth avoiding in headings and short labels where it is most visible.
For search, this means bigram or phrase matching outperforms single-token matching by a wide margin, and most search engines ship a Vietnamese analyser that handles the compounding. Enabling it is a small change with a large effect on result quality.
No plurals, no tense, but classifiers everywhere
Vietnamese has a single CLDR plural category, so trans_choice() takes one form for every number. There is no verb conjugation, no grammatical gender and no obligatory tense marking, which removes most of the agreement problems that dominate European localisation.
One form for every count
// lang/vi/messages.php
'files' => ':count tệp',
// 0 -> 0 tệp
// 1 -> 1 tệp
// 42 -> 42 tệp
What replaces the complexity is classifiers. Vietnamese requires a measure word between a number and a noun, chosen by the nature of the thing counted, in the same way as Japanese and Korean counters.
| Classifier | Used for | Example |
|---|---|---|
| cái | Generic inanimate objects | 3 cái tệp |
| người | People | 3 người dùng |
| chiếc | Vehicles, single items of a pair | 3 chiếc máy |
| tấm | Flat things: images, cards | 3 tấm ảnh |
| lần | Occurrences, attempts | 3 lần thử |
So a generic counting string cannot be reused across contexts. Files, users, images and attempts each need their own key with the correct classifier, and a translator given one shared string has no way to satisfy all of them.
Pronouns encode the relationship, not just the person
Vietnamese has no neutral second-person pronoun equivalent to English you. The pronoun encodes the relative age, status and relationship between speaker and listener, drawing on kinship terms: anh for an older brother figure, chị for an older sister figure, em for a younger person, bạn for a peer.
This is a genuine problem for software, which does not know the user's age or gender and should not presume a relationship. The convention that has emerged is bạn — literally friend, functionally a neutral polite you — and it is what essentially all Vietnamese software uses. It is safe, and it is the right default.
For formal correspondence, quý khách (esteemed customer) serves where English would use a title plus surname. It carries no age or gender assumption and is standard in banking, e-commerce and customer service.
Vietnamese names are written family name first, followed by middle name and given name — Nguyễn Văn An has the surname Nguyễn. Crucially, Vietnamese people are addressed by their given name, not their family name, even in formal contexts, so a greeting constructed as title plus surname is doubly wrong: wrong order and wrong name.
Surnames are also drawn from a very small pool. Nguyễn alone accounts for roughly forty per cent of the population, so any logic treating a surname as distinguishing will collide constantly in search, deduplication and display.
Layout, input and formatting
Vietnamese expands around twenty to thirty per cent over English in character count, and the stacked diacritics need extra vertical space. Marks sit above and below the base letter, so a line height tuned for English will clip them — and clipped tone marks change the word rather than merely looking untidy.
Font choice matters more than in most Latin-script languages. Many fonts cover basic Latin plus a handful of accents and lack the doubly-marked Vietnamese characters, falling back to a different font for those glyphs. The result is text where a few letters are visibly a different typeface, which reads as broken.
Text entry usually goes through an input method such as Telex or VNI, which converts sequences of plain letters into accented characters as the user types. As with CJK input, JavaScript bound to every keystroke will fire on uncommitted intermediate text, so live search, character counters and inline validation must respect composition events.
| Vietnamese convention | |
|---|---|
| Thousands | 1.234.567 |
| Decimal | 1234,56 |
| Currency | 1.234.567 ₫ (after the amount) |
| Short date | 21/03/2026 |
| Long date | ngày 21 tháng 3 năm 2026 |
| First day of week | Monday |
Long dates are written out with the words for day, month and year rather than with month names, so tháng 3 is literally month 3. The đồng has no subunit and amounts run to six or seven digits for ordinary prices, so currency fields need considerably more width than a dollar design assumes.
Getting Vietnamese into the application
Vietnamese asks little of your grammar handling and a great deal of your text handling. The effort goes into normalisation, fonts and input rather than into string architecture, which is the opposite balance from the inflected European languages.
Normalise to NFC at every entry point and store the normalised form. Form submissions, CSV imports, API payloads and translation files all need it, because each source may favour a different composition. Applying it in only some places is worse than applying it nowhere, since it guarantees the same word exists in two forms in your data.
Ship a font that genuinely covers Vietnamese. Many popular webfonts advertise Latin Extended coverage and still lack the doubly-marked characters, so a few letters fall back to a system font. Test with a string exercising all six tones on several vowels rather than assuming coverage from the font's description, and subset carefully if you are trimming file size.
Give the text room vertically. Tone marks sit above the letter and some vowel modifiers sit below, so Vietnamese needs more line height than Latin text at the same size, and clipping is not cosmetic — a truncated mark changes the word. Test at your production line height rather than in a generous prototype.
Handle input-method composition in any field bound to keystroke events. Telex and VNI both build accented characters from sequences of plain letters, so a live search or a character counter reacting to input will fire on half-formed words. Bind to compositionend instead.
Finally, enable a Vietnamese analyser in your search engine. Syllable-level tokenisation combined with accent folding is what makes search behave the way users expect, and the default whitespace tokeniser produces poor results because it treats each syllable as an independent term.
What ships broken most often
- Mixed Unicode normalisation forms. Identical-looking text that compares unequal, splitting records and search results.
- Clipped tone marks. Latin line heights cutting the marks that distinguish one word from another.
- Font fallback for accented characters. A few letters rendering in a visibly different typeface.
- Word logic applied to syllables. Whitespace splitting producing fragments rather than words.
- A shared classifier across contexts. cái used for people, or người used for files.
- Greeting by surname. Vietnamese users are addressed by given name, and the surname comes first.
- Đồng shown with decimals, in narrow fields. Amounts are large and have no subunit.
Normalisation is the one to fix first, because it is the only item here that corrupts data rather than presentation. Normalise to NFC at every entry point — forms, imports, API payloads — and the rest of the list is presentation work that can be corrected at any time.
Vietnamese is otherwise one of the cheaper locales to support well. With no conjugation, no gender, no cases and a single plural form, the translation itself is straightforward and machine translation performs comparatively well, so the budget goes into a native review pass for classifiers and register rather than into wrestling with grammar.
Framework strings already translated
Laravel's own validation, auth and pagination strings are maintained in Vietnamese by the open-source Laravel-Lang project (MIT). Install them, then manage your app's own strings live:
composer require laravel-lang/common --dev
php artisan lang:add vi
php artisan lang:update
Translate your app into Vietnamese today
Import your lang files, translate every key into Vietnamese with one AI click, and publish changes live — no deploy. Set up in 5 minutes.