Update mdBook manual to have information about translations

This commit is contained in:
Ruin0x11 2021-09-15 14:29:30 -07:00
parent 09a8b66e87
commit 5fed5e866d
10 changed files with 139 additions and 40 deletions

View File

@ -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.

View File

@ -56,7 +56,7 @@ be adapted for other preprocessors.
```rust
// nop-preprocessors.rs
{{#include ../../../examples/nop-preprocessor.rs}}
{{#include ../../../../examples/nop-preprocessor.rs}}
```
</details>

View File

@ -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

View 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.

View File

@ -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.

View File

@ -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 = "日本語"

View File

@ -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");
}
}

View File

@ -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.

View File

@ -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)

View File

@ -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.