Utilize Nginx to fulfill bilingualism for Hexo
Tags: hexo, nginx, jquery
Published: 2020-06-21 12:19:54

The bilingualism config process for [Hexo][hexo] is recorded In this article. Different language version is in the same application with common template, any webpage can be switched to another language's corresponding webpage, and for the access url whose language is not specific, automatic redirection will be proceed according to browser language 
<!-- more -->



## Fulfillment Rule


### Address Difference

Chinese Home:
>https://chanvinxiao.com/cn/blog/

English Home:
>https://chanvinxiao.com/en/blog/


### Switch between Languages

The following Chinese page as example
> https://chanvinxiao.com/cn/blog/archives/2020/04/

Click `English` in the top right corner, the following webpage will be shown
> https://chanvinxiao.com/en/blog/archives/2020/04/

Click `中文` in the top right corner in this webpage, the previous webpage will been shown


### Automatic Redirection

The following address as example
>https://chanvinxiao.com/blog/vuejs-tic-tac-toe/

If the browser prefer language is set to English, it will redirect to corresponding English version 
>https://chanvinxiao.com/en/blog/vuejs-tic-tac-toe/

If the browser prefer language is set to Chinese, it will redirect to corresponding Chinese version 
>https://chanvinxiao.com/cn/blog/vuejs-tic-tac-toe/



## Hexo Setting


### Add English Setting

Add `_config-en.yml` in the root directory

```
# Site
title: TITLE
subtitle: SUBTITLE
description: DESCRIPTION
keywords: KEYWORDS
language: en

# URL
url: https://chanvinxiao.com/en/blog
root: /en/blog/

# Directory
source_dir: source-en
public_dir: public-en
```

- in the `#Site` associated setting, I change the original Chinese content to English, and the key point is to change `language` to `en`, thus the template will use english version
- `URL` and `root` need to be set as individual address and directory to distinguish between chinese counterpart
- Divide `source` and `public` directory from chinese, to ensure the Chinese or English version only show Chinese or English article respectively 


### Add Script

Add the following script in `package.json`

```
  "scripts": {
    ...
    "build:en": "hexo generate --config _config.yml,_config-en.yml",
    "clean:en": "hexo clean --config _config.yml,_config-en.yml",
    "server:en": "hexo server --config _config.yml,_config-en.yml"
  },
```

- Add build, clear, and server script for English version, so the Chinese and English version is separated without interfering with each other
- Utilize [Custom Config][hexo-config], combine config `_config.yml` and `_config-en.yml` in the corresponding scripts
- The combining config file `_multiconfig.yml` will be generated, which should be added to .gitignore



## Nginx Config


Add the following config in corresponding `server` session in Nginx

```
  if ( $http_accept_language ~* ^en ) {
    rewrite ^(/blog.*) /en$1 redirect;
  }

  rewrite ^(/blog.*) /cn$1 redirect;

  location /cn/blog {
    alias /PATH/TO/BLOG/public;
    error_page 404 $scheme://$host/cn/blog;
  }

  location /en/blog {
    alias /PATH/TO/BLOG/public-en;
    error_page 404 $scheme://$host/en/blog;
  }
```

- `$http_accept_language` is [embedded variable][nginx-http-variable] set by Nginx's `http` module for request header `Accept-Language`, If prefer language of browser is English, the value will start with `en`, such as `en-US,en;q=0.9`
- `rewrite ^(/blog.*) /en$1 redirect;` will add en  for the address start with /blog, the flag of [`rewrite`][nginx-rewrite] is set to `redirect`, which means 302 redirect, so does the following default cn
- The above setting make redirect decision for address start with `/blog` (aka address without language), If the prefer language of browser is English, English site start with `/en/blog` will be redirected, or else Chinese version start with `/cn/blog` will be redirected
- Because /cn/blog is matched with index.html in the public directory, not cn/blog/index.html, so here [`alias`][nginx-alias] is used, not [`root`][nginx-root]
- [`error_page`][nginx-error_page] is set for 404 handling, `$scheme` is `http` or `https`, which means webpage redirect, and will redirect to Chinese or English homepage



## Webpage Switch

Use template landscape as example, add the following content before `})(jQuery);` in `themes/landscape/source/js/script.js`

```
  let language = {};
  language.now = location.pathname.match(/^\/en/) ? 'en' : 'cn';
  if('en' === language.now){
    language.label = '中文';
    language.href = location.pathname.replace(/^\/en/, '/cn');
  }else{
    language.label = 'English';
    language.href = location.pathname.replace(/^\/cn/, '/en');
  }
  $('#sub-nav').prepend(`<a class="main-nav-link" href="${language.href}">${language.label}</a>`)
```
- Determine the language of current webpage according to the existence of `/en` in the beginning of webpage path
- Add link menu to Chinese webpage in English webpage, and add English link in Chinese version
- Directly change `cn` to `en` or `en` to `cn` in the address to get the corresponding webpage, if there is not corresponding webpage, the associated homepage will be redirected according to the above Nginx config
- Utilize `prepend` of `jQuery` to add link to the sub menu, with the common class `main-nav-link` style



## Summarize

In the fulfillment of blog bilingualism, the following technology is primarily used:
- Custom config of hexo and `scripts` in package.json
- Embedded variable for request header in `http` module of Nginx
- Nginx's directive  `rewrite`, `alias` and `error_page`
- `pathname` of location and `prepend` of jQuery



[hexo]: https://hexo.io/
[hexo-config]: https://hexo.io/docs/configuration#Using-an-Alternate-Config
[nginx-http-variable]: http://nginx.org/en/docs/http/ngx_http_core_module.html#variables
[nginx-rewrite]: http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
[nginx-alias]: http://nginx.org/en/docs/http/ngx_http_core_module.html#alias
[nginx-root]: http://nginx.org/en/docs/http/ngx_http_core_module.html#root
[nginx-error_page]: http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page