PHP 日本會議 2024

gettext

(PHP 4、PHP 5、PHP 7、PHP 8)

gettext在目前的網域中查閱訊息

描述

gettext(string $message): string

在目前的網域中查閱訊息。

參數

message

要翻譯的訊息。

傳回值

如果翻譯表中有找到,則傳回翻譯後的 string,如果找不到,則傳回提交的訊息。

範例

範例 1:gettext() 檢查

<?php
// 將語言設定為德文
putenv('LC_ALL=de_DE');
setlocale(LC_ALL, 'de_DE');

// 指定翻譯表的位置
bindtextdomain("myPHPApp", "./locale");

// 選擇網域
textdomain("myPHPApp");

// 現在會從 ./locale/de_DE/LC_MESSAGES/myPHPApp.mo 中尋找翻譯

// 列印測試訊息
echo gettext("Welcome to My PHP Application");

// 或使用別名 _() 表示 gettext()
echo _("Have a nice day");
?>

注意

注意:

您可以使用底線字元 '_' 作為此函數的別名。

注意:

對於某些系統而言,設定語言是不夠的,應該使用 putenv() 來定義目前的語系。

參見

新增註解

使用者貢獻的註解 17 則註解

6
mikko dot rantalainen at peda dot net
10 年前
值得注意的是,gettext 在選擇要使用的語言時,會採用環境變數: https://gnu.dev.org.tw/software/gettext/manual/html_node/Locale-Environment-Variables.html

「當程式查閱與語系相關的值時,會依以下環境變數的優先順序進行:

LANGUAGE
LC_ALL
LC_xxx,依照選取的語系類別:LC_CTYPE、LC_NUMERIC、LC_TIME、LC_COLLATE、LC_MONETARY、LC_MESSAGES、...
LANG

值已設定但為空的變數會在這次查閱中被忽略。」

簡言之,如果您有非空的 LANGUAGE,最終可能會出現非預期的本地化字串。另一方面,如果缺少某些翻譯,可以使用 LANGUAGE 來定義備用語言。
6
kingjackal at gmail dot com
6 年前
如果您的 PO/MO 檔案使用 msgctxt(上下文),您會發現 gettext(msgid) 無法如預期般運作(即使 msgid 是唯一的),這會讓您感到沮喪。

在這種情況下,您必須在 msgctxt 和 msgid 之間加上 ASCII 字元 4 [EOT,文字結束]。

PO 內容範例

msgctxt "Context"
msgid "Test string"
msgstr "Test translation"

msgid "Standard string"
msgstr "Standard translation"

以下會有效

<?php
gettext
('Context' . "\004" . 'Test string');
gettext('Standard string');
?>

以下將不會有效

<?php
gettext
('Test string');
?>
7
ashi009 at gmail dot com
12 年前
在不重新啟動 Apache 或變更網域的情況下,繞過 gettext() 快取的最簡單方法。

修正方式非常簡單,首先在儲存 .mo 檔案的語系資料夾中建立一個虛擬連結

cd locale
ln -s . nocache

然後在 bindtextdomain() 之前新增一行程式碼

<?php
bindtextdomain
('domain', './locale/nocache');
bindtextdomain('domain', './locale');
?>

現在快取會強制每次都清除。
6
surfchen at gmail dot com
14 年前
從 php 5.3 開始,您可以使用以下程式碼來取得 HTTP 代理程式的慣用語系。

<?php
$locale
= Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
?>
4
smerf(a)druid(d)if(d)uj(d)edu(d)pl
19 年前
Gettext 翻譯會被快取。如果您變更 *.mo 檔案,您的網頁可能不會如預期般翻譯。以下是一個簡單的因應措施,不需要重新啟動網頁伺服器(我知道,這只是個骯髒的駭客方式)

