前言

为了实现可以切换的中英双语博客,我查阅了网上很多教程。大部分都是使用next主题的,或者使用hexo-generator-i18n

经过一番搜寻,我参考 https://shannonhung.github.io/posts/hexo-butterfly-lang-switch/ ,找到了双语切换的解决方案。

大致思路是通过在github上面建立两个仓库,并分别为中文和英文设置config.yml_config.butterfly.yml。在本地分别设置source-en和source-zh两个文件夹,手动翻译中英文。之所以选择手动翻译,是因为一般自动翻译的api都不尽如人意,只有GPT能达到相对比较理想的效果,但是API收费。

STEP 1 - 建立第二个仓库

参考 https://github.com/github/docs/blob/main/content/get-started/quickstart/create-a-repo.md , 建立repository。这个repository直接命名为类似en, zh, sp等语言简写,这样就会自动生成 https://username.github.io/en, https://username/zh 之类的网址,其中 https://username.github.io 就是你的blog网页名。

注意需要设置为public而不是private,不然每月得交48刀的月费还是啥的才能开通Github page功能。

STEP 2 - 设置config.yml

  1. config.yml复制一份,并且一个命名为config-zh.yml,一个命名为config-en.yml
1
2
3
4
5
6
7
8
9
10
.
├── node_modules
├── source
├── themes
├── _config.butterfly.yml
├── config-en.yml # <== here
├── config-zh.yml # <== here
├── db.json
├── package-lock.json
└── package.json
  1. 分别按照下列要求修改、添加代码。

config-zh.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 設定成中文 
language: zh-CH

# 使用原本的url
url: https://your_url # 修改your_url,将其替换为你的blog网址,比如https://aursus.github.io
root: /

# 指定啟動的路徑
source_dir: source
public_dir: public

# 把英文的 source 進行排除
include:
exclude:
ignore:
- source-en/

deploy:
type: git
repository: https://github.com/YourUserName/YourUserNameURL.git
branch: main

config-en.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 設定成英文
language: en

# 添加 en
url: https://your_url/en # 修改your_url,将其替换为你的blog网址,比如https://aursus.github.io/en
root: /en/

# 指定啟動的路徑
source_dir: source-en
public_dir: public-en

# 把中文的 source 進行排除
include:
exclude:
ignore:
- source/

# 修改仓库名
deploy:
type: git
repository: https://github.com/YourUserName/en.git # 将这里修改为你的英文仓库名
branch: main

STEP 3 - 设置切换语言的js脚本

修改source/self下的btf.js,增加内容如下。如果没有btf.js的话,则在该位置新建一个。

btf.js內容如下:

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
26
27
28
29
30
31
(() => {
// 判断是否为英文
const isIncludeEN = item => {
const key = '/en/'
return item.includes(key)
}

// 建立 重新导向到不同语言的 url
window.loadFullPage = (url) => {
window.location.href = url
}

// 重新导向
const eventFn = (elements, includeEN) => {
elements.forEach(item => {
if (!includeEN || !isIncludeEN(item.href)) {
item.href = `javascript:loadFullPage('${item.href}');`
}
})
}

// 判断目前是否为英文
const nowIncludeEN = isIncludeEN(window.location.href)

// 修改你的 url
const selector = nowIncludeEN
? document.querySelectorAll('a[href^="https://<your-url>"]') // 只需要修改这一行就好了,将https://<your-url>替换为你的blog网址。
: document.querySelectorAll('a[href^="/en/"]')

eventFn(selector, nowIncludeEN)
})()

STEP 4 - 拷贝source文件夹

source文件夹复制一份,重命名为source-en。确保两份文件夹里面都在source/self下有btf.js文件。

1
2
3
4
5
6
7
8
9
10
11
.
├── node_modules
├── source
├── source-en # <== here
├── themes
├── _config.butterfly.yml
├── config-en.yml
├── config-zh.yml
├── db.json
├── package-lock.json
└── package.json

STEP 5 - 设置config-butterfly.yml

  1. 复制_config.butterfly.yml,重命名为config-butterfly-zh.ymlconfig-butterfly-en.yml
1
2
3
4
5
6
7
8
9
10
11
12
.
├── node_modules
├── source
├── source-en
├── themes
├── config-butterfly-zh.yml # <== here
├── config-butterfly-en.yml # <== here
├── config-en.yml
├── config-zh.yml
├── db.json
├── package-lock.json
└── package.json
  1. 根据下列代码修改config-butterfly-zh.ymlconfig-butterfly-en.yml

