summaryrefslogtreecommitdiff
path: root/doc/source/user/usage.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/source/user/usage.rst')
-rw-r--r--doc/source/user/usage.rst274
1 files changed, 274 insertions, 0 deletions
diff --git a/doc/source/user/usage.rst b/doc/source/user/usage.rst
new file mode 100644
index 0000000..d26acd1
--- /dev/null
+++ b/doc/source/user/usage.rst
@@ -0,0 +1,274 @@
+.. _usage:
+
+=====================================================
+ How to Use oslo.i18n in Your Application or Library
+=====================================================
+
+Installing
+==========
+
+At the command line::
+
+ $ pip install oslo.i18n
+
+.. _integration-module:
+
+Creating an Integration Module
+==============================
+
+To use oslo.i18n in a project (e.g. myapp), you will need to create a
+small integration module to hold an instance of
+:class:`~oslo_i18n.TranslatorFactory` and references to
+the marker functions the factory creates.
+
+.. note::
+
+ Libraries probably do not want to expose the new integration module
+ as part of their public API, so rather than naming it
+ ``myapp.i18n`` it should be called ``myapp._i18n`` to indicate that
+ it is a private implementation detail, and not meant to be used
+ outside of the library's own code.
+
+.. note::
+
+ Starting with the Pike series, OpenStack no longer supports log
+ translation. It is not necessary to add 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.
+
+.. code-block:: python
+
+ # myapp/_i18n.py
+
+ import oslo_i18n
+
+ DOMAIN = "myapp"
+
+ _translators = oslo_i18n.TranslatorFactory(domain=DOMAIN)
+
+ # The primary translation function using the well-known name "_"
+ _ = _translators.primary
+
+ # The contextual translation function using the name "_C"
+ # requires oslo.i18n >=2.1.0
+ _C = _translators.contextual_form
+
+ # The plural translation function using the name "_P"
+ # requires oslo.i18n >=2.1.0
+ _P = _translators.plural_form
+
+ # Translators for log levels.
+ #
+ # NOTE(dhellmann): This is not needed for new projects as of the
+ # Pike series.
+ #
+ # The abbreviated names are meant to reflect the usual use of a short
+ # name like '_'. The "L" is for "log" and the other letter comes from
+ # the level.
+ _LI = _translators.log_info
+ _LW = _translators.log_warning
+ _LE = _translators.log_error
+ _LC = _translators.log_critical
+
+
+ def get_available_languages():
+ return oslo_i18n.get_available_languages(DOMAIN)
+
+Then, in the rest of your code, use the appropriate marker function
+for each message:
+
+.. code-block:: python
+
+ from myapp._i18n import _, _LW, _LE
+
+ # ...
+
+ variable = "openstack"
+ LOG.warning(_LW('warning message: %s'), variable)
+
+ # ...
+
+ try:
+
+ # ...
+
+ except AnException1:
+
+ # Log only
+ LOG.exception(_LE('exception message'))
+
+ except AnException2:
+
+ # Raise only
+ raise RuntimeError(_('exception message'))
+
+ else:
+
+ # Log and Raise
+ msg = _('Unexpected error message')
+ LOG.exception(msg)
+ raise RuntimeError(msg)
+
+.. note::
+
+ The import of multiple modules from _i18n on a single line is
+ a valid exception to
+ `OpenStack Style Guidelines <http://docs.openstack.org/developer/hacking/#imports>`_
+ for import statements.
+
+
+It is important to use the marker functions (e.g. _LI), rather than
+the longer form of the name, because the tool that scans the source
+code for translatable strings looks for the marker function names.
+
+.. warning::
+
+ The old method of installing a version of ``_()`` in the builtins
+ namespace is deprecated. Modifying the global namespace affects
+ libraries as well as the application, so it may interfere with
+ proper message catalog lookups. Calls to
+ :func:`gettextutils.install` should be replaced with the
+ application or library integration module described here.
+
+
+Handling hacking Objections to Imports
+======================================
+
+The `OpenStack Style Guidelines <http://docs.openstack.org/developer/hacking/#imports>`_
+prefer importing modules and accessing names from those modules after
+import, rather than importing the names directly. For example:
+
+::
+
+ # WRONG
+ from foo import bar
+
+ bar()
+
+ # RIGHT
+
+ import foo
+
+ foo.bar()
+
+The linting tool hacking_ will typically complain about importing
+names from within modules. It is acceptable to bypass this for the
+translation marker functions, because they must have specific names
+and their use pattern is dictated by the message catalog extraction
+tools rather than our style guidelines. To bypass the hacking check
+for imports from this integration module, add an import exception to
+``tox.ini``.
+
+For example::
+
+ # tox.ini
+ [hacking]
+ import_exceptions = myapp._i18n
+
+.. _hacking: https://pypi.python.org/pypi/hacking
+
+.. _lazy-translation:
+
+Lazy Translation
+================
+
+Lazy translation delays converting a message string to the translated
+form as long as possible, including possibly never if the message is
+not logged or delivered to the user in some other way. It also
+supports logging translated messages in multiple languages, by
+configuring separate log handlers.
+
+Lazy translation is implemented by returning a special object from the
+translation function, instead of a unicode string. That special
+message object supports some, but not all, string manipulation
+APIs. For example, concatenation with addition is not supported, but
+interpolation of variables is supported. Depending on how translated
+strings are used in an application, these restrictions may mean that
+lazy translation cannot be used, and so it is not enabled by default.
+
+To enable lazy translation, call :func:`enable_lazy`.
+
+::
+
+ import oslo_i18n
+
+ oslo_i18n.enable_lazy()
+
+Translating Messages
+====================
+
+Use :func:`~oslo_i18n.translate` to translate strings to
+a specific locale. :func:`translate` handles delayed translation and
+strings that have already been translated immediately. It should be
+used at the point where the locale to be used is known, which is often
+just prior to the message being returned or a log message being
+emitted.
+
+::
+
+ import oslo_i18n
+
+ trans_msg = oslo_i18n.translate(msg, my_locale)
+
+If a locale is not specified the default locale is used.
+
+Available Languages
+===================
+
+Only the languages that have translations provided are available for
+translation. To determine which languages are available the
+:func:`~oslo_i18n.get_available_languages` is provided. The integration
+module provides a domain defined specific function.
+
+.. code-block:: python
+
+ import myapp._i18n
+
+ languages = myapp._i18n.get_available_languages()
+
+.. seealso::
+
+ * :doc:`guidelines`
+
+Displaying translated messages
+==============================
+
+Several preparations are required to display translated messages in your
+running application.
+
+Preferred language
+ You need to specify your preferred language through an environment variable.
+ The preferred language can be specified by ``LANGUAGE``, ``LC_ALL``,
+ ``LC_MESSAGES``, or ``LANGUAGE`` (A former one has a priority).
+
+ ``oslo_i18n.translate()`` can be used to translate a string to override the
+ preferred language.
+
+ .. note::
+
+ You need to use ``enable_lazy()`` to override the preferred language
+ by using ``oslo_i18n.translate()``.
+
+Locale directory
+ Python ``gettext`` looks for binary ``mo`` files for the given domain
+ using the path ``<localedir>/<language>/LC_MESSAGES/<domain>.mo``.
+ The default locale directory varies on distributions,
+ and it is ``/usr/share/locale`` in most cases.
+
+ If you store message catalogs in a different location,
+ you need to specify the location via an environment variable
+ named ``<DOMAIN>_LOCALEDIR`` where ``<DOMAIN>`` is an upper-case
+ domain name with replacing ``_`` and ``.`` with ``-``.
+ For example, ``NEUTRON_LOCALEDIR`` for a domain ``neutron`` and
+ ``OSLO_I18N_LOCALEDIR`` for a domain ``oslo_i18n``.
+
+ .. note::
+
+ When you specify locale directories via ``<DOMAIN>_LOCALEDIR``
+ environment variables, you need to specify an environment variable per
+ domain. More concretely, if your application using a domain ``myapp`
+ uses oslo.policy, you need to specify both ``MYAPP_LOCALEDIR`` and
+ ``OSLO_POLICY_LOCALEDIR`` to ensure that translation messages from
+ both your application and oslo.policy are displayed.