虽然自己是个懒惰的 github pages + jekyll user, 连域名都懒得花钱折腾的那种, 但是其他原因折腾了一下 hexo, 简单说下我认为比较靠谱的多语言 blog 方案.

需求

虽说多语言, 当然先以中英文为例, 主要需求是这样的:

  • 目录链接等模板 text 肯定是中英文分开, 这个很容易
  • 中英文 posts 分开, 某些文章可能两种语言都有, 某些文章可能只有其中一种
  • tag/category/archive 都是分开的
    • 因为一开始还尝试过修改 index render 方法, 在 front-matter 里添加一个 lang: cn 然后在 render 的时候 filter 掉
    • 这样 index page 是没有问题, 但是 tag/category/archive 等地方, 一样会混在一起

搜索和尝试

一开始搜索一通之后, 发现这篇文章的作者和我的需求比较一致, 也感谢他的折腾, 我节省了尝试 hexo-generator-i18n 和 hexo-multilingual 插件的时间.

但对于官方国际化机制也 failed, 我表示有一丝丝怀疑, hexo 自己的网站也是用自己的 dogfood 建出来的, 怎么人家有辣么多种语言呢?

仔细看了下它自己网站的代码编译生成的结果, 发现它是这样的:

  • source 文件夹下面, 每种语言一个文件夹
  • 这个语言文件夹下, 首先有一个 index.jade 页面, 按照它网站的设计, 主页只是一个 landing page, 所以没有什么特别的
  • 除此之外就是 api 和 docs 两个文件夹 放着翻译好的 md 文档
  • 按照官网的设计, 只有这两个类别里面的文档需要多语言翻译, 另外三个 menu, 一个是 release news 用的, 一个是展示 plugins 用的, 一个是展示 theme 用的, 都并没有也不需要翻译
  • 另外, 官网的文档也并不使用 tag/category/archive, 因为有一个 algolia 搜索

所以结论很明显: 用官方方案的确不能满足需求.

所以用 npm script 咯

前面那篇 post 建两个文件夹再加 nginx 代理的方法, 我觉得是靠谱的, 但是一个问题是, 作者是分开两个仓库进行更新的, 那么会导致如果想要改样式和 layout, 那就需要再两个仓库里分别更新, 这个是绝对很蛋疼的. 实际上作者的中英文网站的确在布局上不完全一样.

我一定希望只有一个仓库, 所以自己尝试了以下方法:

_config.yml

...
url: http://yoursite.com/
root: /en
language: en
public_dir: public/en
...

其余的就不说了, 先设置默认的 language 是英文, 生成在 public/en 路径下

_config.cn.yml

language: zh-CN
root: /cn
public_dir: public/cn

我另外单独创建了一个中文专用的 config 文件, 她可以只有上面几行.

文件夹

在根目录下分别创建 encn 目录来分别存放中英文 post

scripts 上

其实想法非常简单, 每次 build 的时候, 如果是英文 blog, 则将 en 下的 posts 复制到 source/_posts 下, 也就是正常添加文章的地方, 然后再编译生成.

简单来说就是:

cp -r en/* source/_posts && hexo generate

这样, 在 public 下生成了 en 文件夹包含了所有英文 blog.

中文 blog 类似, 不一样的地方是将 _config.cn.yml 派上用处咯, 所幸 hexo 提供了一个 alternate config 的功能. 也就是说你可以选择当前使用哪一个 config 文件, 或者使用多个 config 文件. 这样就可以用 hexo server --config _config.yml,_config.cn.yml 这种命令来打造中文 blog 所需要的 config. _config.cn.yml 放在后面才能覆盖掉英文 blog 的设置.

所以中文 blog 的 build 就是:

cp -r en/* source/_posts && hexo generate --config _config.yml,_config.cn.yml

这样, 在 public 下就会有 en 和 cn 两个样式一致但内容完全分开的 blog, 直接将 public 丢到 github pages 或者 netlify 之类可以 serve 静态网页 或者自己的服务器上跑一下 nginx, 就 over 了.

一个小问题是这样, 如果没有自己的服务器, 就简单丢到 netlify 类型的网站上 serve 的话, 可能必须直接到 http://yoursite.com/en/ 或者 http://yoursite.com/cn/ 才能正常访问. 这里一个小小的 hack 是这样, 加一个空白的 index.html 在 public 下, 根据浏览器的默认语言选择直接改一下 location redirect 到 /en/ 或者 /cn/ 上即可.

最后 npm script 可以设置成这样:

"build:en": "rm -rf source/_posts/* && cp -r en/* source/_posts && hexo generate && rm -rf source/_posts/*",
"build:cn": "rm -rf source/_posts/* && cp -r cn/* source/_posts && hexo generate --config _config.yml,_config.cn.yml && rm -rf source/_posts/*",
"build": "rm -rf public && npm run build:en && npm run build:cn && cp index.html public/"

当然不用 npm script, 用 Makefile 也同样可以达到目的. 以及这个方法即使有其他更多语言都可以 hold 住了. 🤟🏻🖖🏻