diff --git a/docs/community/i18n.rst b/docs/community/i18n.rst new file mode 100644 index 000000000..6f52941f3 --- /dev/null +++ b/docs/community/i18n.rst @@ -0,0 +1,110 @@ +Internationalization +==================== + +.. warning:: + + This theme is still in the process of setting up internationalization. + Some of the text below may not yet be correct (for example, we do not yet have a ``locales/`` directory). + Follow these issues to track progress: + + - https://github.com/pydata/pydata-sphinx-theme/issues/1162 + - https://github.com/pydata/pydata-sphinx-theme/issues/257 + +Internationalization (I18N) and localization (L10N) is performed using `Gettext `__. + +Types of files +-------------- + +Gettext reads a program's source and extracts text that has been marked as translatable, known as "source strings. +Gettext uses three types of files: + +PO file (``.po``) + A `Portable Object (PO) file `__ is made up of many entries. + Each entry holds the relation between a source string and its translation. + ``msgid`` contains the **source string**, and ``msgstr`` contains the **translation**. + In a given PO file, all translations are expressed in a single target language. + PO files are also known as "message catalogs". + + Entries begin with comments, on lines starting with the character ``#``. + Comments are created and maintained by Gettext. + Comment lines starting with ``#:`` contain references to the program's source. + These references allow a human translator to find the source strings in their original context. + Comment lines starting with ``#,`` contain flags like ``python-format``, which indicates that the source string contains placeholders like ``%(copyright)s``. +POT file (``.pot``) + A Portable Object Template (POT) file is the same as a PO file, except the translations are empty, so that it can be used as a template for new languages. +MO file (``.mo``) + A Machine Object (MO) file is a binary version of a PO file. PO files are compiled to MO files, which are required by Gettext. + +.. _adding-natural-language-text: + +Mark natural language text as translateable +------------------------------------------- + +All natural language text must be marked as translatable, so that it can be extracted by Gettext and translated by humans. + +Jinja2 provides a ``trans`` block and a ``_()`` function to mark text as translatable. +`Please refer to the Jinja2 documentation `__. +Remember to `manually escape `__ variables if needed. + +Any text that is marked in this way will be discoverable by ``gettext`` and used to generate ``.po`` files (see below for information). +Once you've marked text as translateable, complete the steps for :ref:`changing-natural-language-text`. + +.. _changing-natural-language-text: + +Add or change natural language text +----------------------------------- + +These steps cover how to add or change text that has been marked as translateable. + +#. Edit the natural language text as desired. + Ensure that it is {ref}`marked as translateable `. + +#. Generate/update the message catalog template (``POT`` file) with `the PyBabel extract command `__: + + .. code-block:: bash + + pybabel extract . -F babel.cfg -o src/pydata_sphinx_theme/locale/sphinx.pot -k '_ __ l_ lazy_gettext' + +#. Update the message catalogs (``PO`` files) with `the PyBabel update command `__: + + .. code-block:: bash + + pybabel update -i src/pydata_sphinx_theme/locale/sphinx.pot -d src/pydata_sphinx_theme/locale -D sphinx + +This will update these files with new information about the position and text of the language you have modified. + +.. _translating-the-theme: + +Add translations to translateable text +-------------------------------------- + +Once text has been marked as translateable, and ``PO`` files have been generated for it, we may add translations for new languages for the phrase. +This section covers how to do so. + +.. note:: + + These steps use the Spanish language as an example. + To translate the theme to another language, replace ``es`` with the language's two-letter lowercase `ISO 639-1 code `__. + +#. If the language's code matches no sub-directory of the `pydata_sphinx_theme/locale `__ directory, initialize the language's message catalog (PO file) with `PyBabel init `__: + + .. code-block:: bash + + pybabel init -i src/pydata_sphinx_theme/locale/sphinx.pot -d src/pydata_sphinx_theme/locale -D sphinx -l es + +#. Edit the language's message catalog at ``pydata_sphinx_theme/locale/es/LC_MESSAGES/sphinx.po``. For each source string introduced by the ``msgid`` keyword, add its translation after the ``msgstr`` keyword. + +#. Compile the message catalogs of every language. This creates or updates the MO files with `PyBabel compile `__: + +.. code-block:: bash + + pybabel compile -d src/pydata_sphinx_theme/locale -D sphinx + + +References +---------- + +I18N and L10N are deep topics. Here, we only cover the bare minimum needed to fulfill basics technical tasks. You might like: + +- `Internationalis(z)ing Code `__ by Computerphile on YouTube +- `Falsehoods Programmers Believe About Language `__ by Ben Hamill diff --git a/docs/community/index.md b/docs/community/index.md index f704e61ba..2f4bcbe73 100644 --- a/docs/community/index.md +++ b/docs/community/index.md @@ -16,6 +16,7 @@ setup structure topics manual +i18n bootstrap ``` diff --git a/docs/user_guide/i18n.rst b/docs/user_guide/i18n.rst new file mode 100644 index 000000000..7d6756aef --- /dev/null +++ b/docs/user_guide/i18n.rst @@ -0,0 +1,74 @@ +Internationalization +==================== + +This theme contains translatable strings. +There are two kinds of strings in this theme, with different steps to translate each. + +**Built-in strings** are hard-coded in the theme's templates. +They will automatically be translated if the language is `supported `__. +To add another language, see :ref:`translating-the-theme`. + +**Configurable strings** are user-defined with the ``html_theme_options`` variable in your ``conf.py`` file (see other sections in :doc:`the user guide` for examples). +To translate these strings, see the section below. + +Translating configurable strings +-------------------------------- + +These instructions are for translating configurable strings (those that are customizable in ``html_theme_options``). + +These instructions assume that you store your translations in a ``locale`` directory under your documentation directory, and that you want to use ``theme`` as the name of the message catalog for these strings. + +#. In your ``conf.py`` file: + + .. code-block:: python + + import os.path + from sphinx.locale import get_translation + + catalog = "theme" + _ = get_translation(catalog) + + html_theme_options = { + "search_bar_text": _("Search the docs..."), + + # You only need to translate the following if you use these features. + "icon_links_label": _("Quick Links"), + "icon_links": [ + { + "name": _("GitHub"), + "url": "https://github.com//", + "icon": "fab fa-github-square", + }, + ], + "external_links": [ + { + "name": _("link-one-name"), + "url": "https://", + }, + ], + } + + def setup(app): + locale_dir = os.path.join(os.path.abspath(os.path.dirname(__file__), "locale") + + app.add_message_catalog(catalog, locale_dir) + +#. Extract the strings to translate: + + .. code-block:: bash + + pybabel extract . -o locale/theme.pot + +#. Create a message catalog (changing the ``--locale`` option as desired): + + .. code-block:: bash + + pybabel init --input-file=locale/theme.pot --domain=theme --output-dir=locale --locale=fr + +#. Translate the message catalog by editing the file. + +#. Compile the message catalog: + + .. code-block:: bash + + pybabel compile --directory=locale --domain=theme diff --git a/docs/user_guide/index.md b/docs/user_guide/index.md index 886708237..3ca4013d2 100644 --- a/docs/user_guide/index.md +++ b/docs/user_guide/index.md @@ -47,6 +47,7 @@ announcements version-dropdown search keyboard-shortcuts +i18n ``` ```{toctree}