研究 WordPress 插件国际化函数 load_plugin_textdomain

WordPress 插件国际化:深入理解 load_plugin_textdomain

大家好!今天我们来深入探讨 WordPress 插件国际化的核心函数:load_plugin_textdomain。国际化(i18n)和本地化(l10n)是使你的插件能够被全球用户使用的关键步骤。load_plugin_textdomain 正是连接你的插件与不同语言翻译文件的桥梁。

1. 国际化和本地化的概念回顾

在深入 load_plugin_textdomain 之前,我们先简要回顾一下国际化和本地化的概念:

  • 国际化 (i18n): 设计和开发软件,使其能够在无需修改代码的情况下适应不同的语言和区域设置。这包括准备代码以使用翻译文件,处理不同的日期、时间和货币格式等。

  • 本地化 (l10n): 将国际化的软件适配到特定的语言和区域。这通常涉及翻译用户界面文本,调整日期和时间格式,以及适应当地的文化习俗。

2. load_plugin_textdomain 函数详解

load_plugin_textdomain 函数用于加载插件的翻译文件,从而使插件可以显示本地化的文本。它的基本语法如下:

<?php
load_plugin_textdomain(
    string $domain,
    bool $deprecated, // 已弃用,始终传递 false
    string $plugin_rel_path = false
);
?>
  • $domain (string): 插件的唯一文本域 (text domain)。这是最重要的参数,用于区分不同插件或主题的翻译字符串。强烈建议使用与插件 slug (插件目录名) 相同的文本域。

  • $deprecated (bool): 已弃用的参数,始终传递 false

  • $plugin_rel_path (string, optional): 翻译文件相对于插件主文件的路径。如果省略,WordPress 会在 wp-content/languages/plugins/ 目录下查找翻译文件。建议将翻译文件放在插件目录下的 languages 文件夹中,并在此处指定相对路径。

3. 使用 load_plugin_textdomain 的步骤

使用 load_plugin_textdomain 的典型步骤如下:

  1. 确定文本域 (text domain): 为你的插件选择一个唯一的文本域。通常,建议使用与插件目录名相同的名称。例如,如果你的插件目录是 my-awesome-plugin,那么文本域也应该是 my-awesome-plugin

  2. 准备翻译字符串: 在你的插件代码中使用国际化函数 (__(), _e(), _x(), _n(), _ex()) 来包装需要翻译的文本。

  3. 创建 POT 文件: 使用工具(如 Poedit 或 WP-CLI)从你的插件代码中提取所有翻译字符串,并创建一个 .pot (Portable Object Template) 文件。这个文件作为翻译的基础模板。

  4. 创建 MO/PO 文件:.pot 文件分发给翻译人员。翻译人员使用 Poedit 或其他翻译工具创建特定语言的 .po (Portable Object) 文件,然后将其编译成 .mo (Machine Object) 文件。.mo 文件是 WordPress 实际使用的二进制翻译文件。

  5. 放置 MO/PO 文件:.mo.po 文件放置在正确的目录下。通常,建议将它们放在插件目录下的 languages 文件夹中。文件名应遵循 textdomain-locale.mo 的格式,例如 my-awesome-plugin-zh_CN.mo

  6. 调用 load_plugin_textdomain: 在你的插件的主文件中,使用 load_plugin_textdomain 函数加载翻译文件。

4. 代码示例

以下是一个完整的代码示例,演示了如何使用 load_plugin_textdomain

my-awesome-plugin.php (插件主文件):

<?php
/**
 * Plugin Name: My Awesome Plugin
 * Description: A simple plugin to demonstrate internationalization.
 * Version: 1.0.0
 * Author: Your Name
 */

// 确保在 plugins_loaded 钩子上调用 load_plugin_textdomain
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_text() {
    echo '<p>' . __( 'Hello, world!', 'my-awesome-plugin' ) . '</p>';
    echo '<p>' . sprintf( __( 'You have %d new messages.', 'my-awesome-plugin' ), 5 ) . '</p>';
}

add_action( 'wp_footer', 'my_awesome_plugin_output_text' );

languages/my-awesome-plugin-zh_CN.po (中文翻译文件):