config-butterfly-zh.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 使用中文目录
menu:
Home: / || fas fa-home
文章: /archives/ || fas fa-archive
链接: /link/ || fas fa-link
关于我: /about/ || fas fa-heart
语言|| fas fa-language:
English: /en/ || fas fa-e
中文: / || fas fa-c

# inject 刚刚建立好的 js
...
inject:
bottom:
- <script data-pjax src="/self/btf.js"></script>

config-butterfly-en.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 使用英文目录
menu:
Home: / || fas fa-home
Archives: /archives/ || fas fa-archive
Link: /link/ || fas fa-link
About: /about/ || fas fa-heart
Language|| fas fa-language:
English: / || fas fa-e
中文: https://aursus.github.io/ || fas fa-c # 此处修改为你的blog的url

# inject 刚刚建立好的 js
...
inject:
bottom:
- <script data-pjax src="/en/self/btf.js"></script>

注意: config-butterfly-en.yml 中任何 /img/ 图片 或是 /self/ 的 js 档案,都要改成 /en/img/ 或是 /en/self/才能正确显示。

STEP 6 - 更新package.json

更新package.json使其能够产生public-en

package.json

1
2
3
4
5
6
7
8
9
...
"scripts": {
"push": "hexo clean && hexo g && hexo douban && gulp && hexo deploy",
"show": "hexo clean && hexo g && hexo s",
"update": "git init && git add . && git commit -m 'backup' && git push origin main",
"kk": "hexo clean && hexo g && hexo deploy",
"en": "hexo clean && hexo g --config config-en.yml && hexo s --config config-en.yml"
},
...

STEP 7 - 脚本部署

  1. 确认你的根部录下有一下文件
1
2
3
4
5
6
7
8
9
10
11
12
.
├── node_modules
├── source # <== here
├── source-en # <== here
├── themes
├── config-butterfly-zh.yml # <== here
├── config-butterfly-en.yml # <== here
├── config-en.yml # <== here
├── config-zh.yml # <== here
├── db.json
├── package-lock.json
└── package.json
  1. 在根目录下创立deploy.sh

deploy.sh

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/bin/bash

while [[ "$#" -gt 0 ]]; do
case $1 in
-h|--help)
echo "Usage: bash.sh [en|zh|all|show <en|zh>|-h]"
echo "Options:"
echo " [deploy|d] en Deploy English configuration to GitHub Pages"
echo " [deploy|d] zh Deploy Chinese configuration to GitHub Pages"
echo " [deploy|d] all Deploy both English and Chinese configurations to GitHub Pages"
echo " [show|s] en Execute npm run show for English configuration"
echo " [show|s] zh Execute npm run show for Chinese configuration"
echo " -h, --help Display this help message"
exit 0
;;
d | deploy)
lang=$2
if [ "$lang" = "en" ] || [ "$lang" = "zh" ]; then
cp "config-$lang.yml" _config.yml
cp "config-butterfly-$lang.yml" "_config.butterfly.yml"
npm run kk
echo "Deploy $1 success!"
elif [ "$lang" = "all" ]; then
for lang_choice in "zh" "en"; do
cp "config-$lang_choice.yml" _config.yml
cp "config-butterfly-$lang_choice.yml" "_config.butterfly.yml"
npm run kk
echo "Deploy $lang_choice success!"
done
else
echo "Error! Please input 'en' or 'zh' or 'all'!"
fi
shift
;;
s | show)
lang=$2
if [ "$lang" = "en" ] || [ "$lang" = "zh" ]; then
cp "config-$lang.yml" _config.yml
cp "config-butterfly-$lang.yml" "_config.butterfly.yml"
npm run show
echo "Running npm show!"
else
echo "Error! Please use './bash.sh show en' or './bash.sh show zh'!"
fi
shift # Move to the next argument after 'show'
;;
*)
echo "Error! Please input deploy <en|zh|all> or 'show <en|zh>' or '-h' for help!"
exit 1
;;
esac
shift
done
  1. 在git bash里面用下列代码执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 寻求帮助
./deploy.sh -h # 此代码与下列等价
./deploy.sh --help

# 推送英文 到 en repository
./deploy.sh deploy en # 此代码与下列等价
./deploy.sh d en

