各位观众老爷,晚上好!我是今天的主讲人,一个和代码磕了一辈子的码农。今晚咱们聊点有意思的,聊聊WordPress这玩意儿背后的“口语翻译官”——L10n。
啥是L10n?简单说,就是让你的WordPress站点能说各国语言,不管是高贵的英语,还是神秘的中文,亦或是热情似火的西班牙语。这得益于WordPress的国际化 (i18n) 和本地化 (L10n) 机制,而 L10n 就是这个机制的具体实现。
别怕,听着高大上,其实原理贼简单。咱们今天就扒开它的裤衩,看看它到底是怎么运作的。
一、 i18n 和 L10n 的关系:一母同胞的两兄弟
首先,咱们得搞清楚 i18n 和 L10n 的关系。
- i18n (Internationalization,国际化): 是让你的代码具备“多语种”能力,但它本身并不提供任何具体的翻译。 相当于设计了一套标准,让你的代码能轻松应对各种语言。
- L10n (Localization,本地化): 是针对特定语言,将 i18n 处理过的文本翻译成目标语言。 相当于把抽象的标准变成了具体的方言。
i18n 是基础,L10n 是应用。 没 i18n,L10n 就无从谈起。
二、 WordPress L10n 的核心函数:几个当家花旦
WordPress 提供了几个核心函数来支持 L10n。 它们是你的代码与翻译文件交互的桥梁。
函数名 | 功能 | 备注 |
---|---|---|
__() |
获取翻译后的字符串。 这是最常用的函数,用于翻译单个字符串。 | 简单直接,哪里需要翻译,哪里就用它。 |
_e() |
翻译并输出字符串。 相当于 echo __() 。 |
懒人专用,直接输出,省去 echo 步骤。 |
_n() |
根据数量选择不同的翻译。 用于处理单复数情况。 | 比如 "1 comment" 和 "5 comments",用 _n() 可以自动选择正确的翻译。 |
_x() |
带有上下文的翻译。 用于区分相同字符串在不同语境下的含义。 | 比如 "Post" 可以是 "文章"(名词) 或者 "发布"(动词)。 _x() 可以根据上下文选择正确的翻译。 |
_ex() |
带有上下文的翻译并输出。 相当于 echo _x() 。 |
_x() 的懒人版本。 |
_nx() |
带有上下文和数量的翻译。 用于处理复杂情况。 | 结合了 _n() 和 _x() 的功能。 |
esc_attr__() |
获取翻译后的字符串,并进行 HTML 属性转义。 用于翻译 HTML 属性值。 | 确保翻译后的字符串可以安全地用于 HTML 属性中,防止 XSS 攻击。 |
esc_attr_e() |
翻译并输出字符串,并进行 HTML 属性转义。 用于翻译并输出 HTML 属性值。 | esc_attr__() 的懒人版本。 |
esc_html__() |
获取翻译后的字符串,并进行 HTML 转义。 用于翻译 HTML 内容。 | 确保翻译后的字符串可以安全地用于 HTML 内容中,防止 XSS 攻击。 |
esc_html_e() |
翻译并输出字符串,并进行 HTML 转义。 用于翻译并输出 HTML 内容。 | esc_html__() 的懒人版本。 |
load_textdomain() |
加载翻译文件。 这是启动 L10n 的关键步骤。 | 告诉 WordPress 去哪里找翻译文件。 |
三、 实战演练:代码说话,胜过千言万语
光说不练假把式。 咱们来点实际的,看看这些函数怎么用。
1. __()
和 _e()
:最基础的翻译
<?php
// 翻译 "Hello, world!"
$translated_text = __('Hello, world!', 'my-theme');
// 输出翻译后的字符串
echo $translated_text;
// 或者直接用 _e()
_e('Hello, world!', 'my-theme');
?>
这里的 'my-theme'
是 text domain,用来区分不同主题或插件的翻译文件。 后面会详细讲。
2. _n()
:处理单复数
<?php
$comment_count = 5;
// 根据评论数量选择不同的翻译
printf(
_n(
'%s comment',
'%s comments',
$comment_count,
'my-theme'
),
number_format_i18n($comment_count)
);
?>
这段代码会根据 $comment_count
的值,选择 "1 comment" 或 "5 comments" 的翻译。 number_format_i18n()
函数用于格式化数字,使其符合当前语言环境的习惯。
3. _x()
和 _ex()
:区分语境
<?php
// "Post" 作为名词(文章)
$post_label = _x('Post', 'post type general name', 'my-theme');
// "Post" 作为动词(发布)
$post_button_text = _x('Post', 'submit button', 'my-theme');
echo "文章类型:" . $post_label . "<br>";
echo "发布按钮:" . $post_button_text;
?>
通过第二个参数(context),我们可以区分 "Post" 在不同语境下的含义,从而获得更准确的翻译。
4. esc_attr__()
、esc_attr_e()
、esc_html__()
和 esc_html_e()
:安全第一
<?php
// 翻译 HTML 属性值
$title_attribute = esc_attr__('Read more', 'my-theme');
// 翻译 HTML 内容
$link_text = esc_html__('Learn more', 'my-theme');
echo '<a href="#" title="' . $title_attribute . '">' . $link_text . '</a>';
?>
这些函数可以防止 XSS 攻击,确保翻译后的字符串可以安全地用于 HTML 中。 记住,安全无小事!
5. load_textdomain()
:加载翻译文件
<?php
// 在主题的 functions.php 文件中
function my_theme_load_textdomain() {
load_theme_textdomain( 'my-theme', get_template_directory() . '/languages' );
}
add_action( 'after_setup_theme', 'my_theme_load_textdomain' );
?>
这段代码告诉 WordPress,my-theme
这个 text domain 的翻译文件在 get_template_directory() . '/languages'
目录下。 after_setup_theme
action hook 确保在主题初始化完成后加载翻译文件。
四、 Text Domain:翻译文件的身份证
每个主题或插件都应该有一个唯一的 text domain。 就像身份证一样,用来区分不同的翻译文件。
- 命名规则: 通常是主题或插件的 slug。 比如,你的主题叫 "Awesome Theme",那么 text domain 可以是 "awesome-theme"。
- 作用: 告诉 WordPress,哪些翻译字符串属于哪个主题或插件。
- 使用: 在翻译函数中作为第二个参数传递。 比如
__('Hello, world!', 'awesome-theme')
。
五、 翻译文件:藏宝图的秘密
翻译文件是 L10n 的核心。 它包含了原始字符串和翻译后的字符串的对应关系。
- 格式: 通常是
.po
和.mo
文件。.po
文件是人类可读的文本文件,包含了原始字符串和翻译后的字符串。.mo
文件是机器可读的二进制文件,是.po
文件的编译版本。 WordPress 使用.mo
文件来提高翻译效率。
- 位置: 通常放在主题或插件的
/languages
目录下。 - 生成: 可以使用 Poedit 等工具来创建和编辑
.po
文件。
.po
文件示例:
msgid "Hello, world!"
msgstr "你好,世界!"
msgid "%s comment"
msgid_plural "%s comments"
msgstr[0] "%s 条评论"
msgstr[1] "%s 条评论"
msgctxt "post type general name"
msgid "Post"
msgstr "文章"
msgctxt "submit button"
msgid "Post"
msgstr "发布"
msgid
: 原始字符串。msgstr
: 翻译后的字符串。msgid_plural
: 复数形式的原始字符串(用于_n()
函数)。msgstr[0]
、msgstr[1]
: 不同数量对应的翻译(用于_n()
函数)。msgctxt
: 上下文(用于_x()
函数)。
六、 WordPress 如何找到翻译文件?
WordPress 会按照以下顺序查找翻译文件:
WP_LANG_DIR/plugins/{plugin-slug}-{locale}.mo
WP_LANG_DIR/themes/{theme-slug}-{locale}.mo
WP_LANG_DIR/{locale}.mo
wp-content/languages/plugins/{plugin-slug}-{locale}.mo
wp-content/languages/themes/{theme-slug}-{locale}.mo
wp-content/languages/{locale}.mo
wp-includes/languages/{locale}.mo
其中:
WP_LANG_DIR
: 是 WordPress 语言目录的路径,通常是wp-content/languages
。{plugin-slug}
: 是插件的 slug。{theme-slug}
: 是主题的 slug。{locale}
: 是语言区域代码,比如zh_CN
(简体中文) 或en_US
(美式英语)。
WordPress 会找到第一个匹配的 .mo
文件,并加载它。
七、 最佳实践:让你的代码更国际化
- 使用统一的 text domain: 为你的主题或插件选择一个唯一的 text domain,并在所有翻译函数中使用它。
- 尽早开始国际化: 不要等到项目快完成时才考虑国际化。 越早开始,越容易。
- 使用清晰的原始字符串: 原始字符串应该简洁明了,易于理解。 避免使用复杂的语法或缩写。
- 提供上下文: 对于含义模糊的字符串,使用
_x()
函数提供上下文,以便翻译人员能够做出更准确的翻译。 - 测试你的代码: 确保你的代码在不同的语言环境下都能正常工作。
- 使用专业的翻译工具: Poedit 是一个流行的翻译工具,可以帮助你创建和编辑
.po
文件。 - 参与 WordPress 翻译项目: 你可以参与 WordPress 官方的翻译项目,为 WordPress 贡献你的力量。
八、 进阶技巧:更上一层楼
- 动态 Text Domain: 有时候,你可能需要在运行时动态地设置 text domain。 可以使用
load_textdomain()
函数来实现。 - 使用 Transients 缓存翻译: 频繁地读取翻译文件会影响性能。 可以使用 Transients API 来缓存翻译结果。
- 自定义翻译函数: 如果 WordPress 提供的翻译函数不能满足你的需求,你可以自定义翻译函数。
九、 常见问题:疑难杂症,一网打尽
- 翻译不生效: 检查 text domain 是否正确,翻译文件是否存在,以及是否正确加载了翻译文件。
- 乱码: 确保你的文件编码是 UTF-8。
- 翻译不完整: 检查
.po
文件是否包含所有需要翻译的字符串。 - 性能问题: 使用 Transients API 缓存翻译结果。
十、 总结:L10n,让世界倾听你的声音
WordPress L10n 是一套强大而灵活的国际化和本地化机制。 掌握 L10n 的原理和使用方法,可以让你的 WordPress 站点面向全球用户,让世界倾听你的声音。
好了,今晚的讲座就到这里。 希望大家有所收获。 如果有什么问题,欢迎提问。 谢谢大家! 记得点赞关注哦!