Support localizing book title/description
This commit is contained in:
parent
e17ce64f2b
commit
5e223e074e
104
src/config.rs
104
src/config.rs
@ -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.
|
||||
@ -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.
|
||||
@ -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>,
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
@ -873,8 +920,11 @@ mod tests {
|
||||
name = "English"
|
||||
default = true
|
||||
|
||||
[language.fr]
|
||||
name = "Français"
|
||||
[language.ja]
|
||||
name = "日本語"
|
||||
title = "なんかの本"
|
||||
description = "何の役にも立たない本"
|
||||
authors = ["Ruin0x11"]
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
@ -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")]),
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -45,6 +45,7 @@ impl HtmlHandlebars {
|
||||
&localized_src_dir,
|
||||
&localized_destination,
|
||||
&localized_build_dir,
|
||||
&Some(lang_ident.to_string()),
|
||||
html_config,
|
||||
handlebars,
|
||||
theme,
|
||||
@ -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,
|
||||
@ -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,
|
||||
@ -102,6 +105,7 @@ impl HtmlHandlebars {
|
||||
&book,
|
||||
&ctx.book,
|
||||
&ctx.config,
|
||||
language_ident,
|
||||
&html_config,
|
||||
&theme,
|
||||
)?;
|
||||
@ -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"));
|
||||
|
@ -30,3 +30,6 @@ default = true
|
||||
|
||||
[language.ja]
|
||||
name = "日本語"
|
||||
title = "翻訳された本"
|
||||
description = "mdBookの翻訳機能のテスト用の本"
|
||||
authors = ["Ruin0x11"]
|
||||
|
Loading…
Reference in New Issue
Block a user