为了使您的应用程序中的字符串可以翻译,您必须将原始字符串打包到一组特殊功能的调用中。
Gettext简介
WordPress使用i18n的gettext库和工具。 如果你在网上看,你会看到_()
函数,它引用了本地PHP gettext兼容的翻译功能。 使用WordPress,您应该使用__()
WordPress定义的PHP函数。 如果您想获得更广泛和更深入的gettext视图,我们建议您阅读gettext在线手册。
文字域
使用文本域来表示属于该插件的所有文本很重要。 文本域是唯一的标识符,可以确保WordPress能够区分所有加载的翻译。 这增加了可移植性,并通过已经存在的WordPress工具更好地发挥作用。 文本域必须与插件的插槽相匹配。 如果您的插件是一个名为my-plugin.php的文件,或者它包含在一个名为my-plugin的文件夹中,则域名应为my-plugin。 如果您的插件托管在wordpress.org上,那么它必须是插件URL(wordpress.org/plugins/)中的一小部分。
文本域名必须使用破折号而不是下划线。
字符串示例:
__( 'String (text to be internationalized)', 'text-domain' );
将“文本域”更改为插件的插件。
警告:不要在gettext函数的文本域部分使用变量名。 不要做这个快捷方式:__('Translate me。',$ text_domain);
文本域也需要添加到插件头。 即使插件被禁用,WordPress也使用它来国际化你的插件元数据。 文本域应与加载文本域时使用的文本域相同。
标题示例:
/*
* Plugin Name: My Plugin
* Author: Plugin Author
* Text Domain: my-plugin
*/
域路径
使用域路径,以便当插件被禁用时,WordPress知道在哪里找到翻译。 仅当翻译位于单独的语言文件夹中时才有用。 例如,如果.mo文件位于languages文件夹中,则Domain Path将是“/languages”,必须用第一个斜杠写入。 默认为插件的languages文件夹:
标题示例:
/*
* Plugin Name: My Plugin
* Author: Plugin Author
* Text Domain: my-plugin
* Domain Path: /languages
*/
基本字符串
最常用的是__()
。 它只是返回其参数的翻译:
__( 'Blog Options', 'my-plugin' );
另一个简单的是_e(),它输出其参数的翻译。 而不是写:
echo __( 'WordPress is the best!', 'my-plugin' );
你可以使用较短的:
_e( 'WordPress is the best!', 'my-plugin' );
变量
如果您在字符串中使用变量,如下面的示例,您将使用占位符。
echo 'Your city is $city.'
解决方案是使用printf系列函数。 特别有用的是printf和sprintf。 以下是正确的解决方案:
printf(
/* translators: %s: Name of a city */
__( 'Your city is %s.', 'my-plugin' ),
$city
);
请注意,这里的翻译字符串只是模板“你的城市是%s”,这在源代码和运行时都是一样的。
如果字符串中有多个占位符,建议您使用参数交换。 在这种情况下,单引号(')是强制性的:双引号(“)将告诉php将$ s解释为s变量,这不是我们想要的。
printf(
/* translators: 1: Name of a city 2: ZIP code */
__( 'Your city is %1$s, and your zip code is %2$s.', 'my-plugin' ),
$city,
$zipcode
);
这里的邮政编码正在城市名后显示。 在某些语言中,以相反的顺序显示邮政编码和城市更为合适。 在上面的例子中使用%s的前缀,就允许这样的情况。 因此,翻译可以写成:
printf(
/* translators: 1: Name of a city 2: ZIP code */
__( 'Your zip code is %2$s, and your city is %1$s.', 'my-plugin' ),
$city,
$zipcode
);
重要! 此代码不正确。
// This is incorrect do not use.
_e( "Your city is $city.", 'my-plugin' );
翻译的字符串是从源中提取出来的,所以翻译人员会得到这个短语:“你的城市是$ city”。
但是在应用程序中,将会被称为“你的城市是伦敦”。 gettext将不会找到适合的翻译,并返回其论点:“你的城市是伦敦”。 不幸的是,它没有正确翻译。
多个
##基本多元化
如果在项目数量更改时有变化的字符串。 在英语中你有“一个评论”和“两个意见”。 在其他语言中,您可以有多个复数形式。 要在WordPress中处理这个问题,可以使用_n()函数。
printf(
_n(
'%s comment',
'%s comments',
get_comments_number(),
'my-plugin'
),
number_format_i18n( get_comments_number() )
);
_n() 接受4个参数:
- singular – 字符串的单数形式(注意,它可以用于某些语言中的一个以外的数字,因此应使用“%s项”而不是“一个项”)
- plural – 字符串的复数形式
- count – 对象的数量,这将决定是否应该返回单数或复数形式(有多种语言,有两种以上的形式)
- text domain – 插件文本域
功能的返回值是正确的翻译形式,对应于给定的计数。
##稍后完成
您首先使用_n_noop()或_nx_noop()设置多个字符串。
$comments_plural = _n_noop(
'%s comment.',
'%s comments.'
);
然后在稍后的代码中,您可以使用translate_nooped_plural()来加载字符串。
printf(
translate_nooped_plural(
$comments_plural,
get_comments_number(),
'my-plugin'
),
number_format_i18n( get_comments_number() )
);
背景消歧
有时一个术语在多个语境中被使用,虽然它是英文中同一个词,但是在其他语言中它必须被不同地翻译。 例如,Post可以用作动词“点击这里发表你的评论”,作为名词“编辑这篇文章”。 在这种情况下,应该使用_x()或_ex()函数。 它类似于__()和_e(),但它有一个附加的参数 - 上下文:
_x( 'Post', 'noun', 'my-plugin' );
_x( 'Post', 'verb', 'my-plugin' );
在这两种情况下使用此方法,我们将获得原始版本的字符串注释,但翻译器将看到两个用于翻译的注释字符串,每个字符串在不同的上下文中。
请注意,与
__()
类似,_x()
具有回调版本:_ex()
。 前面的例子可以写成:
_ex( 'Post', 'noun', 'my-plugin' );
_ex( 'Post', 'verb', 'my-plugin' );
使用您觉得增强易读性和易于编码的任何一个。
##说明
所以翻译人员知道如何翻译一个字符串__('g:i:s a'),你可以在源代码中添加一个澄清的注释。 它必须从翻译人员开始:在gettext调用之前成为最后一个PHP注释。 这是一个例子:
/* translators: draft saved date format, see http://php.net/date */
$saved_date_format = __( 'g:i:s a' );
它还用于解释字符串中的占位符,如_n_noop(<strong>版本%1 $ s </ strong>
已解决%2 $ s错误,<strong>版本%1 $ s </ strong>
“解决了%2 $ s的错误”)。
/* translators: 1: WordPress version number, 2: plural number of bugs. */
_n_noop( '<strong>Version %1$s</strong> addressed %2$s bug.',
'<strong>Version %1$s</strong> addressed %2$s bugs.' );
换行字符
Gettext不喜欢\ r(ASCII码:13)在可翻译的字符串,所以请避免它,并使用\ n代替。
##空字符串
空字符串保留用于内部Gettext使用,您不得尝试将空字符串国际化。 它也没有任何意义,因为翻译者不会看到任何上下文。
如果您有一个有效的用例来使一个空字符串国际化,请添加上下文以帮助翻译人员,并与Gettext系统保持一致。
处理JavaScript文件
使用wp_localize_script()将已翻译的字符串或其他服务器端数据添加到先前排入的脚本。
##转义字符串
逃避所有的字符串是好的,这样翻译者就不能运行恶意代码。 有几个与国际化功能相结合的逃生功能。
##本地化功能
##基本功能
- __()
- _e()
- _x()
- _ex()
- _n()
- _nx()
- _n_noop()
- _nx_noop()
- translate_nooped_plural()
##翻译和退出功能
必须转义需要翻译并在html标签的属性中使用的字符串。
- esc_html__()
- esc_html_e()
- esc_html_x()
- esc_attr__()
- esc_attr_e()
- esc_attr_x()
日期和数字功能
- number_format_i18n()
- date_i18n()
写字符串的最佳做法
以下是编写字符串的最佳做法
- 使用体面的英式风格 - 尽量减少俚语和缩写。
- 使用整个句子 - 在大多数语言中,单词顺序与英语不同。
- 拆分段落 - 合并相关句子,但不要在一个字符串中包含整个文本页面。
- 不要将前导或尾随空格留在可翻译的短语中。
- 假设翻译时字符串的长度可以翻倍
- 避免不正常的标记和不寻常的控制字符 - 不要包含文本周围的标签
- 不要将不必要的HTML标记放入已翻译的字符串中
- 不要留下翻译的网址,除非他们可以使用其他语言的版本。
- 将变量作为占位符添加到字符串中,如在某些语言中,占位符更改位置。
printf(
__( 'Search results for: %s', 'my-plugin' ),
get_search_query()
);
使用格式字符串而不是字符串连接 - 翻译短语而不是单词 -
printf(
__( 'Your city is %1$s, and your zip code is %2$s.', 'my-plugin' ),
$city,
$zipcode
);
总是比:
__( 'Your city is ', 'my-plugin' ) . $city . __( ', and your zip code is ', 'my-plugin' ) . $zipcode;
尝试使用相同的单词和相同的符号,因此不需要翻译多个字符串,例如__('Posts:','my-plugin');
和__('Posts','my-plugin');
##将文本域添加到字符串
您必须将您的文本域作为参数添加到每个__(),_e()和__n()gettext调用中,否则您的翻译将无法正常工作。
例子:
__( 'Post' )
应该成为
__( 'Post', 'my-theme' )
_e( 'Post' )
应该成为
_e( 'Post', 'my-theme' )
_n( 'One post', '%s posts', $count )
应该成为
_n( 'One post', '%s posts', $count, 'my-theme' )
如果您的插件中也有用于WordPress核心的字符串(例如“设置”),那么您还应该添加自己的文本域,否则如果核心字符串发生变化(如果发生),那么它们将变为非翻译。
手动添加文本域可能是一个负担,如果不是在编写代码时连续完成,这就是为什么你可以自动执行:
如果您的插件位于WordPress.org插件目录中,请转到您的“管理”页面,然后滚动到“添加域到Gettext呼叫”。
上传要添加文本域的文件。
点击“获取域文件”。
WordPress.org Plugin Admin区域
WordPress.org Plugin Admin区域
除此以外:
将add-textdomain.php脚本下载到要添加文本域的文件夹
在命令行中移动到文件所在的目录
运行此命令创建一个添加了文本域的新文件
php add-textdomain.php my-plugin my-plugin.php > new-my-plugin.php
如果您希望将add-textdomain.php放在不同的文件夹中,那么您只需要在命令中定义位置。
php \path\to\add-textdomain.php my-plugin my-plugin.php > new-my-plugin.php
如果您不想输出新文件,请使用此命令。
php add-textdomain.php -i my-plugin my-plugin.php
如果要更改目录中的多个文件,还可以将目录传递给脚本。
php add-textdomain.php -i my-plugin my-plugin-directory
完成后,文本域将被添加到文件中所有gettext调用的末尾。 如果存在现有的文本域,则不会被替换。
加载文本域
注意:WordPress 4.6出来之后,翻译现在以translate.wordpress.org为优先,因此通过translate.wordpress.org翻译的插件不再需要load_plugin_textdomain()了。
如果您不想在您的插件中添加一个load_plugin_textdomain()调用,则必须将readme.txt中的至少要求至少为:。
您需要使用插件的翻译加载MO文件。 您可以通过调用函数load_plugin_textdomain()来加载它们。 此调用从插件的基本目录载入{text-domain} - {locale} .mo。 语言环境是常规设置下的站点语言设置的语言代码和/或国家/地区代码。 有关语言和国家/地区代码的更多信息,请参阅您的语言中的WordPress。
从上面的代码示例,文本域是my-plugin,因此德语MO和PO文件应该命名为my-plugin-de_DE.mo和my-plugin-de_DE.po。
例:
function my_plugin_load_plugin_textdomain() {
load_plugin_textdomain( 'my-plugin', FALSE, basename( dirname( __FILE__ ) ) . '/languages/' );
}
add_action( 'plugins_loaded', 'my_plugin_load_plugin_textdomain' );
语言包
如果您对语言包感兴趣,以及如何进行translate.wordpress.org的导入,请阅读关于翻译的Meta手册页面。