大家好,欢迎来到今天的“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! 下次再见! (挥手)