Support localizing book title/description

This commit is contained in:
Ruin0x11 2020-08-28 03:17:26 -07:00
parent e17ce64f2b
commit 5e223e074e
3 changed files with 91 additions and 26 deletions

View File

@ -253,37 +253,26 @@ impl Config {
self.get(&key).and_then(Value::as_table) self.get(&key).and_then(Value::as_table)
} }
/// Get the source directory of a localized book corresponding to language ident `index`. /// Gets the language configured for a book.
pub fn get_localized_src_path<I: AsRef<str>>(&self, index: Option<I>) -> Result<PathBuf> { pub fn get_language<I: AsRef<str>>(&self, index: Option<I>) -> Result<Option<String>> {
match self.language.default_language() { match self.language.default_language() {
// Languages have been specified, assume directory structure with // Languages have been specified, assume directory structure with
// language subfolders. // language subfolders.
Some(default) => match index { Some(ref default) => match index {
// Make sure that the language we passed was actually // Make sure that the language we passed was actually
// declared in the config, and return `None` if not. // declared in the config, and return `None` if not.
Some(lang_ident) => match self.language.0.get(lang_ident.as_ref()) { Some(lang_ident) => match self.language.0.get(lang_ident.as_ref()) {
Some(_) => { Some(_) => Ok(Some(lang_ident.as_ref().into())),
let mut buf = PathBuf::new();
buf.push(self.book.src.clone());
buf.push(lang_ident.as_ref());
Ok(buf)
}
None => Err(anyhow!( None => Err(anyhow!(
"Expected [language.{}] to be declared in book.toml", "Expected [language.{}] to be declared in book.toml",
lang_ident.as_ref() lang_ident.as_ref()
)), )),
}, },
// Use the default specified in book.toml. // Use the default specified in book.toml.
None => { None => Ok(Some(default.to_string())),
let mut buf = PathBuf::new();
buf.push(self.book.src.clone());
buf.push(default);
Ok(buf)
}
}, },
// No default language was configured in book.toml. Preserve // No default language was configured in book.toml.
// backwards compatibility by just returning `src`.
None => match index { None => match index {
// We passed in a language from the frontend, but the config // We passed in a language from the frontend, but the config
// offers no languages. // offers no languages.
@ -292,11 +281,63 @@ impl Config {
lang_ident.as_ref() lang_ident.as_ref()
)), )),
// Default to previous non-localized behavior. // 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 /// Get the fallback source directory of a book. If chapters/sections are
/// missing in a localization, any links to them will gracefully degrade to /// missing in a localization, any links to them will gracefully degrade to
/// the files that exist in this directory. /// the files that exist in this directory.
@ -497,9 +538,9 @@ pub struct BookConfig {
pub description: Option<String>, pub description: Option<String>,
/// Location of the book source relative to the book's root directory. /// Location of the book source relative to the book's root directory.
pub src: PathBuf, pub src: PathBuf,
/// Does this book support more than one language? /// Does this book support more than one language? (Deprecated.)
pub multilingual: bool, pub multilingual: bool,
/// The main language of the book. /// The main language of the book. (Deprecated.)
pub language: Option<String>, pub language: Option<String>,
} }
@ -787,6 +828,12 @@ pub struct Language {
/// If true, this language is the default. There must be exactly one default /// If true, this language is the default. There must be exactly one default
/// language in the config. /// language in the config.
pub default: bool, 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 { impl LanguageConfig {
@ -873,8 +920,11 @@ mod tests {
name = "English" name = "English"
default = true default = true
[language.fr] [language.ja]
name = "Français" name = "日本語"
title = "なんかの本"
description = "何の役にも立たない本"
authors = ["Ruin0x11"]
"#; "#;
#[test] #[test]
@ -927,13 +977,19 @@ mod tests {
Language { Language {
name: String::from("English"), name: String::from("English"),
default: true, default: true,
title: None,
description: None,
authors: None,
}, },
); );
language_should_be.0.insert( language_should_be.0.insert(
String::from("fr"), String::from("ja"),
Language { Language {
name: String::from("Français"), name: String::from("日本語"),
default: false, default: false,
title: Some(String::from("なんかの本")),
description: Some(String::from("何の役にも立たない本")),
authors: Some(vec![String::from("Ruin0x11")]),
}, },
); );

View File

@ -45,6 +45,7 @@ impl HtmlHandlebars {
&localized_src_dir, &localized_src_dir,
&localized_destination, &localized_destination,
&localized_build_dir, &localized_build_dir,
&Some(lang_ident.to_string()),
html_config, html_config,
handlebars, handlebars,
theme, theme,
@ -74,6 +75,7 @@ impl HtmlHandlebars {
&extra_file_dir, &extra_file_dir,
&ctx.destination, &ctx.destination,
&ctx.config.build.build_dir, &ctx.config.build.build_dir,
&ctx.build_opts.language_ident,
html_config, html_config,
handlebars, handlebars,
theme, theme,
@ -92,6 +94,7 @@ impl HtmlHandlebars {
extra_file_dir: &PathBuf, extra_file_dir: &PathBuf,
destination: &PathBuf, destination: &PathBuf,
build_dir: &PathBuf, build_dir: &PathBuf,
language_ident: &Option<String>,
html_config: &HtmlConfig, html_config: &HtmlConfig,
handlebars: &mut Handlebars<'a>, handlebars: &mut Handlebars<'a>,
theme: &Theme, theme: &Theme,
@ -102,6 +105,7 @@ impl HtmlHandlebars {
&book, &book,
&ctx.book, &ctx.book,
&ctx.config, &ctx.config,
language_ident,
&html_config, &html_config,
&theme, &theme,
)?; )?;
@ -746,23 +750,25 @@ fn make_data(
book: &Book, book: &Book,
loaded_book: &LoadedBook, loaded_book: &LoadedBook,
config: &Config, config: &Config,
language_ident: &Option<String>,
html_config: &HtmlConfig, html_config: &HtmlConfig,
theme: &Theme, theme: &Theme,
) -> Result<serde_json::Map<String, serde_json::Value>> { ) -> Result<serde_json::Map<String, serde_json::Value>> {
trace!("make_data"); trace!("make_data");
let mut data = serde_json::Map::new(); let mut data = serde_json::Map::new();
data.insert( data.insert(
"language".to_owned(), "language".to_owned(),
json!(config.book.language.clone().unwrap_or_default()), json!(config.book.language.clone().unwrap_or_default()),
); );
data.insert( data.insert(
"book_title".to_owned(), "book_title".to_owned(),
json!(config.book.title.clone().unwrap_or_default()), json!(config.get_localized_title(language_ident.as_ref())),
); );
data.insert( data.insert(
"description".to_owned(), "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() { if theme.favicon_png.is_some() {
data.insert("favicon_png".to_owned(), json!("favicon.png")); data.insert("favicon_png".to_owned(), json!("favicon.png"));

View File

@ -30,3 +30,6 @@ default = true
[language.ja] [language.ja]
name = "日本語" name = "日本語"
title = "翻訳された本"
description = "mdBookの翻訳機能のテスト用の本"
authors = ["Ruin0x11"]