msgid ""
msgstr ""
"Project-Id-Version: My Awesome Pluginn"
"POT-Creation-Date: 2023-10-27 10:00+0000n"
"PO-Revision-Date: 2023-10-27 10:00+0000n"
"Last-Translator: Your Name <[email protected]>n"
"Language-Team: Chinese (Simplified) <[email protected]>n"
"Language: zh_CNn"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=UTF-8n"
"Content-Transfer-Encoding: 8bitn"
"Plural-Forms: nplurals=1; plural=0;n"

msgid "Hello, world!"
msgstr "你好,世界!"

msgid "You have %d new messages."
msgstr "您有 %d 条新消息。"

languages/my-awesome-plugin-zh_CN.mo (编译后的中文翻译文件):

(此文件是 .po 文件的二进制编译版本,无法直接查看)

在这个例子中:

  • 文本域被设置为 my-awesome-plugin
  • load_plugin_textdomain 函数在 plugins_loaded 钩子上被调用,确保在所有插件加载后执行。
  • plugin_basename( __FILE__ ) 返回插件主文件的路径。
  • dirname() 函数用于获取插件目录的路径。
  • 相对路径被设置为 languages/,表示翻译文件位于插件目录下的 languages 文件夹中。
  • __() 函数用于包装需要翻译的文本。
  • sprintf() 函数用于处理带有占位符的字符串。
  • .po 文件包含了英文原文和中文翻译。
  • .mo 文件是 .po 文件的编译版本,WordPress 将使用它来显示翻译后的文本。

5. 国际化函数详解

WordPress 提供了多个国际化函数,用于包装需要翻译的文本。以下是一些常用的函数:

函数 描述 示例
__() 返回已翻译的字符串。如果找不到翻译,则返回原始字符串。 echo __( 'Hello, world!', 'my-awesome-plugin' );
_e() 输出已翻译的字符串。如果找不到翻译,则输出原始字符串。 _e( 'Hello, world!', 'my-awesome-plugin' );
_x() 返回带上下文的已翻译的字符串。上下文用于区分具有相同文本但含义不同的字符串。 echo _x( 'Post', 'noun', 'my-awesome-plugin' );
_ex() 输出带上下文的已翻译的字符串。上下文用于区分具有相同文本但含义不同的字符串。 _ex( 'Post', 'noun', 'my-awesome-plugin' );
_n() 返回单数或复数形式的已翻译的字符串,具体取决于给定的数量。 echo sprintf( _n( '%d comment', '%d comments', $comment_count, 'my-awesome-plugin' ), $comment_count );
_nx() 返回带上下文的单数或复数形式的已翻译的字符串,具体取决于给定的数量。 echo sprintf( _nx( '%d item', '%d items', $item_count, 'shopping cart', 'my-awesome-plugin' ), $item_count );
esc_attr__() 返回已翻译的字符串,并对其进行 HTML 属性转义。这对于在 HTML 属性中使用翻译后的字符串非常重要,以防止安全漏洞。 <input type="text" value="<?php echo esc_attr__( 'Search...', 'my-awesome-plugin' ); ?>">
esc_html__() 返回已翻译的字符串,并对其进行 HTML 转义。这对于在 HTML 内容中使用翻译后的字符串非常重要,以防止安全漏洞。 <h1><?php echo esc_html__( 'Welcome!', 'my-awesome-plugin' ); ?></h1>
esc_attr_e() 输出已翻译的字符串,并对其进行 HTML 属性转义。 <input type="text" value="<?php esc_attr_e( 'Search...', 'my-awesome-plugin' ); ?>">
esc_html_e() 输出已翻译的字符串,并对其进行 HTML 转义。 <h1><?php esc_html_e( 'Welcome!', 'my-awesome-plugin' ); ?></h1>
translate() 返回已翻译的字符串。这是所有其他国际化函数的基础。通常不直接使用此函数,而是使用 __(), _e() 等函数。 echo translate( 'Hello, world!', 'my-awesome-plugin' );

重要提示: 始终使用适当的转义函数(如 esc_attr__()esc_html__())来处理翻译后的字符串,以防止 XSS 攻击。

6. 翻译文件的目录结构

