大家好,欢迎来到今天的“WordPress翻译探秘之旅”。我是你们今天的导游,名叫“代码侦探”,专职挖掘那些隐藏在WordPress源码深处的秘密。今天,我们要一起扒一扒 load_plugin_textdomain() 这个神秘函数,看看它到底是怎么为我们的插件加载翻译文件的。
准备好了吗?Let’s go!
第一站:什么是 Text Domain?
在深入 load_plugin_textdomain() 之前,我们先要搞清楚一个核心概念:Text Domain。你可以把它想象成一个“翻译身份证”,每个插件都有一个独一无二的身份证号,用来区分不同的翻译文件。
举个例子,如果你的插件叫做 "My Awesome Plugin",你的 Text Domain 可能是 "my-awesome-plugin"。这个名字很重要,因为它会出现在你的插件代码中,也出现在翻译文件的命名中。
Text Domain 的作用:
- 区分翻译文件: 避免不同插件的翻译文件冲突。
- 绑定翻译与代码: 将特定翻译文件与特定插件的代码关联起来。
第二站:load_plugin_textdomain() 的基本用法
好了,现在我们来看看 load_plugin_textdomain() 函数的基本用法。这个函数通常放在插件的主文件中,在插件激活的时候调用。
<?php
/**
* Plugin Name: My Awesome Plugin
* Description: A plugin that does awesome things.
* Version: 1.0.0
* Author: Code Detective
*/
add_action( 'plugins_loaded', 'my_awesome_plugin_load_textdomain' );
function my_awesome_plugin_load_textdomain() {
load_plugin_textdomain(
'my-awesome-plugin', // Text Domain
false, // Deprecated argument (always false)
dirname( plugin_basename( __FILE__ ) ) . '/languages/' // Path to the languages folder
);
}
代码解释:
add_action( 'plugins_loaded', 'my_awesome_plugin_load_textdomain' ): 这行代码的意思是,当 WordPress 加载完所有插件后,就执行my_awesome_plugin_load_textdomain()函数。load_plugin_textdomain(): 这是我们今天的主角,它负责加载翻译文件。'my-awesome-plugin': 这是 Text Domain,必须和你的插件代码中使用的 Text Domain 保持一致。false: 这个参数已经过时了,始终设置为false。dirname( plugin_basename( __FILE__ ) ) . '/languages/': 这是翻译文件存放的路径。plugin_basename( __FILE__ )获取插件主文件的相对路径,dirname()获取插件主文件的目录,然后拼接上/languages/,表示翻译文件存放在插件目录下的languages文件夹中。
翻译文件的命名规则:
翻译文件必须遵循一定的命名规则,才能被 WordPress 正确加载。规则如下:
{textdomain}-{locale}.mo
{textdomain}: 插件的 Text Domain,例如my-awesome-plugin。{locale}: WordPress 的本地化代码,例如zh_CN(简体中文),en_US(美国英语),fr_FR(法语) 等。- .mo: 这是编译后的二进制翻译文件,需要使用工具从
.po文件生成。
所以,如果你的插件 Text Domain 是 my-awesome-plugin,你想提供简体中文翻译,你的翻译文件就应该命名为 my-awesome-plugin-zh_CN.mo。
第三站:深入 load_plugin_textdomain() 源码
现在,我们来深入 load_plugin_textdomain() 的源码,看看它背后到底做了什么。
为了方便查看,我们简化一下代码(省略一些不常用的参数和错误处理):
// wp-includes/l10n.php
function load_plugin_textdomain( $domain, $deprecated, $plugin_rel_path ) {
return load_textdomain( $domain, WP_PLUGIN_DIR . '/' . $plugin_rel_path . '/' . $domain . '-' . get_locale() . '.mo' );
}
function load_textdomain( $domain, $mofile ) {
global $l10n;
if ( isset( $l10n[ $domain ] ) ) {
return true; // Already loaded
}
if ( ! is_readable( $mofile ) ) {
return false; // File not found
}
$l10n[ $domain ] = new MO();
$loaded = $l10n[ $domain ]->import_from_file( $mofile );
return $loaded;
}
代码解释:
load_plugin_textdomain():- 它接收 Text Domain (
$domain) 和 翻译文件相对路径 ($plugin_rel_path) 作为参数。 - 它拼接出完整的翻译文件路径,然后调用
load_textdomain()函数。
- 它接收 Text Domain (
load_textdomain():- 它接收 Text Domain (
$domain) 和 翻译文件完整路径 ($mofile) 作为参数。 - 检查是否已经加载: 首先检查全局变量
$l10n中是否已经存在该 Text Domain 的翻译,如果存在,则直接返回true,避免重复加载。 - 检查文件是否存在: 然后检查翻译文件是否存在且可读,如果不存在,则返回
false。 - 加载翻译文件: 如果文件存在,则创建一个
MO对象(MO类是 WordPress 用来处理.mo文件的类),并调用import_from_file()方法加载翻译文件。 - 存储翻译数据: 将加载的翻译数据存储到全局变量
$l10n中,以 Text Domain 作为键。 - 返回结果: 返回
import_from_file()的结果,表示是否成功加载翻译文件。
- 它接收 Text Domain (
MO 类:
MO 类负责解析 .mo 文件,并将翻译数据存储在内存中。它的 import_from_file() 方法会读取 .mo 文件的内容,并将其转换为一个关联数组,其中键是原文,值是译文。
总结:
load_plugin_textdomain() 函数实际上只是一个简单的封装,它主要负责拼接翻译文件的完整路径,然后调用 load_textdomain() 函数来真正加载翻译文件。load_textdomain() 函数则负责检查文件是否存在、是否已经加载,以及使用 MO 类加载翻译数据。
第四站:实战演练
光说不练假把式,我们来做一个简单的实战演练。
- 创建插件: 创建一个名为
my-awesome-plugin的插件,包含一个主文件my-awesome-plugin.php和一个languages文件夹。 - 添加代码: 将上面的代码示例添加到
my-awesome-plugin.php文件中。 - 添加翻译: 在
my-awesome-plugin.php文件中添加一些需要翻译的文本。
<?php
/**
* Plugin Name: My Awesome Plugin
* Description: A plugin that does awesome things.
* Version: 1.0.0
* Author: Code Detective
*/
add_action( 'plugins_loaded', 'my_awesome_plugin_load_textdomain' );
function my_awesome_plugin_load_textdomain() {
load_plugin_textdomain(
'my-awesome-plugin',
false,
dirname( plugin_basename( __FILE__ ) ) . '/languages/'
);
}
function my_awesome_plugin_output() {
echo '<p>' . __( 'Hello, world!', 'my-awesome-plugin' ) . '</p>';
echo '<p>' . __( 'This is an awesome plugin.', 'my-awesome-plugin' ) . '</p>';
}
add_action( 'wp_footer', 'my_awesome_plugin_output' );
- 创建
.po文件: 使用 Poedit 或其他翻译工具,创建一个名为my-awesome-plugin-zh_CN.po的文件,并添加以下翻译:
msgid "Hello, world!"
msgstr "你好,世界!"
msgid "This is an awesome plugin."
msgstr "这是一个很棒的插件。"
- 编译
.mo文件: 使用 Poedit 或其他翻译工具,将.po文件编译成.mo文件。 - 上传文件: 将
my-awesome-plugin-zh_CN.mo文件上传到my-awesome-plugin/languages/文件夹中。 - 设置 WordPress 语言: 在 WordPress 后台,将语言设置为简体中文。
- 激活插件: 激活
My Awesome Plugin插件。
现在,刷新你的网站,你应该可以看到 "Hello, world!" 和 "This is an awesome plugin." 已经变成了中文。
第五站:高级用法与技巧
- 使用不同的翻译文件路径: 你可以通过修改
load_plugin_textdomain()的第三个参数来指定不同的翻译文件路径。例如,你可以将翻译文件放在主题的languages文件夹中。 - 使用
load_muplugin_textdomain()和load_child_theme_textdomain(): WordPress 还提供了load_muplugin_textdomain()和load_child_theme_textdomain()函数,分别用于加载 Must-Use 插件和子主题的翻译文件。 - 使用
__(),_e(),_x(),_ex()等翻译函数: WordPress 提供了多个翻译函数,用于处理不同类型的翻译需求。__()返回翻译后的字符串,_e()直接输出翻译后的字符串,_x()允许你提供上下文信息,_ex()结合了_x()和_e()的功能。 - 使用
wp i18n make-pot命令: WordPress CLI 提供了wp i18n make-pot命令,可以自动从你的插件或主题代码中提取需要翻译的文本,并生成一个.po文件。
总结:
| 函数/命令 | 作用 |
|---|---|
load_plugin_textdomain() |
加载插件的翻译文件。 |
load_muplugin_textdomain() |
加载 Must-Use 插件的翻译文件。 |
load_child_theme_textdomain() |
加载子主题的翻译文件。 |
__() |
返回翻译后的字符串。 |
_e() |
输出翻译后的字符串。 |
_x() |
返回翻译后的字符串,允许提供上下文信息。 |
_ex() |
输出翻译后的字符串,允许提供上下文信息。 |
wp i18n make-pot |
自动从代码中提取需要翻译的文本,并生成 .po 文件。 |
第六站:常见问题与解决方法
- 翻译文件没有生效:
- 检查 Text Domain 是否正确。
- 检查翻译文件命名是否符合规则。
- 检查翻译文件路径是否正确。
- 检查 WordPress 语言设置是否正确。
- 清除 WordPress 缓存。
- 翻译文本显示不完整:
- 检查
.po文件中是否存在错误的翻译。 - 检查
.mo文件是否已正确编译。
- 检查
- 使用
wp i18n make-pot命令时出错:- 检查 WordPress CLI 是否已正确安装和配置。
- 检查你的插件或主题代码中是否存在语法错误。
第七站:旅程结束
恭喜你,完成了今天的“WordPress翻译探秘之旅”!希望你对 load_plugin_textdomain() 函数有了更深入的了解。现在,你可以自信地为你的插件添加翻译功能,让你的插件走向世界!
记住,代码的世界充满了乐趣和挑战,Keep exploring! 下次再见! (挥手)