diff --git a/src/book/mod.rs b/src/book/mod.rs index 75bbcc7144..f7df3c93ac 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -190,18 +190,31 @@ impl MDBook { info!("Book building has started"); for renderer in &self.renderers { - self.execute_build_process(&**renderer)?; + // build for the default language + self.execute_build_process(&**renderer, None)?; + // build for each translation language + for translation in &self.config.book.translations { + self.execute_build_process(&**renderer, Some(translation))?; + } } Ok(()) } /// Run the entire build process for a particular [`Renderer`]. - pub fn execute_build_process(&self, renderer: &dyn Renderer) -> Result<()> { + pub fn execute_build_process( + &self, + renderer: &dyn Renderer, + translation: Option<&str>, + ) -> Result<()> { let mut preprocessed_book = self.book.clone(); + let mut config = self.config.clone(); + if let Some(translation) = translation { + config.book.language = Some(translation.to_string()); + } let preprocess_ctx = PreprocessorContext::new( self.root.clone(), - self.config.clone(), + config.clone(), renderer.name().to_string(), ); @@ -213,19 +226,27 @@ impl MDBook { } let name = renderer.name(); - let build_dir = self.build_dir_for(name); + let mut build_dir = self.build_dir_for(name); + // Use sub-dir for each translation + if let Some(translation) = translation { + build_dir = build_dir.join(translation); + } - let mut render_context = RenderContext::new( - self.root.clone(), - preprocessed_book, - self.config.clone(), - build_dir, - ); + let mut render_context = + RenderContext::new(self.root.clone(), preprocessed_book, config, build_dir); render_context .chapter_titles .extend(preprocess_ctx.chapter_titles.borrow_mut().drain()); - info!("Running the {} backend", renderer.name()); + info!( + "Running the {}{} backend", + renderer.name(), + if let Some(translation) = translation { + format!("[{}]", translation) + } else { + "".to_string() + } + ); renderer .render(&render_context) .with_context(|| "Rendering failed") diff --git a/src/config.rs b/src/config.rs index 0c367d8481..c2ac6247c3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -411,6 +411,8 @@ pub struct BookConfig { pub multilingual: bool, /// The main language of the book. pub language: Option, + /// The book's translations. + pub translations: Vec, } impl Default for BookConfig { @@ -422,6 +424,7 @@ impl Default for BookConfig { src: PathBuf::from("src"), multilingual: false, language: Some(String::from("en")), + translations: Vec::new(), } } } @@ -769,6 +772,7 @@ mod tests { multilingual: true, src: PathBuf::from("source"), language: Some(String::from("ja")), + ..Default::default() }; let build_should_be = BuildConfig { build_dir: PathBuf::from("outputs"), diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index e170e2fcda..0d7adce92e 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -94,6 +94,7 @@ impl HtmlHandlebars { }; ctx.data.insert("path".to_owned(), json!(path)); + ctx.data.insert("path_html".to_owned(), json!(filepath)); ctx.data.insert("content".to_owned(), json!(content)); ctx.data.insert("chapter_title".to_owned(), json!(ch.name)); ctx.data.insert("title".to_owned(), json!(title)); @@ -635,6 +636,9 @@ fn make_data( "language".to_owned(), json!(config.book.language.clone().unwrap_or_default()), ); + if !config.book.translations.is_empty() { + data.insert("translations".to_owned(), json!(config.book.translations)); + } data.insert( "book_title".to_owned(), json!(config.book.title.clone().unwrap_or_default()), diff --git a/tests/init.rs b/tests/init.rs index 2b6ad507ce..98d7ae3806 100644 --- a/tests/init.rs +++ b/tests/init.rs @@ -29,7 +29,7 @@ fn base_mdbook_init_should_create_default_content() { let contents = fs::read_to_string(temp.path().join("book.toml")).unwrap(); assert_eq!( contents, - "[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"src\"\n" + "[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"src\"\ntranslations = []\n" ); } @@ -96,7 +96,7 @@ fn run_mdbook_init_with_custom_book_and_src_locations() { let contents = fs::read_to_string(temp.path().join("book.toml")).unwrap(); assert_eq!( contents, - "[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"in\"\n\n[build]\nbuild-dir = \"out\"\ncreate-missing = true\nextra-watch-dirs = []\nuse-default-preprocessors = true\n" + "[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"in\"\ntranslations = []\n\n[build]\nbuild-dir = \"out\"\ncreate-missing = true\nextra-watch-dirs = []\nuse-default-preprocessors = true\n" ); }