Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18n RFC #111

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions rfcs/i18n.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
- Feature Name: i18n
- Start Date: 2017-08-21
- RFC PR: (leave this empty)

# Summary
[summary]: #summary

This feature aims to make Gutenberg support multilingual sites.

# Motivation
[motivation]: #motivation

Some sites are in multiple languages and want to share templates/content while only translating
bits of the UI of the actual markdown content.

# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation

## Overview

### Configuration
`language_code` is renamed to `default_language` as it is used for i18n mainly and is clearer that way.

A map is added to the Config struct to hold some i18n strings:

```toml
default_language = "en"

[translations]

[translations.en]
title = "My blog"
description = "Hello world"

[translations.fr]
title = "Mon blog"
```

### Url

The default language base url will be equal to `config.base_url`.
Other languages will be available at `{config.base_url}/{language}`.

There will be an option (`force_i18n_redirect` or something similar) in the config
to always redirect to a URL with a language code in it, ie `base_url` would redirect
to `{base_url}/{default_language}`.


### File organisation
The content files have to have the same name for multiple languages.
The language is defined in the extension prefix: `{name}.{language_code}.{extension}`

The language code can be omitted for the default language.

```shell
content
├── _index.md
├── _index.fr.md
├── about.md
├── about.fr.md
└── some_section
├── _index.md
└── _index.fr.md

```

### Templates
All templates will get an additional parameter: `lang` for the current language (`en`, `fr`, etc)
and a new global Tera function will be added to get the i18n values out of the config.toml.

```jinja2
{{ trans(key="title", lang=lang) }}
```
If a value isn't found for the current `lang`, it will look up the key in the default language map.

`get_page`, `get_section` and `get_url` will also have to take an optional `lang` parameter.
Each page/section will have a `languages` map with the URLs to the other languages pages of the same content.

### Content
Internal links in the markdown text will refer to the current lang and fallback to the actual file if nothing was found.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

## Loading
The `Site` struct will have to be updated from:
```rust
// from
pub pages: HashMap<PathBuf, Page>,
pub sections: HashMap<PathBuf, Section>,

// to
pub pages: HashMap<String, HashMap<PathBuf, Page>>,
pub sections: HashMap<String, HashMap<PathBuf, Section>>,
```

Section and pages will be loaded as usual otherwise.
There will be another phase once all the pages are loaded to reconcile different language versions of the same content.

Each page/section will have its `lang` attribute automatically filled based on its filename

## Template and rendering

Rendering will be done language by language and the `lang` will be passed in all Tera context.

## RSS
A separate RSS file will be rendered for each language:

- `{base_url}/rss.xml`
- `{base_url}/fr/rss.xml`

and so on.

# Drawbacks
[drawbacks]: #drawbacks

This change requires changing pretty much all the logic in Gutenberg to account for multiple languages for a feature
used by a minority of people.

# Rationale and Alternatives
[alternatives]: #alternatives

This design is similar to Hugo and Lektor and is the simplest to use from a user point of view, as far as I know.

## Alternative design: do nothing
A user could create a `fr` section and mirror the content of the default language for example.
This is even simpler than the solution in the RFC but it doesn't work well with posts with assets as those will need
to be duplicated or put in the `static` folder.
i18n in the templates could be solved by adding a `lang` attribute in the `extra` of the front-matter of section of pages by
the user and using that.

### Pros
- Easy to implement: pretty much nothing to do
- Easier to understand (imo)

### Cons
- No RSS per language
- Harder to get started for a user
- No way to link articles from different languages unless it is done manually in the front-matter


# Unresolved questions
[unresolved]: #unresolved-questions

## RSS
How to only render a RSS feed for a given language if `generate_rss` is set to true. Do we even care about that feature?

## Content with url set
Some content can have a path hardcoded in the front-matter: what to do with multiple languages version
of such content?
Prepending the language code to the URL is the obvious solution but is not intuitive and change implicitly
the meaning of the url field so it's not an option.
I think having 2 files with the same url in front-matter should not be allowed.