Skip to content
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ coverage.xml
*.cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
include babel.cfg
include MANIFEST.in
include LICENSE
include README.md
Expand Down
5 changes: 5 additions & 0 deletions babel.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# See https://github.com/sphinx-doc/sphinx/blob/4.x/babel.cfg
[jinja2: **.html]
encoding = utf-8
ignore_tags = script,style
include_attrs = alt title summary placeholder
73 changes: 73 additions & 0 deletions docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,79 @@ is required. The steps are roughly:
- potentially remove the font being replaced from ``package.json`` and re-run ``yarn``
- commit all of the changed files

Internationalization
====================

.. note::

Internationalization (I18N) and localization (L10N) is performed using `Gettext <https://docs.python.org/3/library/gettext.html>`__. 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 <https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files>`__ is made up of many entries, each entry holding the relation between a source string and its translation. The source string is introduced by the keyword ``msgid``, and the translation, by ``msgstr``. In a given PO file, all translations are expressed in a single target language. PO files are also known as message catalogs.
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.

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 <https://www.youtube.com/watch?v=0j74jcxSunY>`__ by Computerphile on YouTube
- `Falsehoods Programmers Believe About Language <http://garbled.benhamill.com/2017/04/18/falsehoods-programmers-believe-about-language>`__ by Ben Hamill

.. _adding-natural-language-text:

Adding natural language text
----------------------------

All natural language text must be marked as translatable, so that it can be extracted by Gettext and translated.

Jinja2 provides a ``trans`` block and a ``_()`` function to mark text as translatable. `Please refer to the Jinja2 documentation <https://jinja.palletsprojects.com/en/2.11.x/templates/#i18n>`__. Remember to `manually escape <https://jinja.palletsprojects.com/en/2.11.x/templates/#working-with-manual-escaping>`__ variables if needed.

Then, complete the steps for :ref:`changing-natural-language-text`.

.. note::

When a variable is used in a source string (for example, ``{% trans %}Hello, {{ user }}!{% endtrans %}``), the value of the variable is not translated. If ``user`` is "John", it will be substituted as "John", not as "Иван" or "约翰". In other words, don't do ``{{ _(theme_search_bar_text) }}``.

.. _changing-natural-language-text:

Changing natural language text
------------------------------

#. Edit the natural language text as desired.

#. Update the message catalog template (POT file):

.. code-block:: bash

python setup.py extract_messages

#. Update the message catalogs (PO files):

.. code-block:: bash

python setup.py update_catalog

.. _translating-the-theme:

Translating the theme
---------------------

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 <https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes>`__.

#. If the language's code matches no sub-directory of the `pydata_sphinx_theme/locale <https://github.com/pydata/pydata-sphinx-theme/tree/master/pydata_sphinx_theme/locale>`__ directory, initialize the language's message catalog:

.. code-block:: bash

python setup.py init_catalog -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:

.. code-block:: bash

python setup.py compile_catalog

Contributing changes
====================
Expand Down
61 changes: 61 additions & 0 deletions docs/user_guide/i18n.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Internationalization
====================

This theme contains translatable strings. Most strings will automatically be translated if the language is `supported <https://github.com/pydata/pydata-sphinx-theme/tree/master/pydata_sphinx_theme/locale>`__. To add another language, see :ref:`translating-the-theme`.

The theme's :doc:`options<configuring>` also contain translatable strings, which require a different process. The following 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/<your-org>/<your-repo>",
"icon": "fab fa-github-square",
},
],
"external_links": [
{
"name": _("link-one-name"),
"url": "https://<link-one>",
},
],
}
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
1 change: 1 addition & 0 deletions docs/user_guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ User Guide
configuring
sections
customizing
i18n
5 changes: 4 additions & 1 deletion pydata_sphinx_theme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,9 @@ def setup(app):
app.add_html_theme("pydata_sphinx_theme", theme_path)
app.set_translator("html", BootstrapHTML5Translator)

