Translations
============
We use `Weblate `_ to manage PyPI translations across several languages. Visit the
`Warehouse project on Weblate `_
to contribute.
If you are experiencing issues as a translator, please let us know by opening a
`translation issue on the Warehouse issue tracker `_.
Adding a newly completed translation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Weblate will automatically add commits to a pull request as translations are
updated.
When a translation reaches 100%, it should be added as a known locale and have
it's MO file (Machine Object file) compiled.
To add a new known locale:
1. Check for `outstanding Weblate pull requests
`_ and merge them if so.
2. In a new branch for |pypi/warehouse|_, add the new language identifier to
``KNOWN_LOCALES`` in |warehouse/i18n/__init__.py|_ and |webpack.plugin.localize.js|_.
The value is the locale code, and corresponds to a directory in
``warehouse/locale``.
3. Commit these changes and make a new pull request to |pypi/warehouse|_.
4. In a new branch for |pypi/infra|_, add the new identifier to the
``accept.language_lookup`` call in `PyPI's VCL configuration
`_.
The value is the `IANA language subtag
`_
string for the locale.
.. note::
This value may differ from the identifier used for ``KNOWN_LOCALES``,
e.g. ``pt-BR`` vs ``pt_BR``.
5. Commit these change and make a new pull request to |pypi/infra|_ referencing
your pull request to |pypi/warehouse|_.
.. |pypi/warehouse| replace:: ``pypi/warehouse``
.. _pypi/warehouse: https://github.com/pypi/warehouse
.. |warehouse/i18n/__init__.py| replace:: ``warehouse/i18n/__init__.py``
.. _warehouse/i18n/__init__.py: https://github.com/pypi/warehouse/blob/main/warehouse/i18n/__init__.py
.. |webpack.plugin.localize.js| replace:: ``webpack.plugin.localize.js``
.. _webpack.plugin.localize.js: https://github.com/pypi/warehouse/blob/main/webpack.plugin.localize.js
.. |pypi/infra| replace:: ``pypi/infra``
.. _pypi/infra: https://github.com/pypi/infra
Marking new strings for translation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In an HTML template, use the :code:`{% trans %}` and :code:`{% endtrans %}`
tags to mark a string for translation.
In Python, given a request context, call :code:`request._(message)` to mark
:code:`message` for translation. Without a request context, you can do the following:
.. code-block:: python
from warehouse.i18n import localize as _
message = _("Your message here.")
In javascript, use :code:`gettext("singular", ...placeholder_values)` and
:code:`ngettext("singular", "plural", count, ...placeholder_values)`.
The function names are important because they need to be recognised by pybabel.
.. code-block:: javascript
import { gettext, ngettext } from "../utils/messages-access";
gettext("Get some fruit");
// -> (en) "Get some fruit"
ngettext("Yesterday", "In the past", numDays);
// -> (en) numDays is 1: "Yesterday"; numDays is 3: "In the past"
Passing non-translatable values to translated strings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In html, to pass values you don't want to be translated into
translated strings, define them inside the :code:`{% trans %}` tag.
For example, to pass a non-translatable link
:code:`request.route_path('classifiers')` into a string, instead of
placing it directly in the string like so:
.. code-block:: html
{% trans %}
Filter by classifier
{% endtrans %}
Instead, define it inside the :code:`{% trans %}` tag:
.. code-block:: html
{% trans href=request.route_path('classifiers') %}
Filter by classifier
{% endtrans %}
In javascript, use :code:`%1`, :code:`%2`, etc as
placeholders and provide the placeholder values:
.. code-block:: javascript
import { ngettext } from "../utils/messages-access";
ngettext("Yesterday", "About %1 days ago", numDays, numDays);
// -> (en) numDays is 1: "Yesterday"; numDays is 3: "About 3 days ago"
Marking new strings for pluralization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To pluralize a translated string in an HTML template,
use the :code:`{% pluralize %}` tag to separate the singular and plural
variants of a string, for example:
.. code-block:: html
:emphasize-lines: 3
{% trans n_hours=n_hours %}
This link will expire in {{ n_hours }} hour.
{% pluralize %}
This link will expire in {{ n_hours }} hours.
{% endtrans %}
This is not yet directly possible in Python for Warehouse.
In javascript, use :code:`ngettext()` as described above.
Marking views as translatable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If a view's renderer uses translations, you should mark the view as
translatable by setting the :code:`has_translations` option in
the view's configuration:
.. code-block:: python
:emphasize-lines: 4
@viewconfig(
route_name="sample.route",
renderer="translatable_sample.html",
has_translations=True,
)
class SampleViews:
You may have to :ref:`rebuild the translation files `.