-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
gettext
command to generate translated output
This command is the second part of a Gettext-based translation (i18n) workflow. It takes an `xx.po` file with translations and uses this to translate the chapters of the book. Paragraphs without a translation are kept in the original language. Part of the solution for #5.
- Loading branch information
Showing
2 changed files
with
84 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
use crate::cmd::xgettext::extract_paragraphs; | ||
use crate::get_book_dir; | ||
use crate::utils; | ||
use clap::{arg, App, Arg, ArgMatches}; | ||
use mdbook::MDBook; | ||
use polib::po_file::parse; | ||
use std::path::Path; | ||
|
||
// Create clap subcommand arguments | ||
pub fn make_subcommand<'help>() -> App<'help> { | ||
App::new("gettext") | ||
.about("Output translated book") | ||
.arg( | ||
Arg::new("dest-dir") | ||
.short('d') | ||
.long("dest-dir") | ||
.value_name("dest-dir") | ||
.help( | ||
"Output directory for the translated book{n}\ | ||
Relative paths are interpreted relative to the book's root directory{n}\ | ||
If omitted, mdBook defaults to `./src/xx` where `xx` is the language of the PO file." | ||
), | ||
) | ||
.arg(arg!(<po> "PO file to generate translation for")) | ||
.arg(arg!([dir] | ||
"Root directory for the book{n}\ | ||
(Defaults to the Current Directory when omitted)" | ||
)) | ||
} | ||
|
||
// Gettext command implementation | ||
pub fn execute(args: &ArgMatches) -> mdbook::errors::Result<()> { | ||
let book_dir = get_book_dir(args); | ||
let book = MDBook::load(&book_dir)?; | ||
|
||
let po_file = Path::new(args.value_of("po").unwrap()); | ||
let lang = po_file.file_stem().unwrap(); | ||
let catalog = parse(po_file).unwrap(); | ||
let dest_dir = book.root.join( | ||
args.value_of("dest-dir") | ||
.map(|path| path.into()) | ||
.unwrap_or(Path::new("src").join(lang)), | ||
); | ||
|
||
for item in book.iter() { | ||
match item { | ||
mdbook::BookItem::Chapter(chapter) if !chapter.is_draft_chapter() => { | ||
let mut output = String::with_capacity(chapter.content.len()); | ||
let mut current_lineno = 1; | ||
|
||
for (lineno, paragraph) in extract_paragraphs(&chapter.content) { | ||
// Fill in blank lines between paragraphs. This is | ||
// important for code blocks where blank lines can | ||
// be significant. | ||
while current_lineno < lineno { | ||
output.push('\n'); | ||
current_lineno += 1; | ||
} | ||
current_lineno += paragraph.lines().count(); | ||
|
||
let translated = catalog | ||
.find_message(paragraph) | ||
.and_then(|msg| msg.get_msgstr().ok()) | ||
.filter(|msgstr| !msgstr.is_empty()) | ||
.map(|msgstr| msgstr.as_str()) | ||
.unwrap_or(paragraph); | ||
output.push_str(translated); | ||
output.push('\n'); | ||
} | ||
|
||
utils::fs::write_file( | ||
&dest_dir, | ||
chapter.source_path.as_ref().unwrap(), | ||
output.as_bytes(), | ||
)?; | ||
} | ||
_ => {} | ||
} | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters