Laravel localization in Chinese (Simplified) 简体中文

Everything you need to ship Chinese (Simplified) in a Laravel app: the right locale codes, the exact plural forms trans_choice() expects, real localized Carbon output and Han (Simplified)-script considerations. Every value on this page was generated by running ICU, CLDR and Carbon — not copied from another article.

ISO 639-1

zh

Script / Direction

Han (Simplified) · LTR

Plural forms (Laravel)

1

Text vs English

Contracts

Locale codes

Set the base locale in config/app.php. For regional variants, Chinese (Simplified) commonly uses: zh_CN, zh_SG

// config/app.php
'locale' => 'zh',
'fallback_locale' => 'en',

// Or switch at runtime
App::setLocale('zh');

Plural rules: what Chinese (Simplified) actually needs

CLDR defines 1 cardinal category for Chinese (Simplified). 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/zh/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 Chinese (Simplified) (zh_CN locale), generated by Carbon for March 21, 2026:

$date = now()->locale('zh_CN');

$date->translatedFormat('l, j F Y');
// "星期六, 21 三月 2026"

$date->isoFormat('LLLL');
// "2026年3月21日星期六下午2点30分"

$date->isoFormat('L');
// "2026/03/21"

$date->subDays(3)->diffForHumans();
// "3个月前"

What to watch out for in Chinese (Simplified)

Simplified and Traditional are not a formatting switch

Chinese is written in two character sets. Simplified is used in mainland China and Singapore; Traditional is used in Taiwan, Hong Kong and Macau. Converting between them is not a character-for-character mapping, and treating it as one produces text that is recognisably machine-converted.

Several Simplified characters merge multiple Traditional ones, so the reverse conversion is ambiguous and needs context. The character 发 corresponds to both 發 (to send) and 髮 (hair), and 干 covers 乾, 幹 and 干. A one-to-one table gets these wrong at a predictable rate.

Vocabulary diverges as well, particularly in technology, which is exactly the domain your interface occupies.

English Mainland (zh-Hans) Taiwan (zh-Hant-TW)
software 软件 軟體
network 网络 網路
video 视频 影片
information 信息 資訊
mouse 鼠标 滑鼠

Note that the last two rows differ in word choice, not only in character form, so no script conversion produces them. Treat zh-Hans and zh-Hant as separate locales with separate translations, and be aware that Hong Kong Traditional differs from Taiwan Traditional in vocabulary again.

Use script subtags rather than country codes where you can. zh-Hans and zh-Hant describe what actually differs, while zh-CN and zh-TW conflate script with market and leave Singapore and Hong Kong ambiguous.

No spaces, no plurals, no inflection

Chinese is analytic and isolating: words do not inflect at all. There is no plural marking, no verb conjugation, no tense inflection, no gender and no case. CLDR gives Chinese a single plural category, so trans_choice() takes one form for every number.

One form for every count

// lang/zh_CN/messages.php
'files' => ':count 个文件',

// 0  -> 0 个文件
// 1  -> 1 个文件
// 42 -> 42 个文件

Measure words carry the load that inflection carries elsewhere. A number cannot attach directly to a noun; a classifier goes between them, chosen by the nature of the thing counted.

Classifier Used for Example
Generic default 3 个文件
People (respectful) 3 位用户
Flat things: images, cards 3 张图片
Long thin things, messages, records 3 条消息
Machines, devices 3 台设备
Occurrences, attempts 3 次尝试

个 is the general-purpose classifier and is acceptable in many contexts, which makes Chinese more forgiving here than Japanese or Korean. It is still noticeably wrong in some cases — 条 for messages and 张 for images are strongly expected — so a single shared counting string produces copy that reads as slightly off rather than as broken.

Chinese is written without spaces between words, so whitespace-based word counts, truncation and search tokenisation all fail in the same way as in Thai and Japanese. Search needs a Chinese analyser doing dictionary or n-gram segmentation; a whitespace tokeniser will index entire sentences as single terms.

Typography and layout

Chinese is the most compact language you are likely to support. Character counts run forty to sixty per cent below English, though each character occupies a full-width cell, so rendered width lands roughly at or below the English original. Overflow is rare and under-filled containers are the more common problem — a button sized for "Settings" looks empty holding 设置.

Vertical space is the constraint instead. Chinese characters are dense, with some containing more than twenty strokes in a single cell, and they become genuinely illegible at small sizes that work fine for Latin text. Set a minimum font size for Chinese rather than inheriting the Latin scale, and give generous line height.

Punctuation is full-width and distinct from the Latin equivalents. The Chinese comma is ,not ,; the full stop is 。not .; quotation marks are “ ” or 「 」. These are different code points and mixing Latin punctuation into Chinese text reads as careless, so any normalisation routine that converts punctuation must leave Chinese text alone.

