Multilingual(i18n) Page + Post Support
- 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
Assessment
This issue has not been assessed yet.