Skip to content
Go back

魔改 OneNav 一为导航使其更适配 Polylang 多语言(国际化)插件

| 0 Views Edit page

前言

默认情况下,一为导航只会展示按发布时间降序的数篇公告,而不会判断 Polylang 所带来的语言。
通过修改原文件实现只展示该语言下的最新公告。
标题中的 适配 并非将主题与插件结合,而是通过一些理念的融合、代码的修改使整站的国际化更彻底

实现流程

一、修改 templates/bulletin.php

OneNav 主题中公告对应的关键词是 bulletin
首页的公告模块是 templates/bulletin.php,核心代码在这里:

<div class="carousel-inner" role="listbox">
    <?php 
    $args = array(
        'post_type' => 'bulletin', 
        'posts_per_page' => io_get_option('bulletin_n',5)
    );
    $i = 0;
    $the_query = new WP_Query($args); 
    while ( $the_query->have_posts() ) : $the_query->the_post();
    ?>
    <?php 
        if(get_post_meta(get_the_ID(),'_goto',true)){
            the_title( sprintf( '<div class="carousel-item %s"><a class="overflowClip_1" href="%s" target="_blank" rel="bulletin noreferrer noopener%s">',$i==0?'active':'',  esc_url( get_permalink() ),get_post_meta(get_the_ID(),'_nofollow',true)?' external nofollow':'' ), ' ('. get_the_time('m/d').')</a></div>' ); 
        }else{
            the_title( sprintf( '<div class="carousel-item %s"><a class="overflowClip_1" href="%s" rel="bulletin">',$i==0?'active':'',  esc_url( get_permalink() ) ), ' ('. get_the_time('m/d').')</a></div>' ); 
        }
    ?>
    <?php $i ++; endwhile; ?>
    <?php wp_reset_postdata(); ?>
</div>

首先明确下 WP_Queryhave_posts()the_post() 在 WordPress 中的作用:

  1. WP_Query:是一个类,用于自定义查询 WordPress 数据库中的帖子。
    通过创建 WP_Query 对象,可以根据特定的参数(如分类、标签、作者等)获取特定的帖子集合。
    <?php
    $query = new WP_Query(array(
        'category_name' => 'news',
        'posts_per_page' => 5
    ));
  2. have_posts():是一个方法,用于检查当前查询是否有更多的帖子可供循环处理,通常与 while 循环一起使用。
  3. the_post():也是一个方法,用于设置当前帖子数据。
    每次调用 the_post() 时,WordPress 会将全局 $post 对象设置为当前循环中的帖子,并准备好模板标签(如 the_titlethe_content)以显示该帖子的内容。

现在就好理解了,上述代码是通过 'post_type' => 'bulletin''posts_per_page' => io_get_option('bulletin_n',5) 这两个参数找文章,然后进行显示。
那我们只需要先拿到当前的语言,然后作为查询参数一起传到后端即可。

而 Polylang 就提供获取当前语言的方法 pll_current_language

官方文档:pll_current_language

pll_current_language( $value );

参数默认为 slug,参数和返回值如下:

  • slug:返回当前语言代码,如 1
  • name:返回当前语言名称,如 中文
  • locale:返回当前语言的标识,如 zh_CN

于是修改下核心部分的代码:

