xgettext:從原始碼萃取字串 → .pot(範本)msginit:依 .pot 建立語系 .po(翻譯檔)msgfmt:編譯 .po → .mo(二進位,給程式讀取)gettext / _():執行時翻譯<?php
// home.php
$str = _('home'); // 或 gettext('home')
echo "<a href='#'>{$str}</a>";
xgettext -a home.php -o home.pot
產生 home.pot,包含 msgid "home" 待翻譯。
export LANG=zh_TW.UTF-8
msginit -l zh_TW.UTF-8 -i home.pot
產生 zh_TW.po,編輯 msgstr "首頁"。
msgfmt zh_TW.po -o zh_TW.mo
mkdir -p locale/zh_TW/LC_MESSAGES
cp zh_TW.mo locale/zh_TW/LC_MESSAGES/home.mo
<?php
putenv('LANG=zh_TW.UTF-8');
setlocale(LC_ALL, 'zh_TW.UTF-8');
bindtextdomain('home', './locale'); // 指定 .mo 根目錄
textdomain('home'); // 設定預設域
echo _("home"); // 輸出:首頁
project/
├── home.php
├── locale/
│ ├── zh_TW/
│ │ └── LC_MESSAGES/
│ │ └── home.mo
│ ├── en_US/
│ │ └── LC_MESSAGES/
│ │ └── home.mo
│ └── ja_JP/
│ └── LC_MESSAGES/
│ └── home.mo
<?php
$lang = $_GET['lang'] ?? 'zh_TW';
putenv("LANG={$lang}");
setlocale(LC_ALL, $lang);
bindtextdomain('home', './locale');
textdomain('home');
| 問題 | 解決 |
|---|---|
| 翻譯不生效 | 檢查 setlocale 系統支援、.mo 路徑、textdomain 名稱 |
| 中文亂碼 | 確保 .po 為 UTF-8、PHP 檔案 UTF-8、bind_textdomain_codeset('home', 'UTF-8') |
| Apache 需重啟 | gettext 快取機制,修改 .mo 後需 apachectl graceful 或重啟 php-fpm |
| Windows 環境 | 需安裝 gettext 擴展,setlocale 行為不同 |
// .po
msgid "%d file"
msgid_plural "%d files"
msgstr[0] "%d 個檔案"
msgstr[1] "%d 個檔案" // 中文無複數變化
// PHP
echo ngettext("%d file", "%d files", $count);