【更新】【PHP】Gettext 實作多國語言網站 (I18N)

2018-03-28 |

本篇文章將教您如何編寫 PHP 製作多國語言網站

在文章開始前我們先了解一下什麼是 Gettext,Gettext 是 GNU國際化與在地化(i18n)函式庫,它常被用於編寫多語言程式。
Gettext 使用其中的字串尋找對應的其他語言翻譯,若沒有可用翻譯則返回原始內容。

除 PHP 外,GNU gettext 還支援 C 語言、C++、Objective-C、Pascal/Object Pascal、sh 指令碼、bash 指令碼、Python、GNU CLISP、Emacs Lisp、librep、GNU Smalltalk、Java、GNU awk、wxWidgets (通過 wxLocale 類)、YCP (YaST2語言)、Tcl、Perl、Pike、Ruby 以及 R,用法均與在 PHP 上類似。

我們先來建立目錄結構,首先在網站根目錄創建 languages 資料夾,然後再 languages 資料夾內分別創建 en_USzh_CNzh_TW 這三個資料夾 (這三個資料夾代表的是語系,你也可以自由新增刪除,但在後續需要改程式),在這三個資料夾內創建 LC_MESSAGES 資料夾 (用來丟語言檔的資料夾),結構就完成了。

接下來來說明程式碼部分,首先先在網站根目錄創建 index.php,程式碼內容如下

<?php
/*
 * 張文相 Zhang Wenxiang - 個人 Blog
 * https://blog.reh.tw/
 *
 * 範例教學
 * https://blog.reh.tw/gettext-multi-language-website/
 */
include_once("languages/languages.php"); //引入語言設定文件
?>
<html>
<head>
    <title><?php echo _('Gettext Multi-language website demo'); ?></title>
</head>
<body>
    <h1><?php echo _('Gettext Multi-language website demo'); ?></h1>
    <hr><br>
    <p><font color="#ff0000"><?php echo _('Hello world'); ?></font></p>
    <br>
    <h3><?php echo _('language selection'); ?></h3>
    <a href="setlang.php?lang=zh_TW"><?php echo _('Traditional Chinese'); ?></a> <a href="setlang.php?lang=zh_CN"><?php echo _('Simplified Chinese'); ?></a> <a href="setlang.php?lang=en_US"><?php echo _('English'); ?></a>
    <br><br>
    $_COOKIE["lang"]: <font color="#ff0000"><?php echo $_COOKIE["lang"]; ?></font>
    <br><br><br><hr>
    <a href="https://blog.reh.tw/gettext-multi-language-website/" target="_blank">https://blog.reh.tw/gettext-multi-language-website/</a>
</body>
</html>

程式碼重點部分我特別標註起來,第 9 行為引入語言設定文件,後面或說明,在 13、16、18、20、21 行有一段程式碼為 <?php echo _('內容文字 (請輸入英文)'); ?>,這是要套用語言檔的字串,原本 PHP 輸出字串使用 <?php echo "Test"; ?>,我們修改成 <?php echo _('Test'); ?>,這樣才會判斷為語言字串!

接下來在同一個資料夾內創建 setlang.php,程式碼內容如下

<?php
/*
 * 張文相 Zhang Wenxiang - 個人 Blog
 * https://blog.reh.tw/
 *
 * 範例教學
 * https://blog.reh.tw/gettext-multi-language-website/
 */
$lang = $_GET["lang"]; //取得 lang 參數

if ($lang == null) { //如果網址的 lang 參數為空
    //header('Location: '.getenv("HTTP_REFERER")); //返回原頁面
    echo '$_GET["lang"] is null.';
    exit;
}

if ($lang == "en_US") { //English
    setcookie("lang", "en_US", time() + (86400 * 30), "/"); //設定 Cookie lang 為 en_US
    header('Location: '.getenv("HTTP_REFERER")); //返回原頁面
}
if ($lang == "zh_TW") { //正體中文 (台灣)
    setcookie("lang", "zh_TW", time() + (86400 * 30), "/"); //設定 Cookie lang 為 zh_TW
    header('Location: '.getenv("HTTP_REFERER")); //返回原頁面
}
if ($lang == "zh_CN") { //简体中文 (中国)
    setcookie("lang", "zh_CN", time() + (86400 * 30), "/"); //設定 Cookie lang 為 zh_CN
    header('Location: '.getenv("HTTP_REFERER")); //返回原頁面
}
?>

這檔案是在處理設定 Cookie 的,當使用者點擊英文語言時,連結為 <a href="setlang.php?lang=en_US"><?php echo _('English'); ?></a> (可以看看上一個 index.php 程式碼),你會發現路徑是 setlang.php 帶參數 ?lang=en_US,進到此頁面後就會設定 Cookie langen_US,然後返回原頁面,上方程式碼都有註解。

