WordPress 日历在 Polylang 多语言环境下的兼容性修复实践

在英文页面 https://www.shuijingwanwq.com/en/ 中,22 号显示蓝色链接

从经典到块:主题迁移

从Hueman到Twenty Twenty-Five,主题切换与多语言菜单配置

(1) 从Hueman到Twenty Twenty-Five,主题切换与多语言菜单配置

经过以上步骤,语言切换器最终在页面上的效果符合预期。(见图 9)

(2) 在 WordPress 2025 主题中,把 Polylang 语言切换器移到右上角的完整记录

页眉导航宽度异常问题:导航被内容宽度限制(图 4)

(3) WordPress Twenty Twenty-Five 全局宽度布局实操笔记:宽屏全幅+大屏限宽配置方案

中文(中国)前台首页:66主内容文章+33标准化侧边栏,区块正常显示(对应图6)

(4) 实操|WordPress Twenty Twenty-Five 区块主题 Text Blog Home 改造经典两栏首页(双语无损适配)

改造完成最终首页效果(图5)

(5) WordPress Twenty Twenty-Five 两栏首页改造:Text Blog 小图列表模板完整实操记录

图11:样式重写后下拉美观,但层级子分类在原生 Option 标签下以空格缩进表示

(6) 分类列表下拉菜单的美化与渲染机制调试实录

图3:应用修正后的 CSS,日历占据了应有的侧边栏宽度,有文章的日子用主题同色系进行了高亮,悬停时会变黑

(7) 修复日历在侧边栏“占不满”的问题:WordPress 2025 主题日历样式优化

图5:English 下的页面显示第二个 Language Visibility 区块

(8) 为博客首页侧边栏添加多语言「个人品牌」区块

图4:调整后的分页效果

(9) 一次 FSE 分页丢失的排查与修复:从纯布局样板到查询循环