WordPress 查找翻译文件的目录结构如下:

  1. WP_LANG_DIR/plugins (推荐): wp-content/languages/plugins/ 目录。这是存储插件翻译文件的推荐位置。文件名应遵循 textdomain-locale.mo 的格式,例如 my-awesome-plugin-zh_CN.mo

  2. 插件的 languages 目录: 如果 $plugin_rel_path 参数被传递给 load_plugin_textdomain 函数,WordPress 将在插件目录下的指定路径中查找翻译文件。建议将翻译文件放在插件目录下的 languages 文件夹中,并在此处指定相对路径。

  3. WP_LANG_DIR: wp-content/languages/ 目录。WordPress 也会在此处查找翻译文件,但不建议将插件翻译文件放在此目录中,因为它主要用于存储 WordPress 核心的翻译文件。

WordPress 首先在 WP_LANG_DIR/plugins 目录中查找翻译文件。如果找不到,它将在插件的 languages 目录中查找(如果指定了 $plugin_rel_path),最后在 WP_LANG_DIR 目录中查找。

7. 使用 WP-CLI 进行国际化

WP-CLI (WordPress Command Line Interface) 提供了一组命令,可以简化国际化过程。以下是一些常用的 WP-CLI 命令:

  • wp i18n make-pot: 从 PHP 文件或主题/插件中提取翻译字符串,并创建一个 .pot 文件。

    wp i18n make-pot ./my-awesome-plugin my-awesome-plugin.pot
  • wp i18n update-po: 使用 .pot 文件更新现有的 .po 文件。

    wp i18n update-po my-awesome-plugin-zh_CN.po my-awesome-plugin.pot
  • wp i18n make-json: 从 MO 文件生成 JSON 文件。这对于使用 JavaScript 进行国际化非常有用。

    wp i18n make-json languages/my-awesome-plugin-zh_CN.mo languages/

使用 WP-CLI 可以自动化许多国际化任务,从而节省时间和精力。

8. 调试国际化问题

当国际化没有按预期工作时,可以尝试以下调试步骤:

  1. 检查文本域: 确保在 load_plugin_textdomain 函数和国际化函数中使用的文本域一致。

  2. 检查 MO/PO 文件名: 确保 MO/PO 文件的文件名遵循 textdomain-locale.mo 的格式,并且 locale 正确。

  3. 检查 MO/PO 文件路径: 确保 MO/PO 文件位于正确的目录中,并且 $plugin_rel_path 参数(如果使用)指向正确的路径。

  4. 清除缓存: 清除 WordPress 缓存和浏览器缓存,以确保加载最新的翻译文件。

  5. 启用 WP_DEBUG:wp-config.php 文件中启用 WP_DEBUG 模式,以查看任何 PHP 错误或警告。

  6. 使用 Loco Translate 插件: Loco Translate 是一款流行的 WordPress 插件,可以简化翻译文件的管理和编辑。它还提供了一些调试工具,可以帮助你找到国际化问题。

9. 插件更新与国际化

当更新插件时,务必重新生成 .pot 文件,并将其提供给翻译人员,以便他们更新翻译文件。此外,确保在插件更新后清除 WordPress 缓存,以确保加载最新的翻译文件。

10. 最佳实践

以下是一些国际化的最佳实践:

  • 使用唯一的文本域: 为你的插件选择一个唯一的文本域,以避免与其他插件或主题冲突。
  • 使用国际化函数包装所有文本: 确保使用国际化函数 (__(), _e(), _x(), _n()) 包装所有需要翻译的文本。
  • 使用适当的转义函数: 始终使用适当的转义函数(如 esc_attr__()esc_html__())来处理翻译后的字符串,以防止 XSS 攻击。
  • 提供高质量的翻译: 确保翻译准确、流畅,并且符合当地的文化习俗。
  • 与翻译人员合作: 与专业的翻译人员合作,以确保翻译的质量。
  • 使用 WP-CLI 自动化国际化任务: 使用 WP-CLI 可以自动化许多国际化任务,从而节省时间和精力。
  • 定期更新翻译文件: 当更新插件时,务必重新生成 .pot 文件,并将其提供给翻译人员,以便他们更新翻译文件。
  • 测试国际化: 在不同的语言和区域设置下测试你的插件,以确保国际化按预期工作。

加载翻译文件和使用国际化函数

load_plugin_textdomain 函数是 WordPress 插件国际化的关键,它将插件与翻译文件连接起来。通过正确使用此函数和相关的国际化函数,你可以轻松地将你的插件翻译成多种语言,并使其能够被全球用户使用。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注