接下來在 languages 資料夾內創建 languages.php,程式碼內容如下

<?php
/*
 * 張文相 Zhang Wenxiang - 個人 Blog
 * https://blog.reh.tw/
 *
 * 範例教學
 * https://blog.reh.tw/gettext-multi-language-website/
 */
preg_match("/^([a-z\-]+)/i", $_SERVER["HTTP_ACCEPT_LANGUAGE"], $matches); //分析 HTTP_ACCEPT_LANGUAGE 的屬性
$lang = $matches[1]; //取第一語言設置

//默認語言 & 類型
putenv("LANG=en_US");
setlocale(LC_ALL, $lang);

$lang = isset($_COOKIE["lang"]) ? $_COOKIE["lang"] : $lang;
$lang = strtolower($lang); //轉換為小寫
if ($lang == "en-us" || $lang == "en_us") { //English
    putenv("LANG=en_US");
    setlocale(LC_ALL, "en_US");
}
if ($lang == "zh-tw" || $lang == "zh_tw") { //正體中文 (台灣)
    putenv("LANG=zh_TW");
    setlocale(LC_ALL, "zh_TW");
}
if ($lang == "zh-cn" || $lang == "zh_cn") { //简体中文 (中国)
    putenv("LANG=zh_CN");
    setlocale(LC_ALL, "zh_CN");
}

define('PACKAGE', 'demo'); //demo 語言檔案名稱,可自行修改

//gettext 設定
bindtextdomain(PACKAGE, 'languages'); // or $your_path/languages, ex: /var/www/test/languages
textdomain(PACKAGE);
bind_textdomain_codeset(PACKAGE, "utf-8");
?>

這檔案就是剛剛在 index.php 所提到的語言設定文件,在此程式碼標註的地方就是用來判斷語言並設定的。
第 9、10 行程式碼是用來分析使用者語系。
第 13、14 行是設定默認語言,就是當翻譯檔並沒有使用者的語系時就顯示默認語言。
第 16 行是當網址有帶語系參數時就抓取,否則就使用第 6、8 行分析出來的使用者語系。
第 17 行的 strtolower() 是 PHP 中用來將任何英文轉成小寫字母,如果不轉換可能會發生判斷錯誤,因為每個瀏覽器的值都不太一樣。
第 31 行 define('PACKAGE', 'demo'); 中的 demo 是語言檔檔名,可自行修改 (demo.podemo.mo),.po 檔是人工翻譯檔.po 檔編譯會輸出 .mo 檔,是給系統讀的

接下來開始教如何快速替網站生成翻譯模板 (.pot 檔),首先我們先去下載 Poedit 這軟體,開啟後介面如下

點擊軟體左上方檔案 > 新增

譯文的語言輸入 en_US,然後按下確定

確定後先點擊軟體左上方的儲存,然後檔名輸入你在程式碼 define(‘PACKAGE’, ‘demo’); 所設定的名稱,副檔名改為 .pot (如果不做這一步會無法繼續)。

點擊從來源更新

點擊路徑方框下方的 +,在點擊加入資料夾

選擇網站的專案目錄,選擇完畢後按下確定

字串都抓取出來了,一樣按下左上方儲存,然後刪除儲存產生的 .mo 文件。

這樣翻譯模板就生成完成了!

接下來要建立翻譯語言檔,打開翻譯模板後點擊下方建立新翻譯 (這邊以新增正體中文 zh_TW 為範例)

按下確定後就可開始翻譯

翻譯完畢後按下左上儲存,然後選擇翻譯語言的目錄 (我們是以 zh_TW 作範例,路徑為 /languages/zh_TW/LC_MESSAGES/),記得存檔時檔名要更改為你在 define(‘PACKAGE’, ‘demo’); 所設定的名稱,副檔名不用改

然後軟體就會自動生成 .mo 文件了!

這樣就完成多國語言網站了OUO


文長懶得看或看不懂嗎? 沒關西,我爬文時也常常很懶,我個人是比較喜歡直接看專案學習的,我有把專案丟上 GitHub,也寫了一個範例網頁,在此附上連結XDDD

GitHub
https://github.com/GoneTone/Gettext-Multi-language-website-demo

範例網頁
https://demo.reh.tw/gettext/


【更新】【PHP】Gettext 實作多國語言網站 (I18N) - QR Code
本站內容未經授權許可請勿擅自抄襲
如果需引用部分文章內容請註明來源網址

發表時間:2018-03-28 18:08:23
此文章網址:https://blog.reh.tw/archives/158
關於作者
張文相 Zhang Wenxiang 的頭像

張文相 Zhang Wenxiang

我是本站的站長,喜歡 Coding 的一位學生。

張文相 Zhang Wenxiang

我是本站的站長,喜歡 Coding 的一位學生。


分類:教學 程式
標籤:Gettext I18N PHP Poedit 多國語言



Facebook 留言