各位观众老爷,大家好!今天咱们来聊聊 WordPress 翻译背后的功臣:load_textdomain()
函数。这玩意儿听起来高大上,但其实就像个辛勤的搬运工,负责把各种语言包(也就是 .mo
文件)搬到 WordPress 的大脑里,让你的网站能说多国语言。
咱们今天就来扒一扒它的源码,看看它是怎么工作的,以及我们作为开发者该如何正确使用它。准备好了吗?发车!
1. load_textdomain()
函数的身世背景
load_textdomain()
函数是 WordPress 内核中的一个核心函数,定义在 wp-includes/l10n.php
文件中。它的作用就是加载指定文本域(Text Domain)的翻译文件,让 WordPress 能够根据用户的语言设置显示相应的翻译文本。
简单来说,它就是个翻译器,把你的英文(或其他语言)代码里的文本,翻译成用户选择的语言。
2. 函数签名及参数详解
先来看看 load_textdomain()
的函数签名:
/**
* Loads a .mo file into the text domain.
*
* If the text domain already exists, the translations will be merged. If both
* sets of translations have the same string, the translation from the original
* text domain will be used.
*
* @since 1.5.0
*
* @global array $l10n An array of translations.
*
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the MO file.
* @param string|null $locale Optional. Locale to load. If not set, uses the active locale.
* @return bool True on success, false on failure.
*/
function load_textdomain( $domain, $mofile, $locale = null ) {
// 函数体,后面再详细分析
}
参数解释:
$domain
(string): 文本域。这是个非常重要的参数,它就像你的插件或主题的“名字”,WordPress 用它来区分不同的翻译文件。 建议使用插件或主题的slug命名,避免冲突。$mofile
(string):.mo
文件的完整路径。.mo
文件是编译后的机器可读的翻译文件,包含了所有翻译信息。$locale
(string, optional): 可选参数,指定要加载的语言区域设置。 如果为空(null
),则使用 WordPress 当前的语言区域设置。
返回值:
bool
: 成功加载返回true
,失败返回false
。
3. 源码深度解析:load_textdomain()
的工作流程
现在,让我们深入 load_textdomain()
的源码,看看它到底做了些什么:
function load_textdomain( $domain, $mofile, $locale = null ) {
global $l10n;
/**
* Filters the locale to use when loading a text domain.
*
* @since 4.7.0
*
* @param string|null $locale The locale to use. Null if the locale is not set.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the MO file.
*/
$locale = apply_filters( 'load_textdomain_locale', $locale, $domain, $mofile );
if ( null === $locale ) {
$locale = determine_locale();
}
if ( ! is_readable( $mofile ) ) {
return false;
}
$l10n[ $domain ] = new MO();
if ( ! $l10n[ $domain ]->import_from_file( $mofile ) ) {
unset( $l10n[ $domain ] );
return false;
}
$l10n[ $domain ]->set_domain( $domain );
/**
* Fires after the text domain is loaded.
*
* @since 2.9.0
*
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the MO file.
*/
do_action( 'load_textdomain', $domain, $mofile );
return true;
}
逐行分析:
-
global $l10n;
: 声明全局变量$l10n
。 这个全局数组是 WordPress 用来存储所有已加载的翻译信息的“大仓库”。 每个文本域对应一个MO
对象,MO
对象里包含了该文本域的所有翻译。 -
$locale = apply_filters( 'load_textdomain_locale', $locale, $domain, $mofile );
: 应用load_textdomain_locale
过滤器。 这个过滤器允许开发者修改要加载的语言区域设置。 比如,你可以根据用户的 IP 地址,动态选择加载不同的语言包。 -
if ( null === $locale ) { $locale = determine_locale(); }
: 如果$locale
为空,则使用determine_locale()
函数获取 WordPress 当前的语言区域设置。determine_locale()
函数会从 WordPress 的配置中读取WPLANG
常量,如果WPLANG
没有设置,则会使用默认的'en_US'
。 -
if ( ! is_readable( $mofile ) ) { return false; }
: 检查.mo
文件是否存在且可读。 如果文件不存在或无法读取,则加载失败,直接返回false
。 -
$l10n[ $domain ] = new MO();
: 创建一个MO
对象,并将其赋值给$l10n
数组中以$domain
为键的元素。MO
类负责解析.mo
文件,并将其中的翻译信息存储在内存中。 -
if ( ! $l10n[ $domain ]->import_from_file( $mofile ) ) { unset( $l10n[ $domain ] ); return false; }
: 调用MO
对象的import_from_file()
方法,从.mo
文件中导入翻译信息。 如果导入失败,则从$l10n
数组中删除该文本域,并返回false
。 -
$l10n[ $domain ]->set_domain( $domain );
: 设置MO
对象的文本域。 这主要是为了方便后续的翻译查找。 -
do_action( 'load_textdomain', $domain, $mofile );
: 触发load_textdomain
动作。 这个动作允许开发者在文本域加载完成后执行一些自定义操作,比如记录日志或更新缓存。 -
return true;
: 加载成功,返回true
。
4. 核心类:MO
类
MO
类是 WordPress 中处理 .mo
文件的核心类,它负责解析 .mo
文件,并将其中的翻译信息存储在内存中。 MO
类的源码位于 wp-includes/pomo/mo.php
文件中。
MO
类的主要方法包括:
import_from_file( $filename )
: 从指定的文件中导入翻译信息。translate( $string )
: 翻译指定的字符串。set_domain( $domain )
: 设置文本域。
MO
类的内部实现比较复杂,涉及到文件读取、字节序转换、哈希表查找等技术。 这里就不深入分析了,有兴趣的同学可以自行研究。
5. 如何正确使用 load_textdomain()
要正确使用 load_textdomain()
,需要注意以下几点:
- 选择合适的文本域: 文本域应该具有唯一性,通常使用插件或主题的 slug。
- 放置正确的
.mo
文件:.mo
文件应该放在插件或主题的languages
目录下,并以[text-domain]-[locale].mo
的格式命名。例如,my-plugin-zh_CN.mo
。 - 在合适的时间调用
load_textdomain()
: 建议在插件或主题的初始化阶段调用load_textdomain()
,比如在plugins_loaded
或after_setup_theme
动作中。 - 使用
__()
、_e()
、_x()
、_n()
等翻译函数: 这些函数会自动使用已加载的翻译信息,将你的代码中的文本翻译成用户选择的语言。
6. 示例代码:在插件中使用 load_textdomain()
下面是一个简单的示例,演示如何在插件中使用 load_textdomain()
:
<?php
/**
* Plugin Name: My Awesome Plugin
* Description: A simple plugin to demonstrate how to use load_textdomain().
* Version: 1.0.0
*/
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>';
}
add_action( 'wp_footer', 'my_awesome_plugin_output' );
代码解释:
-
add_action( 'plugins_loaded', 'my_awesome_plugin_load_textdomain' );
: 在plugins_loaded
动作中注册my_awesome_plugin_load_textdomain()
函数。 -
function my_awesome_plugin_load_textdomain() { ... }
:my_awesome_plugin_load_textdomain()
函数调用load_plugin_textdomain()
函数加载翻译文件。 -
load_plugin_textdomain( 'my-awesome-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
:load_plugin_textdomain()
函数是 WordPress 提供的一个便捷函数,用于加载插件的翻译文件。 它实际上是对load_textdomain()
函数的封装。'my-awesome-plugin'
:文本域。false
: 是否加载全局文本域。通常设置为false
。dirname( plugin_basename( __FILE__ ) ) . '/languages/'
: 翻译文件的相对路径。
-
function my_awesome_plugin_output() { ... }
:my_awesome_plugin_output()
函数输出一个包含翻译文本的段落。 -
echo '<p>' . __( 'Hello, world!', 'my-awesome-plugin' ) . '</p>';
:__()
函数用于翻译字符串。 第一个参数是要翻译的字符串,第二个参数是文本域。
7. load_plugin_textdomain()
和 load_theme_textdomain()
WordPress 还提供了两个方便的函数,用于加载插件和主题的翻译文件:
load_plugin_textdomain( $domain, $deprecated, $plugin_rel_path )
: 加载插件的翻译文件。load_theme_textdomain( $domain, $template_directory )
: 加载主题的翻译文件。
这两个函数实际上是对 load_textdomain()
函数的封装,简化了参数的设置。
8. 翻译文件格式:.po
和 .mo
翻译文件有两种格式:.po
和 .mo
。
- .po (Portable Object) 文件是人类可读的文本文件,包含了原始字符串和对应的翻译。 开发者可以使用
.po
文件进行翻译。 - .mo (Machine Object) 文件是编译后的机器可读的文件,包含了所有翻译信息。 WordPress 使用
.mo
文件进行翻译。
可以使用 Poedit 等工具创建和编辑 .po
文件,并将其编译成 .mo
文件。
9. 常见问题及解决方案
- 翻译不生效: 检查文本域是否正确,
.mo
文件是否存在且可读,以及是否在合适的时间调用了load_textdomain()
函数。 另外,确保 WordPress 的语言设置正确。 还可以尝试清除 WordPress 的缓存。 - 文本域冲突: 确保你的插件或主题的文本域与其他插件或主题不冲突。 建议使用插件或主题的 slug 作为文本域。
.mo
文件损坏: 重新编译.po
文件生成.mo
文件。
10. 总结
load_textdomain()
函数是 WordPress 翻译机制的核心。 理解它的工作原理,可以帮助你更好地进行插件和主题的国际化。 记住,选择合适的文本域,放置正确的 .mo
文件,并在合适的时间调用 load_textdomain()
函数,就可以让你的网站说多国语言,走向世界!
今天的讲座就到这里,希望对大家有所帮助。 感谢收看!