Update mdBook manual to have information about translations
This commit is contained in:
parent
09a8b66e87
commit
5fed5e866d
@ -14,13 +14,19 @@ up for you:
|
||||
```bash
|
||||
book-test/
|
||||
├── book
|
||||
├── book.toml
|
||||
└── src
|
||||
└── en
|
||||
├── chapter_1.md
|
||||
└── SUMMARY.md
|
||||
```
|
||||
|
||||
- The `src` directory is where you write your book in markdown. It contains all
|
||||
the source files, configuration files, etc.
|
||||
- The `src` directory is where you write your book in Markdown. It contains all
|
||||
the source files for each translation of your book. By default, a directory
|
||||
for the English translation is created, `src/en`.
|
||||
|
||||
- The `book.toml` file holds configuration about how your book gets rendered.
|
||||
See the [configuration](../format/config.md) section for more details.
|
||||
|
||||
- The `book` directory is where your book is rendered. All the output is ready
|
||||
to be uploaded to a server to be seen by your audience.
|
||||
|
@ -56,7 +56,7 @@ be adapted for other preprocessors.
|
||||
```rust
|
||||
// nop-preprocessors.rs
|
||||
|
||||
{{#include ../../../examples/nop-preprocessor.rs}}
|
||||
{{#include ../../../../examples/nop-preprocessor.rs}}
|
||||
```
|
||||
</details>
|
||||
|
||||
|
@ -4,9 +4,11 @@ This section details the configuration options available in the ***book.toml***:
|
||||
- **[General]** configuration including the `book`, `rust`, `build` sections
|
||||
- **[Preprocessor]** configuration for default and custom book preprocessors
|
||||
- **[Renderer]** configuration for the HTML, Markdown and custom renderers
|
||||
- **[Translations]** configuration for books written in more than one language
|
||||
- **[Environment Variable]** configuration for overriding configuration options in your environment
|
||||
|
||||
[General]: general.md
|
||||
[Preprocessor]: preprocessors.md
|
||||
[Renderer]: renderers.md
|
||||
[Translations]: translations.md
|
||||
[Environment Variable]: environment-variables.md
|
86
guide/src/en/format/configuration/translations.md
Normal file
86
guide/src/en/format/configuration/translations.md
Normal file
@ -0,0 +1,86 @@
|
||||
## Translations
|
||||
|
||||
It's possible to write your book in more than one language and bundle all of its
|
||||
translations into a single output folder, with the ability for readers to switch
|
||||
between each one in the rendered output. The available languages for your book
|
||||
are defined in the `[language]` table:
|
||||
|
||||
```toml
|
||||
[language.en]
|
||||
name = "English"
|
||||
|
||||
[language.ja]
|
||||
name = "日本語"
|
||||
title = "本のサンプル"
|
||||
description = "この本は実例です。"
|
||||
authors = ["Ruin0x11"]
|
||||
```
|
||||
|
||||
Each language must have a human-readable `name` defined. Also, if the
|
||||
`[language]` table is defined, you must define `book.language` to be a key of
|
||||
this table, which will indicate the language whose files will be used for
|
||||
fallbacks if a page is missing in a translation.
|
||||
|
||||
The `title` and `description` fields, if defined, will override the ones set in
|
||||
the `[book]` section. This way you can translate the book's title and
|
||||
description. `authors` provides a list of this translation's authors.
|
||||
|
||||
After defining a new language like `[language.ja]`, add a new subdirectory
|
||||
`src/ja` and create your `SUMMARY.md` and other files there.
|
||||
|
||||
> **Note:** Whether or not the `[language]` table is defined changes the format
|
||||
> of the `src` directory that mdBook expects to see. If there is no `[language]`
|
||||
> table, mdBook will treat the `src` directory as a single translation of the
|
||||
> book, with `SUMMARY.md` at the root:
|
||||
>
|
||||
> ```
|
||||
> ├── book.toml
|
||||
> └── src
|
||||
> ├── chapter
|
||||
> │ ├── 1.md
|
||||
> │ ├── 2.md
|
||||
> │ └── README.md
|
||||
> ├── README.md
|
||||
> └── SUMMARY.md
|
||||
> ```
|
||||
>
|
||||
> If the `[language]` table is defined, mdBook will instead expect to find
|
||||
> subdirectories under `src` named after the keys in the table:
|
||||
>
|
||||
> ```
|
||||
> ├── book.toml
|
||||
> └── src
|
||||
> ├── en
|
||||
> │ ├── chapter
|
||||
> │ │ ├── 1.md
|
||||
> │ │ ├── 2.md
|
||||
> │ │ └── README.md
|
||||
> │ ├── README.md
|
||||
> │ └── SUMMARY.md
|
||||
> └── ja
|
||||
> ├── chapter
|
||||
> │ ├── 1.md
|
||||
> │ ├── 2.md
|
||||
> │ └── README.md
|
||||
> ├── README.md
|
||||
> └── SUMMARY.md
|
||||
> ```
|
||||
|
||||
If the `[language]` table is used, you can pass the `-l <language id>` argument
|
||||
to commands like `mdbook build` to build the book for only a single language. In
|
||||
this example, `<language id>` can be `en` or `ja`.
|
||||
|
||||
Some extra notes on translations:
|
||||
|
||||
- In a translation's `SUMMARY.md` or inside Markdown files, you can link to
|
||||
pages, images or other files that don't exist in the current translation, but
|
||||
do exist in the default translation. This is so you can have a fallback in
|
||||
case new pages get added in the default language that haven't been translated
|
||||
yet.
|
||||
- Each translation can have its own `SUMMARY.md` with differing content from
|
||||
other translations. Even if the translation's summary goes out of sync with
|
||||
the default language, the links will continue to work so long as the pages
|
||||
exist in either translation.
|
||||
- Each translation can have its own pages listed in `SUMMARY.md` that don't
|
||||
exist in the default translation at all, in case extra information specific to
|
||||
that language is needed.
|
@ -20,5 +20,6 @@ shout-out to them!
|
||||
- Vivek Akupatni ([apatniv](https://github.com/apatniv))
|
||||
- Eric Huss ([ehuss](https://github.com/ehuss))
|
||||
- Josh Rotenberg ([joshrotenberg](https://github.com/joshrotenberg))
|
||||
- [Ruin0x11](https://github.com/Ruin0x11)
|
||||
|
||||
If you feel you're missing from this list, feel free to add yourself in a PR.
|
||||
|
@ -1020,6 +1020,7 @@ mod tests {
|
||||
assert_eq!(got.rust, rust_should_be);
|
||||
assert_eq!(got.html_config().unwrap(), html_should_be);
|
||||
assert_eq!(got.language, language_should_be);
|
||||
assert_eq!(got.default_language(), Some(String::from("ja")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1369,7 +1370,18 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Invalid configuration file")]
|
||||
fn validate_config_default_language_must_exist_in_languages_table() {
|
||||
fn book_language_without_languages_table() {
|
||||
let src = r#"
|
||||
[book]
|
||||
language = "en"
|
||||
"#;
|
||||
|
||||
Config::from_str(src).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Invalid configuration file")]
|
||||
fn default_language_must_exist_in_languages_table() {
|
||||
let src = r#"
|
||||
[language.ja]
|
||||
name = "日本語"
|
||||
|
@ -10,7 +10,7 @@ use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub use self::string::{
|
||||
take_anchored_lines, take_lines, take_rustdoc_include_anchored_lines,
|
||||
@ -99,9 +99,9 @@ pub fn id_from_content(content: &str) -> String {
|
||||
normalize_id(trimmed)
|
||||
}
|
||||
|
||||
fn rewrite_if_missing(
|
||||
fn rewrite_if_missing<P: AsRef<Path>>(
|
||||
fixed_link: &mut String,
|
||||
path_to_dest: &PathBuf,
|
||||
path_to_dest: P,
|
||||
dest: &str,
|
||||
src_dir: &PathBuf,
|
||||
language: &str,
|
||||
@ -114,7 +114,7 @@ fn rewrite_if_missing(
|
||||
// if the file exists.
|
||||
let mut path_on_disk = src_dir.clone();
|
||||
path_on_disk.push(language);
|
||||
path_on_disk.push(path_to_dest);
|
||||
path_on_disk.push(path_to_dest.as_ref());
|
||||
path_on_disk.push(dest);
|
||||
|
||||
debug!("Checking if {} exists", path_on_disk.display());
|
||||
@ -122,7 +122,7 @@ fn rewrite_if_missing(
|
||||
// Now see if the file exists in the fallback language directory (like "src/en").
|
||||
let mut fallback_path = src_dir.clone();
|
||||
fallback_path.push(fallback_language);
|
||||
fallback_path.push(path_to_dest);
|
||||
fallback_path.push(path_to_dest.as_ref());
|
||||
fallback_path.push(dest);
|
||||
|
||||
debug!(
|
||||
@ -133,7 +133,7 @@ fn rewrite_if_missing(
|
||||
// We can fall back to this link. Get enough parent directories to
|
||||
// reach the root source directory, append the fallback language
|
||||
// directory to it, the prepend the whole thing to the link.
|
||||
let mut relative_path = PathBuf::from(path_to_dest);
|
||||
let mut relative_path = PathBuf::from(path_to_dest.as_ref());
|
||||
relative_path.push(dest);
|
||||
|
||||
let mut path_to_fallback_src = fs::path_to_root(&relative_path);
|
||||
@ -158,7 +158,6 @@ fn fix<'a>(dest: CowStr<'a>, ctx: Option<&RenderMarkdownContext>) -> CowStr<'a>
|
||||
if base.ends_with(".md") {
|
||||
base.replace_range(base.len() - 3.., ".html");
|
||||
}
|
||||
info!("{:?} {:?}", base, dest);
|
||||
return format!("{}{}", base, dest).into();
|
||||
} else {
|
||||
return dest;
|
||||
@ -173,6 +172,8 @@ fn fix<'a>(dest: CowStr<'a>, ctx: Option<&RenderMarkdownContext>) -> CowStr<'a>
|
||||
let mut fixed_link = String::new();
|
||||
|
||||
if let Some(ctx) = ctx {
|
||||
let base = ctx.path.parent().expect("path can't be empty");
|
||||
|
||||
// If the book is multilingual, check if the file actually
|
||||
// exists, and if not rewrite the link to the fallback
|
||||
// language's page.
|
||||
@ -180,7 +181,7 @@ fn fix<'a>(dest: CowStr<'a>, ctx: Option<&RenderMarkdownContext>) -> CowStr<'a>
|
||||
if let Some(fallback_language) = &ctx.fallback_language {
|
||||
rewrite_if_missing(
|
||||
&mut fixed_link,
|
||||
&ctx.path,
|
||||
&base,
|
||||
&dest,
|
||||
&ctx.src_dir,
|
||||
&language,
|
||||
@ -190,13 +191,7 @@ fn fix<'a>(dest: CowStr<'a>, ctx: Option<&RenderMarkdownContext>) -> CowStr<'a>
|
||||
}
|
||||
|
||||
if ctx.prepend_parent {
|
||||
let base = ctx
|
||||
.path
|
||||
.parent()
|
||||
.expect("path can't be empty")
|
||||
.to_str()
|
||||
.expect("utf-8 paths only");
|
||||
|
||||
let base = base.to_str().expect("utf-8 paths only");
|
||||
if !base.is_empty() {
|
||||
write!(fixed_link, "{}/", base).unwrap();
|
||||
}
|
||||
@ -562,27 +557,22 @@ more text with spaces
|
||||
);
|
||||
};
|
||||
|
||||
test("../b/summary.md", "a", true, "../b/summary.html");
|
||||
test("../b/summary.md", "a", false, "../../en/../b/summary.html");
|
||||
test("../c/summary.md", "a/b", true, "../c/summary.html");
|
||||
test("../b/summary.md", "a.md", true, "../b/summary.html");
|
||||
test(
|
||||
"../b/summary.md",
|
||||
"a.md",
|
||||
false,
|
||||
"../../en/../b/summary.html",
|
||||
);
|
||||
test("../c/summary.md", "a/b.md", true, "../c/summary.html");
|
||||
test(
|
||||
"../c/summary.md",
|
||||
"a/b",
|
||||
"a/b.md",
|
||||
false,
|
||||
"../../../en/../c/summary.html",
|
||||
);
|
||||
test(
|
||||
"#translations",
|
||||
"config.md",
|
||||
true,
|
||||
"#translations",
|
||||
);
|
||||
test(
|
||||
"#translations",
|
||||
"config.md",
|
||||
false,
|
||||
"#translations",
|
||||
);
|
||||
test("#translations", "config.md", true, "#translations");
|
||||
test("#translations", "config.md", false, "#translations");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
# Localized Book
|
||||
|
||||
This is a test of the book localization features.
|
||||
|
||||
Select a language from the dropdown to see a translation of the current page.
|
||||
|
@ -5,5 +5,5 @@
|
||||
- [第一節](chapter/1.md)
|
||||
- [第二節](chapter/2.md)
|
||||
- [Untranslated Page](untranslated-page.md)
|
||||
- [日本語専用のページ](translation-local-page.md)
|
||||
- [内部リンクの入れ替え](inline-link-fallbacks.md)
|
||||
- [日本語専用のページ](translation-local-page.md)
|
||||
|
@ -8,7 +8,7 @@ If inline link substitution works, then an image should appear below, sourced fr
|
||||
|
||||
Here is an [inline link](translation-local-page.md) to an existing page in this translation.
|
||||
|
||||
Here is an [inline link](missing-summary-chapter.md) to a page missing from this translation's SUMMARY.md. It should have been modified to point to the page in the English version of the book.
|
||||
Here is an [inline link](missing-summary-chapter.md) to a page missing from this translation's `SUMMARY.md`. It should have been modified to point to the page in the English version of the book.
|
||||
|
||||
Also, here is an [inline link](blah.md) to a page missing from both translations. It should point to this language's 404 page.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user