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

For internationalization guidelines, see the
`oslo.i18n documentation <https://docs.openstack.org/oslo.i18n/latest/>`_.
The information below can be used to get started.

Cinder uses `gettext <https://docs.python.org/3/library/gettext.html>`_ so that
user-facing strings such as log messages appear in the appropriate
language in different locales.

To use gettext, make sure that the strings passed to the logger are wrapped
in a ``_Lx()`` function call. For example::

    LOG.info(_LI("block_device_mapping %s"), block_device_mapping)

There are a few different _() translation markers, depending on the logging
level of the text:

- _LI() - Used for INFO level log messages
- _LW() - Used for WARNING level log messages
- _LE() - Used for ERROR level log messages (this includes LOG.exception)
- _() - Used for any exception messages, including strings used for both
            logging and exceptions.

.. note::

   Starting with the Pike series, OpenStack no longer supports log
   translation markers like ``_Lx()``, only ``_()`` should still be used for
   exceptions that could be user facing. It is not necessary to add ``_Lx()``
   translation instructions to new code, and the instructions can be removed
   from old code. Refer to the email thread `understanding log domain change
   <http://lists.openstack.org/pipermail/openstack-dev/2017-March/thread.html#113365>`_
   on the openstack-dev mailing list for more details.

Do not use ``locals()`` for formatting messages because:

1. It is not as clear as using explicit dicts.
2. It could produce hidden errors during refactoring.
3. Changing the name of a variable causes a change in the message.
4. It creates a lot of otherwise unused variables.

If you do not follow the project conventions, your code may cause pep8 hacking
check failures.

For translation to work properly, the top level scripts for Cinder need
to first do the following before any Cinder modules are imported::

    from cinder import i18n
    i18n.enable_lazy()

Note: this should _only_ be called from top level scripts - no library code
or common modules should call this method.

Any files that use the _() for translation then must have the following
lines::

    from cinder.i18n import _

If the above code is missing, it may result in an error that looks
like::

    NameError: name '_' is not defined

