本文约 4,011 字,预计阅读 11 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:插件装好了,主题里的字纹丝不动
装完 WPML 或 Polylang,文章和页面都能翻译,但主题自带的那部分文字——比如”阅读全文””上一篇””相关推荐””共 N 条评论”——依然是中文。更麻烦的是,主导航在英文站下还是中文菜单,切换语言后页面能切、菜单不切。再往后,Google Search Console 提示 hreflang 缺少返回链接。
这些问题分属三层:主题字符串有没有走翻译函数、菜单与链接有没有按语言取值、hreflang 有没有被正确输出。前两层是主题适配问题,第三层属于插件职责,但主题写法会影响它能不能输出完整。
原理分析:翻译链路与语言上下文
WordPress 的国际化(i18n)分两步:主题先用 load_theme_textdomain() 告诉核心”翻译文件在哪个目录、文本域叫什么”,然后模板里所有面向用户的字符串必须用 __() / _e() / esc_html__() 等函数包裹,并传入与主题一致的文本域。
如果主题把文字直接硬编码成中文(如 echo '阅读全文';),翻译文件里根本没有对应条目,插件自然无从下手。这类情况需要在子主题里改写模板,把硬编码换成带文本域的调用。
动态内容(后台填写的字符串,如主题选项里的”联系电话”)不在翻译文件里,需要显式注册给插件:Polylang 用 pll_register_string() 后在”字符串翻译”里填各语言版本,WPML 则在 String Translation 里扫描,或用 wpml-config.xml 声明主题选项字段。
菜单方面,Polylang 与 WPML 都支持为每种语言分配不同菜单,但前提是主题用的是 register_nav_menus() + wp_nav_menu( array( 'theme_location' => ... ) ) 这种标准写法;手写 SQL 或直接调用 wp_list_pages() 的菜单不会跟随语言。
| 问题 | 归属 | 处理方式 |
|---|---|---|
| 主题固定文字翻不动 | 主题 | 改用 __() 并补 .po/.mo |
| 后台填写的主题选项翻不动 | 插件 | pll_register_string() / wpml-config.xml |
| 菜单不跟随语言 | 主题写法 | 用标准 theme_location |
| 链接指向错误语言 | 主题 | 用 pll_home_url() 或 wpml_object_id |
| hreflang 缺失 | 插件 | 检查语言目录与翻译是否完整 |
保姆级实操
- 确认主题文本域:查看
style.css头注释里的Text Domain,模板里所有__()的第二个参数必须与它一致。 - 加载翻译目录:在
after_setup_theme里调用load_theme_textdomain(),目录通常是languages/,也可直接用load_child_theme_textdomain()让子主题覆盖父主题条目。 - 改写硬编码字符串:把模板里直接输出的中文换成带文本域的调用,输出前用
esc_html__/esc_attr__做转义。 - 注册动态字符串:主题选项里的文本用
pll_register_string()注册,之后在”语言 → 字符串翻译”里填各语言。 - 声明主题选项给 WPML:用
wpml-config.xml把选项名写进去,WPML 会自动纳入翻译包。 - 处理菜单与链接:保持标准菜单位置写法;需要跨语言取同一篇文章时,用插件提供的 ID 转换过滤器。
- 核对 hreflang:查看页面源码里的
link rel="alternate" hreflang,确认各语言互为返回链接,且包含x-default。
<?php
// 1) 子主题加载自己的翻译文件
add_action( 'after_setup_theme', 'mimangfei_child_i18n' );
function mimangfei_child_i18n() {
load_child_theme_textdomain( 'lumen-mimangfei', get_stylesheet_directory() . '/languages' );
}
// 2) 模板里的字符串必须带文本域并做转义
// 错误:echo '阅读全文';
// 正确:
echo '<a class="more-link" href="' . esc_url( get_permalink() ) . '">'
. esc_html__( '阅读全文', 'lumen-mimangfei' )
. '</a>';
// 带变量的字符串用占位符,不要拼接翻译
printf(
esc_html__( '共 %d 条评论', 'lumen-mimangfei' ),
(int) get_comments_number()
);
<?php
// 3) 把主题选项里的文本注册给 Polylang,后台逐语言填写
add_action( 'init', 'mimangfei_register_strings' );
function mimangfei_register_strings() {
if ( ! function_exists( 'pll_register_string' ) ) {
return;
}
pll_register_string( 'lumen-footer', get_theme_mod( 'lumen_footer_text', '' ), '页脚文案' );
pll_register_string( 'lumen-cta', get_theme_mod( 'lumen_cta_text', '' ), '首页按钮文案' );
}
// 输出时按当前语言取值
function mimangfei_footer_text() {
$text = get_theme_mod( 'lumen_footer_text', '' );
if ( function_exists( 'pll__' ) ) {
$text = pll__( $text );
}
return $text;
}
// 4) 跨语言取同一篇文章的对应版本(WPML)
function mimangfei_translated_id( $post_id, $lang = null ) {
if ( ! has_filter( 'wpml_object_id' ) ) {
return $post_id;
}
return (int) apply_filters( 'wpml_object_id', $post_id, 'post', false, $lang );
}
<!-- 5) wpml-config.xml:声明主题选项纳入翻译包 -->
<wpml-config>
<admin-texts>
<key name="theme_mods_lumen-mimangfei">
<key name="lumen_footer_text" />
<key name="lumen_cta_text" />
</key>
</admin-texts>
</wpml-config>
常见踩坑
- 主题把文字硬编码成中文,翻译文件里没有条目,插件再怎么扫也翻不了。
Text Domain写的是lumen,模板里却传lumen-mimangfei,翻译文件加载了但匹配不上。- 后台主题选项里的文案没注册字符串,切换语言后仍是原语言。
- 菜单用
wp_list_pages()手写输出,不跟随语言切换。 - 案例:某外贸站英文版首页按钮一直显示”立即咨询”。排查发现该文案来自主题选项,开发人员没注册字符串,Polylang 无从翻译。补上
pll_register_string()并在字符串翻译里填英文后正常;后来把这类文案统一改为”选项存 key、模板里用__()输出”,彻底避免遗漏。 - 只翻译了文章没翻译分类与标签,hreflang 指向 404。
- 两种语言用了同一个 slug,固定链接冲突导致跳转错乱。
- 忘记检查 RTL:如果站点含阿拉伯语或希伯来语,主题还需要
rtl.css与is_rtl()判断。
总结
多语言适配的三层:主题固定文字走 load_theme_textdomain + __(),后台选项走字符串注册,菜单与链接走插件 API。判断标准是”切换语言后,主题自带文字、菜单、页脚、按钮全部跟着变,且源码里 hreflang 互为返回链接”。行动清单:① 统一文本域;② 消灭硬编码输出;③ 注册动态字符串;④ 菜单保持标准写法;⑤ 上线前用富媒体/国际化检查工具核对 hreflang。延伸阅读 WordPress 多语言插件对比、WordPress 子主题制作 与 lumen-mimangfei 主题自定义 CSS 写法。