在英文页面(https://www.shuijingwanwq.com/en/)中,日历上每个日期点击后跳转的链接仍然是 https://www.shuijingwanwq.com/2026/06/08/ 的形式,而不是预期的 https://www.shuijingwanwq.com/en/2026/06/08/。

(10) WordPress 2025 主题 + Polylang:修复日历链接缺少语言目录的完整记录

图4:中文站点,下拉菜单样式美观,显示“选择年份”。

(11) 优化 WordPress 2025 主题页脚:多语言导航、社交链接与归档下拉栏的完整改造记录

图2:分类页单栏效果

(12) 从单栏到两栏:WordPress分类页统一首页侧边栏及列表结构的实操记录

套用上述代码后,标签云立刻有了质的飞跃:

(13) 告别参差不齐!只用 CSS 打造适配 2025 主题的现代标签云

搜索“alipay”的结果,每篇文章都带了一张大尺寸的特色图片,紧跟着就是完整的正文内容。我的文章里还有代码片段,全都被拉出来显示在列表里,页面无限拉长,排版也乱糟糟的。如图1

(14) 搜索结果页太长了?我给WordPress 2025主题做了一次“断舍离”

在英文页面 https://www.shuijingwanwq.com/en/ 中,22 号显示蓝色链接

(15) WordPress 日历在 Polylang 多语言环境下的兼容性修复实践

引言

在将博客主题从 Hueman 切换到 Twenty Twenty-Five 后,我遇到了一个棘手的问题:日历区块在多语言环境下显示异常。在英文页面(如 https://www.shuijingwanwq.com/en/)中,日历上某些日期(如 22 号)明明没有发布过英文文章,却依然显示链接,点击后返回 404 错误页面。而中文页面则正常显示对应语言的链接。经过 1 天的排查与修复,最终通过 PHP 代码片段解决了问题,现将过程与方案整理如下。

原始问题:英文页面日历链接缺少语言前缀

问题描述:在英文页面 https://www.shuijingwanwq.com/en/ 中,日历上每个日期点击后跳转的链接仍然是 https://www.shuijingwanwq.com/2026/06/08/ 的形式,而不是预期的 https://www.shuijingwanwq.com/en/2026/06/08/。这导致用户点击日历链接时,因缺少 /en/ 前缀而跳转至错误页面,相当于语言切换了。

初步解决方案:替换 URL 前缀(及新问题)

初步思路

最初,我尝试通过替换 URL 前缀来解决原始问题,参考了博客文章《修复日历在侧边栏”占不满”的问题:WordPress 2025 主题日历样式优化》中的解决方案。

新问题出现

尽管 URL 前缀问题暂时解决,但新的问题随之而来:在英文页面(https://www.shuijingwanwq.com/en/)中,日历上 22 号显示蓝色链接,但该日期未发布英文文章,点击后返回 404。这表明仅替换 URL 前缀无法解决数据过滤问题——日历仍显示所有语言的文章日期,而非仅当前语言的文章。

方案对比:完全重写 vs. 基于 HTML 修改

针对上述问题,我对比了两种解决方案:

方案一:完全重写日历区块(架构清晰,但易引入 Bug)

思路:废弃 WordPress 原生日历的 get_calendar() 函数,通过 WP_Query 查询当前语言的文章数据,手动生成 HTML 结构。
优点

  • 架构清晰,从数据层直接控制日历显示,避免依赖原生函数的潜在问题。
  • 性能更好,因为直接查询数据而不需要解析 HTML。
    缺点:日历逻辑复杂(跨月、周首日对齐等),完全重写易引入排版 Bug,且需确保与主题 CSS 兼容,维护成本高。

方案二:基于原生 HTML 结构修改(保留原生日历逻辑,风险低)

思路:让 WordPress 先生成原生日历 HTML,再通过 DOMDocument 解析并修正:

  1. 查询当前语言当月有文章的日期集合。
  2. 遍历日历表格中的每个 <td>,核对日期是否有文章:
  • 有文章但无链接:创建 <a> 标签并添加正确语言前缀。
  • 无文章但有链接:移除 <a> 标签,保留纯文本。
  1. 重建月份导航链接,确保基于当前语言数据生成。
    优点:保留原生日历的排版逻辑,避免引入新 Bug,兼容主题 CSS,风险低。
    缺点:需额外解析 HTML,性能稍受影响,但可接受。

最终选择与效果展示

考虑到时间有限且主题切换已耗时 4 天,我选择方案二,通过 WPCode 插件添加 PHP 代码片段实现修复。以下是修复前后的效果对比:

修复前:英文页面 22 号错误显示链接

在英文页面 https://www.shuijingwanwq.com/en/ 中,22 号显示蓝色链接,但该日期未发布英文文章,点击后返回 404。

在英文页面 https://www.shuijingwanwq.com/en/ 中,22 号显示蓝色链接
在英文页面 https://www.shuijingwanwq.com/en/ 中,22 号显示蓝色链接

但该日期未发布英文文章,点击后返回 404
但该日期未发布英文文章,点击后返回 404

修复后:英文页面 22 号无链接

修复后,英文页面 22 号仅显示纯文本,无链接,符合预期。

修复后,英文页面 22 号仅显示纯文本,无链接,符合预期。

插件兼容性考虑:Calendas 插件

期间曾考虑使用 Calendas 插件(明确支持 Polylang),但提示 PHP 版本不兼容(需 8.2 或更高),升级 PHP 需额外时间,因此放弃。

期间曾考虑使用 Calendas 插件(明确支持 Polylang),但提示 PHP 版本不兼容(需 8.2 或更高),升级 PHP 需额外时间,因此放弃。

代码实现(基于方案二)

以下是通过 WPCode 插件添加的 PHP 代码片段,核心逻辑为:

  1. 查询当前语言当月有文章的日期。
  2. 使用 DOMDocument 遍历日历 <td>,修正链接或移除错误链接。
  3. 重建导航链接,确保语言前缀正确。
PHP
<?php
function fix_polylang_calendar_dom_patch_v2( $block_content, $block ) {
    if ( 'core/calendar' !== $block['blockName'] || ! function_exists( 'pll_current_language' ) ) {
        return $block_content;
    }
    global $wp_locale;
    $current_lang = pll_current_language( 'slug' );
    $default_lang = pll_default_language( 'slug' );
    $home_url = home_url( '/' );
    // 修正 URL 前缀
    $fix_url = function( $url ) use ( $current_lang, $default_lang, $home_url ) {
        if ( $current_lang === $default_lang ) return $url;
        if ( strpos( $url, $home_url . $current_lang . '/' ) === false ) {
            $relative = str_replace( $home_url, '', $url );
            return $home_url . $current_lang . '/' . $relative;
        }
        return $url;
    };
    // 查询当前语言当月有文章的日期
    $year = get_query_var( 'year' ) ?: (int) gmdate( 'Y' );
    $month = get_query_var( 'monthnum' ) ?: (int) gmdate( 'm' );
    $args = [
        'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => -1,
        'fields' => 'ids', 'lang' => $current_lang, 'year' => $year, 'monthnum' => $month
    ];
    $query = new WP_Query( $args );
    $valid_days = array_map( 'intval', array_column( $query->posts, 'ID' ) );
    // 解析原生 HTML 并修正
    $dom = new DOMDocument();
    libxml_use_internal_errors( true );
    $dom->loadHTML( '<?xml encoding="utf-8" ?>' . $block_content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
    $xpath = new DOMXPath( $dom );
    // 遍历每个日期单元格
    $td_nodes = $xpath->query( '//table[contains(@class, "wp-calendar-table")]/tbody/tr/td' );
    foreach ( $td_nodes as $td ) {
        if ( $td->getAttribute('class') === 'pad' ) continue;
        $day_text = trim( $td->nodeValue );
        if ( ! preg_match('/^\d{1,2}$/', $day_text) ) continue;
        $day_num = (int) $day_text;
        $has_post = in_array( $day_num, $valid_days );
        $existing_a = $xpath->query( './a', $td )->item(0);
        if ( $has_post ) {
            if ( $existing_a ) $existing_a->setAttribute( 'href', $fix_url( get_day_link( $year, $month, $day_num ) ) );
            else {
                $td->nodeValue = '';
                $new_a = $dom->createElement('a', $day_num);
                $new_a->setAttribute( 'href', $fix_url( get_day_link( $year, $month, $day_num ) ) );
                $td->appendChild( $new_a );
            }
        } else {
            if ( $existing_a ) $td->removeChild( $existing_a );
        }
    }
    // 重建导航链接(略,逻辑与正文一致)
    // 输出修正后的 HTML
    $modified_html = $dom->saveHTML();
    return trim( preg_replace( '/<!DOCTYPE[^>]*>|<html[^>]*>|<\/html>|<body[^>]*>|<\/body>/', '', $modified_html ) );
}
add_filter( 'render_block_core/calendar', 'fix_polylang_calendar_dom_patch_v2', 20, 2 );

总结

在 WordPress 中处理历史遗留问题时,需权衡“完全重写”与“后置修补”的利弊。本次修复通过保留原生日历逻辑,仅修改数据与链接,成功解决了多语言兼容问题,避免了新 Bug 的引入。对于类似问题,建议优先考虑基于原生结构的修改方案,确保稳定性和兼容性。

搜索结果页太长了?我给WordPress 2025主题做了一次“断舍离”

评论

发表回复

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

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理