Translate a Django app into Simplified Chinese
Generate locale/zh_Hans/LC_MESSAGES/django.po with makemessages and upload it to Manuce. You get the same file back with the msgstr entries filled in Simplified Chinese, placeholders and tags checked, ready for compilemessages. Anything outside the .po, such as fonts, language settings and database content, remains on your side.
What it costs
For the language files of a Django app totalling about 3,000 words, into Chinese (Simplified):
To understand, internal use.
Ready to send, by the technical specialist.
Cross-checked. For documents that commit you.
Price for one language, original layout included. VAT not applicable — article 293 B of the French General Tax Code (CGI). The exact quote, based on your file's word count, is shown before you pay.
zh_Hans, zh-hans, zh-CN: getting the locale name right
Django identifies Simplified Chinese as zh-hans in LANGUAGES and LANGUAGE_CODE, and as zh_Hans for the locale directory. Running django-admin makemessages -l zh_Hans therefore creates locale/zh_Hans/LC_MESSAGES/django.po. Avoid the legacy zh_CN and zh-cn: with LocaleMiddleware enabled, Django maps a browser announcing zh-CN to zh-hans anyway.
Traditional Chinese (zh_Hant, Taiwan and Hong Kong) is a separate language at Manuce and a separate file in your project. Characters and sometimes vocabulary differ: 'software' is 软件 in mainland usage and 軟體 in Taiwan. Ordering both counts as two languages, which brings a 20% discount on the whole order.
Check the file header as well. Chinese has a single plural category ('other'), so the header should read Plural-Forms: nplurals=1; plural=0;. A .po copied from another locale often still says nplurals=2. Since Manuce only changes values, the header you upload is the one compilemessages will read.
What Chinese changes in your msgstr values
A few rules you will see in the returned file, and should know when reviewing it:
- Full-width punctuation.
"Saved."becomes"已保存。"and"Email:"becomes"邮箱:", with no surrounding spaces. A template that appends its own colon after a label will drop a Latin colon into Chinese text. - No spaces between words. Strings assembled in code, such as
_("Delete") + " " + name, leave a stray space. Use one string with a placeholder instead:_("Delete %(name)s?"), rendered as"删除 %(name)s?". - Word order.
"Welcome back, %(name)s"may become"%(name)s,欢迎回来". Named placeholders can move freely; two anonymous%slock the order and the sentence reads awkwardly. - One plural form. For
ngettext("%(count)s file", "%(count)s files", n)there is onlymsgstr[0]:"%(count)s 个文件", with the measure word 个 between number and noun. - Ambiguity. 'Open' may be 打开 (open a file) or 营业中 (shop open). A
pgettext("store status", "Open")call or a#. Translators:comment puts the meaning in the file. - Register. 您 is polite, 你 more direct; decide which suits your users and check it on the free extract.
Chinese needs two to three times fewer characters than English, but each character is wider, so a button takes roughly the same space.
What Manuce returns, and what it does not do
You upload django.po; you get the same file back, in the same format, ready to drop into locale/zh_Hans/LC_MESSAGES/ and recompile with compilemessages. Indentation, entry order, quotes, comments, line endings, encoding and BOM are preserved: only the values change. The msgid strings stay untouched, as they are the keys Django looks up.
%(name)sand{name}placeholders are checked: every Chinese value is compared with the source, placeholders and tags included.- If a mismatch persists, the source value is kept and the report says so, so the string stays in its original language rather than breaking formatting at render time.
- Not translated: keys, empty values, URLs, email addresses, numbers, colours, date formats, identifiers and anything marked as non-translatable.
- The report lists translated strings and those left unchanged, with the reason.
What Manuce does not do: run makemessages or compilemessages, or edit settings.py, your templates or your CSS. It does not translate what is not in the file, such as content stored in the database through the admin. Displayed dates like 2024年5月3日 come from Django's locale formats, not from the .po. Manuce does not produce certified (sworn) translations either; if your Chinese terms of service need one, use an accredited translator.
Chinese carries a surcharge (×1.6 on the per-word rate); pricing counts the words in the values, excluding keys and tags.
Preparing the file and checking after compilemessages
- Use named placeholders whenever a string holds more than one variable; makemessages already warns about strings with several anonymous
%s. - Resolve entries flagged
#, fuzzybefore uploading: compilemessages skips them, and since comments are preserved, the flag will be too. - If your front-end JavaScript calls
gettext, those strings live indjangojs.po, a second file to upload. - After compiling, view the interface in
zh-hans. Check the font: a web font subset to Latin characters has no hanzi, so the browser falls back to a system font that may look out of place. Add a Chinese font to yourfont-familystack, for example"PingFang SC", "Microsoft YaHei", "Noto Sans SC". - Look at line breaks: Chinese can break between almost any two characters, but not before 。 or ,. A
word-breakrule tuned for English can produce odd wrapping. - Review screens where a placeholder meets Chinese text. Spacing between Latin digits and hanzi varies (
3 个文件or3个文件): pick one convention and keep to it.
In practice
- Add ('zh-hans', '简体中文') to LANGUAGES and run django-admin makemessages -l zh_Hans.
- Check the Plural-Forms header (nplurals=1), resolve fuzzy entries, then upload django.po.
- Read the free extract to confirm register (您 or 你) and terminology, then choose a level.
- Put the file back in locale/zh_Hans/LC_MESSAGES/, run compilemessages and read the report.
- Test the interface in zh-hans: font, line wrapping, full-width punctuation.
Frequently asked questions
Should the locale folder be zh_Hans or zh_CN?
Use zh_Hans for the folder and zh-hans in LANGUAGES; these are the names Django recognises for Simplified Chinese. zh_CN is a legacy name. With LocaleMiddleware, browsers sending zh-CN are matched to zh-hans.
How are my ngettext plurals handled?
Chinese has one form, so each plural entry only needs msgstr[0], for instance '%(count)s 个文件'. Make sure the header reads nplurals=1; plural=0;, because Manuce only changes values and leaves the header as you uploaded it.
What happens if a placeholder goes missing in translation?
Each translated value is compared with the source, placeholders and tags included. If the mismatch persists, the source value is kept and the report flags it. That way the page renders instead of raising a formatting error.
Is Traditional Chinese included?
No. Traditional Chinese (Taiwan, Hong Kong) is a separate language at Manuce and a separate zh_Hant folder in Django. Ordering both counts as two languages, with a 20% discount on the whole order.
Will content stored in my database be translated?
No. Manuce translates the file you upload, and text entered through the admin and stored in the database is not in django.po. That content has to be exported separately or handled with a model translation solution.
The specialist in charge
This subject goes to Dédale, the technical specialist. See how it works.
The same file, into another language
Into Chinese (Simplified), other files
See also
Try it on your own file, free
A sample of your file translated at the level you choose, before any payment. You judge, then you decide.