WordPress国际化:如何利用`wp_i18n`和`PO/MO`文件实现多语言支持?

WordPress国际化:wp_i18n与PO/MO文件的多语言实践

各位同学,大家好。今天我们来深入探讨WordPress的国际化(i18n)和本地化(l10n),重点讲解如何利用WordPress内置的wp_i18n函数和PO/MO文件来实现主题和插件的多语言支持。

1. 国际化(i18n)与本地化(l10n)的概念区分

首先,我们需要明确国际化(i18n)和本地化(l10n)的区别:

  • 国际化 (i18n):指的是在软件设计和开发阶段,使其能够适应不同地区用户的语言、文化和技术要求的过程。简单来说,就是让你的代码具备支持多种语言的能力,而无需修改代码本身。
  • 本地化 (l10n):指的是根据特定地区或语言的需要,对软件进行修改和定制的过程。例如,将文本翻译成中文、调整日期格式、货币符号等。

在WordPress中,国际化主要通过wp_i18n函数来实现,本地化则主要通过PO/MO文件来存储翻译后的文本。

2. wp_i18n函数:国际化的基石

wp_i18n提供了一系列函数,用于标记需要翻译的文本。这些函数会根据当前WordPress设置的语言环境,查找对应的翻译文本,并将其显示出来。

以下是一些常用的wp_i18n函数:

函数名 功能描述
__() 最基础的翻译函数。用于获取翻译后的文本,并直接输出。
_e() __()类似,但直接输出翻译后的文本。
_x() 带上下文的翻译函数。当同一个词在不同上下文中有不同的含义时,可以使用此函数区分。
_ex() _x()类似,但直接输出翻译后的文本。
_n() 用于处理单复数形式的翻译。根据数量的不同,选择不同的翻译文本。
_nx() 带上下文的单复数翻译函数。
esc_attr__() 翻译并转义HTML属性值。
esc_attr_e() 翻译并转义HTML属性值,并直接输出。
esc_html__() 翻译并转义HTML内容。
esc_html_e() 翻译并转义HTML内容,并直接输出。
translate() 底层翻译函数。接受文本、域 (text domain) 和上下文 (context) 作为参数,返回翻译后的文本。
load_theme_textdomain() 加载主题的翻译文件。
load_plugin_textdomain() 加载插件的翻译文件。
get_locale() 获取当前的语言环境。
is_rtl() 判断当前的语言环境是否为从右向左书写。

2.1 使用__()_e()

这两个函数是最常用的翻译函数。__()返回翻译后的文本,_e()则直接输出翻译后的文本。

<?php
// 使用 __()
$translated_text = __('Hello, world!', 'my-theme');
echo '<p>' . $translated_text . '</p>';

// 使用 _e()
_e('Welcome to my website!', 'my-theme');
?>

2.2 使用_x()_ex()

当同一个词在不同上下文中具有不同的含义时,可以使用_x()函数来指定上下文。

<?php
// "Post" 作为名词
$noun_post = _x('Post', 'noun', 'my-theme');
echo '<p>' . $noun_post . '</p>';

// "Post" 作为动词
$verb_post = _x('Post', 'verb', 'my-theme');
echo '<p>' . $verb_post . '</p>';
?>

2.3 使用_n()_nx()

_n()函数用于处理单复数形式的翻译。它接受三个参数:单数形式、复数形式和数量。

<?php
$item_count = 5;
$message = sprintf( _n( '%s item', '%s items', $item_count, 'my-theme' ), number_format_i18n( $item_count ) );
echo '<p>' . $message . '</p>';
?>

_nx()函数是_n()的带上下文版本。

<?php
$item_count = 1;
$message = sprintf( _nx( '%s comment', '%s comments', $item_count, 'comments', 'my-theme' ), number_format_i18n( $item_count ) );
echo '<p>' . $message . '</p>';

$item_count = 5;
$message = sprintf( _nx( '%s comment', '%s comments', $item_count, 'comments', 'my-theme' ), number_format_i18n( $item_count ) );
echo '<p>' . $message . '</p>';
?>

2.4 转义函数

为了防止XSS攻击,建议在使用翻译后的文本时进行转义。

  • esc_attr__()esc_attr_e():用于转义HTML属性值。
  • esc_html__()esc_html_e():用于转义HTML内容。
<?php
// 转义HTML属性值
$title = esc_attr__('My Awesome Title', 'my-theme');
echo '<a href="#" title="' . $title . '">Link</a>';

// 转义HTML内容
$content = esc_html__('This is some awesome content.', 'my-theme');
echo '<p>' . $content . '</p>';
?>

3. PO/MO文件:存储翻译文本