# 推送中文 到 zh repository
./deploy.sh deploy zh # 此代码与下列等价
./deploy.sh d zh

# 本地运行英文
./deploy.sh show en # 此代码与下列等价
./deploy.sh s en

# 本地运行中文
./deploy.sh show zh # 此代码与下列等价
./deploy.sh s z

页面中英文互译

修改 config-butterfly.yml

修改config-butterfly-zh.ymlconfig-butterfly-en.yml

config-butterfly-zh.yml

1
2
3
4
5
6
7
8
9
10
11
12
translate:
enable: true
# The text of a button
default:
# the language of website (1 - Traditional Chinese/ 2 - Simplified Chinese)
defaultEncoding: 1 # 选择什么都不影响结果
# Time delay
translateDelay: 0 # 选择什么都不影响结果
# The text of the button when the language is English
msgToEnglish: 'EN'
# The text of the button when the language is Simplified Chinese
msgToSimplifiedChinese: '中'

config-butterfly-en.yml

1
2
3
4
5
6
7
8
9
10
11
12
translate:
enable: true
# The text of a button
default: EN
# the language of website (1 - Traditional Chinese/ 2 - Simplified Chinese)
defaultEncoding: 1 # 选择什么都不影响结果
# Time delay
translateDelay: 0 # 选择什么都不影响结果
# The text of the button when the language is English
msgToEnglish: 'EN'
# The text of the button when the language is Simplified Chinese
msgToSimplifiedChinese: '中'

创建tw_en.js

  1. source/self/source-en/self/下建立文件ch_en.js

  2. 在两个ch_en.js文件内都输入如下代码

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
document.addEventListener("DOMContentLoaded", function () {
const { defaultEncoding, translateDelay, msgToSimplifiedChinese } =
GLOBAL_CONFIG.translate;
const msgToEnglish = "EN";
const snackbarData = GLOBAL_CONFIG.Snackbar;
let currentEncoding = defaultEncoding;
const targetEncodingCookie = "translate-en-chn";
let targetEncoding =
saveToLocal.get(targetEncodingCookie) === undefined
? defaultEncoding
: Number(saveToLocal.get("translate-en-chn"));
let translateButtonObject;
const isSnackbar = snackbarData !== undefined;

const isIncludeEN = (item) => {
const key = "/en/";
return item.includes(key);
};

const nowIncludeEN = isIncludeEN(window.location.href);
console.log(nowIncludeEN);

function translatePage() {
let currentUrl = window.location.href;
if (nowIncludeEN) {
// 英文 => 中文简体
translateButtonObject.textContent = msgToSimplifiedChinese;
// 网址: /en/... => /...
let newUrl = currentUrl.replace("/en/", "/");
console.log(`Redirect to ${newUrl}`);
window.location.href = newUrl;
} else {
// 中文简体 => 英文
translateButtonObject.textContent = msgToEnglish;
// 网址 /... => /en/...
let newUrl = currentUrl.replace(/^(https?:\/\/[^\/]+)(\/)?/, "$1/en/");
console.log(`Redirect to ${newUrl}`);
window.location.href = newUrl;
}
}

function translateInitialization() {
translateButtonObject = document.getElementById("translateLink");
if (translateButtonObject) {
if (nowIncludeEN) {
translateButtonObject.textContent = msgToSimplifiedChinese;
} else {
translateButtonObject.textContent = msgToEnglish;
}
translateButtonObject.addEventListener('click', translatePage, false)
}
}
document.addEventListener("pjax:complete", translateInitialization);
translateInitialization();
});

修改 config-butterfly.yml

修改config-butterfly-zh.ymlconfig-butterfly-en.yml

config-butterfly-zh.yml

1
2
3
4
5
6
inject:
head:
...
bottom:
- <script data-pjax src="/self/btf.js"></script>
- <script data-pjax src="/self/ch_en.js"></script> # <== 這裡

config-butterfly-en.yml

1
2
3
4
5
6
inject:
head:
...
bottom:
- <script data-pjax src="/en/self/btf.js"></script>
- <script data-pjax src="/en/self/ch_en.js"></script> # <== 這裡

(可选)删除tw_cn.js

如果加载出来的博客还是繁简转换,则将
.\node_modules\hexo-theme-butterfly\source\js下的tw_cn.js文件删除

重新加载

在Git Bash里面输入命令,重新刷新网页查看。

1
./deploy.sh deploy all

如果有错误请留言纠正,谢谢