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)
|
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")]),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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"));
|
||||||
|
@ -30,3 +30,6 @@ default = true
|
|||||||
|
|
||||||
[language.ja]
|
[language.ja]
|
||||||
name = "日本語"
|
name = "日本語"
|
||||||
|
title = "翻訳された本"
|
||||||
|
description = "mdBookの翻訳機能のテスト用の本"
|
||||||
|
authors = ["Ruin0x11"]
|
||||||
|
Loading…
Reference in New Issue
Block a user