Line breaking follows its own rules, since a break may occur between almost any two characters but must not leave certain punctuation at the start of a line. Browsers handle this correctly when the language is declared, so lang="zh-Hans" is doing real work rather than being metadata.

There is no bold or italic tradition in Chinese typography. Synthesised bold thickens strokes until dense characters become an unreadable blur, and synthesised italics look wrong. Use colour, size or a different weight of a font designed for it.

Input, sorting and names

Chinese text entry goes through an input method that converts pinyin or another phonetic input into characters, with the user choosing among candidates. Any JavaScript reacting to every keystroke will fire on the intermediate Latin text before conversion, so live search, character counters and inline validation must respect composition events.

Wait for the input method to commit

let composing = false

input.addEventListener('compositionstart', () => composing = true)
input.addEventListener('compositionend', () => {
  composing = false
  search(input.value)
})

input.addEventListener('input', () => {
  if (!composing) search(input.value)
})

Sorting has no single obvious answer. Chinese can be ordered by pinyin, by stroke count or by radical, and users expect different orders in different contexts — pinyin for name lists, stroke count for formal and official listings. Byte order is meaningless. Use a collator with an explicit ordering rather than accepting a default.

Names are written family name first with no space: 王小明 has the surname 王. Surnames are usually one character and given names one or two, and the pool of surnames is small enough that collisions are constant — a handful of surnames cover a very large share of the population.

Form design should account for that shape. A layout assuming a long given name and a distinguishing surname fits Chinese names poorly, and code assembling a display name given-first produces a name that reads as reversed.

Storage needs utf8mb4 without exception. Many Chinese characters, including ones used in personal names, sit outside the Basic Multilingual Plane, and MySQL's three-byte utf8 will reject or truncate them — affecting precisely the users whose names are unusual.

Formatting and the numbers that group in fours

Chinese groups large numbers in units of ten thousand rather than of a thousand. 万 is ten thousand and 亿 is a hundred million, so a Chinese reader parses 1,0000 as one 万 where a Western reader parses 10,000 as ten thousand.

Displayed digits generally still use Western three-digit grouping in software, so this rarely breaks formatting outright. It matters when numbers are written out or abbreviated: a summary showing 12.3万 is natural Chinese, while 123K is not, and a dashboard abbreviating large figures with K and M reads as untranslated.

Mainland convention
Thousands 1,234,567
Decimal 1234.56
Currency ¥1,234.56
Large numbers 12.3万 rather than 123K
Short date 2026/3/21 or 2026-03-21
Long date 2026年3月21日
First day of week Monday

Dates run largest unit first with the markers 年, 月 and 日, which aligns with ISO order and makes Chinese one of the least ambiguous locales for dates. Numbers otherwise follow English conventions, so there is no decimal-comma hazard.

Note that ¥ is ambiguous between the Chinese yuan and the Japanese yen. Where both currencies may appear, use the explicit codes CNY and JPY, or the Chinese-specific 元 marker, rather than relying on the shared symbol.

Practicalities of shipping into mainland China

Chinese localisation has an operational dimension that most locales do not, and it affects whether the translated product is usable at all rather than merely whether it reads well.

Third-party assets are the immediate issue. Google Fonts, Google-hosted script CDNs, and several common analytics and map providers are not reliably reachable from mainland China, so a page that renders instantly elsewhere may hang for seconds or fall back to system fonts. Self-host fonts and scripts, or serve them from a CDN with mainland presence, and verify from inside the network rather than assuming.

Web font size deserves separate thought. A Chinese font covering the common character set is measured in megabytes rather than kilobytes, since it needs thousands of glyphs rather than a hundred or so. Subsetting to the characters actually used in your interface is worthwhile, and for user-generated content a system font stack is usually the right choice — the platform fonts are good and already installed.

Phone numbers, addresses and identity formats differ enough to break validation written for Western markets. Chinese addresses run largest unit first — province, city, district, street — which is the reverse of a Western address form, and a form laid out in Western order confuses users even when every label is translated.

Finally, set the locale with a script subtag and store it that way. A user preference recorded as zh is ambiguous about script, and the ambiguity surfaces the first time you add Traditional — at which point every stored preference needs interpreting rather than reading.

What ships broken most often

The script decision is the one to make deliberately and early. Committing to Simplified alone is entirely reasonable for a mainland-focused product, but discovering later that Taiwan and Hong Kong need their own locales — with their own vocabulary rather than a converted script — is a translation project rather than a configuration change.

Framework strings already translated

Laravel's own validation, auth and pagination strings are maintained in Chinese (Simplified) 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 zh
php artisan lang:update

Translate your app into Chinese (Simplified) today

Import your lang files, translate every key into Chinese (Simplified) with one AI click, and publish changes live — no deploy. Set up in 5 minutes.

We use cookies to improve your experience and analyze site traffic. Cookie Policy

Cookie Preferences

Essential

Required for the site to work

Analytics

Help us improve the site

Marketing

Personalized ads and content