# https://www.sphinx-doc.org/en/master/extdev/i18n.html#extension-internationalization-i18n-and-localization-l10n-using-i18n-api
app.add_message_catalog("sphinx", os.path.join(theme_path, "locale"))

# Read the Docs uses ``readthedocs`` as the name of the build, and also
# uses a special "dirhtml" builder so we need to replace these both with
# our custom HTML builder
Expand All @@ -529,7 +532,7 @@ def setup(app):

# Update templates for sidebar
pkgdir = os.path.abspath(os.path.dirname(__file__))
path_templates = os.path.join(pkgdir, "_templates")
path_templates = os.path.join(pkgdir, "templates")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flag for @jorisvandenbossche, any reason we wouldn’t want to use templates wo the underscore? I don’t think this would affect anything downstream

Copy link
Contributor Author

@jpmckinney jpmckinney Apr 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't affect theme users. When theme users override a template, it's based on the file's basename, not on its path within a particular theme, to my knowledge.

app.config.templates_path.append(path_templates)

return {"parallel_read_safe": True, "parallel_write_safe": True}
14 changes: 7 additions & 7 deletions pydata_sphinx_theme/icon-links.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
{%- macro icon_link_nav_item(url, icon, name) -%}
{%- if url | length > 2 %}
<li class="nav-item">
<a class="nav-link" href="{{ url }}" rel="noopener" target="_blank" title="{{ _(name) }}">
<a class="nav-link" href="{{ url }}" rel="noopener" target="_blank" title="{{ name }}">
<span><i class="{{ icon }}"></i></span>
<label class="sr-only">{{ _(name) }}</label>
<label class="sr-only">{{ name }}</label>
</a>
</li>
{%- endif -%}
{%- endmacro -%}

<ul id="navbar-icon-links" class="navbar-nav" aria-label="{{ _(theme_icon_links_label) }}">
<ul id="navbar-icon-links" class="navbar-nav" aria-label="{{ theme_icon_links_label }}">
{%- block icon_link_shortcuts -%}
{{ icon_link_nav_item(theme_github_url, "fab fa-github-square", "GitHub") -}}
{{ icon_link_nav_item(theme_gitlab_url, "fab fa-gitlab", "GitLab") -}}
{{ icon_link_nav_item(theme_bitbucket_url, "fab fa-bitbucket", "Bitbucket") -}}
{{ icon_link_nav_item(theme_twitter_url, "fab fa-twitter-square", "Twitter") -}}
{{ icon_link_nav_item(theme_github_url, "fab fa-github-square", _("GitHub")) -}}
{{ icon_link_nav_item(theme_gitlab_url, "fab fa-gitlab", _("GitLab")) -}}
{{ icon_link_nav_item(theme_bitbucket_url, "fab fa-bitbucket", _("Bitbucket")) -}}
{{ icon_link_nav_item(theme_twitter_url, "fab fa-twitter-square", _("Twitter")) -}}
{% endblock -%}
{%- for icon_link in theme_icon_links -%}
{{ icon_link_nav_item(icon_link["url"], icon_link["icon"], icon_link["name"]) -}}
Expand Down
Binary file not shown.
83 changes: 83 additions & 0 deletions pydata_sphinx_theme/locale/es/LC_MESSAGES/sphinx.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Spanish translations for pydata-sphinx-theme.
# Copyright (C) 2021 ORGANIZATION
# This file is distributed under the same license as the pydata-sphinx-theme
# project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: pydata-sphinx-theme 0.6.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-04-22 16:46-0400\n"
"PO-Revision-Date: 2021-04-22 16:46-0400\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: es\n"
"Language-Team: es <[email protected]>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.0\n"

#: pydata_sphinx_theme/docs-navbar.html:9
msgid "Toggle navigation"
msgstr "Alternar navegación"

#: pydata_sphinx_theme/icon-links.html:14
msgid "GitHub"
msgstr "GitHub"

