Hexo Next 双语切换(7.1版本)

2020年更新:本方法bug太多,已弃坑,只针对7.1版本的Next主题。新方法请看Hexo Next 7.7 双语切换

以下为原内容


有英语版网站的需要,所以需要加一个双语切换功能,Hexo有对网站国际化的支持,即i18n,但存在缺陷,各种语言的文章会混杂在一起显得很混乱,需要稍加改造,步骤如下:

安装插件

安装Hexo国际化插件i18n,在博客根目录执行下列命令

1
npm install hexo-generator-i18n

注意事项

需要确保 i18n 插件位于根目录package.json中的所有插件的最后,每次安装新的插件时都要手动调整一次,因为每次安装新插件都会将插件按照字母顺序重新排列,目前没有发现好的方法,格式如下,注意最后一项没有逗号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"dependencies": {
"bookmark": "^0.2.3",
"clipboard": "^2.0.4",
"gitment": "0.0.3",
"hexo": "^3.8.0",
"hexo-asset-image": "0.0.3",
"hexo-deployer-git": "^1.0.0",
"hexo-generator-archive": "^0.1.5",
"hexo-generator-category": "^0.1.3",
"hexo-generator-index": "^0.2.1",
"hexo-generator-search": "^2.4.0",
"hexo-generator-sitemap": "^1.2.0",
"hexo-generator-tag": "^0.2.0",
"hexo-helper-live2d": "^3.1.1",
"hexo-prism-plugin": "^2.3.0",
"hexo-renderer-ejs": "^0.3.1",
"hexo-renderer-marked": "^0.3.2",
"hexo-renderer-stylus": "^0.3.3",
"hexo-server": "^0.3.3",
"hexo-symbols-count-time": "^0.4.4",
"hexo-wordcount": "^6.0.1",
"live2d-widget-model-tororo": "^1.0.5",
"live2d-widget-model-z16": "^1.0.5",
"hexo-generator-i18n": "0.0.7"
}

修改配置文件

打开博客根目录中的配置文件_config.yml,在language栏作如下修改

1
2
3
4
5
6
7
# language:
# - zh-CN
# - en
language: [zh-CN,en]
i18n:
type: [page, post]
generator: [index, archive, categorie, tag]

完成后执行hexo clhexo g二连重新生成public文件夹,此时会生成新目录/en用来存放英文站点文件,但此时不同语言的网站还是混合在一起的,需要添加生成条件让不同语言的页面出现在对的位置。

添加生成条件

打开.\themes\next\layout\index.swig并在末尾添加如下代码

1
2
3
4
5
6
7
8
9
10
{% block content %}
<section id="posts" class="posts-expand">
{% for post in page.posts %}
{% if page.lang === post.lang %}
{{ post_template.render(post, true) }}
{% endif %}
{% endfor %}
</section>
{% include '_partials/pagination.swig' %}
{% endblock %}

此时只有页面语言与文章完全一致时文章才会被生成,同理,在tag.swigcategory.swigarchive.swig等文件中搜索设置post_template.render(post)判断条件即可隐藏其他语言的文章,示例如下:
tag

1
2
3
4
5
{% for post in page.posts %}
{% if page.lang === post.lang %}
{{ post_template.render(post) }}
{% endif %}
{% endfor %}

archive

1
2
3
{% if page.lang === post.lang %}
{{ post_template.render(post) }}
{% endif %}

category

1
2
3
4
5
{% for post in page.posts %}
{% if page.lang === post.lang %}
{{ post_template.render(post) }}
{% endif %}
{% endfor %}

文章写作格式

在博文标题栏加上lang:表示用来区分不同语言文章,中文为lang: zh-CN,英文为lang: en,示例如下:

1
2
3
4
5
title: Hexo双语切换
date: 2019-04-09 17:12:53
lang: zh-CN
tags: [HEXO]
categories: Blog

添加切换按钮

打开Next主题配置文件.\themes\next\_config.yml并在Menu:下添加switch_lang:,示例如下

1
2
3
4
5
6
7
8
9
10
menu:
home: / || home
about: /about/ || user
tags: /tags/ || tags
categories: /categories/ || th
archives: /archives/ || archive
switch_lang: /en || language
#schedule: /schedule/ || calendar
#sitemap: /sitemap.xml || sitemap
#commonweal: /404/ || heartbeat

打开.\themes\next\languages下的zh-CN.ymlen.yml文件,分别在menu:下添加switch_lang:,示例如下

zh-CN

1
2
3
4
5
6
7
8
9
10
11
menu:
home: 首页
archives: 归档
categories: 分类
tags: 标签
switch_lang: English
about: 关于
search: 搜索
schedule: 日程表
sitemap: 站点地图
commonweal: 公益 404

en

1
2
3
4
5
6
7
8
9
10
11
menu:
home: Home
archives: Archives
categories: Categories
tags: Tags
switch_lang: zh-CN
about: About
search: Search
schedule: Schedule
sitemap: Sitemap
commonweal: Commonweal 404

添加判断条件

此时链接仍然是单项可用的,只能跳转到英文页面但是不能跳转回中文页面,因此需要添加判断条件
.\themes\next\layout\_partials\head\head-unique.swig中添加以下代码,在加载完英文页面后将页面切换按钮重定向到中文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script type="text/javascript">
// Wait for the page to load first
var _prevOnload = window.onload;
window.onload = function() {
var switchLang = document.getElementsByClassName("menu-item menu-item-switch_lang")[0];
switchLang.onclick = function() {
var href = window.location.href;
var indexOfEn = href.toLowerCase().indexOf('/en');
if(indexOfEn !== -1) {
window.location.href = href.replace('/en/', '/');
}
else {
window.location.href = href.replace(/(^http[s]?:\/\/[a-z0-9.]*[:?0-9]*\/)(.*)/i, '$1en/$2');
}
if(typeof(_prevOnload) === 'function') {
_prevOnload();
}
return false;
}
}
</script>

JavaScript萌新表示在这里卡了好久,document.getElementsByClassName返回的数值是数组,调试的时候一直报错,在后面加上了[0]才能返回Class的名称

缺陷

虽然上述方法可以实现切换,但是在英文页面点击Tags、Archives、Categories等标签时会跳转中文页面,需要再跳转后的页面再点击一次英文切换按钮才能切换到相应页面的中文,如果大佬们有什么好的办法欢迎评论区留言

参考wm4n