WordPress 主题国际化(i18n)完全指南
WordPress 主题国际化(Internationalization,缩写 i18n)指的是让主题中的文本能够被翻译成其他语言的技术实践。这不是一个可选项,而是现代 WordPress 主题开发的标准要求——无论你使用哪种语言开发主题,都应该遵循这套规范。
本文会从头讲解国际化在 WordPress 主题中的运作方式:什么是文本域(text domain)、如何定义它、怎样在代码中正确包裹可翻译字符串,以及翻译文件该如何加载。文中不堆砌术语,每个概念都配有代码演示,适合对 WordPress 主题开发有基本了解的读者。
如果你是一次接触主题开发,建议先掌握 WordPress 主题的基本文件结构(style.css、functions.php、模板文件等),再回来看这篇。文章后会附上官方手册的延伸阅读链接。
一、为什么你的主题需要国际化
WordPress 在全球范围内被广泛使用,用户来自不同语言背景。如果你的主题代码中写死了英文(或其他语言)的文本,那么:
- 非该语言用户无法直接使用,除非他们修改你的源代码——这会导致无法安全更新主题。
- 提交到 WordPress 官方主题目录时,审核会被直接拒绝,因为国际化是提交规则里的硬性要求。
- 限制了主题的潜在受众,不利于传播和商业价值。
注意:即便你只打算给自己的网站用,也建议养成国际化的习惯。WordPress 内置的翻译系统允许用户在不修改主题源码的情况下切换语言,这意味着用户既可以获得翻译后的界面,又能随时安全地更新主题。
二、准备文本域(Text Domain)
什么是文本域?
文本域是一个标识符,WordPress 用它来区分哪些翻译文件属于你的主题,哪些属于插件或其他主题。翻译文件(.mo 文件)的文件名中就包含文本域,WordPress 根据当前加载的主题和插件的文本域去查找对应的翻译。
文本域的命名规则
文本域必须与主题目录名(主题 slug)保持一致。这是官方要求,也是翻译系统正常工作的前提。
命名规范如下:
- 全部使用小写字母
- 多个单词之间用连字符(-)分隔(kebab-case 风格)
- 不要使用下划线、空格或大写字母
举例:如果你的主题名为“Fabled Sunset”,那么主题的文件夹名称和文本域都应该命名为 fabled-sunset。
在 style.css 中声明文本域
主题的 style.css 文件头部需要添加 Text Domain 字段。另外还有一个可选的 Domain Path 字段,用于指定翻译文件存放的目录(相对于主题根目录),默认是 /languages。
示例:
css
/** * Theme Name: Fabled Sunset * Theme URI: https://example.com/fabled-sunset * Description: 一个优雅的博客主题 * Author: 你的名字 * Text Domain: fabled-sunset * Domain Path: /assets/lang */
这段声明有两个作用:
Text Domain告知 WordPress 这个主题的文本域是什么。Domain Path帮助 WordPress 在主题未激活时也能找到翻译文件(例如在后台“外观 > 主题”预览界面中展示翻译后的主题描述)。
三、用国际化函数包裹文本
这是国际化工作中频繁的操作。你需要将所有在主题中直接写死的文本,改为通过特定的 WordPress 函数输出。
基础示例
原始写法(无法翻译):
html
<h2>新文章</h2>
国际化写法:
php
<h2><?php _e( '新文章', 'fabled-sunset' ); ?></h2>
这里用到了 _e() 函数,它接受两个参数:
- 一个参数是要翻译的文本字符串。
- 二个参数是文本域,告诉 WordPress 这个字符串属于哪个主题/插件。
注意:所有国际化函数都必须带上正确的文本域。如果文本域写错或漏写,翻译系统将无法匹配到对应的翻译文件。
常用的国际化函数
不同的使用场景需要选择不同的函数:
1. __() — 返回翻译后的字符串
适用于需要将翻译结果赋值给变量或作为函数参数的情况。
php
$read_more_text = __( '阅读全文', 'fabled-sunset' ); echo $read_more_text;
2. _e() — 直接输出翻译后的字符串
与 __() 的区别是 _e() 会直接打印到页面,而 __() 只是返回。
php
<h2><?php _e( '新文章', 'fabled-sunset' ); ?></h2>
3. _n() — 处理单复数形式
某些语言(如英文)有单复数变化,这个函数能根据数字选择合适的翻译形态。
php
printf(
_n( '找到 %s 篇文章', '找到 %s 篇文章', $count, 'fabled-sunset' ),
number_format_i18n( $count )
);
注意这里两个字符串表面看起来一样(中文单复数形式相同),但对其他语言(如英文)来说,一个会被翻译为 “Found %s post”,二个为 “Found %s posts”,WordPress 会根据 $count 的值自动选择。
4. esc_html__() / esc_html_e() — 翻译并转义
输出到 HTML 中的文本,建议使用转义函数包裹,防止 XSS 攻击。
php
<h2><?php echo esc_html__( '新文章', 'fabled-sunset' ); ?></h2>
或者直接输出:
php
<h2><?php esc_html_e( '新文章', 'fabled-sunset' ); ?></h2>
WordPress 建议在输出翻译文本时尽量配合转义函数使用,这是安全编码的基本原则。
完整的模板文件示例
php
<?php
/**
* 文章列表模板
*/
get_header();
?>
<main>
<h1><?php esc_html_e( '文章归档', 'fabled-sunset' ); ?></h1>
<?php if ( have_posts() ) : ?>
<ul>
<?php while ( have_posts() ) : the_post(); ?>
<li>
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
<span>
<?php
printf(
esc_html__( '发布于:%s', 'fabled-sunset' ),
get_the_date()
);
?>
</span>
</li>
<?php endwhile; ?>
</ul>
<?php else : ?>
<p><?php esc_html_e( '暂无文章', 'fabled-sunset' ); ?></p>
<?php endif; ?>
</main>
<?php get_footer(); ?>
四、在主题中加载翻译文件
官方主题目录 vs 自用主题
如果你的主题提交到了 WordPress 官方主题目录,不需要在主题中主动加载翻译文件。WordPress 会自动从 wp-content/languages/themes/ 目录加载官方翻译,用户可以通过 WordPress 后台直接安装语言包。
如果你自己分发主题(不在官方目录中),或者你需要让主题自带翻译文件,就需要用 load_theme_textdomain() 函数手动加载。
翻译文件是什么格式?
WordPress 使用两种翻译文件格式:
.po文件:人类可读的翻译源文件,可以用 Poedit 等工具编辑。.mo文件:机器可读的编译文件,WordPress 实际读取的是.mo文件。
加载翻译的两种方式
WordPress 默认在两个位置查找翻译文件:
wp-content/themes/你的主题/{Domain Path}/{语言代码}.mowp-content/languages/themes/{文本域}-{语言代码}.mo
如果你的主题不在官方目录,或者你需要加载额外的翻译,可以在 functions.php 中添加如下代码:
父主题的翻译加载
php
add_action( 'after_setup_theme', 'fabled_sunset_load_textdomain' );
function fabled_sunset_load_textdomain() {
load_theme_textdomain(
'fabled-sunset',
get_parent_theme_file_path( 'assets/lang' )
);
}
子主题的翻译加载
如果你开发的是子主题,使用 load_child_theme_textdomain() 替代:
php
add_action( 'after_setup_theme', 'fabled_sunset_child_load_textdomain' );
function fabled_sunset_child_load_textdomain() {
load_child_theme_textdomain(
'fabled-sunset-child',
get_stylesheet_directory() . '/languages'
);
}
注意:load_theme_textdomain() 必须挂在 after_setup_theme 钩子上,这是 WordPress 加载主题后早可用的钩子之一,能确保翻译在页面渲染前被加载。
完整的翻译加载示例
php
add_action( 'after_setup_theme', 'fabled_sunset_setup' );
function fabled_sunset_setup() {
// 加载翻译
load_theme_textdomain(
'fabled-sunset',
get_parent_theme_file_path( 'languages' )
);
// 其他主题设置...
add_theme_support( 'title-tag' );
add_theme_support( 'post-thumbnails' );
}
五、翻译文件的存放与命名
语言代码(Locale)
WordPress 中的语言代码遵循标准格式,例如:
zh_CN— 简体中文zh_TW— 繁体中文ja— 日语en_US— 美式英语(默认)fr_FR— 法国法语
翻译文件名格式为:{文本域}-{语言代码}.mo
例如,fabled-sunset-zh_CN.mo 就是该主题的简体中文翻译文件。
存放位置
- 官方主题目录的主题:翻译文件由 WordPress 自动下载到
wp-content/languages/themes/。 - 自用或私人分发的主题:放在主题目录下的
languages/(或你在Domain Path中指定的目录)。
六、延伸阅读与官方资源
国际化的内容不止于此,WordPress 官方手册中还有更的讲解,包括:
- 字符串中占位符的处理(使用
sprintf()配合翻译函数) - 上下文注释(使用
_x()为同一个英文单词在不同场景提供不同的翻译提示) - JavaScript 中的国际化(使用
wp.i18n模块)
如果你准备将主题提交到官方目录,建议通读以下资料:
总结
- 为什么要做国际化:全球用户都能用、官方目录强制要求、更新安全。
- 文本域是关键:必须与主题文件夹名称一致,在
style.css中声明,并在所有翻译函数中作为参数传入。 - 代码中不要直接写死文本:全部用
__()、_e()、_n()等函数包裹,并尽量配合转义函数(如esc_html__())。 - 翻译文件加载:官方目录的主题无需手动加载;自用主题在
after_setup_theme钩子上调用load_theme_textdomain()。 - 翻译文件位置:
Domain Path指定存放目录,默认是/languages,文件命名为{textdomain}-{locale}.mo。
把国际化当作主题开发的基础配置,就像注册导航菜单或添加缩略图支持一样自然。养成习惯后,你会发现这套机制简洁而强大,既保护了代码的可维护性,也打开了一扇面向全球用户的门。