<?php
function initialize_i18n($locale) {
putenv('LANG='.$locale);
setlocale(LC_ALL,"");
setlocale(LC_MESSAGES,$locale);
setlocale(LC_CTYPE,$locale);
$domains = glob($locales_root.'/'.$locale.'/LC_MESSAGES/messages-*.mo');
$current = basename($domains[0],'.mo');
$timestamp = preg_replace('{messages-}i','',$current);
bindtextdomain($current,$locales_root);
textdomain($current);
}
?>

為了讓這段程式碼運作,您必須將您的語系放置在名為 messages-[unix_time].mo 的檔案中,並使用此名稱(不含 .mo 副檔名)作為您的網域,以欺騙快取機制(網域名稱會不同)。

msgfmt messages.po -o messages-`date +%s`.mo

對我來說,這樣運作得很好(雖然這不是非常優雅的解決方案)。
2
nayana at corp - gems dot com
10 年前
在 OSX (10.9.3) 和 PHP (5.4.24) 上,您需要使用包含字元集的全名語系。

例如,對於德語,需要使用 de_DE.UTF-8,即使 setlocale 在不使用 .UTF-8 的情況下傳回成功,查找仍然無法運作。
2
iguy at ionsphere dot org
23 年前
根據所使用的 gettext 實作,您可能需要呼叫 setlocale(LC_ALL, "") 命令。
所以您的範例程式碼會是:

<?php

// 設定語言為德語
putenv ("LANG=de");

// 將語系設定到 gettext 的實例中
setlocale(LC_ALL, "");

// 指定翻譯表的所在位置
bindtextdomain ("myPHPApp", "./locale");

// 選擇網域
textdomain ("myPHPApp");

// 列印測試訊息
print (gettext ("Welcome to My PHP Application"));
?>

注意:如果 setlocale 傳回 NULL,則表示指定的 LANG 無效且「不支援」。
2
jmeile at hotmail dot com
10 年前
我只是想說 gettext 在 WAMP Server 2.4 / 64 位元上無法運作,請參閱我在此處發布的討論串。

標題:Gettext 在 WAMP 64 位元上無法運作
http://forum.wampserver.com/read.php?2,120770,120770#msg-120770

我沒有只用 apache 64 位元測試,所以,我不知道問題是否與 apache 或 WAMP 有關。無論如何,要使其在 WAMP 上運作,請安裝 32 位元版本的 WAMP,然後執行以下操作:

define('LOCALE_DIR', '<您的 po 檔案的根目錄>'); //例如:C:/wamp/www/your_app/locale
$locale = '<您的語系>'; //例如:es_CO
$domain = '您的 gettext 網域'; //例如:messages
putenv('LC_ALL=' . $locale);
bindtextdomain($domain, LOCALE_DIR);
textdomain($domain);
echo _('<您的字串>'; // 例如:Hello world

在 Windows 下,「setlocale」或設定 LANG、LANGUAGE 和 LC_MESSAGES 環境變數似乎不是必要的。我只設定「LC_ALL」就讓它運作了。
0
ck at claudiokuenzler dot com
4 年前
如果您遇到翻譯在 CLI 上運作正常,但在 Apache 上卻無法運作的情況,可能是因為 Perl Apache 模組所導致。

基本的 translate.php

<?php
// 設定語系
putenv("LC_ALL=de_CH.UTF-8");
putenv("LANGUAGE=");
putenv("LANG=de_CH.UTF-8");
$res = setlocale(LC_ALL, 'de_CH.UTF-8', 'de_CH', 'de');
echo
bindtextdomain("homepage", "./locale");
textdomain("homepage");

$results = gettext("My English Text");
if (
$results === "My English Text") {
echo
"傳回原始英文。出錯了\n";
} else {
echo
$results;
}
?>

在 CLI 上,翻譯可以運作。

$ php7.3 translate.php
Mein deutscher Text.

但透過 Apache Web 伺服器則不行。

$ curl localhost/translate.php
傳回原始英文。出錯了

停用 Perl 模組並重新啟動 Apache。

# a2dismod perl
# systemctl restart apache2

突然之間,翻譯就可以運作了。

$ curl localhost/translate.php
Mein deutscher Text.

這種行為的確切原因(截至目前)我還不清楚。
0
jespersaNOSPAM at diku dot NO_SPAM dot dk
22 年前
http://zez.org/article/articleview/42 有一篇關於 PHP 使用的 GetText 工具的好教學。
我唯一需要做的修改是使用正確的 ISO 語言/國家代碼(不知道 ISO 編號)並呼叫 setlocale。
helloworld.php

<?php
putenv
("LC_ALL=da_DK"); // 丹麥語/丹麥
setlocale(LC_ALL, "");

// ./locale/da/LC_MESSAGES 包含 helloworld.mo 檔案
bindtextdomain("helloworld", "./locale");
textdomain("helloworld");

print(
gettext("Hello world!"));
?>

不過,我在 Red Hat (Yellow Dog) Linux 上遇到很多問題才能讓它運作。
-1
naguissa at foroelectro dot net
1 年前
我正在自製的 NAS (Debian + OpenMediaVault) 上進行測試,有些翻譯沒有顯示出來。

有些翻譯運作正常,但有些則被忽略。

問題的原因是我沒有將這些語系新增到我的 NAS 語系中。

1) 編輯檔案 /etc/locale.gen
2) 檢查您的語系是否已啟用(已寫入且未被註解)。
3) 以 root 身分(或 sudo)執行 "locale-gen"。