<div class="carousel-inner" role="listbox">
    <?php 
    $args = array(
        'post_type' => 'bulletin', 
        'posts_per_page' => io_get_option('bulletin_n',5)
    );
    # 2024/10/18 Rabbir add start
    # 1. 判断是否有多语言插件
    if (function_exists('pll_current_language')):
        # 2. 通过 pll_current_language() 获取当前语言的表示 locale
        $language_locale_for_bulletin_search = pll_current_language("locale");
        # 3. 新增检索条件:meta_key = "onenav_bulletin_language_locale" & meta_value = $language_locale_for_bulletin_search
        $meta_args = array(
            'meta_query' => array(
                array(
                    'key' => 'onenav_bulletin_language_locale',
                    'value' => $language_locale_for_bulletin_search,
                    'compare' => '='
                )
            )
        );
        # 4. 将 meta_query 添加到 $args 中
        $args = array_merge($args, $meta_args);
    endif;
    # 2024/10/18 Rabbir add end
    $i = 0;
    $the_query = new WP_Query($args); 
    while ( $the_query->have_posts() ) : $the_query->the_post();
    ?>
    <?php 
        if(get_post_meta(get_the_ID(),'_goto',true)){
            the_title( sprintf( '<div class="carousel-item %s"><a class="overflowClip_1" href="%s" target="_blank" rel="bulletin noreferrer noopener%s">',$i==0?'active':'',  esc_url( get_permalink() ),get_post_meta(get_the_ID(),'_nofollow',true)?' external nofollow':'' ), ' ('. get_the_time('m/d').')</a></div>' ); 
        }else{
            the_title( sprintf( '<div class="carousel-item %s"><a class="overflowClip_1" href="%s" rel="bulletin">',$i==0?'active':'',  esc_url( get_permalink() ) ), ' ('. get_the_time('m/d').')</a></div>' ); 
        }
    ?>
    <?php $i ++; endwhile; ?>
    <?php wp_reset_postdata(); ?>
</div>

之后重新打包并更新主题。

二、确认各语言下 locale 的值

各语言属性

语言slugnamelocale
英文enEnglishen_US
中文zh中文 (中国)zh_CN
日语ja日本語ja

三、测试添加公告

1、中文

中文模式下暂时没有公告:
中文模式下暂时没有公告
为既有的公告添加一条自定义字段:
添加自定义字段 onenav_bulletin_language_locale
回到首页就能看到公告了:
中文模式下对应的公告出现
中文模式公告详情显示成功

2、英文

英文模式下也暂时没有公告: 英文模式下暂时没有公告
发布公告的同时添加下字段: 英文公告添加字段
回到首页就能看到公告了:
英文模式下对应的公告出现
在详情页面发生了 404 错误,大概率是 en/ 路径导致的英文模式公告详情显示失败

将路径从 https://test.steam.cash/en/bulletin/45.html 修改为 https://test.steam.cash/bulletin/45.html 之后,果然页面出现了:
英文模式修改路径后公告详情显示成功

3、日语

日语模式下就不测了,肯定会和英语出现一样的问题。

四、修复非默认语言公告详情 404 的问题

由于非默认语言会在路径中携带 en/jp/ 等语言标识,因此会导致 OneNav 找不到对应的公告出现 404 错误。
同样的问题也会出现了 网址 详情页中。

这里使用最简单也是最彻底的方式,正则匹配路径并将 ^/en/(.*)/(.*)^/jp/(.*)/(.*) 路径全部 302 到 /$1/$2 下。
需要使用到 Wordpress 的插件 Redirection
Redirection
安装并启用后,在 工具 -> Redirections 中配置重定向规则:
重定向英文页面

  • 原始 URL:^/en/(.*)/(.*)(在右侧勾上 正则表达式
  • 匹配:匹配 URL
  • 302 重定向到
  • 目标 URL:/$1/$2

其他语言的重定向,参数与英文一样,只是将 en 替换为 ja 等。

之后保存,再去首页检查就可以发现详情页和网站都正常了:
详情页正常

顺便介绍下 301 和 302 重定向的区别:

  • 301 重定向:永久重定向,浏览器会缓存。
    > 如果是永久重定向那么浏览器客户端就会缓存此次重定向结果,下次如果有请求则直接从缓存读取,譬如我们切换域名,将所有老域名的流量转入新域名,可以使用永久重定向。
  • 302 重定向:临时重定向,浏览器不缓存。
    > 如果只是临时重定向那么浏览器则不会缓存,譬如我们的服务临时升级,会使用临时重定向。

而关于 301 和 302 的区别,Google 的人员是这么说的:

当我们识别到一个重定向并看到它是 302 时,我们首先假定它是一个临时重定向,并假定你想要为初始 URL 编制索引,而不是为了重定向。 […] 然而,当我们意识到它实际上更像是一个永久重定向,302 可能是你不小心设置的,那么我们会将其视为 301。我们不会为此 URL 编制索引, 而将为重定向目标建立索引。

这意味着如果你不怎么介意的话,全设置为 302 重定向即可,搜索引擎会自己纠正。


参考资料:


Edit page