#: pydata_sphinx_theme/icon-links.html:15
msgid "GitLab"
msgstr "GitLab"

#: pydata_sphinx_theme/icon-links.html:16
msgid "Bitbucket"
msgstr "Bitbucket"

#: pydata_sphinx_theme/icon-links.html:17
msgid "Twitter"
msgstr "Twitter"

#: pydata_sphinx_theme/layout.html:7
msgid "previous page"
msgstr "página anterior"

#: pydata_sphinx_theme/layout.html:10
msgid "next page"
msgstr "siguiente página"

#: pydata_sphinx_theme/templates/copyright.html:3
#, python-format
msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."

#: pydata_sphinx_theme/templates/copyright.html:5
#, python-format
msgid "&copy; Copyright %(copyright)s."
msgstr "&copy; Copyright %(copyright)s."

#: pydata_sphinx_theme/templates/edit-this-page.html:5
msgid "Edit this page"
msgstr "Editar esta página"

#: pydata_sphinx_theme/templates/last-updated.html:2
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr "Última actualización el %(last_updated)s"

#: pydata_sphinx_theme/templates/page-toc.html:5
msgid "On this page"
msgstr "En esta página"

#: pydata_sphinx_theme/templates/sidebar-nav-bs.html:1
msgid "Main navigation"
msgstr "Navegación principal"

#: pydata_sphinx_theme/templates/sphinx-version.html:2
#, python-format
msgid ""
"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
"%(sphinx_version)s."
msgstr "Creado con <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
"%(sphinx_version)s."
Binary file not shown.
83 changes: 83 additions & 0 deletions pydata_sphinx_theme/locale/fr/LC_MESSAGES/sphinx.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# French translations for pydata-sphinx-theme.
# Copyright (C) 2021 ORGANIZATION
# This file is distributed under the same license as the pydata-sphinx-theme
# project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: pydata-sphinx-theme 0.6.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-04-22 16:46-0400\n"
"PO-Revision-Date: 2021-04-22 16:46-0400\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: fr\n"
"Language-Team: fr <[email protected]>\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.0\n"

#: pydata_sphinx_theme/docs-navbar.html:9
msgid "Toggle navigation"
msgstr "Basculer la navigation"

#: pydata_sphinx_theme/icon-links.html:14
msgid "GitHub"
msgstr "GitHub"

#: pydata_sphinx_theme/icon-links.html:15
msgid "GitLab"
msgstr "GitLab"

#: pydata_sphinx_theme/icon-links.html:16
msgid "Bitbucket"
msgstr "Bitbucket"

#: pydata_sphinx_theme/icon-links.html:17
msgid "Twitter"
msgstr "Twitter"

#: pydata_sphinx_theme/layout.html:7
msgid "previous page"
msgstr "page précédente"

#: pydata_sphinx_theme/layout.html:10
msgid "next page"
msgstr "page suivante"

#: pydata_sphinx_theme/templates/copyright.html:3
#, python-format
msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr "&copy; <a href=\"%(path)s\">Droit d'auteur</a> %(copyright)s."

#: pydata_sphinx_theme/templates/copyright.html:5
#, python-format
msgid "&copy; Copyright %(copyright)s."
msgstr "&copy; Droit d'auteur %(copyright)s."

#: pydata_sphinx_theme/templates/edit-this-page.html:5
msgid "Edit this page"
msgstr "Modifier cette page"

#: pydata_sphinx_theme/templates/last-updated.html:2
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr "Dernière mise à jour le %(last_updated)s."

#: pydata_sphinx_theme/templates/page-toc.html:5
msgid "On this page"
msgstr "Sur cette page"

#: pydata_sphinx_theme/templates/sidebar-nav-bs.html:1
msgid "Main navigation"
msgstr "Navigation principale"

#: pydata_sphinx_theme/templates/sphinx-version.html:2
#, python-format
msgid ""
"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
"%(sphinx_version)s."
msgstr "Créé à l'aide de <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
"%(sphinx_version)s."
Loading