ARES資通電子報

技術交流

L10N with PHP(上)

文 -Dennis

引言
何謂 L10n?
開發人員把 Localization 簡寫成 L10N,中間的數字 10 是前後兩個字母 L 和 N 之間的字母個數。它允許開發人員寫一個簡單的文件,就可以將顯示的功能表和文本翻譯成本地語言。

為什麼要使用 L10N?
L10N 標準能夠很好地支援您查看、輸入或處理非英語語言。

本地化設置需要具備三個條件:
1) 語言代碼 ( Language Code)
2) 國家代碼 ( Country Code )
3) 編碼 ( Encoding )

本地名字可以用下面這些部分組成:
語言代碼_國家代碼.編碼。例如(zh_CN.UTF-8, en_US等)。

哪些軟體用到 gettext
1)
大名鼎鼎的個人 blog 系統 wordpress http://www.wordpress.org
2) Linux 系統上大部分應用軟體。

本文主要討論利用 PHP built-in 函數 gettext 來實現程式的本地化。本文假定編碼 ( encoding ) 都為 “utf-8”。

開始
自 PHP4 版本開始,PHP已經內建支援 gettext function了,不需要額外安裝。
直接打開 php.ini,找到 extension=php_gettext.dll 把前面的分號去掉,重啟 Apache Server。

Gettext 的實現方式
程式設計者在程式碼中寫入所要顯示的欄位的標籤或是相關 messages,在運行程式時並不會直接顯示程式設計師所寫的資訊,它會根據設定的語系去找對應語系的文字,如果沒有找到才會去顯示程式碼中的原本的語言。例如:程式設計者在源代碼裏使用的是繁體中文,如果系統在 run 的時候設定成簡體中文( zh_CN ) 語系,程式會自動到相關的目錄 ( local/zh_CN/LC_MESSAGES/ ) 中尋找簡體中文的語系,如果找不到就會顯示原來的繁體中文,而這一切我們只需要做簡單的設定即可,gettext 會自動幫我們完成這些瑣碎的工作。

Gettext 相關函數參考:
在 PHP gettext 中有以下幾個 functions:
bind_textdomain_codeset — Specify the character encoding in which the messages from the DOMAIN message catalog will be returned
bindtextdomain — Sets the path for a domain
dcgettext — Overrides the domain for a single lookup
dcngettext — Plural version of dcgettext
dgettext — Override the current domain
dngettext — Plural version of dgettext
gettext — Lookup a message in the current domain
ngettext — Plural version of gettext
textdomain — Sets the default domain
本文只涉及到 bintextdomain()、textdomain() 及 bind_text_domain_codeset() 這三個 functions,其他 functions 有興趣的朋友可以自行研究。

資料夾結構 (Directories Structure)
為了讓 gettext 自動選取設定的語系,資料夾的結構建議如下圖所示:

下面對圖上做簡單的說明:
Local: 自定義名稱,可以按喜好改成 languages 等等,代碼中做相應調整就可以了。
Local\en_US: 英文語系所在資料夾,也可改成自己喜歡的,但是推薦用標準的 language code。
Local\zh_CN: 簡體中文語系所在資料夾,也可改成自己喜歡的,但是推薦用標準的 language code。
LC_MESSAGES:固定名稱,請不要修改。
Messages.mo/po: 多語的檔案名稱,可以按自己的喜好來命名,程式代碼中要做相關調整. .po 可編輯,.mo 不可編輯。
     PHP 代碼實現
      在程式初始化時,初始化相關多語參數:
       1)語系代碼
       2).mo 檔案名稱
       3)多語文件所在資料夾
func.php
<?php
  /**
   * Init Local Language
   * 目錄結構必須是
   * xxx/local/zh_CN/LC_MESSAGES/messages.po/.mo
   * xxx/local/zh_TW/LC_MESSAGES/messages.po/.mo
   * @param string $lang_code 標準語言代碼,如: zh_TW, zh_CN
   * @param string $mo_filename mo 檔案名
   * @param string $localfile_url "local" 目錄所在的相對或是絕對路徑
   * @author Dennis 20090826
   * @return void
   */
   function _initLocal ($lang_code,$mo_filename,$localfile_url)
   {
      //設置目的語言
      putenv("LANG=$lang_code");
      setlocale(LC_ALL, $lang_code);
      //$package為 mo 文件的名字
      $package = $mo_filename;
      //綁定 mo 檔的路徑,
      bindtextdomain($package, $localfile_url);
      //設置搜索的 mo 檔的檔案名
      textdomain($package);
      //指定mo檔的返回到gettext的編碼
      bind_textdomain_codeset($package, 'UTF-8');
    }
     _initLocal('en_US','messages', '/ehr/local');
?>

多語在源代碼中的書寫方式
 源代碼中多語書寫方式的 sample:
 Test.php
 <?php
   include_once 'func.php';
   echo gettext ('資通電腦');
  ?>

  需要轉換的多語在源代碼中的寫法有多種形式,也可以寫全名 “gettext()” 也可以簡寫成 “_()”。
  如上面的代碼,也可以寫成如下:
  <?php
     include_once 'func.php';
    echo _('資通電腦');
   ?>

創建 .po 多語二進位檔
  編輯指令如下:
  xgettext -d [您定義的 PACKAGE 名稱] [程序文件名]

限於篇幅的關係,本期就先介紹到這。下期將於下集介紹有關 PHP L10N 的應用範例探討。敬請期待!

>>回電子報首頁