其實照著官方文件一步一步做不會有什麼問題,只是沒想到….
本文 Django 對應 2 版
- 首先照著以下標準步驟設定 Settings:
# 不用解釋
USE_I18N = True# 非必要、預設網站語言
LANGUAGE_CODE = 'zh-hant'# 非必要、方便做語言選單用的
from django.utils.translation import gettext_lazy as _
LANGUAGES = (
('en', _('English')),
('zh-hans', _('Simplified Chinese')),
('zh-hant', _('Traditional Chinese')),
)# 設定我們的語言檔案所放的路徑
# 此例採用 Two Scoops 的結構, locale 放在:
# {專案路徑}/locale
# 因設定檔路徑如下,所以 -3 將設定檔路徑前移為 {專案路徑}/ 作為 ROOT_DIR
# {專案路徑}/config/settings/{設定檔}.py
ROOT_DIR = environ.Path(__file__) - 3
LOCALE_PATHS = (
os.path.join(ROOT_DIR, 'locale'),
)# 加入 LocaleMiddleware 至 SessionMiddleware 與 CommonMiddleware 之間
MIDDLEWARE = [
# 其他 ...
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
# 其他 ...
]# Templates 設定中加上 i18n 的 context processors
TEMPLATES = [
{
# 其他 ...
'OPTIONS': {
'context_processors': [
# 其他 ...
'django.template.context_processors.i18n',
],
},
},
]
2. 接著我們利用 Django 整合好 GNU gettext 的命令列工具,將專案中標註為須翻譯的字串轉出至 PO 檔格式:
django-admin makemessages -l en
django-admin makemessages -l zh_Hans
django-admin makemessages -l zh_Hant
# 初始化,以後用 django-admin makemessages 即可更新
# JS 的部分則須指定 domain 用 django-admin makemessages -d djangojs
原始碼中標註方式如
gettext(), gettext_lazy(), {% trans "mystr"%}
等超出本文範圍,請參照 官方文件關於 gettext:
● Windows 上需 安裝編譯好的 gettext
● OSX 上安裝指令brew link gettext --force
3. 翻譯轉出的 PO 檔內容,如 locale/zh_Hant/LC_MESSAGES/django.po
#: .\my_project\supplier\models.py:115
msgid "supplier"
msgstr "供應商"
4. 將 PO檔編譯成高效的 MO 二進位檔案。
django-admin compilemessages
5. 其他課題如【用 session 切換語言】【用 cookie 儲存使用者選擇的語言】【翻譯前端 Javascript code】【多語URL的處理】就不再此詳述,教學非本篇重點。
😵😵問題來了,Language Code 明明是zh-hant
和 zh-hans
,為啥資料夾要用zh_Hant
和zh_Hans
,Django 才能成功地找到翻譯檔?
魔鬼藏在細節裡
Django 的 i18n 直接套 python 使用的 GNU gettext 標準,其語言檔的目錄結構為: {設定路徑}/{語言碼}_{國碼}或{語言碼}/LC_MESSAGES/*.mo
例如 Django admin source code 中的 locale 結構:
華語國家、地域、文化傻傻分不清的特殊性/政治性,有許多約定成俗的名稱如 zh-TW
、zh-CN
、zh-HK
、zh-SG
等,如果不想細分,就如統一使用 zh-Hant
(繁/正體)、zh-Hans
(簡體) 兩者即可。
其行為如瀏覽器發出標頭: Accept-Language:zh-TW
Django 內部使用 fallback key 轉換 zh-tw
至 zh-hant
後回應:Content-Language:zh-Hant
也因採用 gettext 的目錄結構, Django 模組 translation.trans_real
會將破折號的分隔符號均被轉成底線,再傳給 gettext.translation()
作為找到 MO 檔路徑之一。
就因為這個不重造輪子的轉換過程,不明所以的整台車卡在坑裡 (茶~~~
2020/5/18 坑 2
若遭遇 JS Template literals 寫法 gettext()
抓不到翻譯 Key 時,請將 gettext 升級至 0.20.2 以後的版本 (bug #56678, Wrong behaviour of template strings)