PHP 多國語系製作 i18n library 筆記 (一),相信大家使用上沒有任何問題, 但是一定會有共同疑問,那就是可不可以做到根據偵測瀏覽器來決定預設載入語系,也就是說 load method 只需要帶入第一個參數即可。
$lang = new Language(); $lang->load("about"); echo $lang->line("index") . "\n";
我們可以透過
$_SERVER[‘HTTP_ACCEPT_LANGUAGE’] 來取得瀏覽器語系資料,底下先來看 $_SERVER[‘HTTP_ACCEPT_LANGUAGE’] 輸出什麼資訊,以英文版 FireFox 為例
en-us,en;q=0.5我們只需要 en-us 字串,所以寫一個 \_default\_lang method 來處理
private function _default_lang() { $browser_lang = !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? strtolower(strtok(strip_tags($_SERVER['HTTP_ACCEPT_LANGUAGE']), ',')) : ''; return (!empty($browser_lang) and array_key_exists($browser_lang, $this->_language_list)) ? strtolower($browser_lang) : 'en-us'; }拿到 en-us 字串後,該如何對應到 language/english 目錄呢,那就是需要一個陣列對照表
$this->language_list = array( 'en-us' => 'english', 'zh-tw' => 'zh-tw' );並且將 load method 部份改寫
public function load($langfile = '', $idiom = 'english') { // 省略幾千行程式碼 ...... if ($idiom == '') { $deft_lang = $this->language_list[$this->__default_lang()]; $idiom = ($deft_lang == '') ? 'english' : $deft_lang; } // 省略幾千行程式碼 ...... }寫到這裡,我相信讀者又會出現一個疑問,那就是該如何切換語系呢?大部份都是透過 $_GET['lang'] 變數修改,並且將定存放在 session,接著看如何寫這段程式碼
private function _set_language() { $lang = (isset($_GET['lang'])) ? strtolower($_GET['lang']) : (isset($_GET['lang'])) ? strtolower($_GET['lang']) : ""; if ($lang != '') { // check lang is exist in group if (array_key_exists($lang, $this->language_list)) { $_SESSION['lang'] = $lang; } } // set default browser language if (!isset($_SESSION['lang'])) { $_SESSION['lang'] = $this->_default_lang(); } $this->language_folder = $this->language_list[$_SESSION['lang']]; return $this; }load method 改成底下
public function load($langfile = '', $idiom = '') { $this->_set_language(); // 省略幾千行程式碼 ...... if ($idiom == '') { $deft_lang = $this->language_folder; $idiom = ($deft_lang == '') ? 'english' : $deft_lang; } // 省略幾千行程式碼 ...... }index.php 測試程式請改成
load("about"); echo "上面程式碼已經完成一個簡單的多國語系雛型,這裏面會有一個小 bug,那就是假如兩個檔案 a.php 跟 b.php 語系檔裏面都包含Index value
"; echo "" . $lang->line("index") . "
"; echo " Chinese | English
";
$lang['index'] = "xxxx";這樣就會衝突,為了解決此問題,將架構改成
# load a 時 $this->load("a") # load a 語系 $this->line("a.index") # load a 時 $this->load("b") # load a 語系 $this->line("b.index")這時我們必須增加每個語系的 prefix
private function _set_prefix($lang = array()) { $output = array(); foreach ($lang as $key => $val) { $key = $this->language_prefix . "." . $key; $output[$key] = $val; } return $output; }load method 改寫
public function load($langfile = '', $idiom = '') { $this->_set_language(); $langfile = str_replace('.php', '', $langfile); // set prefix name $this->language_prefix = $langfile; // 省略幾千行程式碼 ...... // add prefix value of array key $lang = $this->_set_prefix($lang); $this->language = array_merge($this->language, $lang); unset($lang); return TRUE; }多國語系就介紹到這裡了,如可以到
php-i18n @ githib 參考程式碼,至於 CodeIgniter 可以參考 CodeIgniter-i18n @ github
See also
- 來聊聊 PHP & JavaScript & CSS 的 Coding Style
- 為什麼我選擇使用 Laravel Framework?
- Laravel 搭配 Google, Facebook, Twitter 第三方 OAuth 認證
- 將 wordpress 強制使用 SSL 連線
- PHP 7 vs HHVM Benchmark 比較
- Laravel 50 個小技巧 + Laravel 5.2 新功能
- Laravel Homestead 支援 MySQL 5.7 和 Node 5.0
- PHP-FIG 新網站
- Laravel Homestead 支援 PHP 7
- Laravel 5.1 is released