国际化是指以这样一种方式开发主题,使其自定义文本能够被翻译成其他语言。由于首尾字母“i”和“n”之间恰好相隔18个字母,这一术语通常被缩写为“i18n”。

在本文中,您将了解如何实现WordPress主题的国际化以及为何这如此重要。

为何国际化很重要

WordPress在全球范围内被广泛使用,包括那些并不使用您母语的国家。因此,WordPress主题中的字符串需要以特殊方式编码,这样才能方便地被翻译成其他语言。

即便您自己不会多种语言,国际化也为翻译人员提供了对文本进行本地化的可能。本地化指的是将已国际化的文本翻译为特定语言和地区版本的过程,这一术语通常被缩写为“l10n”。

WordPress拥有内置的翻译系统,无需修改主题的源代码即可实现本地化。这一点非常重要,因为它意味着用户可以在使用自己偏好的翻译版本的同时,继续获取主题的更新内容。

您当然也可以创建不支持国际化的WordPress主题,尤其是针对那些肯定不会被翻译的网站。但在大多数情况下,为主题的所有文本实现国际化被视为标准做法。其一,这样可以让使用其他语言的用户也能使用该主题,从而扩大您的受众群体;其二,提交主题到官方的Theme Directory时,这也是一个必填要求。

如何实现主题的国际化

获取文本域

文本域是一个唯一标识符,用于帮助WordPress区分所有已加载的翻译内容。这意味着您的主题需要有一个唯一的文本域,以便WordPress能够识别出属于该主题的翻译内容。

文本域在主题中会被用在三个不同的位置:

  • 在style.css文件的头部。
  • 作为国际化函数中的参数。
  • 在加载翻译内容时作为参数使用(对于提交到WordPress Theme Directory的主题来说这是可选的)。

正如阅读本手册文档中所说明的,主题的文本域应始终与主题的slug保持一致。这是确保主题具备翻译功能的核心要素。

实际上通用的标准(也是向WordPress Theme Directory提交主题时的要求)是使用主题名称的kebab-case格式。也就是说,主题名称应当:

  • 全部使用小写字母。
  • 不包含空格。
  • 如果由多个单词组成,则需用连字符连接。

因此,如果您的主题名称是Fabled Sunset,那么其文本域就应该为fabled-sunset。

定义文本域

如主样式表文档中所描述的,您可以通过style.css文件的头部来配置与主题相关的多项重要元数据。尤其是,有两组与国际化相关的元数据值可供定义:

  • Text Domain:用于翻译的文本域字符串。
  • Domain Path:主题翻译文件存储位置的相对路径。当主题被禁用时,WordPress会使用此字段来查找翻译内容。如果未定义,其默认值为/languages。

为了使翻译功能正常工作,您至少需要定义Text Domain字段,该字段的值应为您主题的slug。

假设您的主题名称为“Fabled Sunset”,并且希望将翻译内容存储在主题的/assets/lang文件夹中,那么您的style.css文件应如下定义这些字段:

/**
 * Theme Name:        Fabled Sunset
 * ...
 * Text Domain:       fabled-sunset
 * Domain Path:       /assets/lang
 * ...
 */

将此元数据添加到style.css文件中非常重要,因为即使主题未被启用,WordPress也会使用它(例如,在管理后台的外观 > 主题页面中查看所有主题时)。

用国际化函数包裹文本

为了让主题中的文本能够轻松被翻译,必须将其用国际化函数包裹起来,而非直接硬编码。可用的国际化函数在《常用API手册》中有列出。

在典型的基于HTML的网页中,人们会直接添加纯文本字符串。例如,看看这个标题示例:

<h2>Latest Posts</h2>

由于这只是纯文本,如果不直接修改代码,就无法将其翻译成其他语言。

让我们用_e()国际化函数来包裹这段文本,该函数会告知WordPress,其中的文本需要被翻译并显示出来:

<h2><?php _e( 'Latest Posts', 'themeslug' ); ?></h2>

现在,用户无需修改代码即可为您的主题添加翻译内容。

您可能已经注意到,_e()函数接受第二个参数themeslug,这个参数应当替换为您的文本域。

还有许多其他的国际化函数可供使用,您稍后会进一步了解它们。目前,只是想向您介绍基本概念。

由于国际化后的文本在技术上属于PHP变量,因此它有可能被利用从而形成安全漏洞。在可能的情况下,您应始终使用翻译与转义函数。否则,在输出时务必用转义函数将其包裹起来,具体方法可见安全相关文档。

加载翻译内容

对于托管在WordPress Theme Directory中的主题,您无需手动加载翻译内容。WordPress会自动检查用户安装环境中的wp-content/languages目录,并从Translating WordPress网站下载翻译文件。所有的翻译工作都可以在那里完成,您无需担心在主题中存储或加载这些翻译内容。

WordPress中的翻译内容保存为.po(供人类阅读)和.mo(供机器读取)格式的文件,实际被WordPress使用的正是.mo文件。

根据网站所设置的用户区域设置,WordPress会在两个位置查找翻译文件:

  • wp-content/themes/your-theme/{domain-path}/{locale}.mo
  • wp-content/languages/themes/{textdomain}-{locale}.mo

若要从您的主题中加载翻译文件,必须使用以下两个函数之一:

让我们来看看load_theme_textdomain()函数的签名(这两个函数的签名是相同的):

load_theme_textdomain(
	string $domain, 
	string|false $path = false 
): bool

该函数接受两个参数:

  • $domain:应当是您在style.css中定义的主题文本域。
  • $path:必须是主题中翻译文件所在位置的完整目录路径。如果未定义,WordPress将默认使用主题的根目录。

继续使用之前提到的“Fabled Sunset”主题为例,假设翻译内容存储在/assets/lang文件夹中,现在我们来尝试从该主题中加载翻译内容。

请在主题的functions.php文件中添加以下代码:

add_action( 'after_setup_theme', 'themeslug_load_textdomain' );

function themeslug_load_textdomain() {
	load_theme_textdomain(
		'fabled-sunset',
		get_parent_theme_file_path( 'assets/lang' )
	);
}

上述对load_theme_textdomain()的调用是在after_setup_theme动作钩子上执行的,该钩子会在主题的functions.php文件加载完成后立即触发。

如果您正在创建子主题,那么您的functions.php文件代码则应如下所示:

add_action( 'after_setup_theme', 'themeslug_load_textdomain' );

function themeslug_load_textdomain() {
	load_child_theme_textdomain(
		'fabled-sunset',
		get_theme_file_path( 'assets/lang' )
	);
}

参考资源

国际化是一个范围很广的主题,在《常用API手册》的国际化章节中有详尽介绍。您在那里学到的知识同样适用于主题和插件的开发。

WordPress提供了许多国际化函数,供您在包裹文本时使用。具体使用哪种函数需视具体情境而定。请花时间研究每一种函数,以便知道何时该使用它们。国际化指南将为您指明正确的方向。