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.
-
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 amessages.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 thebook.toml
file, then every time you executemdbook build
, it will automatically output thebook/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. -
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 asen
,zh-CN
, etc.You can directly modify
po/messages.pot
topo/xx.po
, but you must manually update the header (the first entry withmsgid
) to reflect the correct language. -
Manually translate the content corresponding to each
msgstr
in thepo/xx.po
file. Here,xx
refers to the language code defined in ISO 639, such asen
,zh-CN
, etc.Do not edit the
msgid
entries in thepo/xx.po
file. Only translate the correspondingmsgstr
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.
-
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 amessages.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 thebook.toml
file, then every time you executemdbook build
, it will automatically output thebook/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. -
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 asen
,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.
-
Manually translate the
msgstr
entries in thepo/xx.po
file that have changed. Here,xx
refers to the language code defined in ISO 639, such asen
,zh-CN
, etc. You only need to update themsgstr
content that has been modified, based on the latest.pot
file.Do not edit the
msgid
entries in thepo/xx.po
file. Only translate the correspondingmsgstr
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
-
Since
mdbook
itself does not support internationalization, it requires quite a few modifications tomdbook
. -
The search functionality in
mdbook
does not support Chinese. -
目前无法再本地同时预览多个语言的版本(我们添加的动态切换无效),这是由于 mdbook 会清理掉其他语言的文档。暂时的解决方法是,在启动
mdbook serve
之后,再把构建的其他语言的文档放到book
目录下