因此,簡而言之,如果您的系統是 Linux 並且翻譯被忽略,請檢查您系統中是否已啟用該語系。
-2
bla at taxistop dot be
13 年前
對我來說,呼叫 setlocale() 時,將 "nl_BE" 之類的字串作為第二個參數,就足以讓 gettext() 運作。僅使用 "nl" 是不夠的。

當使用 LANG 之類的環境變數時也是如此: "en"、"fr"、"nl"、"de" 是不夠的:我也必須指定國家/地區。
-2
saul dot dobney at notanant dot com
5 年前
當升級或在系統之間移動時,putenv(...) 可能會導致難以診斷的隱藏問題。

在一台 Linux 伺服器上,我們透過 setlocale 讓以下程式碼完美運作:

putenv("LANG=$locale");

我們切換伺服器後,發現 gettext 無法運作,儘管所有語系檔案和設定都相同。

切換為:

putenv("LC_ALL=$locale");

無法解決問題。

但是,

putenv("LANGUAGE=$locale");

可以解決問題。因此,如果您有問題,請檢查所有三個設定。
-3
simen at nconel dot no
12 年前
gettext 會從 .mo 檔案傳回標頭。
如果訊息參數設定為空白時。

因此,如果您正在使用 Smarty 區塊之類的內容,請確保給定的值會檢查文字是否有內容,否則您的文字將會列印一堆標頭。

如果您要將變數放到 gettext 中,像是這樣:
_($text);
您最好建立另一個像這樣的函式:
<?php
function __($text){
if(empty(
$text)) return "";
else
gettext($text);
}
?>
-2
florent at eledo dot com
19 年前
從原始程式碼檔案中擷取字串時要小心:如果您的原始程式碼檔案不是以 ascii 編碼,則必須使用 --from-code 選項來使用 xgettext,且產生的 .po 檔案*一律*為 UTF-8(即使您使用了不同的 --from-code 字元集)。

gettext 後續將無法處理包含非 ascii 字元的字串。為了讓它能運作,您必須使用 msgconv 將 .po 檔案轉換為您正確的字元集。

