-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Build translations from mdbook #84
Open
sakex
wants to merge
18
commits into
google:main
Choose a base branch
from
sakex:translate-from-mdbook
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
69d7979
Build translations from mdbook
sakex 4aa9c3d
Move the code from binary mdbook-i18n-normalize.rs into library code
kdarkhan ba90283
Add new fuzz target `normalize`
kdarkhan f3e480d
Update github workflow to run the new fuzzer normalize
kdarkhan aaeb589
Fix typo in src/normalize.rs
mgeisler 260f496
Simplify HTML comments
mgeisler f32ef16
Run `cargo update` to update all dependencies
mgeisler 202b066
Bump all dependencies
mgeisler 99f90a9
Update version to 0.2.3
mgeisler 76eaeac
Update changelog for 0.2.3
mgeisler 800b4dd
Link to usage in old changelog entry
mgeisler 4378475
Fix clippy errors
sakex 1fae421
Set POT-Creation-Date in newly generated POT files
mgeisler 51b4114
Refactor repository to use workspaces (#86)
sakex 98dbcae
Refactor repository to use workspaces (#86)
sakex f63882e
Merge branch 'main' into translate-from-mdbook
sakex f22b512
Update i18n-helpers/src/bin/mdbook-i18n.rs
sakex d4e0c95
Use anyhow
sakex File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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,105 @@ | ||
use anyhow::{anyhow, Result}; | ||
use mdbook::renderer::RenderContext; | ||
use serde::Deserialize; | ||
use std::collections::BTreeMap; | ||
use std::io; | ||
|
||
/// Parameters for the i18n renderer. | ||
/// | ||
/// They are set in the `output.i18n` section of the book's `book.toml` file. | ||
#[derive(Deserialize)] | ||
struct I18nConfiguration { | ||
/// A map of language codes to language names. | ||
/// | ||
/// ## Example | ||
/// | ||
/// ```toml | ||
/// [output.i18n.languages] | ||
/// "en" = "English" | ||
/// "es" = "Spanish (Español)" | ||
/// "ko" = "Korean (한국어)" | ||
/// "pt-BR" = "Brazilian Portuguese (Português do Brasil)" | ||
/// ``` | ||
#[serde(default)] | ||
languages: BTreeMap<String, String>, | ||
/// Default language code. It will not be translated. | ||
default_language: Option<String>, | ||
|
||
/// Whether to translate all languages or just the selected language in `mdbook.config.book.language`, defaults to false. | ||
#[serde(default)] | ||
translate_all_languages: bool, | ||
/// Whether to move the translations to their renderer's directory, defaults to false. | ||
/// | ||
/// By default, translations' output will live in `book/i18n/<language>/<renderer>`. | ||
/// For all renderers in this list, we will move individual translations to `book/<renderer>/<language>`. | ||
#[serde(default)] | ||
move_translations_directories: Vec<String>, | ||
} | ||
|
||
fn main() -> Result<()> { | ||
let mut stdin = io::stdin(); | ||
|
||
// Get the configs | ||
sakex marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let ctx = RenderContext::from_json(&mut stdin)?; | ||
let i18n_config: I18nConfiguration = ctx | ||
.config | ||
.get_deserialized_opt("output.i18n")? | ||
.ok_or_else(|| anyhow!("No output.i18n config in book.toml"))?; | ||
|
||
if !i18n_config.translate_all_languages { | ||
return Ok(()); | ||
} | ||
|
||
let mut mdbook = mdbook::MDBook::load(&ctx.root)?; | ||
// Overwrite with current values from stdin. This is necessary because mdbook will add data to the config. | ||
mdbook.book = ctx.book.clone(); | ||
mdbook.config = ctx.config.clone(); | ||
mdbook.root = ctx.root.clone(); | ||
sakex marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let book_config = mdbook | ||
.config | ||
.get_mut("output.i18n") | ||
.ok_or_else(|| anyhow!("No output.i18n config in book.toml"))?; | ||
// Set translate_all_languages to false for nested builds to prevent infinite recursion. | ||
book_config | ||
.as_table_mut() | ||
.ok_or_else(|| anyhow!("output.i18n config in book.toml is not a table"))? | ||
.insert(String::from("translate_all_languages"), false.into()); | ||
|
||
let output_directory = ctx.destination; | ||
let default_language = &i18n_config.default_language; | ||
|
||
for language in i18n_config.languages.keys() { | ||
// Skip current language and default language. | ||
if Some(language) == ctx.config.book.language.as_ref() { | ||
continue; | ||
} | ||
if default_language.as_ref() == Some(language) { | ||
continue; | ||
} | ||
let translation_path = output_directory.join(language); | ||
|
||
// Book doesn't implement clone, so we just mutate in place. | ||
mdbook.config.book.language = Some(language.clone()); | ||
mdbook.config.book.multilingual = true; | ||
mdbook.config.build.build_dir = translation_path; | ||
mdbook.build()?; | ||
for renderer in &i18n_config.move_translations_directories { | ||
std::fs::create_dir_all( | ||
output_directory | ||
.parent() | ||
.ok_or_else(|| anyhow!("Failed to retrieve parent directory"))? | ||
.join(renderer), | ||
)?; | ||
std::fs::rename( | ||
output_directory.join(language).join(renderer), | ||
output_directory | ||
.parent() | ||
.ok_or_else(|| anyhow!("Failed to retrieve parent directory"))? | ||
.join(renderer) | ||
.join(language), | ||
)?; | ||
} | ||
} | ||
Ok(()) | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're saying here that you'll break the contract defined by mdbook.
I don't want the new renderer to touch files in the output directories of other renderers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's very convenient with
mdbook serve
to view the output like it will be on the final site. It doesn't need to be enabled otherwise and by default does nothingThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you addressed my concern: if the code is writing outside of the output directly, then the code is doing something wrong.
I don't doubt that it is convenient: we should just write everything inside of the designated output directory.
Maybe you're not aware, but I often use
mdbook build -d /tmp/foo
and similar to generate output in non-standard directories. So this renderer must respect the output setting.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By default, we don't break the contract but if we enable this, we do. That's also what we're already doing in comprehensive rust, so I don't really see a problem as it is opt-in only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope our
mdbook
plugins are not breaking this?Are you talking about the code in
publish.yml
, then that is quite different: the code there relies on the contract ofmdbook
which says that it will put things into directory so-and-so. After callingmdbook build
, we are of course free to move things around and mess with thebook/
directory — we own it then!This is the main difference between implementing this functionality as a wrapper script (as suggested in #18!) and writing it as a
mdbook
plugin. As a plugin, you are subjected to the rules of the surrounding system.It might be a subtle difference, but I believe it's an important one. By following the principle carefully on every level of the stack, we will be able to build bigger "stacks" of software which behaves in a predictable manner when seen as a whole.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The script does this:
Note that the move happens after the
mdbook build
command ran. Which respects this statement:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't think I know what script you're referring to here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This renderer I mean