gettext

(PHP 4, PHP 5, PHP 7, PHP 8)

gettext在当前域中查找消息

说明

gettext(string $message): string

在当前域中查找消息。

参数

message

要翻译的消息。

返回值

如果在翻译表中找到,则返回已翻译的 string,否则返回提交的消息。

示例

示例 #1 gettext()-check

<?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() 来定义当前区域设置。

参见

添加备注

用户贡献的备注 20 则备注

mikko dot rantalainen at peda dot net
10 年前
值得注意的是,gettext 在选择要使用的语言时会尊重环境变量:http://www.gnu.org/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 可以用来定义当某些翻译丢失时的回退语言。
kingjackal at gmail dot com
6 年前
如果您的 PO/MO 文件使用 msgctxt(上下文),您会沮丧地发现 gettext(msgid) 无法按预期工作(即使 msgid 是唯一的)。

在这种情况下,您必须使用 ASCII 字符 4 [EOT,文本结束] 粘贴在 msgctxt 和 msgid 之间。

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');
?>
ashi009 at gmail dot com
11 年前
绕过 gettext() 缓存的最简单方法,无需重启 Apache 也不必更改域。

修复方法非常简单,首先创建一个指向存储 .mo 文件的区域设置文件夹的虚拟链接

cd locale
ln -s . nocache

然后在 bindtextdomain() 之前添加一行

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

现在缓存将在每次请求时强制刷新。
surfchen at gmail dot com
14 年前
从 php 5.3 开始,您可以使用以下代码来获取 http 代理的首选区域设置。

<?php
$locale
= Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
?>
smerf(a)druid(d)if(d)uj(d)edu(d)pl
18 年前
Gettext 翻译会被缓存。如果您更改了 *.mo 文件,您的页面可能不会按预期进行翻译。以下是一个简单的解决方法,无需重启 web 服务器(我知道,这只是一个肮脏的技巧)

<?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

对我来说,这工作正常(尽管这不是一个很优雅的解决方案)
nayana at corp - gems dot com
10 年前
在 OSX(10.9.3)和 PHP(5.4.24)上,您需要使用包含代码集的完整本地名称

例如,对于德语,您需要使用 de_DE.UTF-8,即使 setlocale 在没有 .UTF-8 的情况下返回成功,查找也不会起作用。
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 无效且“不受支持”。
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 上运行,请安装 WAMP 的 32 位版本,只执行以下操作

define('LOCALE_DIR', '<root_dir_of_your_po_files>'); //例如:C:/wamp/www/your_app/locale
$locale = '<your_locale>'; //例如:es_CO
$domain = 'your_gettext_domain'; //例如:messages
putenv('LC_ALL=' . $locale);
bindtextdomain($domain, LOCALE_DIR);
textdomain($domain);
echo _('<your_string>'; //例如:Hello world

在 Windows 下,"setlocale" 以及设置 LANG、LANGUAGE 和 LC_MESSAGES 环境变量似乎没有必要。我通过仅设置 "LC_ALL" 使其工作。
ck at claudiokuenzler dot com
3 年前
如果您遇到翻译在 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
"Original English was returned. Something wrong\n";
} else {
echo
$results;
}
?>

在 CLI 上,翻译有效

$ php7.3 translate.php
Mein deutscher Text.

但通过 Apache web 服务器无效

$ curl localhost/translate.php
Original English was returned. Something wrong

禁用 Perl 模块并重启 Apache

# a2dismod perl
# systemctl restart apache2

突然,翻译就有效了

$ curl localhost/translate.php
Mein deutscher Text.

这种行为的确切原因目前对我来说尚不清楚。
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 上遇到了很多麻烦才能使它工作。
naguissa at foroelectro dot net
8 个月前
我正在一个自制的 NAS(Debian + OpenMediaVault)上进行测试,我没有获得某些翻译。

一些翻译工作正常,但其他一些却被忽略了。

问题是由于我没有将这些区域设置添加到我的 NAS 区域设置中造成的

1) 编辑文件 /etc/locale.gen
2) 检查您的区域设置是否处于活动状态(已写入且未被注释)。
3) 以 root 用户身份执行 "locale-gen"(或 sudo)。

因此,简而言之,如果您有一个 Linux 系统并且您的翻译被忽略,请检查您的系统中是否启用了该区域设置。
bla at taxistop dot be
13 年前
对我来说,只需使用 "nl_BE" 之类的字符串作为 setlocale() 的第二个参数,就可以使 gettext() 工作。仅仅 "nl" 不够。

同样,当使用类似 LANG 的环境变量时:"en"、"fr"、"nl"、"de" 不够:我必须也指定国家/地区。
saul dot dobney at notanant dot com
5 年前
putenv(...) 在升级或在系统之间移动时会导致难以诊断的隐藏问题。

在一台 Linux 服务器上,我们使用 setlocale 使以下代码完美运行

putenv("LANG=$locale");

我们切换了服务器,发现 gettext 无法工作,尽管我们拥有相同的区域设置文件和设置。

切换到以下代码的建议

putenv("LC_ALL=$locale");

没有解决问题。

但是,

putenv("LANGUAGE=$locale");

解决了。因此,如果您遇到问题,请检查所有三个设置。
simen at nconel dot no
12 年前
gettext 返回 .mo 文件中的标题
如果 message 参数设置为 empty。

因此,如果您例如使用 Smarty 块,请确保给定的值检查文本是否有内容,否则您的文本将包含一组打印的标题。

如果您将变量放入 gettext,例如
_($text);
您最好创建另一个这样的函数
<?php
function __($text){
if(empty(
$text)) return "";
else
gettext($text);
}
?>
florent at eledo dot com
18 年前
从源文件提取字符串时要小心:如果您的源文件不是用 ascii 编码的,那么 xgettext 必须与 --from-code 选项一起使用,并且生成的 .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
... 现在翻译该文件。
adino at adino dot sk
21 年前
如果您遇到 gettext() 无法正常工作并且只偶尔获得翻译文本的问题,请在启动 apache 之前使用:unset LANG。
接下来,您必须在更改 .mo 文件后重启 apache,因为它们被视为共享库。
我只在 Linux(Sourcemage Linux 发行版,Mandrake)上测试过,但它也可能适用于其他系统。
vinaykuruvila at gmail dot com
18 年前
如果您像我一样,需要使大量代码可本地化,您必须遍历所有 php 文件并将所有字符串包装在 _("string") 中。以下是一个可以帮助您的 elisp 函数。

此函数使您能够突出显示 emacs 缓冲区中的某些文本,并使用键盘快捷键 C-l(Ctrl 和 l)将其设为可本地化的字符串。如果突出显示的第一个字符是 " 或 ',则它假定文本位于 php 上下文中,并将其更改为:_(HIGHLIGHTED_TEXT)。否则,它假定文本位于 html 上下文中,并将其更改为 <?= _('HIGHLIGHTED_TEXT')?>

快捷键 C-k 可用于翻译包含 html 选项卡的 php 字符串的部分。我们不想翻译包含选项卡的整个字符串,因此我们仅突出显示需要翻译的子字符串并使用 C-k。

要使用它,请执行以下任一操作
将以下代码复制并粘贴到您的 .emacs 文件中。这将永久地将键盘快捷键 C-l 与此函数关联。
将代码保存在以 .el 结尾的新文件中。使用 M-x eval-buffer 对其进行评估。这使 C-l 键盘快捷键仅在当前 Emacs 会话中有效。

代码
;author: Vinay Kuruvila March 01 2006
;updated to handle php strings containing html tabs

;makes the text starting at left and ending at right in the
;current buffer a localizable string, assuming that the
;string is within php context
(defun make-localizable-string-in-php-context(left right)
(goto-char left)
(insert "_(")
(goto-char (+ right 2))
(insert ")")
)

;makes the text starting at left and ending at right in the
;current buffer a localizable string, assuming that the
;string is within html context
(defun make-localizable-string-in-html-context(left right)
(goto-char left)
(insert "<?= _('")
(goto-char (+ right 7))
(insert "'
)?>")
)

;makes the highlighted text a localizable string
;uses php-context localization if the first char highlighted
;is " or '
;otherwise uses html-context localization
(defun make-localizable-string()
(interactive)

; 查找突出显示文本的左右端位置
; 突出显示的文本
(如果 (> (点) (标记))
(progn
(设置q 右 (点))
(设置q 左 (标记))
)
(progn
(设置q 右 (标记))
(设置q 左 (点))
)
)

; 确定 php 上下文或 html 上下文并分发
(如果 (或 (字符相等 (字符-后 左) ?\") (字符相等 (字符-后 左) ?'))
(创建-本地化-字符串-在-php-上下文 左 右)
(创建-本地化-字符串-在-html-上下文 左 右)
)
(停用-标记)
)

; 处理包含 html 选项卡的 php 字符串
; 我们不想翻译 html 选项卡
(defun 创建-本地化-字符串-在-php-字符串-中 ()
(interactive)

; 查找突出显示文本的左右端位置
; 突出显示的文本
(如果 (> (点) (标记))
(progn
(设置q 右 (点))
(设置q 左 (标记))
)
(progn
(设置q 右 (标记))
(设置q 左 (点))
)
)
(goto-char left)
(插入 "\". _(\"")
(跳转-字符 (+ 右 6))
(插入 "\").\"")
(停用-标记)
)

; 为键盘快捷键分配
(全局-设置-键 "\C-l" '创建-本地化-字符串)
(全局-设置-键 "\C-k" '创建-本地化-字符串-在-php-字符串-中)
suchy(d)ivan(a)gmail.com
18 年前
默认行为是在每个语言版本中同名 .mo 文件
===
区域设置-目录

--- en_US
------ LC_MESSAGES
--------- lang.mo

--- sk_SK
------ LC_MESSAGES
--------- lang.mo
===

我认为,更好的形式是
===
区域设置-目录

--- en_US
------ LC_MESSAGES
--------- en.mo

--- sk_SK
------ LC_MESSAGES
--------- sk.mo
===

然后以下代码运行得很好(令人惊讶的是在 win32 上也能运行),并且您不需要重启 apache 以及其他令人困惑的操作

<?php
$gettext_domain
= 'sk'; // 根据语言更改
setlocale(LC_ALL, 'sk_SK.UTF-8'); // 根据语言更改,目录名称 sk_SK,而不是 sk_SK.UTF-8
bindtextdomain($gettext_domain, "lang");
textdomain($gettext_domain);
bind_textdomain_codeset($gettext_domain, 'UTF-8');
?>

祝您有美好的一天!:-)
daemonraco at yahoo dot com dot ar
17 年前
我遇到了与 “adino at adino dot sk” 所说类似的问题,因此我取消了 LANG 的设置($ unset LANG),但这还不够,我不得不取消环境变量 LANGUAGE 的设置。

我尝试使用 “sudo” 来执行此操作,但它不起作用,因此我不得不使用 “su” 切换到 root 用户。

如果您需要知道,我使用的是 Musix(Devia 的一个子发行版)。

我希望这对您有所帮助,再见!^__^'
telefoontoestel at hotmail dot com
10 年前
此函数无法处理空值。如果您输入空值作为参数,它可以返回完整的翻译文件。
To Top