Skip to content

Commit

Permalink
Support localizing book title/description
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruin0x11 committed Sep 15, 2021
1 parent e17ce64 commit 5e223e0
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 26 deletions.
104 changes: 80 additions & 24 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,37 +253,26 @@ impl Config {
self.get(&key).and_then(Value::as_table)
}

/// Get the source directory of a localized book corresponding to language ident `index`.
pub fn get_localized_src_path<I: AsRef<str>>(&self, index: Option<I>) -> Result<PathBuf> {
/// Gets the language configured for a book.
pub fn get_language<I: AsRef<str>>(&self, index: Option<I>) -> Result<Option<String>> {
match self.language.default_language() {
// Languages have been specified, assume directory structure with
// language subfolders.
Some(default) => match index {
Some(ref default) => match index {
// Make sure that the language we passed was actually
// declared in the config, and return `None` if not.
Some(lang_ident) => match self.language.0.get(lang_ident.as_ref()) {
Some(_) => {
let mut buf = PathBuf::new();
buf.push(self.book.src.clone());
buf.push(lang_ident.as_ref());
Ok(buf)
}
Some(_) => Ok(Some(lang_ident.as_ref().into())),
None => Err(anyhow!(
"Expected [language.{}] to be declared in book.toml",
lang_ident.as_ref()
)),
},
// Use the default specified in book.toml.
None => {
let mut buf = PathBuf::new();
buf.push(self.book.src.clone());
buf.push(default);
Ok(buf)
}
None => Ok(Some(default.to_string())),
},

// No default language was configured in book.toml. Preserve
// backwards compatibility by just returning `src`.
// No default language was configured in book.toml.
None => match index {
// We passed in a language from the frontend, but the config
// offers no languages.
Expand All @@ -292,11 +281,63 @@ impl Config {
lang_ident.as_ref()
)),
// Default to previous non-localized behavior.
None => Ok(self.book.src.clone()),
None => Ok(None),
},
}
}

/// Get the source directory of a localized book corresponding to language ident `index`.
pub fn get_localized_src_path<I: AsRef<str>>(&self, index: Option<I>) -> Result<PathBuf> {
let language = self.get_language(index)?;

match language {
Some(lang_ident) => {
let mut buf = PathBuf::new();
buf.push(self.book.src.clone());
buf.push(lang_ident);
Ok(buf)
}

// No default language was configured in book.toml. Preserve
// backwards compatibility by just returning `src`.
None => Ok(self.book.src.clone()),
}
}

/// Gets the localized title of the book.
pub fn get_localized_title<I: AsRef<str>>(&self, index: Option<I>) -> Option<String> {
let language = self.get_language(index).unwrap();

match language {
Some(lang_ident) => self
.language
.0
.get(&lang_ident)
.unwrap()
.title
.clone()
.or(self.book.title.clone()),
None => self.book.title.clone(),
}
}

/// Gets the localized description of the book.
pub fn get_localized_description<I: AsRef<str>>(&self, index: Option<I>) -> Option<String> {
let language = self.get_language(index).unwrap();

match language {
Some(lang_ident) => self
.language
.0
.get(&lang_ident)
.unwrap()
.description
.clone()
.or(self.book.description.clone()),
None => self.book.description.clone(),
}
}

/// Get the fallback source directory of a book. If chapters/sections are
/// missing in a localization, any links to them will gracefully degrade to
/// the files that exist in this directory.
Expand Down Expand Up @@ -497,9 +538,9 @@ pub struct BookConfig {
pub description: Option<String>,
/// Location of the book source relative to the book's root directory.
pub src: PathBuf,
/// Does this book support more than one language?
/// Does this book support more than one language? (Deprecated.)
pub multilingual: bool,
/// The main language of the book.
/// The main language of the book. (Deprecated.)
pub language: Option<String>,
}

Expand Down Expand Up @@ -787,6 +828,12 @@ pub struct Language {
/// If true, this language is the default. There must be exactly one default
/// language in the config.
pub default: bool,
/// Localized title of the book.
pub title: Option<String>,
/// The authors of the translation.
pub authors: Option<Vec<String>>,
/// Localized description of the book.
pub description: Option<String>,
}

impl LanguageConfig {
Expand Down Expand Up @@ -873,8 +920,11 @@ mod tests {
name = "English"
default = true
[language.fr]
name = "Français"
[language.ja]
name = "日本語"
title = "なんかの本"
description = "何の役にも立たない本"
authors = ["Ruin0x11"]
"#;

#[test]
Expand Down Expand Up @@ -927,13 +977,19 @@ mod tests {
Language {
name: String::from("English"),
default: true,
title: None,
description: None,
authors: None,
},
);
language_should_be.0.insert(
String::from("fr"),
String::from("ja"),
Language {
name: String::from("Français"),
name: String::from("日本語"),
default: false,
title: Some(String::from("なんかの本")),
description: Some(String::from("何の役にも立たない本")),
authors: Some(vec![String::from("Ruin0x11")]),
},
);

Expand Down
10 changes: 8 additions & 2 deletions src/renderer/html_handlebars/hbs_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ impl HtmlHandlebars {
&localized_src_dir,
&localized_destination,
&localized_build_dir,
&Some(lang_ident.to_string()),
html_config,
handlebars,
theme,
Expand Down Expand Up @@ -74,6 +75,7 @@ impl HtmlHandlebars {
&extra_file_dir,
&ctx.destination,
&ctx.config.build.build_dir,
&ctx.build_opts.language_ident,
html_config,
handlebars,
theme,
Expand All @@ -92,6 +94,7 @@ impl HtmlHandlebars {
extra_file_dir: &PathBuf,
destination: &PathBuf,
build_dir: &PathBuf,
language_ident: &Option<String>,
html_config: &HtmlConfig,
handlebars: &mut Handlebars<'a>,
theme: &Theme,
Expand All @@ -102,6 +105,7 @@ impl HtmlHandlebars {
&book,
&ctx.book,
&ctx.config,
language_ident,
&html_config,
&theme,
)?;
Expand Down Expand Up @@ -746,23 +750,25 @@ fn make_data(
book: &Book,
loaded_book: &LoadedBook,
config: &Config,
language_ident: &Option<String>,
html_config: &HtmlConfig,
theme: &Theme,
) -> Result<serde_json::Map<String, serde_json::Value>> {
trace!("make_data");

let mut data = serde_json::Map::new();

data.insert(
"language".to_owned(),
json!(config.book.language.clone().unwrap_or_default()),
);
data.insert(
"book_title".to_owned(),
json!(config.book.title.clone().unwrap_or_default()),
json!(config.get_localized_title(language_ident.as_ref())),
);
data.insert(
"description".to_owned(),
json!(config.book.description.clone().unwrap_or_default()),
json!(config.get_localized_description(language_ident.as_ref())),
);
if theme.favicon_png.is_some() {
data.insert("favicon_png".to_owned(), json!("favicon.png"));
Expand Down
3 changes: 3 additions & 0 deletions tests/localized_book/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ default = true

[language.ja]
name = "日本語"
title = "翻訳された本"
description = "mdBookの翻訳機能のテスト用の本"
authors = ["Ruin0x11"]

0 comments on commit 5e223e0

Please sign in to comment.