Introduction

This document uses the mdbook-i18n-helpers provided by Google to offer internationalization support. The mdbook-i18n-helpers mainly includes two executables: mdbook-xgettext and mdbook-gettext. Among them, mdbook-xgettext is a mdbook renderer that helps extract the source text that needs to be translated, while mdbook-gettext is a mdbook preprocessor responsible for re-injecting the translated text into the Markdown files.

Translation

mdbook-i18n-helpers uses the GNU Gettext system for translation. GNU Gettext is a set of utilities that provides a framework in which we can easily translate into multiple languages. This system is widely used for translating open-source software and is also quite effective for translating documentation.

.po file

In GNU Gettext, each language corresponds to a .po file named after the language code defined in ISO 639, such as en.po, which records all the original content that needs to be translated along with its corresponding translated content. Therefore, our translation work does not require copying the original Markdown files and manually tracking changes; we only need to modify the .po files.

New translation

Once our original document is completed, we first need to create the corresponding .po files for the required languages to enable internationalization support. mdbook-xgettext can help us extract all the content that needs to be translated from the original document and generate a .pot file (a PO template). We can then create different language-specific .po files based on this template.

  1. Executing the command MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' mdbook build -d po will automatically extract all the content that needs to be translated from the original document and generate a messages.pot file. After running this command, the default po/messages.pot file will be created. This file serves as the template for creating the language-specific .po files.

    If you add the configuration output.xgettext.pot-file = messages.pot in the book.toml file, then every time you execute mdbook build, it will automatically output the book/xgettext/messages.pot file. This configuration ensures that the .pot file is generated consistently with each build, saving you from having to manually specify it every time.

    Do not edit the po/messages.pot file, nor should you commit it to your repository, as it is generated entirely from the source Markdown files.

  2. Execute msginit -i po/messages.pot -l xx -o po/xx.po to generate the corresponding language .po file. Here, xx refers to the language code defined in ISO 639, such as en, zh-CN, etc.

    You can directly modify po/messages.pot to po/xx.po, but you must manually update the header (the first entry with msgid ) to reflect the correct language.

  3. Manually translate the content corresponding to each msgstr in the po/xx.po file. Here, xx refers to the language code defined in ISO 639, such as en, zh-CN, etc.

    Do not edit the msgid entries in the po/xx.po file. Only translate the corresponding msgstr entries.

Update translation

As the content of the documentation gradually increases or decreases, the corresponding translation content also needs to be adjusted accordingly. In this case, we need to use mdbook-xgettext to re-extract all the translatable content from the documentation and generate a .pot file. Then, based on the .pot file, we update the corresponding .po files for each language, rather than simply editing the original document and .po files directly.

  1. Executing the command MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' mdbook build -d po will automatically extract all the content that needs to be translated from the original document and generate a messages.pot file. After running this command, the default po/messages.pot file will be created. This file serves as the template for creating the language-specific .po files.

    If you add the configuration output.xgettext.pot-file = messages.pot in the book.toml file, then every time you execute mdbook build, it will automatically output the book/xgettext/messages.pot file. This configuration ensures that the .pot file is generated consistently with each build, saving you from having to manually specify it every time.

    Do not edit the po/messages.pot file, nor should you commit it to your repository, as it is generated entirely from the source Markdown files.

  2. Run msgmerge --update po/xx.po po/messages.pot to update the corresponding language .po file. Here, xx refers to the language code defined in ISO 639, such as en, zh-CN, etc.

    Unchanged content will remain as is, deleted messages will be marked as outdated, and updated messages will be marked as "fuzzy." "Fuzzy" entries will retain the previous translation, and we need to review them, update as necessary, and then remove the "fuzzy" tag.

  3. Manually translate the msgstr entries in the po/xx.po file that have changed. Here, xx refers to the language code defined in ISO 639, such as en, zh-CN, etc. You only need to update the msgstr content that has been modified, based on the latest .pot file.

    Do not edit the msgid entries in the po/xx.po file. Only translate the corresponding msgstr entries.

Apply translation

The application of our translated content is done through the mdbook-gettext preprocessor.

Configuration

First, you need to add the following configuration items to our book.toml file in order to enable it in the project. This will allow mdbook-gettext to be run on the source code after operations like {{ #include }} are executed, making it possible to translate the included source code.

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

To automatically reload our documentation whenever the po/xx.po file is changed, you need to add the following configuration item to the project's book.toml file:

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

Build

After adding the above configuration, every time we execute mdbook build, it will automatically select and apply the corresponding po/xx.po file based on the language specified in the book.language setting in the book.toml file, and generate the documentation for the corresponding language under the book directory.

If no language is set or if the corresponding .po file for the specified language cannot be found, the system will automatically use the untranslated content.

To build the documentation for a specific language individually, you can use the command MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx to generate the xx language documentation in the book/xx directory. Here, xx is the language code defined in ISO 639, such as en, zh-CN, etc.

Each language corresponds to a separate, complete documentation.

Online preview

Since the build generates the documentation for the specified language based on the book.language in the book.toml file, using the mdbook serve command will also allow you to view the documentation for the corresponding language locally online.

To view the documentation for a specific language individually, you can use the command MDBOOK_BOOK__LANGUAGE=xx mdbook serve -d book/xx to preview it online. Here, xx is the language code defined in ISO 639, such as en, zh-CN, etc.

Dynamic switching

Multilingual support requires dynamic switching, rather than independent deployment for each language. However, since mdbook itself does not support internationalization and its default theme does not include a menu for switching between different languages, we need to modify the default theme template files to implement dynamic language switching.

index.hbs

index.hbs is the base HTML template for all pages generated by mdbook. We can create a theme/index.hbs file and modify its contents. During the build process, mdbook will automatically use the theme/index.hbs file from the current directory, allowing us to implement a custom theme!

For internationalization support, we first need to modify the existing index.hbs by adding an icon for switching languages on the right side of the top menu bar, along with a menu for various languages. We also need to implement the functionality where clicking the language icon displays the language menu, and selecting a language from the menu switches to the corresponding language's documentation. Furthermore, after switching to the selected language, the URL path should be updated accordingly, and the page should be refreshed to display the content in the selected language. For specific modifications, refer to the theme/index.hbs file!

Add styles

To enhance the style, we also added a CSS file theme/language-picker.css, which is used to control the style of the newly added language selection menu. Additionally, to make this file take effect, it needs to be explicitly referenced in the output.html.additional-css section of the book.toml file.

Deploy to GitHub Pages

The documentation generated by mdbook already supports deployment on GitHub Pages. However, after adding internationalization, some additional steps need to be performed.

Without internationalization, we only need to build the documentation using mdbook build. However, after adding internationalization, it is necessary to build the documentation for each language and place the generated documentation for each language into subdirectories named after the language codes defined in ISO 639 within the original build directory (this is because we hardcoded the file names in the modified index.hbs). For specific changes, see .github/workflows/build_deploy.yml.

Limitations

  1. Since mdbook itself does not support internationalization, it requires quite a few modifications to mdbook.

  2. The search functionality in mdbook does not support Chinese.

  3. 目前无法再本地同时预览多个语言的版本(我们添加的动态切换无效),这是由于 mdbook 会清理掉其他语言的文档。暂时的解决方法是,在启动 mdbook serve 之后,再把构建的其他语言的文档放到 book 目录下

Copyright © 2025 • Created by ArceOS Team