为了使您的应用程序中的字符串可以翻译,您必须将原始字符串打包到一组特殊功能的调用中。
## 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/ <slug>)中的一小部分。
文本域名必须使用破折号而不是下划线。
字符串示例:
```
__( 'String (text to be internationalized)', 'text-domain' );
```
将“文本域”更改为插件的插件。
>[warning] 警告:不要在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
);
```
>[warning] 请注意,这里的翻译字符串只是模板“你的城市是%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' );
```
在这两种情况下使用此方法,我们将获得原始版本的字符串注释,但翻译器将看到两个用于翻译的注释字符串,每个字符串在不同的上下文中。
>[info] 请注意,与`__()`类似,`_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调用的末尾。 如果存在现有的文本域,则不会被替换。
## 加载文本域
>[warning] 注意: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手册页面。
- 简介
- 主题开发
- WordPress许可证
- 什么是主题
- 开发环境
- 主题开发示例
- 主题基础
- 模板文件
- 主样式表(style.css)
- 文章类型
- 规划主题文件
- 模板层级
- 模板标签
- 循环
- 主题函数
- 连接主题文件和目录
- 使用CSS和JavaScript
- 条件标签
- 类别,标签和自定义分类
- 模板文件
- 内容模板文件
- 页面模板文件
- 附件模板文件
- 自定义内容类型
- 部分和其他模板文件
- 评论模板
- 分类模板
- 404页面
- 主题功能
- 核心支持的功能
- 管理菜单
- 自定义Headers
- 自定义Logo
- 文章格式
- 置顶文章
- Sidebars
- Widgets
- 导航菜单
- 分页
- 媒体
- Audio
- Images
- Galleries
- Video
- 精选图片和缩略图
- 国际化
- 本地化
- 辅助功能
- 主题选项 – 自定义API
- 定制对象
- 改进用户体验的工具
- 定制JavaScript API
- JavaScript / Underscore.js渲染的自定义控件
- 高级用法
- 主题安全
- 数据消毒/逃避
- 数据验证
- 使用随机数
- 常见漏洞
- 高级主题
- 子主题
- UI最佳实践
- JavaScript最佳做法
- 主题单元测试
- 验证你的主题
- Plugin API Hooks
- 发布你的主题
- 所需的主题文件
- 测试
- 主题评论指南
- 写文档
- 提交你的主题到WordPress.org
- 参考文献
- 模板标签列表
- 条件标签列表
- 编码标准
- HTML编码标准
- CSS编码标准
- JavaScript编码标准
- PHP编码标准
- 插件开发
- 插件开发简介
- 什么是插件
- 插件基础
- 头部要求
- 包括软件许可证
- 启用 / 停用 Hooks
- 卸载方法
- 最佳做法
- 插件安全
- 检查用户功能
- 数据验证
- 保护输入
- 保护输出
- 随机数
- Hooks
- Actions
- Filters
- 自定义Hooks
- 高级主题
- 管理菜单
- 顶级菜单
- 子菜单
- 短代码
- 基本短码
- 封闭短码
- 带参数的短代码
- TinyMCE增强型短码
- 设置
- 设置API
- 使用设置API
- 选项API
- 自定义设置页面
- 元数据
- 管理帖子元数据
- 自定义元数据
- 渲染元数据
- 自定义文章类型
- 注册自定义文章类型
- 使用自定义文章类型
- 分类
- 使用自定义分类
- 在WP 4.2+中使用“split术语”
- 用户
- 创建和管理用户
- 使用用户元数据
- 角色和功能
- HTTP API
- JavaScript
- jQuery
- Ajax
- 服务器端PHP和入队
- Heartbeat API
- 概要
- 计划任务
- 了解WP-Cron计划
- 安排WP-Cron 事件
- 将WP-Cron挂接到系统任务计划程序中
- WP-Cron简单测试
- 国际化
- 本地化
- 如何国际化您的插件
- 国际化安全
- WordPress.org
- 详细插件指南
- 规划您的插件
- 如何使用Subversion
- 插件开发者常见问题
- 开发工具
- Debug Bar 和附加组件
- 辅助插件
- REST API手册
- 资源
- 文章
- 文章修订
- 文章类型
- 文章状态
- 类别
- 标签
- 页面
- 评论
- 分类
- 媒体
- 用户
- 设置
- 使用REST API
- 全局参数
- 分页
- 链接和嵌入
- 发现
- 认证
- 经常问的问题
- 骨干JavaScript客户端
- 客户端库
- 扩展REST API
- 添加自定义端点
- 自定义内容类型
- 修改回应
- 模式
- 词汇表
- 路由和端点
- 控制器类