Skip to content

Latest commit

 

History

History
275 lines (197 loc) · 8.14 KB

USAGE.md

File metadata and controls

275 lines (197 loc) · 8.14 KB

Usage

How to use the translation infrastructure with your mdbook project.

Installation

Run

cargo install mdbook-i18n-helpers

to install three binaries:

  • mdbook-xgettext: This program extracts the source text. It is an mdbook renderer.
  • mdbook-gettext: This program translates the book into a target language. It is an mdbook preprocessor.
  • mdbook-i18n-normalize: This program normalizs a PO file. Use it after breaking changes.

Together, the two programs makes it possible to do i18n for mdbook in a standard and maintainable way.

Gettext Overview

We use the Gettext system for translations. This system is widely used for translations of open source software and it also works reasonably well for documentation.

The advantage of Gettext is that you get a structured way to approach the translations. Instead of copying Markdown files and tracking changes by hand, you modify .po files in a po/ directory. The .po files are small text-based translation databases. You update the .po files using tools (described below) and you can see at a glance how much text still needs to be translated.

Tip: You should never edit the .po files by hand. Instead use a PO editor, such as Poedit. There are also several online editors available. This will ensure that the file is encoded correctly.

There is a .po file for each language. They are named after the ISO 639 language codes: Danish would go into po/da.po, Korean would go into po/ko.po, etc. The .po files contain all the source text plus the translations. They are initialized from a messages.pot file (a PO template) which contains the extracted source text from your mdbook project.

If your source files are in English, then the messages.pot file will contain the English text and your translators will be translating from English into their target language.

We will show how to update and manipulate the .po and .pot files using the GNU Gettext utilities below.

Creating and Updating Translations

First, you need to know how to update the .pot and .po files.

As a general rule, you should never touch the auto-generated po/messages.pot file. You should not even check it into your repository since it can be fully generated from your source Markdown files.

You should also never edit the msgid entries in a po/xx.po file. If you find mistakes, you need to update the original text instead. The fixes to the original text will flow into the .po files the next time the translators update them.

Generating the PO Template

To extract the original text and generate a messages.pot file, you run mdbook with the mdbook-xgettext renderer:

MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' \
  mdbook build -d po

You will find the generated POT file as po/messages.pot.

Initialize a New Translation

To start a new translation for a fictional xx locale, first generate the po/messages.pot file. Then use msginit to create a xx.po file:

msginit -i po/messages.pot -l xx -o po/xx.po

You can also simply copy po/messages.pot to po/xx.po if you don't have msginit from the GNU Gettext tools available. If you do that, then you have to update the header (the first entry with msgid "") manually to the correct language.

Tip: You can use the cloud-translate tool to quickly machine-translate a new translation. Untranslated entries will be sent through GCP Cloud Translate. Some of the translations will be wrong after this, so you must inspect them by hand afterwards.

Updating an Existing Translation

As the source text changes, translations gradually become outdated. To update the po/xx.po file with new messages, first extract the source text into a po/messages.pot template file. Then run

msgmerge --update po/xx.po po/messages.pot

Unchanged messages will stay intact, deleted messages are marked as old, and updated messages are marked "fuzzy". A fuzzy entry will reuse the previous translation: you should then go over it and update it as necessary before you remove the fuzzy marker.

Using Translations

This will show you how to use the translations to generate localized HTML output.

Note: mdbook-gettext will use the original untranslated text for all entries marked as "fuzzy" (visible as "Needs work" in Poedit). This is especially important when using cloud-translate for initial translation as all entries will be marked as "fuzzy".

If your text isn't translated, double-check that you have removed all "fuzzy" flags from your xx.po file.

Building a Translated Book

The translation is done using the mdbook-gettext preprocessor. Enable it in your project by adding this snippet to your book.toml file:

[preprocessor.gettext]
after = ["links"]

This will run mdbook-gettext on the source after things like {{ #include }} has been executed. This makes it possible to translate included source code.

You can leave mdbook-gettext enabled: if no language is set or if it cannot find the .po file corresponding to the language (e.g., it cannot find po/en.po for English), then it will return the book untranslated.

To use the po/xx.po file for your output, you simply set book.language to xx. You can do this on the command line:

MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx

This will set the book's language to xx and store the generated files in book/xx.

Serving a Translated Book

Like normal, you can use mdbook serve to view your translation as you work on it. You use the same command as with mdbook build above:

MDBOOK_BOOK__LANGUAGE=xx mdbook serve -d book/xx

To automatically reload the book when you change the po/xx.po file, add this to your book.toml file:

[build]
extra-watch-dirs = ["po"]

Publishing Translations with GitHub Actions

Please see the publish.yml workflow in the Comprehensive Rust 🦀 repository.

Marking Sections to be Skipped for Translation

A block can be marked to be skipped for translation by prepending a special HTML comment <!-- mdbook-xgettext:skip --> to it.

For example:

The following code block should not be translated.

<!-- mdbook-xgettext:skip -->

```
fn hello() {
  println!("Hello world!");
}
```

Itemized list:

- A should be translated.

<!-- mdbook-xgettext:skip -->

- B should be skipped.
- C should be translated.

Note that we don't extract the full text of code blocks. Only text that is recognized as comments and literal strings is extracted.

Normalizing Existing PO Files

When mdbook-i18n-helpers change, the generated PO files change as well. This can result in a situation where the messages in a xx.po file are no longer exactly like the ones expected by mdbook-gettext.

An example is the change from version 0.1.0 to 0.2.0: mdbook-xgettext from version 0.1.0 will output a list as a whole:

- foo
- bar

becomes

msgid ""
"- foo\n"
"- bar\n"
msgstr ""

in the PO file. However, mdbook-xgettext version 0.2.0 will produce two messages instead:

msgid "foo"
msgstr ""

msgid "bar"
msgstr ""

Use mdbook-i18n-normalize version 0.2.0 to convert the old PO file to the new format. Importantly, existing translations are kept intact! If the old PO file is translated like this

msgid ""
"- foo\n"
"- bar\n"
msgstr ""
"- FOO\n"
"- BAR\n"

then the new PO file generated with mdbook-i18n-normalize will contain two messages:

msgid "foo"
msgstr "FOO"

msgid "bar"
msgstr "BAR"

You will only need to run mdbook-i18n-normalize once after upgrading mdbook-i18n-helpers.