範例
我的原始程式碼檔案以 iso-8859-1 編碼
$ xgettext --from-code=iso-8859-1 -n *.php -o myapp.po
==> myapp.po 是 UTF-8 格式(且產生的 .mo 檔案將無法與 gettext 搭配使用)。
我必須先將其轉換為 iso-8859-1 才能翻譯。
$ msgconv --to-code=iso-8859-1 myapp.po -o myapp.po
...現在翻譯檔案。
-4
adino at adino dot sk
21 年前
如果您遇到像是 gettext() 無法運作,而且只有偶爾會出現翻譯文字的問題,請在使用 Apache 前取消設定 LANG 環境變數:unset LANG。
接下來,您必須在變更 .mo 檔案後重新啟動 Apache,因為它們被視為類似共享函式庫的東西。
我只在 Linux (Sourcemage Linux 發行版、Mandrake) 上測試過,但可能也適用於其他系統。
-5
vinaykuruvila at gmail dot com
18 年前
如果您像我一樣,被大量程式碼需要本地化的問題困擾,您必須遍歷所有的 PHP 檔案,並將所有字串包在 _("字串") 中。這裡有一個 Elisp 函式可以幫助您。

這個函式讓您可以在 Emacs 緩衝區中反白文字,並使用鍵盤快捷鍵 C-l (Ctrl 和 l) 將其轉換為可本地化的字串。如果反白的第一個字元是 " 或 ',則假設文字位於 PHP 上下文中,並將其變更為:_(反白文字)。否則,它假設文字位於 HTML 上下文中,並將其變更為 <?=_('反白文字')?>

快捷鍵 C-k 可以用來翻譯包含 HTML 標籤的 PHP 字串的部分。我們不想翻譯包含標籤的整個字串,所以我們只反白需要翻譯的子字串並使用 C-k。

要使用它,請執行以下其中一項操作:
將以下程式碼複製貼上到您的 .emacs 檔案中。這會將鍵盤快捷鍵 C-l 與此函式永久關聯。
將程式碼儲存到一個以 .el 副檔名結尾的新檔案中。使用 M-x eval-buffer 評估它。這會使 C-l 鍵盤快捷鍵僅在目前的 Emacs 工作階段中有效。

程式碼
;作者:Vinay Kuruvila 2006 年 3 月 1 日
;已更新以處理包含 HTML 標籤的 PHP 字串

;將目前緩衝區中左側開始、右側結束的文字
;轉換為可本地化的字串,假設
;字串位於 PHP 上下文中
(defun make-localizable-string-in-php-context(left right)
(goto-char left)
(insert "_(")
(goto-char (+ right 2))
(insert ")")
)

;將目前緩衝區中左側開始、右側結束的文字
;轉換為可本地化的字串,假設
;字串位於 HTML 上下文中
(defun make-localizable-string-in-html-context(left right)
(goto-char left)
(insert "<?= _('")
(goto-char (+ right 7))
(insert "'
)?>")
)

;將反白的文字轉換為可本地化的字串
;如果反白的第一個字元是 " 或 ',則使用 PHP 上下文本地化
;否則使用 HTML 上下文本地化
(defun make-localizable-string()
(interactive)
(interactive)

;找出反白文字的左端和右端的位置
;找出反白文字的左端和右端的位置
(if (> (point) (mark))
(progn
(setq right (point))
(setq left (mark))
)
(progn
(setq right (mark))
(setq left (point))
)
)

;判斷 PHP 上下文或 HTML 上下文並分派
(if (or (char-equal (char-after left) ?\") (char-equal (char-after left) ?'))
(make-localizable-string-in-php-context left right)
(make-localizable-string-in-html-context left right)
)
(deactivate-mark)
)

;處理包含 HTML 標籤的 PHP 字串
;我們不想翻譯 HTML 標籤
(defun make-localizable-string-within-php-string ()
(interactive)

;找出反白文字的左端和右端的位置
;找出反白文字的左端和右端的位置
(if (> (point) (mark))
(progn
(setq right (point))
(setq left (mark))
)
(progn
(setq right (mark))
(setq left (point))
)
)
(goto-char left)
(insert "\". _(\"")
(goto-char (+ right 6))
(insert "\").\"")
(deactivate-mark)
)

;指派鍵盤快捷鍵
(global-set-key "\C-l" 'make-localizable-string)
(global-set-key "\C-k" 'make-localizable-string-within-php-string)
To Top