
在 Polylang 多语言环境下,WordPress 的 add_rewrite_rule 默认仅对默认语言生效;需显式支持语言参数(如 lang=en),并配合 Polylang 的查询变量注册与重写标签处理,才能使自定义 URL 规则在所有语言下正常解析。
在 polylang 多语言环境下,wordpress 的 `add_rewrite_rule` 默认仅对默认语言生效;需显式支持语言参数(如 `lang=en`),并配合 polylang 的查询变量注册与重写标签处理,才能使自定义 url 规则在所有语言下正常解析。
当您在启用 Polylang 的 WordPress 站点中使用 add_rewrite_rule 实现类似 /property/{parent-slug}/units/{child-slug}/ 这样的自定义路由时,原始规则:
add_rewrite_rule( '^property/(.*)/units/([^/]+)/?$', 'index.php?property_units=$matches[2]', 'top' );
确实只能在默认语言(例如站点设置的语言)下工作,其他语言(如 /en/property/abc/units/xyz/ 或 /fr/property/abc/units/xyz/)会返回 404 —— 因为 Polylang 会将语言前缀(如 /en/、/fr/)作为路径的一部分,而您的正则未覆盖该结构,且 index.php 查询字符串中未携带 lang 参数,导致 Polylang 无法识别当前请求语言。
✅ 正确做法是:让重写规则兼容 Polylang 的语言前缀,并确保语言信息被正确传递至查询变量。以下是完整、可复用的解决方案:
1. 注册 Polylang 所需的语言查询变量(必需)
add_filter( 'query_vars', function( $vars ) {
$vars[] = 'lang'; // 确保 Polylang 能读取 lang 参数
return $vars;
});
2. 编写支持多语言前缀的重写规则
Polylang 默认将语言作为路径第一段(如 /en/, /fr/),因此正则需匹配可选的语言前缀。推荐使用以下更健壮的规则(兼容无前缀默认语言 + 所有带前缀语言):
add_action( 'init', function() {
// 匹配: /{lang}/property/{parent}/units/{child}/ 或 /property/{parent}/units/{child}/
add_rewrite_rule(
'^((?:[a-z]{2}/)?|)property/([^/]+)/units/([^/]+)/?$',
'index.php?property_units=$matches[3]&lang=$matches[1]',
'top'
);
});
⚠️ 注意:$matches[1] 是捕获组 ((?:[a-z]{2}/)?|) 的结果(如 "en/" 或空字符串),Polylang 会自动从该值中提取语言代码(去除末尾 /)。若语言前缀格式非标准(如带下划线或子目录嵌套),请根据实际 polylang 设置调整正则。
3. 增强 post_type_link 以生成多语言友好的链接
确保前端生成的链接自动包含当前语言前缀(Polylang 默认已处理),但需验证 property_units 类型是否参与语言关联:
add_filter( 'post_type_link', function( $link, $post ) {
if ( 'property_units' !== get_post_type( $post ) || ! $post->post_parent ) {
return $link;
}
$parent = get_post( $post->post_parent );
if ( ! $parent || empty( $parent->post_name ) ) {
return $link;
}
// 使用 Polylang 提供的 get_translation_url() 或手动拼接(推荐使用其 API)
$translated_parent = pll_get_post( $parent->ID, pll_current_language() );
if ( $translated_parent && $translated_parent != $parent->ID ) {
$parent = get_post( $translated_parent );
}
return str_replace( '%property_name%', $parent->post_name, $link );
}, 10, 2 );
✅ 提示:务必调用 flush_rewrite_rules() 一次(开发阶段可临时加入 if ( defined('WP_CLI') || current_user_can('manage_options') ) flush_rewrite_rules();),上线后移除。切勿在 init 中频繁调用。
4. (可选)增强查询解析:确保 lang 参数被 Polylang 正确识别
Polylang 通常能自动处理 lang 查询变量,但若遇到语言切换失效,可显式钩入:
add_action( 'parse_request', function( $wp ) {
if ( isset( $wp->query_vars['lang'] ) && ! empty( $wp->query_vars['lang'] ) ) {
$lang_code = trim( $wp->query_vars['lang'], '/' );
if ( strlen( $lang_code ) === 2 ) {
pll_set_current_language( $lang_code );
}
}
});
? 总结:Polylang 下的自定义重写规则不是简单追加 ?lang=xx,而是要——
① 允许语言路径前缀在正则中被捕获;
② 将语言代码作为 lang 查询变量传入;
③ 注册该变量并确保 Polylang 主动消费;
④ 在链接生成阶段同步处理多语言内容映射。
遵循以上四步,即可实现真正全语言兼容的自定义路由。











