hexojs / hexojs/hexo

Multilingual(i18n) Page + Post Support

Open
#4,701 3 comments 5 reactions 0 assignees View on GitHub
enhancement feature-request help wanted i18n
Dominant language
TypeScript
Stars
41.8k
Forks
41
PR merge metrics
No merged PRs in 30d

Description

## Check List

- [x] I have already read [Docs page](https://hexo.io/docs/)
- [x] I have already searched existing issues

---

I've been searching on the "Best Practice" of Hexo's Multitilingual (i18n) feature in recent days, and here are some of the results I've got so far, with detailed usages of each feature.

## Multilingual Support for Pages

For **built-in pages** like `archive` and `category`, I chose [hexo-generator-i18n](https://github.com/Jamling/hexo-generator-i18n). It performs well.

For **custom pages**, the best way is to place files in different language-identifier folders under the `source` folder, **excluding default language**. Here's an example tree:

```
├─about
│ index.md

├─zh-CN
│ └─about
│ index.md
```

The reason for this is that most `language-switcher` components will roll back to the normal path (which does not contain language-ids) when switching to default languages, such as [theme-next](https://github.com/next-theme/hexo-theme-next/blob/master/scripts/helpers/engine.js#L102):

```js
return this.url_for(`${this.languages.indexOf(language) === 0 ? '' : '/' + language}/${base}`);
```

For config like this:

```yml
language:
- en
- zh-CN
```

This will change path from `/zh-CN/about/` to `/about/`.

## Multilingual Support for Posts

For **posts**, the best way is to place files in different language-identifier folders (same as custom pages) under `_posts` folder, **including default language**. Here's an example tree:

```
├─en
│ └─common
│ index.md

├─zh-CN
│ └─common
│ index.md
```

Then, set config like this:

```yml
language:
- en # Default language
- zh-CN
i18n_dir: :lang
i18n: # hexo-generator-i18n settings
type:
- page
# - post # Disable direct copy
generator:
- archive
- category
- tag
- index

permalink_defaults:
lang: en
permalink: :lang/:title/
new_post_name: :lang/:title.md
```

And you can see your posts in different languages in `/en/my-post/` and `/zh-CN/my-post/`.

The reason we need to place all posts in language folder is, the `i18n_dir` [use `permalink` to resolve language info](https://hexo.io/docs/internationalization.html), and the `permalink` [use `new_post_name` to resolve page meta](https://hexo.io/docs/permalinks.html). I'm also confused about this, but that's really what I tested. If you don't configure like this, you may find something strange with the generated path and page info.

So I forked `hexo-theme-next` and made some changes on the `language-switcher`. It now looks like this:

```js
/**
* Get page path given a certain language tag
*/
hexo.extend.helper.register('i18n_path', function(language) {
const { path, lang, layout } = this.page;
const base = path.startsWith(lang) ? path.slice(lang.length + 1) : path;
return this.url_for(`${this.languages.indexOf(language) === 0 && layout !== 'post' ? '' : '/' + language}/${base}`);
});
```

It will rollback to default path without language only when `layout !== 'post'`. This performs well when testing.

---

And there are still some small issues:

- The index page will show **all posts with all languages**. I think maybe someone can combine [hexo-generator-index-multi-lang](https://github.com/zyzyz/hexo-generator-index-multi-lang) with [hexo-generator-i18n](https://github.com/Jamling/hexo-generator-i18n) to let hexo-generator-i18n also generate correct indexes with posts of each language.

- The language of sidebar won't change when navigating across languages, not using language-switcher. (maybe this is an issue for hexo-theme-next.

---

Hope that Hexo will eventually be able to fully support i18n for all pages.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.