PO (Portable Object) 文件和 MO (Machine Object) 文件是用于存储翻译文本的标准格式。

  • PO文件:是人类可读的文本文件,包含了原始文本和对应的翻译文本。
  • MO文件:是PO文件的编译版本,是机器可读的二进制文件,用于WordPress快速加载翻译文本。

3.1 创建PO文件

可以使用Poedit等工具创建和编辑PO文件。

  1. 安装Poedit: 下载并安装Poedit (https://poedit.net/)。
  2. 创建新的目录: 在你的主题或插件目录下创建一个 languages 目录 (例如:my-theme/languages/)。
  3. 创建PO文件: 打开 Poedit,选择 "File" -> "New from POT file…"。
  4. 生成POT文件: 首先,我们需要生成一个POT文件,它是一个包含所有需要翻译文本的模板文件。可以使用命令行工具 wp i18n make-pot 来生成POT文件。

    wp i18n make-pot . languages/my-theme.pot

    这个命令会在当前目录下扫描所有PHP文件,提取需要翻译的文本,并将其保存到 languages/my-theme.pot 文件中。

  5. 从POT创建PO: 在Poedit中选择刚刚生成的 my-theme.pot 文件。
  6. 选择语言: Poedit会提示你选择语言。选择你想要翻译的语言 (例如:中文 – 简体中文)。
  7. 编辑翻译: Poedit会显示一个包含所有原始文本的列表。你可以逐个编辑,输入对应的翻译文本。
  8. 保存PO文件: 将PO文件保存到 languages 目录下,并以语言代码命名 (例如:zh_CN.po)。

3.2 编辑PO文件

在Poedit中,你可以看到原始文本和对应的翻译文本。在"Translation"列中输入对应的翻译文本。

3.3 生成MO文件

Poedit会自动生成MO文件。当你保存PO文件时,Poedit会自动创建一个同名的MO文件 (例如:zh_CN.mo)。如果没有自动生成,你可以选择 "File" -> "Compile to MO" 来手动生成MO文件。

3.4 PO文件格式

PO文件是一个文本文件,包含一系列的"msgid"和"msgstr"对。

  • msgid:原始文本。
  • msgstr:翻译后的文本。
#: template-parts/content.php:20
msgid "Read More"
msgstr "阅读更多"

#: functions.php:35
msgid "Posted on %s by %s"
msgstr "发表于 %s,作者 %s"

#: functions.php:40
msgid "Edit"
msgstr "编辑"

4. 加载翻译文件

为了让WordPress加载你的翻译文件,需要在主题或插件的functions.php文件中添加以下代码:

<?php
/**
 * 加载主题的翻译文件
 */
function my_theme_load_textdomain() {
    load_theme_textdomain( 'my-theme', get_template_directory() . '/languages' );
}
add_action( 'after_setup_theme', 'my_theme_load_textdomain' );

//对于插件
/**
 * 加载插件的翻译文件
 */
function my_plugin_load_textdomain() {
    load_plugin_textdomain( 'my-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
}
add_action( 'plugins_loaded', 'my_plugin_load_textdomain' );

?>
  • load_theme_textdomain():用于加载主题的翻译文件。
    • 'my-theme':是文本域 (text domain),用于区分不同的翻译文件。
    • get_template_directory() . '/languages':是翻译文件所在的目录。
  • load_plugin_textdomain():用于加载插件的翻译文件。
    • 'my-plugin':是文本域 (text domain)。
    • dirname( plugin_basename( __FILE__ ) ) . '/languages/':是翻译文件所在的目录。

5. 文本域 (Text Domain)

文本域 (Text Domain) 是一个用于区分不同主题和插件的翻译文件的唯一标识符。建议使用你的主题或插件的名称作为文本域。

wp_i18n函数中,需要指定文本域。例如:

<?php
__('Hello, world!', 'my-theme');
?>

在这个例子中,'my-theme'就是文本域。

6. 更新翻译

当你的主题或插件中的文本发生变化时,需要更新翻译文件。

  1. 更新POT文件: 运行 wp i18n make-pot 命令重新生成POT文件。
  2. 更新PO文件: 使用Poedit打开PO文件,Poedit会自动检测到POT文件中的变化,并提示你更新翻译。
  3. 编译MO文件: 保存PO文件,Poedit会自动编译MO文件。

7. 示例:一个简单的国际化主题

我们创建一个简单的WordPress主题,并对其进行国际化。

7.1 创建主题文件

创建一个名为 my-theme 的主题目录,并在该目录下创建以下文件:

  • style.css
  • index.php
  • functions.php
  • languages/ (空目录,用于存放翻译文件)

7.2 style.css

/*
Theme Name: My Theme
Text Domain: my-theme
*/

7.3 index.php

<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
    <meta charset="<?php bloginfo( 'charset' ); ?>">
    <title><?php wp_title(); ?></title>
</head>
<body>
    <h1><?php _e('Hello, world!', 'my-theme'); ?></h1>
    <p><?php _e('Welcome to my website!', 'my-theme'); ?></p>
    <?php
    $item_count = 5;
    $message = sprintf( _n( '%s item', '%s items', $item_count, 'my-theme' ), number_format_i18n( $item_count ) );
    echo '<p>' . $message . '</p>';
    ?>
</body>
</html>

7.4 functions.php

<?php
/**
 * 加载主题的翻译文件
 */
function my_theme_load_textdomain() {
    load_theme_textdomain( 'my-theme', get_template_directory() . '/languages' );
}
add_action( 'after_setup_theme', 'my_theme_load_textdomain' );
?>

7.5 生成POT文件

wp i18n make-pot . languages/my-theme.pot

7.6 创建并编辑PO文件

使用Poedit打开 languages/my-theme.pot 文件,选择中文 (简体中文) 作为语言,创建 zh_CN.po 文件,并添加以下翻译:

#: index.php:8
msgid "Hello, world!"
msgstr "你好,世界!"

#: index.php:9
msgid "Welcome to my website!"
msgstr "欢迎来到我的网站!"

#: index.php:12
msgid "%s item"
msgstr "%s 个项目"

#: index.php:12
msgid "%s items"
msgstr "%s 个项目"

7.7 生成MO文件

保存PO文件,Poedit会自动生成 zh_CN.mo 文件。

7.8 设置WordPress语言

在WordPress后台,选择 "设置" -> "常规",将站点语言设置为 "中文 (简体中文)"。

7.9 验证

刷新你的网站,你应该看到翻译后的文本。

8. 插件国际化

插件的国际化过程与主题类似,主要区别在于加载翻译文件的函数和目录。

8.1 创建插件文件

创建一个名为 my-plugin 的插件目录,并在该目录下创建以下文件:

  • my-plugin.php (插件主文件)
  • languages/ (空目录,用于存放翻译文件)

8.2 my-plugin.php

<?php
/**
 * Plugin Name: My Plugin
 * Text Domain: my-plugin
 */

function my_plugin_output() {
    echo '<p>' . __('This is my plugin!', 'my-plugin') . '</p>';
}
add_action( 'wp_footer', 'my_plugin_output' );

/**
 * 加载插件的翻译文件
 */
function my_plugin_load_textdomain() {
    load_plugin_textdomain( 'my-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
}
add_action( 'plugins_loaded', 'my_plugin_load_textdomain' );
?>

8.3 生成POT文件

wp i18n make-pot . languages/my-plugin.pot

8.4 创建并编辑PO文件

使用Poedit打开 languages/my-plugin.pot 文件,选择中文 (简体中文) 作为语言,创建 zh_CN.po 文件,并添加以下翻译:

#: my-plugin.php:7
msgid "This is my plugin!"
msgstr "这是我的插件!"

8.5 生成MO文件

保存PO文件,Poedit会自动生成 zh_CN.mo 文件。

8.6 激活插件

在WordPress后台激活你的插件。

8.7 验证

刷新你的网站,你应该在页脚看到翻译后的文本。

9. 其他注意事项

  • 编码: 确保你的PO文件和MO文件使用UTF-8编码。
  • 语言代码: 使用正确的语言代码 (例如:zh_CNen_USfr_FR)。
  • 翻译质量: 翻译质量直接影响用户体验,建议聘请专业的翻译人员进行翻译。
  • 动态文本: 对于包含变量的动态文本,可以使用 sprintf() 函数进行格式化,并在PO文件中包含格式化字符串。
  • JavaScript国际化: WordPress也支持JavaScript的国际化,可以使用wp_localize_script()函数将翻译后的文本传递给JavaScript。具体可以参考WordPress官方文档。
  • GlotPress: 可以使用GlotPress来协同翻译WordPress主题和插件。

代码规范和最佳实践

  • 始终使用wp_i18n函数: 避免在代码中直接硬编码文本。
  • 正确使用文本域: 确保所有wp_i18n函数都使用了正确的文本域。
  • 保持POT文件最新: 定期更新POT文件,以确保包含所有需要翻译的文本。
  • 提供详细的上下文: 在使用_x()函数时,提供清晰的上下文描述,以便翻译人员理解文本的含义。
  • 测试不同语言环境: 在发布主题或插件之前,在不同的语言环境下进行测试,以确保翻译正确显示。

总结来说:

  • 利用wp_i18n函数进行国际化标记,为多语言支持打下基础。
  • 通过Poedit等工具创建和编辑PO/MO文件,存储不同语言的翻译文本。
  • 使用load_theme_textdomain()load_plugin_textdomain()加载翻译文件,让WordPress识别并应用翻译。

希望今天的讲解能够帮助大家更好地理解和应用WordPress的国际化和本地化技术。 谢谢大家。

发表回复

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