From 4759020bbfe91e9e62c10720fe14d5fcadf10587 Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Mon, 17 Apr 2017 19:36:51 +0200 Subject: [PATCH] Retire repo This repo was created by accident, use deb-python-oslo.i18n instead. Needed-By: I1ac1a06931c8b6dd7c2e73620a0302c29e605f03 Change-Id: I81894aea69b9d09b0977039623c26781093a397a --- .coveragerc | 8 - .gitignore | 24 - .gitreview | 4 - .mailmap | 3 - .testr.conf | 7 - CONTRIBUTING.rst | 16 - HACKING.rst | 4 - LICENSE | 175 ----- README.rst | 20 - README.txt | 13 + babel.cfg | 1 - doc/source/api.rst | 39 - doc/source/conf.py | 77 -- doc/source/contributing.rst | 5 - doc/source/guidelines.rst | 237 ------ doc/source/history.rst | 1 - doc/source/index.rst | 33 - doc/source/policy.rst | 9 - doc/source/usage.rst | 218 ------ oslo_i18n/__init__.py | 16 - oslo_i18n/_factory.py | 205 ------ oslo_i18n/_gettextutils.py | 90 --- oslo_i18n/_i18n.py | 25 - oslo_i18n/_lazy.py | 38 - oslo_i18n/_locale.py | 25 - oslo_i18n/_message.py | 233 ------ oslo_i18n/_translate.py | 73 -- oslo_i18n/fixture.py | 165 ----- oslo_i18n/locale/de/LC_MESSAGES/oslo_i18n.po | 26 - .../locale/en_GB/LC_MESSAGES/oslo_i18n.po | 25 - oslo_i18n/locale/es/LC_MESSAGES/oslo_i18n.po | 25 - oslo_i18n/locale/fr/LC_MESSAGES/oslo_i18n.po | 26 - oslo_i18n/locale/it/LC_MESSAGES/oslo_i18n.po | 25 - oslo_i18n/locale/ja/LC_MESSAGES/oslo_i18n.po | 18 - .../locale/ko_KR/LC_MESSAGES/oslo_i18n.po | 25 - .../locale/pl_PL/LC_MESSAGES/oslo_i18n.po | 26 - oslo_i18n/locale/pt/LC_MESSAGES/oslo_i18n.po | 25 - .../locale/zh_CN/LC_MESSAGES/oslo_i18n.po | 25 - oslo_i18n/log.py | 97 --- oslo_i18n/tests/__init__.py | 0 oslo_i18n/tests/fakes.py | 59 -- oslo_i18n/tests/test_factory.py | 147 ---- oslo_i18n/tests/test_fixture.py | 118 --- oslo_i18n/tests/test_gettextutils.py | 131 ---- oslo_i18n/tests/test_handler.py | 106 --- oslo_i18n/tests/test_lazy.py | 40 - oslo_i18n/tests/test_locale_dir_variable.py | 32 - oslo_i18n/tests/test_logging.py | 42 -- oslo_i18n/tests/test_message.py | 687 ------------------ oslo_i18n/tests/test_public_api.py | 44 -- oslo_i18n/tests/test_translate.py | 44 -- oslo_i18n/tests/utils.py | 42 -- requirements.txt | 7 - setup.cfg | 51 -- setup.py | 29 - test-requirements.txt | 15 - tox.ini | 38 - 57 files changed, 13 insertions(+), 3726 deletions(-) delete mode 100644 .coveragerc delete mode 100644 .gitignore delete mode 100644 .gitreview delete mode 100644 .mailmap delete mode 100644 .testr.conf delete mode 100644 CONTRIBUTING.rst delete mode 100644 HACKING.rst delete mode 100644 LICENSE delete mode 100644 README.rst create mode 100644 README.txt delete mode 100644 babel.cfg delete mode 100644 doc/source/api.rst delete mode 100755 doc/source/conf.py delete mode 100644 doc/source/contributing.rst delete mode 100644 doc/source/guidelines.rst delete mode 100644 doc/source/history.rst delete mode 100644 doc/source/index.rst delete mode 100644 doc/source/policy.rst delete mode 100644 doc/source/usage.rst delete mode 100644 oslo_i18n/__init__.py delete mode 100644 oslo_i18n/_factory.py delete mode 100644 oslo_i18n/_gettextutils.py delete mode 100644 oslo_i18n/_i18n.py delete mode 100644 oslo_i18n/_lazy.py delete mode 100644 oslo_i18n/_locale.py delete mode 100644 oslo_i18n/_message.py delete mode 100644 oslo_i18n/_translate.py delete mode 100644 oslo_i18n/fixture.py delete mode 100644 oslo_i18n/locale/de/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/en_GB/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/es/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/fr/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/it/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/ja/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/ko_KR/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/pl_PL/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/pt/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/locale/zh_CN/LC_MESSAGES/oslo_i18n.po delete mode 100644 oslo_i18n/log.py delete mode 100644 oslo_i18n/tests/__init__.py delete mode 100644 oslo_i18n/tests/fakes.py delete mode 100644 oslo_i18n/tests/test_factory.py delete mode 100644 oslo_i18n/tests/test_fixture.py delete mode 100644 oslo_i18n/tests/test_gettextutils.py delete mode 100644 oslo_i18n/tests/test_handler.py delete mode 100644 oslo_i18n/tests/test_lazy.py delete mode 100644 oslo_i18n/tests/test_locale_dir_variable.py delete mode 100644 oslo_i18n/tests/test_logging.py delete mode 100644 oslo_i18n/tests/test_message.py delete mode 100644 oslo_i18n/tests/test_public_api.py delete mode 100644 oslo_i18n/tests/test_translate.py delete mode 100644 oslo_i18n/tests/utils.py delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 test-requirements.txt delete mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 8283626..0000000 --- a/.coveragerc +++ /dev/null @@ -1,8 +0,0 @@ -[run] -branch = True -source = oslo_i18n -omit = oslo_i18n/tests/* - -[report] -ignore_errors = True -precision = 2 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 9d826ce..0000000 --- a/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -*~ -*.swp -*.pyc -*.log -.coverage -.venv -.tox -cover/ -oslo.i18n.egg-info/ -.openstack-common-venv/ -skeleton.egg-info/ -build/ -dist/ -doc/source/api -AUTHORS -.update-venv/ -ChangeLog -openstack/versioninfo -*.egg -openstack/common/db/*.sqlite -.testrepository/ -.project -.pydevproject -etc/openstack.conf.sample diff --git a/.gitreview b/.gitreview deleted file mode 100644 index 61b80ba..0000000 --- a/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack/oslo.i18n.git diff --git a/.mailmap b/.mailmap deleted file mode 100644 index cc92f17..0000000 --- a/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -# Format is: -# -# \ No newline at end of file diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index fb62267..0000000 --- a/.testr.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list \ No newline at end of file diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index fe2c9be..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,16 +0,0 @@ -If you would like to contribute to the development of OpenStack, -you must follow the steps in this page: - - http://docs.openstack.org/infra/manual/developers.html - -Once those steps have been completed, changes to OpenStack -should be submitted for review via the Gerrit tool, following -the workflow documented at: - - http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad, not GitHub: - - https://bugs.launchpad.net/oslo.i18n \ No newline at end of file diff --git a/HACKING.rst b/HACKING.rst deleted file mode 100644 index 8f0f190..0000000 --- a/HACKING.rst +++ /dev/null @@ -1,4 +0,0 @@ - Style Commandments -=============================================== - -Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 67db858..0000000 --- a/LICENSE +++ /dev/null @@ -1,175 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. diff --git a/README.rst b/README.rst deleted file mode 100644 index 91fcef1..0000000 --- a/README.rst +++ /dev/null @@ -1,20 +0,0 @@ -================================================== - oslo.i18n -- Oslo Internationalization Utilities -================================================== - -.. image:: https://img.shields.io/pypi/v/oslo.i18n.svg - :target: https://pypi.python.org/pypi/oslo.i18n/ - :alt: Latest Version - -.. image:: https://img.shields.io/pypi/dm/oslo.i18n.svg - :target: https://pypi.python.org/pypi/oslo.i18n/ - :alt: Downloads - -The oslo.i18n library contain utilities for working with -internationalization (i18n) features, especially translation for text -strings in an application or library. - -* Free software: Apache license -* Documentation: http://docs.openstack.org/developer/oslo.i18n -* Source: http://git.openstack.org/cgit/openstack/oslo.i18n -* Bugs: http://bugs.launchpad.net/oslo.i18n diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..e6abc94 --- /dev/null +++ b/README.txt @@ -0,0 +1,13 @@ +This project is no longer maintained. + +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". + +Use instead the project deb-python-oslo.i18n at +http://git.openstack.org/cgit/openstack/deb-python-oslo.i18n . + +For any further questions, please email +openstack-dev@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index efceab8..0000000 --- a/babel.cfg +++ /dev/null @@ -1 +0,0 @@ -[python: **.py] diff --git a/doc/source/api.rst b/doc/source/api.rst deleted file mode 100644 index 02095f7..0000000 --- a/doc/source/api.rst +++ /dev/null @@ -1,39 +0,0 @@ -===== - API -===== - -oslo_i18n -========= - -.. automodule:: oslo_i18n - -.. autoclass:: oslo_i18n.TranslatorFactory - :members: - -.. seealso:: - - An example of using a :class:`TranslatorFactory` is provided in - :ref:`integration-module`. - -.. autofunction:: oslo_i18n.enable_lazy - -.. seealso:: - - :ref:`lazy-translation` - -.. autofunction:: oslo_i18n.translate - -.. autofunction:: oslo_i18n.get_available_languages - -oslo_i18n.log -============= - -.. automodule:: oslo_i18n.log - :members: - -oslo_i18n.fixture -================= - -.. automodule:: oslo_i18n.fixture - :members: - :special-members: diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100755 index ef1b1b3..0000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,77 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -sys.path.insert(0, os.path.abspath('../..')) -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - #'sphinx.ext.intersphinx', - 'oslosphinx' -] - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'oslo.i18n' -copyright = u'2014, OpenStack Foundation' - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -# html_theme_path = ["."] -# html_theme = '_theme' -# html_static_path = ['static'] - -html_use_modindex = True - -# Output file base name for HTML help builder. -htmlhelp_basename = '%sdoc' % project - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', - '%s.tex' % project, - u'%s Documentation' % project, - u'OpenStack Foundation', 'manual'), -] - -# Example configuration for intersphinx: refer to the Python standard library. -#intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst deleted file mode 100644 index 2ca75d1..0000000 --- a/doc/source/contributing.rst +++ /dev/null @@ -1,5 +0,0 @@ -============== - Contributing -============== - -.. include:: ../../CONTRIBUTING.rst diff --git a/doc/source/guidelines.rst b/doc/source/guidelines.rst deleted file mode 100644 index e610f53..0000000 --- a/doc/source/guidelines.rst +++ /dev/null @@ -1,237 +0,0 @@ -================================= - Guidelines for Use In OpenStack -================================= - -The OpenStack I18N team has a limited capacity to translate messages, -so we want to make their work as effective as possible by identifying -the most useful text for them to translate. All text messages *the -user sees* via exceptions or API calls should be marked for -translation. However, some exceptions are used internally to signal -error conditions between modules and are not intended to be presented -to the user. Those do not need to be translated. - -.. seealso:: - - * :doc:`usage` - * :doc:`api` - -Gettext Contextual Form and Plural Form -======================================= - -Sometimes under different contexts, the same word should be -translated into different phrases using -:py:attr:`TranslatorFactory.contextual_form `. - -And recommend the following code to use contextual form:: - - # The contextual translation function using the name "_C" - _C = _translators.contextual_form - - ... - msg = _C('context', 'string') - -In some languages, sometimes the translated strings are different -with different item counts using -:py:attr:`TranslatorFactory.plural_form ` - -And recommend the following code to use plural form:: - - # The plural translation function using the name "_P" - _P = _translators.plural_form - - ... - msg = _P('single', 'plural', count) - -The contextual form and plural form are used only when needed. -By default, the translation should use the ``_()``. - -.. note:: - These two functions were only available in oslo.i18n >= 2.1.0. - -Log Translation -=============== - -OpenStack supports translating some log levels using separate message -catalogs, and so has separate marker functions. These well-known names -are used by the build system jobs that extract the messages from the -source code and pass it to the translation tool. - -========== ========== - Level Function -========== ========== - INFO ``_LI()`` - WARNING ``_LW()`` - ERROR ``_LE()`` - CRITICAL ``_LC()`` -========== ========== - -.. note:: - * Debug level log messages are not translated. - * LOG.exception creates an ERROR level log, so when a marker function is - used (see below) ``_LE()`` should be used. - - -Using a Marker Function -======================= -The marker functions are used to mark the translatable strings in the -code. The strings are extracted into catalogs using a tool that -looks for these specific markers, so the function argument must just -be a string. - -For example: **do not do this**:: - - # WRONG - msg = _(variable_containing_msg) - w_msg = _LW(variable_warning_msg) - -Instead, use this style:: - - # RIGHT - msg = _('My message.') - w_msg = _LW('My warning message') - - -Choosing a Marker Function -========================== - -The purpose of the different marker functions is to separate the -translatable messages into different catalogs, which the translation -teams can prioritize translating. It is important to choose the right -marker function, to ensure that strings the user sees will be -translated and to help the translation team manage their work load. - -Everything marked with ``_()`` will be translated. Prioritizing the -catalogs created from strings marked with the log marker functions is -up to the individual translation teams and their users, but it is -expected that they will work on critical and error messages before -warning or info. - -``_()`` is preferred for any user facing message, even if it is also -going to a log file. This ensures that the translated version of the -message will be available to the user. - -The log marker functions (``_LI()``, ``_LW()``, ``_LE()``, and ``_LC()``) -must only be used when the message is only sent directly to the log. -Anytime that the message will be passed outside of the current context -(for example as part of an exception) the ``_()`` marker function -must be used. - -A common pattern is to define a single message object and use it more -than once, for the log call and the exception. In that case, ``_()`` -must be used because the message is going to appear in an exception that -may be presented to the user. - -For example, **do not do this**:: - - # WRONG - msg = _LE('There was an error.') - LOG.exception(msg) - raise LocalExceptionClass(msg) - -Instead, use this style:: - - # RIGHT - msg = _('There was an error.') - LOG.exception(msg) - raise LocalExceptionClass(msg) - -Except in the case above, ``_()`` should not be used for translating -log messages. This avoids having the same string in two message -catalogs, possibly translated differently by two different -translators. The log message will translate properly because when -the message is not found in the log specific catalog the ``_()`` -catalog will be used. - -If a common message is not being used, they should each be treated -separately with respect to choosing a marker function. - -For example, **do not do this**:: - - # WRONG - LOG.exception(_('There was an error.')) - raise LocalExceptionClass(_('An error occured.')) - -Instead, use this style:: - - # RIGHT - LOG.exception(_LE('There was an error.')) - raise LocalExceptionClass(_('An error occured.')) - - -Adding Variables to Translated Messages -======================================= - -Translated messages should not be combined with other literal strings -to create partially translated messages. For example, **do not do -this**:: - - # WRONG - raise ValueError(_('some message') + ': variable=%s' % variable) - -Instead, use this style:: - - # RIGHT - raise ValueError(_('some message: variable=%s') % variable) - -Including the variable reference inside the translated message allows -the translator to take into account grammar rules, differences in -left-right vs. right-left rendering, and other factors to make the -translated message more useful to the end user. - -Any message with more than one variable should use named interpolation -instead of positional, to allow translators to move the variables -around in the string to account for differences in grammar and writing -direction. - -For example, **do not do this**:: - - # WRONG - raise ValueError(_('some message: v1=%s v2=%s') % (v1, v2)) - -Instead, use this style:: - - # RIGHT - raise ValueError(_('some message: v1=%(v1)s v2=%(v2)s') % {'v1': v1, 'v2': v2}) - - -Adding Variables to Log Messages -================================ - -String interpolation should be delayed to be handled by the logging -code, rather than being done at the point of the logging call. For -example, **do not do this**:: - - # WRONG - LOG.info(_LI('some message: variable=%s') % variable) - -Instead, use this style:: - - # RIGHT - LOG.info(_LI('some message: variable=%s'), variable) - -This allows the logging package to skip creating the formatted log -message if the message is not going to be emitted because of the -current log level. - -Avoid Forcing the Translation of Translatable Variables -======================================================= - -Translation can also be delayed for variables that potentially contain -translatable objects such as exceptions. - -Whenever possible translation should not be forced by use of :func:`str`, -:func:`unicode`, or :func:`six.text_type` on a message being used with -a format string. - -For example, **do not do this**:: - - # WRONG - LOG.info(_LI('some message: exception=%s'), six.text_type(exc)) - -Instead, use this style:: - - # RIGHT - LOG.info(_LI('some message: exception=%s'), exc) - -This allows the translation of the translatable replacement text to be -delayed until the message is translated. diff --git a/doc/source/history.rst b/doc/source/history.rst deleted file mode 100644 index 69ed4fe..0000000 --- a/doc/source/history.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../ChangeLog diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index fde034a..0000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,33 +0,0 @@ -================================================== - oslo.i18n -- Oslo Internationalization Utilities -================================================== - -The oslo.i18n library contain utilities for working with -internationalization (i18n) features, especially translation for text -strings in an application or library. - -Contents -======== - -.. toctree:: - :maxdepth: 2 - - usage - guidelines - api - policy - contributing - -Release Notes -============= - -.. toctree:: - :maxdepth: 1 - - history - -Indices and tables -================== - -* :ref:`modindex` -* :ref:`search` diff --git a/doc/source/policy.rst b/doc/source/policy.rst deleted file mode 100644 index 7ff67af..0000000 --- a/doc/source/policy.rst +++ /dev/null @@ -1,9 +0,0 @@ -================ - Policy History -================ - -* `Discussion from Havana Summit `__ -* `Discussion from Icehouse Summit `__ -* `Discussion from Juno Summit `__ -* `I18n team wiki page `__ -* `LoggingStandards wiki page `__ diff --git a/doc/source/usage.rst b/doc/source/usage.rst deleted file mode 100644 index 14c0b35..0000000 --- a/doc/source/usage.rst +++ /dev/null @@ -1,218 +0,0 @@ -===================================================== - 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. - -.. 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. - # - # 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 `_ - 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 `_ -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` diff --git a/oslo_i18n/__init__.py b/oslo_i18n/__init__.py deleted file mode 100644 index 4602749..0000000 --- a/oslo_i18n/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ._factory import * -from ._gettextutils import * -from ._lazy import * -from ._translate import * diff --git a/oslo_i18n/_factory.py b/oslo_i18n/_factory.py deleted file mode 100644 index c732b01..0000000 --- a/oslo_i18n/_factory.py +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Translation function factory -""" - -import gettext -import os - -import six - -from oslo_i18n import _lazy -from oslo_i18n import _locale -from oslo_i18n import _message - - -__all__ = [ - 'TranslatorFactory', -] - -# magic gettext number to separate context from message -CONTEXT_SEPARATOR = _message.CONTEXT_SEPARATOR - - -class TranslatorFactory(object): - "Create translator functions" - - def __init__(self, domain, localedir=None): - """Establish a set of translation functions for the domain. - - :param domain: Name of translation domain, - specifying a message catalog. - :type domain: str - :param localedir: Directory with translation catalogs. - :type localedir: str - """ - self.domain = domain - if localedir is None: - variable_name = _locale.get_locale_dir_variable_name(domain) - localedir = os.environ.get(variable_name) - self.localedir = localedir - - def _make_translation_func(self, domain=None): - """Return a translation function ready for use with messages. - - The returned function takes a single value, the unicode string - to be translated. The return type varies depending on whether - lazy translation is being done. When lazy translation is - enabled, :class:`Message` objects are returned instead of - regular :class:`unicode` strings. - - The domain argument can be specified to override the default - from the factory, but the localedir from the factory is always - used because we assume the log-level translation catalogs are - installed in the same directory as the main application - catalog. - - """ - if domain is None: - domain = self.domain - t = gettext.translation(domain, - localedir=self.localedir, - fallback=True) - # Use the appropriate method of the translation object based - # on the python version. - m = t.gettext if six.PY3 else t.ugettext - - def f(msg): - """oslo_i18n.gettextutils translation function.""" - if _lazy.USE_LAZY: - return _message.Message(msg, domain=domain) - return m(msg) - return f - - def _make_contextual_translation_func(self, domain=None): - """Return a translation function ready for use with context messages. - - The returned function takes two values, the context of - the unicode string, the unicode string to be translated. - The returned type is the same as - :method:`TranslatorFactory._make_translation_func`. - - The domain argument is the same as - :method:`TranslatorFactory._make_translation_func`. - - """ - if domain is None: - domain = self.domain - t = gettext.translation(domain, - localedir=self.localedir, - fallback=True) - # Use the appropriate method of the translation object based - # on the python version. - m = t.gettext if six.PY3 else t.ugettext - - def f(ctx, msg): - """oslo.i18n.gettextutils translation with context function.""" - if _lazy.USE_LAZY: - msgid = (ctx, msg) - return _message.Message(msgid, domain=domain, - has_contextual_form=True) - - msgctx = "%s%s%s" % (ctx, CONTEXT_SEPARATOR, msg) - s = m(msgctx) - if CONTEXT_SEPARATOR in s: - # Translation not found - return msg - return s - return f - - def _make_plural_translation_func(self, domain=None): - """Return a plural translation function ready for use with messages. - - The returned function takes three values, the single form of - the unicode string, the plural form of the unicode string, - the count of items to be translated. - The returned type is the same as - :method:`TranslatorFactory._make_translation_func`. - - The domain argument is the same as - :method:`TranslatorFactory._make_translation_func`. - - """ - if domain is None: - domain = self.domain - t = gettext.translation(domain, - localedir=self.localedir, - fallback=True) - # Use the appropriate method of the translation object based - # on the python version. - m = t.ngettext if six.PY3 else t.ungettext - - def f(msgsingle, msgplural, msgcount): - """oslo.i18n.gettextutils plural translation function.""" - if _lazy.USE_LAZY: - msgid = (msgsingle, msgplural, msgcount) - return _message.Message(msgid, domain=domain, - has_plural_form=True) - return m(msgsingle, msgplural, msgcount) - return f - - @property - def primary(self): - "The default translation function." - return self._make_translation_func() - - @property - def contextual_form(self): - """The contextual translation function. - - The returned function takes two values, the context of - the unicode string, the unicode string to be translated. - - .. versionadded:: 2.1.0 - - """ - return self._make_contextual_translation_func() - - @property - def plural_form(self): - """The plural translation function. - - The returned function takes three values, the single form of - the unicode string, the plural form of the unicode string, - the count of items to be translated. - - .. versionadded:: 2.1.0 - - """ - return self._make_plural_translation_func() - - def _make_log_translation_func(self, level): - return self._make_translation_func(self.domain + '-log-' + level) - - @property - def log_info(self): - "Translate info-level log messages." - return self._make_log_translation_func('info') - - @property - def log_warning(self): - "Translate warning-level log messages." - return self._make_log_translation_func('warning') - - @property - def log_error(self): - "Translate error-level log messages." - return self._make_log_translation_func('error') - - @property - def log_critical(self): - "Translate critical-level log messages." - return self._make_log_translation_func('critical') diff --git a/oslo_i18n/_gettextutils.py b/oslo_i18n/_gettextutils.py deleted file mode 100644 index 75a8313..0000000 --- a/oslo_i18n/_gettextutils.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""gettextutils provides a wrapper around gettext for OpenStack projects -""" - -import copy -import gettext -import os - -from babel import localedata -import six - -from oslo_i18n import _factory -from oslo_i18n import _locale - -__all__ = [ - 'install', - 'get_available_languages', -] - - -def install(domain): - """Install a _() function using the given translation domain. - - Given a translation domain, install a _() function using gettext's - install() function. - - The main difference from gettext.install() is that we allow - overriding the default localedir (e.g. /usr/share/locale) using - a translation-domain-specific environment variable (e.g. - NOVA_LOCALEDIR). - - :param domain: the translation domain - """ - from six import moves - tf = _factory.TranslatorFactory(domain) - moves.builtins.__dict__['_'] = tf.primary - - -_AVAILABLE_LANGUAGES = {} - - -def get_available_languages(domain): - """Lists the available languages for the given translation domain. - - :param domain: the domain to get languages for - """ - if domain in _AVAILABLE_LANGUAGES: - return copy.copy(_AVAILABLE_LANGUAGES[domain]) - - localedir = os.environ.get(_locale.get_locale_dir_variable_name(domain)) - find = lambda x: gettext.find(domain, - localedir=localedir, - languages=[x]) - - # NOTE(mrodden): en_US should always be available (and first in case - # order matters) since our in-line message strings are en_US - language_list = ['en_US'] - locale_identifiers = localedata.locale_identifiers() - language_list.extend(language for language in locale_identifiers - if find(language)) - - # In Babel 1.3, locale_identifiers() doesn't list some OpenStack supported - # locales (e.g. 'zh_CN', and 'zh_TW') so we add the locales explicitly if - # necessary so that they are listed as supported. - aliases = {'zh': 'zh_CN', - 'zh_Hant_HK': 'zh_HK', - 'zh_Hant': 'zh_TW', - 'fil': 'tl_PH'} - - language_list.extend(alias for locale, alias in six.iteritems(aliases) - if (locale in language_list and - alias not in language_list)) - - _AVAILABLE_LANGUAGES[domain] = language_list - return copy.copy(language_list) diff --git a/oslo_i18n/_i18n.py b/oslo_i18n/_i18n.py deleted file mode 100644 index 7755571..0000000 --- a/oslo_i18n/_i18n.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Translation support for messages in this library. -""" - -from oslo_i18n import _factory - -# Create the global translation functions. -_translators = _factory.TranslatorFactory('oslo_i18n') - -# The primary translation function using the well-known name "_" -_ = _translators.primary diff --git a/oslo_i18n/_lazy.py b/oslo_i18n/_lazy.py deleted file mode 100644 index 82de17d..0000000 --- a/oslo_i18n/_lazy.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -__all__ = [ - 'enable_lazy', -] - -USE_LAZY = False - - -def enable_lazy(enable=True): - """Convenience function for configuring _() to use lazy gettext - - Call this at the start of execution to enable the gettextutils._ - function to use lazy gettext functionality. This is useful if - your project is importing _ directly instead of using the - gettextutils.install() way of importing the _ function. - - :param enable: Flag indicating whether lazy translation should be - turned on or off. Defaults to True. - :type enable: bool - - """ - global USE_LAZY - USE_LAZY = enable diff --git a/oslo_i18n/_locale.py b/oslo_i18n/_locale.py deleted file mode 100644 index 51908db..0000000 --- a/oslo_i18n/_locale.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -def get_locale_dir_variable_name(domain): - """Build environment variable name for local dir. - - Convert a translation domain name to a variable for specifying - a separate locale dir. - - """ - return domain.upper().replace('.', '_').replace('-', '_') + '_LOCALEDIR' diff --git a/oslo_i18n/_message.py b/oslo_i18n/_message.py deleted file mode 100644 index 0bd83c5..0000000 --- a/oslo_i18n/_message.py +++ /dev/null @@ -1,233 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Private Message class for lazy translation support. -""" - -import copy -import gettext -import locale -import logging -import os -import warnings - -import six - -from oslo_i18n import _locale -from oslo_i18n import _translate - -# magic gettext number to separate context from message -CONTEXT_SEPARATOR = "\x04" - - -LOG = logging.getLogger(__name__) - - -class Message(six.text_type): - """A Message object is a unicode object that can be translated. - - Translation of Message is done explicitly using the translate() method. - For all non-translation intents and purposes, a Message is simply unicode, - and can be treated as such. - """ - - def __new__(cls, msgid, msgtext=None, params=None, - domain='oslo', has_contextual_form=False, - has_plural_form=False, *args): - """Create a new Message object. - - In order for translation to work gettext requires a message ID, this - msgid will be used as the base unicode text. It is also possible - for the msgid and the base unicode text to be different by passing - the msgtext parameter. - """ - # If the base msgtext is not given, we use the default translation - # of the msgid (which is in English) just in case the system locale is - # not English, so that the base text will be in that locale by default. - if not msgtext: - msgtext = Message._translate_msgid(msgid, domain) - # We want to initialize the parent unicode with the actual object that - # would have been plain unicode if 'Message' was not enabled. - msg = super(Message, cls).__new__(cls, msgtext) - msg.msgid = msgid - msg.domain = domain - msg.params = params - msg.has_contextual_form = has_contextual_form - msg.has_plural_form = has_plural_form - return msg - - def translate(self, desired_locale=None): - """Translate this message to the desired locale. - - :param desired_locale: The desired locale to translate the message to, - if no locale is provided the message will be - translated to the system's default locale. - - :returns: the translated message in unicode - """ - - translated_message = Message._translate_msgid(self.msgid, - self.domain, - desired_locale, - self.has_contextual_form, - self.has_plural_form) - - if self.params is None: - # No need for more translation - return translated_message - - # This Message object may have been formatted with one or more - # Message objects as substitution arguments, given either as a single - # argument, part of a tuple, or as one or more values in a dictionary. - # When translating this Message we need to translate those Messages too - translated_params = _translate.translate_args(self.params, - desired_locale) - - return self._safe_translate(translated_message, translated_params) - - @staticmethod - def _translate_msgid(msgid, domain, desired_locale=None, - has_contextual_form=False, has_plural_form=False): - if not desired_locale: - system_locale = locale.getdefaultlocale() - # If the system locale is not available to the runtime use English - if not system_locale or not system_locale[0]: - desired_locale = 'en_US' - else: - desired_locale = system_locale[0] - - locale_dir = os.environ.get( - _locale.get_locale_dir_variable_name(domain) - ) - lang = gettext.translation(domain, - localedir=locale_dir, - languages=[desired_locale], - fallback=True) - - if not has_contextual_form and not has_plural_form: - # This is the most common case, so check it first. - translator = lang.gettext if six.PY3 else lang.ugettext - translated_message = translator(msgid) - - elif has_contextual_form and has_plural_form: - # Reserved for contextual and plural translation function, - # which is not yet implemented. - raise ValueError("Unimplemented.") - - elif has_contextual_form: - (msgctx, msgtxt) = msgid - translator = lang.gettext if six.PY3 else lang.ugettext - - msg_with_ctx = "%s%s%s" % (msgctx, CONTEXT_SEPARATOR, msgtxt) - translated_message = translator(msg_with_ctx) - - if CONTEXT_SEPARATOR in translated_message: - # Translation not found, use the original text - translated_message = msgtxt - - elif has_plural_form: - (msgsingle, msgplural, msgcount) = msgid - translator = lang.ngettext if six.PY3 else lang.ungettext - translated_message = translator(msgsingle, msgplural, msgcount) - - return translated_message - - def _safe_translate(self, translated_message, translated_params): - """Trap translation errors and fall back to default translation. - - :param translated_message: the requested translation - - :param translated_params: the params to be inserted - - :return: if parameter insertion is successful then it is the - translated_message with the translated_params inserted, if the - requested translation fails then it is the default translation - with the params - """ - - try: - translated_message = translated_message % translated_params - except (KeyError, TypeError) as err: - # KeyError for parameters named in the translated_message - # but not found in translated_params and TypeError for - # type strings that do not match the type of the - # parameter. - # - # Log the error translating the message and use the - # original message string so the translator's bad message - # catalog doesn't break the caller. - # Do not translate this log message even if it is used as a - # warning message as a wrong translation of this message could - # cause infinite recursion - msg = (u'Failed to insert replacement values into translated ' - u'message %s (Original: %r): %s') - warnings.warn(msg % (translated_message, self.msgid, err)) - LOG.debug(msg, translated_message, self.msgid, err) - - translated_message = self.msgid % translated_params - - return translated_message - - def __mod__(self, other): - # When we mod a Message we want the actual operation to be performed - # by the base class (i.e. unicode()), the only thing we do here is - # save the original msgid and the parameters in case of a translation - params = self._sanitize_mod_params(other) - unicode_mod = self._safe_translate(six.text_type(self), params) - modded = Message(self.msgid, - msgtext=unicode_mod, - params=params, - domain=self.domain) - return modded - - def _sanitize_mod_params(self, other): - """Sanitize the object being modded with this Message. - - - Add support for modding 'None' so translation supports it - - Trim the modded object, which can be a large dictionary, to only - those keys that would actually be used in a translation - - Snapshot the object being modded, in case the message is - translated, it will be used as it was when the Message was created - """ - if other is None: - params = (other,) - elif isinstance(other, dict): - # Merge the dictionaries - # Copy each item in case one does not support deep copy. - params = {} - if isinstance(self.params, dict): - params.update((key, self._copy_param(val)) - for key, val in self.params.items()) - params.update((key, self._copy_param(val)) - for key, val in other.items()) - else: - params = self._copy_param(other) - return params - - def _copy_param(self, param): - try: - return copy.deepcopy(param) - except Exception: - # Fallback to casting to unicode this will handle the - # python code-like objects that can't be deep-copied - return six.text_type(param) - - def __add__(self, other): - from oslo_i18n._i18n import _ - msg = _('Message objects do not support addition.') - raise TypeError(msg) - - def __radd__(self, other): - return self.__add__(other) diff --git a/oslo_i18n/_translate.py b/oslo_i18n/_translate.py deleted file mode 100644 index 1809e1e..0000000 --- a/oslo_i18n/_translate.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -__all__ = [ - 'translate', -] - - -def translate(obj, desired_locale=None): - """Gets the translated unicode representation of the given object. - - If the object is not translatable it is returned as-is. - - If the desired_locale argument is None the object is translated to - the system locale. - - :param obj: the object to translate - :param desired_locale: the locale to translate the message to, if None the - default system locale will be used - :returns: the translated object in unicode, or the original object if - it could not be translated - - """ - from oslo_i18n import _message # avoid circular dependency at module level - message = obj - if not isinstance(message, _message.Message): - # If the object to translate is not already translatable, - # let's first get its unicode representation - message = six.text_type(obj) - if isinstance(message, _message.Message): - # Even after unicoding() we still need to check if we are - # running with translatable unicode before translating - return message.translate(desired_locale) - return obj - - -def translate_args(args, desired_locale=None): - """Translates all the translatable elements of the given arguments object. - - This method is used for translating the translatable values in method - arguments which include values of tuples or dictionaries. - If the object is not a tuple or a dictionary the object itself is - translated if it is translatable. - - If the locale is None the object is translated to the system locale. - - :param args: the args to translate - :param desired_locale: the locale to translate the args to, if None the - default system locale will be used - :returns: a new args object with the translated contents of the original - """ - if isinstance(args, tuple): - return tuple(translate(v, desired_locale) for v in args) - if isinstance(args, dict): - translated_dict = dict((key, translate(value, desired_locale)) - for key, value in six.iteritems(args)) - return translated_dict - return translate(args, desired_locale) diff --git a/oslo_i18n/fixture.py b/oslo_i18n/fixture.py deleted file mode 100644 index 35dc694..0000000 --- a/oslo_i18n/fixture.py +++ /dev/null @@ -1,165 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Test fixtures for working with oslo_i18n. - -""" - -import gettext - -import fixtures -import six - -from oslo_i18n import _lazy -from oslo_i18n import _message - - -class Translation(fixtures.Fixture): - """Fixture for managing translatable strings. - - This class provides methods for creating translatable strings - using both lazy translation and immediate translation. It can be - used to generate the different types of messages returned from - oslo_i18n to test code that may need to know about the type to - handle them differently (for example, error handling in WSGI apps, - or logging). - - Use this class to generate messages instead of toggling the global - lazy flag and using the regular translation factory. - - """ - - def __init__(self, domain='test-domain'): - """Initialize the fixture. - - :param domain: The translation domain. This is not expected to - coincide with an actual set of message - catalogs, but it can. - :type domain: str - """ - self.domain = domain - - def lazy(self, msg): - """Return a lazily translated message. - - :param msg: Input message string. May optionally include - positional or named string interpolation markers. - :type msg: str or unicode - - """ - return _message.Message(msg, domain=self.domain) - - def immediate(self, msg): - """Return a string as though it had been translated immediately. - - :param msg: Input message string. May optionally include - positional or named string interpolation markers. - :type msg: str or unicode - - """ - return six.text_type(msg) - - -class ToggleLazy(fixtures.Fixture): - """Fixture to toggle lazy translation on or off for a test.""" - - def __init__(self, enabled): - """Force lazy translation on or off. - - :param enabled: Flag controlling whether to enable or disable - lazy translation, passed to :func:`~oslo_i18n.enable_lazy`. - :type enabled: bool - """ - super(ToggleLazy, self).__init__() - self._enabled = enabled - self._original_value = _lazy.USE_LAZY - - def setUp(self): - super(ToggleLazy, self).setUp() - self.addCleanup(self._restore_original) - _lazy.enable_lazy(self._enabled) - - def _restore_original(self): - _lazy.enable_lazy(self._original_value) - - -class _PrefixTranslator(gettext.NullTranslations): - """Translator that adds prefix to message ids - - NOTE: gettext.NullTranslations is an old style class - - :parm prefix: prefix to add to message id. If not specified (None) - then 'noprefix' is used. - :type prefix: string - - """ - - def __init__(self, fp=None, prefix='noprefix'): - gettext.NullTranslations.__init__(self, fp) - self.prefix = prefix - - def gettext(self, message): - msg = gettext.NullTranslations.gettext(self, message) - return self.prefix + msg - - def ugettext(self, message): - msg = gettext.NullTranslations.ugettext(self, message) - return self.prefix + msg - - -def _prefix_translations(*x, **y): - """Use message id prefixed with domain and language as translation - - """ - return _PrefixTranslator(prefix=x[0] + '/' + y['languages'][0] + ': ') - - -class PrefixLazyTranslation(fixtures.Fixture): - """Fixture to prefix lazy translation enabled messages - - Use of this fixture will cause messages supporting lazy translation to - be replaced with the message id prefixed with 'domain/language:'. - For example, 'oslo/en_US: message about something'. It will also - override the available languages returned from - oslo_18n.get_available_languages to the specified languages. - - This will enable tests to ensure that messages were translated lazily - with the specified language and not immediately with the default language. - - NOTE that this does not work unless lazy translation is enabled, so it - uses the ToggleLazy fixture to enable lazy translation. - - :param languages: list of languages to support. If not specified (None) - then ['en_US'] is used. - :type languages: list of strings - - """ - - _DEFAULT_LANG = 'en_US' - - def __init__(self, languages=None, locale=None): - super(PrefixLazyTranslation, self).__init__() - self.languages = languages or [PrefixLazyTranslation._DEFAULT_LANG] - self.locale = locale - - def setUp(self): - super(PrefixLazyTranslation, self).setUp() - self.useFixture(ToggleLazy(True)) - self.useFixture(fixtures.MonkeyPatch( - 'oslo_i18n._gettextutils.get_available_languages', - lambda *x, **y: self.languages)) - self.useFixture(fixtures.MonkeyPatch( - 'oslo_i18n.get_available_languages', - lambda *x, **y: self.languages)) - self.useFixture(fixtures.MonkeyPatch('gettext.translation', - _prefix_translations)) - self.useFixture(fixtures.MonkeyPatch('locale.getdefaultlocale', - lambda *x, **y: self.locale)) diff --git a/oslo_i18n/locale/de/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/de/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index 0a0b25a..0000000 --- a/oslo_i18n/locale/de/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,26 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# Andreas Jaeger , 2014 -# Robert Simai, 2015 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-06-01 09:23+0000\n" -"Last-Translator: Andreas Jaeger \n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: German\n" - -msgid "Message objects do not support addition." -msgstr "Message-Objekte unterstützen keine Addition." diff --git a/oslo_i18n/locale/en_GB/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/en_GB/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index 26e2c59..0000000 --- a/oslo_i18n/locale/en_GB/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,25 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# Andi Chandler , 2014 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2014-09-02 09:09+0000\n" -"Last-Translator: Andi Chandler \n" -"Language: en-GB\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: English (United Kingdom)\n" - -msgid "Message objects do not support addition." -msgstr "Message objects do not support addition." diff --git a/oslo_i18n/locale/es/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/es/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index 71d799a..0000000 --- a/oslo_i18n/locale/es/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,25 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# Adriana Chisco Landazábal , 2015 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2015-06-22 09:03+0000\n" -"Last-Translator: Adriana Chisco Landazábal \n" -"Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: Spanish\n" - -msgid "Message objects do not support addition." -msgstr "Objectos de mensaje no soportan adición." diff --git a/oslo_i18n/locale/fr/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/fr/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index 3e97285..0000000 --- a/oslo_i18n/locale/fr/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,26 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# Jonathan Dupart , 2014 -# Maxime COQUEREL , 2014 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2014-09-25 09:36+0000\n" -"Last-Translator: Jonathan Dupart \n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: French\n" - -msgid "Message objects do not support addition." -msgstr "Les objects message ne supportent pas l'ajout." diff --git a/oslo_i18n/locale/it/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/it/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index 1b3dbf5..0000000 --- a/oslo_i18n/locale/it/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,25 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# PierAlberto , 2014 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2014-08-24 11:27+0000\n" -"Last-Translator: PierAlberto \n" -"Language: it\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: Italian\n" - -msgid "Message objects do not support addition." -msgstr "I messaggi oggetti non supportano aggiunte." diff --git a/oslo_i18n/locale/ja/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/ja/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index 01b71ac..0000000 --- a/oslo_i18n/locale/ja/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,18 +0,0 @@ -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-02-20 06:44+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Japanese\n" -"Language: ja\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=1; plural=0\n" - -msgid "Message objects do not support addition." -msgstr "メッセージオブジェクトは追加機能をサポートしていません。" diff --git a/oslo_i18n/locale/ko_KR/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/ko_KR/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index e8f31e2..0000000 --- a/oslo_i18n/locale/ko_KR/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,25 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# Sungjin Kang , 2014 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2014-09-24 04:32+0000\n" -"Last-Translator: Sungjin Kang \n" -"Language: ko-KR\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: Korean (South Korea)\n" - -msgid "Message objects do not support addition." -msgstr "메시지 객체는 추가 지원을하지 않습니다." diff --git a/oslo_i18n/locale/pl_PL/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/pl_PL/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index e375326..0000000 --- a/oslo_i18n/locale/pl_PL/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,26 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# Łukasz Jernaś , 2014 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2014-08-21 11:28+0000\n" -"Last-Translator: Łukasz Jernaś \n" -"Language: pl-PL\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2);\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: Polish (Poland)\n" - -msgid "Message objects do not support addition." -msgstr "Obiekty Message nie wspierają dodawania." diff --git a/oslo_i18n/locale/pt/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/pt/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index 89ea556..0000000 --- a/oslo_i18n/locale/pt/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,25 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# MMSRS , 2015 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2015-08-11 05:02+0000\n" -"Last-Translator: MMSRS \n" -"Language: pt\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: Portuguese\n" - -msgid "Message objects do not support addition." -msgstr "Os objetos de mensagem não suportam a adição." diff --git a/oslo_i18n/locale/zh_CN/LC_MESSAGES/oslo_i18n.po b/oslo_i18n/locale/zh_CN/LC_MESSAGES/oslo_i18n.po deleted file mode 100644 index 1dbca44..0000000 --- a/oslo_i18n/locale/zh_CN/LC_MESSAGES/oslo_i18n.po +++ /dev/null @@ -1,25 +0,0 @@ -# Translations template for oslo.i18n. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the oslo.i18n project. -# -# Translators: -# Xiao Xi LIU , 2014 -# Andreas Jaeger , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.i18n 3.6.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-04 05:29+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2014-11-20 12:40+0000\n" -"Last-Translator: Xiao Xi LIU \n" -"Language: zh-CN\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 2.0\n" -"X-Generator: Zanata 3.7.3\n" -"Language-Team: Chinese (China)\n" - -msgid "Message objects do not support addition." -msgstr "消息对象不支持添加操作。" diff --git a/oslo_i18n/log.py b/oslo_i18n/log.py deleted file mode 100644 index 563c1b3..0000000 --- a/oslo_i18n/log.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""logging utilities for translation -""" - -from logging import handlers - -from oslo_i18n import _translate - - -class TranslationHandler(handlers.MemoryHandler): - """Handler that translates records before logging them. - - When lazy translation is enabled in the application (see - :func:`~oslo_i18n.enable_lazy`), the :class:`TranslationHandler` - uses its locale configuration setting to determine how to - translate LogRecord objects before forwarding them to the - logging.Handler. - - When lazy translation is disabled, the message in the LogRecord is - converted to unicode without any changes and then forwarded to the - logging.Handler. - - The handler can be configured declaratively in the - ``logging.conf`` as follows:: - - [handlers] - keys = translatedlog, translator - - [handler_translatedlog] - class = handlers.WatchedFileHandler - args = ('/var/log/api-localized.log',) - formatter = context - - [handler_translator] - class = oslo_i18n.log.TranslationHandler - target = translatedlog - args = ('zh_CN',) - - If the specified locale is not available in the system, the handler will - log in the default locale. - - """ - - def __init__(self, locale=None, target=None): - """Initialize a TranslationHandler - - :param locale: locale to use for translating messages - :param target: logging.Handler object to forward - LogRecord objects to after translation - """ - # NOTE(luisg): In order to allow this handler to be a wrapper for - # other handlers, such as a FileHandler, and still be able to - # configure it using logging.conf, this handler has to extend - # MemoryHandler because only the MemoryHandlers' logging.conf - # parsing is implemented such that it accepts a target handler. - handlers.MemoryHandler.__init__(self, capacity=0, target=target) - self.locale = locale - - def setFormatter(self, fmt): - self.target.setFormatter(fmt) - - def emit(self, record): - # We save the message from the original record to restore it - # after translation, so other handlers are not affected by this - original_msg = record.msg - original_args = record.args - - try: - self._translate_and_log_record(record) - finally: - record.msg = original_msg - record.args = original_args - - def _translate_and_log_record(self, record): - record.msg = _translate.translate(record.msg, self.locale) - - # In addition to translating the message, we also need to translate - # arguments that were passed to the log method that were not part - # of the main message e.g., log.info(_('Some message %s'), this_one)) - record.args = _translate.translate_args(record.args, self.locale) - - self.target.emit(record) diff --git a/oslo_i18n/tests/__init__.py b/oslo_i18n/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/oslo_i18n/tests/fakes.py b/oslo_i18n/tests/fakes.py deleted file mode 100644 index 6bed973..0000000 --- a/oslo_i18n/tests/fakes.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2012 Intel Inc, OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Fakes For translation tests. -""" - -import gettext - - -class FakeTranslations(gettext.GNUTranslations): - """A test GNUTranslations class that takes a map of msg -> translations.""" - - def __init__(self, translations): - self.translations = translations - - # used by Python 3 - def gettext(self, msgid): - return self.translations.get(msgid, msgid) - - # used by Python 2 - def ugettext(self, msgid): - return self.translations.get(msgid, msgid) - - @staticmethod - def translator(locales_map): - """Build mock translator for the given locales. - - Returns a mock gettext.translation function that uses - individual TestTranslations to translate in the given locales. - - :param locales_map: A map from locale name to a translations map. - { - 'es': {'Hi': 'Hola', 'Bye': 'Adios'}, - 'zh': {'Hi': 'Ni Hao', 'Bye': 'Zaijian'} - } - - - """ - def _translation(domain, localedir=None, - languages=None, fallback=None): - if languages: - language = languages[0] - if language in locales_map: - return FakeTranslations(locales_map[language]) - return gettext.NullTranslations() - return _translation diff --git a/oslo_i18n/tests/test_factory.py b/oslo_i18n/tests/test_factory.py deleted file mode 100644 index 6bbe684..0000000 --- a/oslo_i18n/tests/test_factory.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from oslotest import base as test_base -import six - -from oslo_i18n import _factory -from oslo_i18n import _lazy -from oslo_i18n import _message - -# magic gettext number to separate context from message -CONTEXT_SEPARATOR = _message.CONTEXT_SEPARATOR - - -class TranslatorFactoryTest(test_base.BaseTestCase): - - def setUp(self): - super(TranslatorFactoryTest, self).setUp() - # remember so we can reset to it later in case it changes - self._USE_LAZY = _lazy.USE_LAZY - - def tearDown(self): - # reset to value before test - _lazy.USE_LAZY = self._USE_LAZY - super(TranslatorFactoryTest, self).tearDown() - - def test_lazy(self): - _lazy.enable_lazy(True) - with mock.patch.object(_message, 'Message') as msg: - tf = _factory.TranslatorFactory('domain') - tf.primary('some text') - msg.assert_called_with('some text', domain='domain') - - def test_not_lazy(self): - _lazy.enable_lazy(False) - with mock.patch.object(_message, 'Message') as msg: - msg.side_effect = AssertionError('should not use Message') - tf = _factory.TranslatorFactory('domain') - tf.primary('some text') - - def test_change_lazy(self): - _lazy.enable_lazy(True) - tf = _factory.TranslatorFactory('domain') - r = tf.primary('some text') - self.assertIsInstance(r, _message.Message) - _lazy.enable_lazy(False) - r = tf.primary('some text') - self.assertNotIsInstance(r, _message.Message) - - def test_py2(self): - _lazy.enable_lazy(False) - with mock.patch.object(six, 'PY3', False): - with mock.patch('gettext.translation') as translation: - trans = mock.Mock() - translation.return_value = trans - trans.gettext.side_effect = AssertionError( - 'should have called ugettext') - tf = _factory.TranslatorFactory('domain') - tf.primary('some text') - trans.ugettext.assert_called_with('some text') - - def test_py3(self): - _lazy.enable_lazy(False) - with mock.patch.object(six, 'PY3', True): - with mock.patch('gettext.translation') as translation: - trans = mock.Mock() - translation.return_value = trans - trans.ugettext.side_effect = AssertionError( - 'should have called gettext') - tf = _factory.TranslatorFactory('domain') - tf.primary('some text') - trans.gettext.assert_called_with('some text') - - def test_log_level_domain_name(self): - with mock.patch.object(_factory.TranslatorFactory, - '_make_translation_func') as mtf: - tf = _factory.TranslatorFactory('domain') - tf._make_log_translation_func('mylevel') - mtf.assert_called_with('domain-log-mylevel') - - def test_contextual_form_py2(self): - _lazy.enable_lazy(False) - with mock.patch.object(six, 'PY3', False): - with mock.patch('gettext.translation') as translation: - trans = mock.Mock() - translation.return_value = trans - trans.gettext.side_effect = AssertionError( - 'should have called ugettext') - trans.ugettext.return_value = "some text" - tf = _factory.TranslatorFactory('domain') - tf.contextual_form('context', 'some text') - trans.ugettext.assert_called_with( - "%s%s%s" % ('context', CONTEXT_SEPARATOR, 'some text')) - - def test_contextual_form_py3(self): - _lazy.enable_lazy(False) - with mock.patch.object(six, 'PY3', True): - with mock.patch('gettext.translation') as translation: - trans = mock.Mock() - translation.return_value = trans - trans.ugettext.side_effect = AssertionError( - 'should have called gettext') - trans.gettext.return_value = "some text" - tf = _factory.TranslatorFactory('domain') - tf.contextual_form('context', 'some text') - trans.gettext.assert_called_with( - "%s%s%s" % ('context', CONTEXT_SEPARATOR, 'some text')) - - def test_plural_form_py2(self): - _lazy.enable_lazy(False) - with mock.patch.object(six, 'PY3', False): - with mock.patch('gettext.translation') as translation: - trans = mock.Mock() - translation.return_value = trans - trans.ngettext.side_effect = AssertionError( - 'should have called ungettext') - tf = _factory.TranslatorFactory('domain') - tf.plural_form('single', 'plural', 1) - trans.ungettext.assert_called_with( - 'single', 'plural', 1) - - def test_plural_form_py3(self): - _lazy.enable_lazy(False) - with mock.patch.object(six, 'PY3', True): - with mock.patch('gettext.translation') as translation: - trans = mock.Mock() - translation.return_value = trans - trans.ungettext.side_effect = AssertionError( - 'should have called ngettext') - tf = _factory.TranslatorFactory('domain') - tf.plural_form('single', 'plural', 1) - trans.ngettext.assert_called_with( - 'single', 'plural', 1) diff --git a/oslo_i18n/tests/test_fixture.py b/oslo_i18n/tests/test_fixture.py deleted file mode 100644 index 171feb0..0000000 --- a/oslo_i18n/tests/test_fixture.py +++ /dev/null @@ -1,118 +0,0 @@ -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base as test_base -import six - -import oslo_i18n -from oslo_i18n import _gettextutils -from oslo_i18n._i18n import _ -from oslo_i18n import _lazy -from oslo_i18n import _message -from oslo_i18n import _translate -from oslo_i18n import fixture - - -class TranslationFixtureTest(test_base.BaseTestCase): - - def setUp(self): - super(TranslationFixtureTest, self).setUp() - self.trans_fixture = self.useFixture(fixture.Translation()) - - def test_lazy(self): - msg = self.trans_fixture.lazy('this is a lazy message') - self.assertIsInstance(msg, _message.Message) - self.assertEqual(msg.msgid, 'this is a lazy message') - - def test_immediate(self): - msg = self.trans_fixture.immediate('this is a lazy message') - self.assertNotIsInstance(msg, _message.Message) - self.assertIsInstance(msg, six.text_type) - self.assertEqual(msg, u'this is a lazy message') - - -class ToggleLazyFixtureText(test_base.BaseTestCase): - - def test_on_on(self): - _lazy.USE_LAZY = True - f = fixture.ToggleLazy(True) - f.setUp() - self.assertTrue(_lazy.USE_LAZY) - f._restore_original() - self.assertTrue(_lazy.USE_LAZY) - - def test_on_off(self): - _lazy.USE_LAZY = True - f = fixture.ToggleLazy(False) - f.setUp() - self.assertFalse(_lazy.USE_LAZY) - f._restore_original() - self.assertTrue(_lazy.USE_LAZY) - - def test_off_on(self): - _lazy.USE_LAZY = False - f = fixture.ToggleLazy(True) - f.setUp() - self.assertTrue(_lazy.USE_LAZY) - f._restore_original() - self.assertFalse(_lazy.USE_LAZY) - - def test_off_off(self): - _lazy.USE_LAZY = False - f = fixture.ToggleLazy(False) - f.setUp() - self.assertFalse(_lazy.USE_LAZY) - f._restore_original() - self.assertFalse(_lazy.USE_LAZY) - - -_FAKE_LANG = 'en_ZZ' - - -class PrefixLazyTranslationTest(test_base.BaseTestCase): - - def test_default(self): - - # Turn lazy off to check that fixture turns it on - self.useFixture(fixture.ToggleLazy(False)) - self.useFixture(fixture.PrefixLazyTranslation()) - self.assertTrue(_lazy.USE_LAZY) - default_lang = fixture.PrefixLazyTranslation._DEFAULT_LANG - raw_id1 = 'fake msg1' - expected_msg = 'oslo_i18n/' + default_lang + ': ' + raw_id1 - msg1 = _(raw_id1) # noqa - self.assertEqual([default_lang], - _gettextutils.get_available_languages('oslo_i18n')) - self.assertEqual([default_lang], - oslo_i18n.get_available_languages('oslo_i18n')) - self.assertEqual(expected_msg, _translate.translate(msg1)) - - def test_extra_lang(self): - languages = _gettextutils.get_available_languages('oslo') - languages.append(_FAKE_LANG) - self.useFixture(fixture.PrefixLazyTranslation(languages=languages)) - raw_id1 = 'fake msg1' - expected_msg_en_US = ('oslo_i18n/' + - fixture.PrefixLazyTranslation._DEFAULT_LANG + - ': ' + raw_id1) - expected_msg_en_ZZ = 'oslo_i18n/' + _FAKE_LANG + ': ' + raw_id1 - msg1 = _(raw_id1) # noqa - self.assertEqual(languages, - _gettextutils.get_available_languages('oslo_i18n')) - self.assertEqual(languages, - oslo_i18n.get_available_languages('oslo_i18n')) - self.assertEqual(expected_msg_en_US, _translate.translate(msg1)) - self.assertEqual(expected_msg_en_ZZ, - _translate.translate(msg1, - desired_locale=_FAKE_LANG)) diff --git a/oslo_i18n/tests/test_gettextutils.py b/oslo_i18n/tests/test_gettextutils.py deleted file mode 100644 index a2531b0..0000000 --- a/oslo_i18n/tests/test_gettextutils.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import gettext -import logging - -from babel import localedata -import mock -from oslotest import base as test_base -from oslotest import moxstubout -import six - -from oslo_i18n import _factory -from oslo_i18n import _gettextutils -from oslo_i18n import _lazy -from oslo_i18n import _message - - -LOG = logging.getLogger(__name__) - - -class GettextTest(test_base.BaseTestCase): - - def setUp(self): - super(GettextTest, self).setUp() - moxfixture = self.useFixture(moxstubout.MoxStubout()) - self.stubs = moxfixture.stubs - self.mox = moxfixture.mox - # remember so we can reset to it later in case it changes - self._USE_LAZY = _lazy.USE_LAZY - self.t = _factory.TranslatorFactory('oslo_i18n.test') - - def tearDown(self): - # reset to value before test - _lazy.USE_LAZY = self._USE_LAZY - super(GettextTest, self).tearDown() - - def test_gettext_does_not_blow_up(self): - LOG.info(self.t.primary('test')) - - def test__gettextutils_install(self): - _gettextutils.install('blaa') - _lazy.enable_lazy(False) - self.assertTrue(isinstance(self.t.primary('A String'), - six.text_type)) - - _gettextutils.install('blaa') - _lazy.enable_lazy(True) - self.assertTrue(isinstance(self.t.primary('A Message'), - _message.Message)) - - def test_gettext_install_looks_up_localedir(self): - with mock.patch('os.environ.get') as environ_get: - with mock.patch('gettext.install'): - environ_get.return_value = '/foo/bar' - _gettextutils.install('blaa') - environ_get.assert_has_calls([mock.call('BLAA_LOCALEDIR')]) - - def test_gettext_install_updates_builtins(self): - with mock.patch('os.environ.get') as environ_get: - with mock.patch('gettext.install'): - environ_get.return_value = '/foo/bar' - if '_' in six.moves.builtins.__dict__: - del six.moves.builtins.__dict__['_'] - _gettextutils.install('blaa') - self.assertIn('_', six.moves.builtins.__dict__) - - def test_get_available_languages(self): - # All the available languages for which locale data is available - def _mock_locale_identifiers(): - # 'zh', 'zh_Hant'. 'zh_Hant_HK', 'fil' all have aliases - # missing from babel but we add them in _gettextutils, we - # test that here too - return ['zh', 'es', 'nl', 'fr', 'zh_Hant', 'zh_Hant_HK', 'fil'] - - self.stubs.Set(localedata, - 'list' if hasattr(localedata, 'list') - else 'locale_identifiers', - _mock_locale_identifiers) - - # Only the languages available for a specific translation domain - def _mock_gettext_find(domain, localedir=None, languages=None, all=0): - languages = languages or [] - if domain == 'domain_1': - return 'translation-file' if any(x in ['zh', 'es', 'fil'] - for x in languages) else None - elif domain == 'domain_2': - return 'translation-file' if any(x in ['fr', 'zh_Hant'] - for x in languages) else None - return None - self.stubs.Set(gettext, 'find', _mock_gettext_find) - - # Ensure that no domains are cached - _gettextutils._AVAILABLE_LANGUAGES = {} - - # en_US should always be available no matter the domain - # and it should also always be the first element since order matters - domain_1_languages = _gettextutils.get_available_languages('domain_1') - domain_2_languages = _gettextutils.get_available_languages('domain_2') - self.assertEqual('en_US', domain_1_languages[0]) - self.assertEqual('en_US', domain_2_languages[0]) - # The domain languages should be included after en_US with - # with their respective aliases when it applies - self.assertEqual(6, len(domain_1_languages)) - self.assertIn('zh', domain_1_languages) - self.assertIn('zh_CN', domain_1_languages) - self.assertIn('es', domain_1_languages) - self.assertIn('fil', domain_1_languages) - self.assertIn('tl_PH', domain_1_languages) - self.assertEqual(4, len(domain_2_languages)) - self.assertIn('fr', domain_2_languages) - self.assertIn('zh_Hant', domain_2_languages) - self.assertIn('zh_TW', domain_2_languages) - self.assertEqual(2, len(_gettextutils._AVAILABLE_LANGUAGES)) - # Now test an unknown domain, only en_US should be included - unknown_domain_languages = _gettextutils.get_available_languages('huh') - self.assertEqual(1, len(unknown_domain_languages)) - self.assertIn('en_US', unknown_domain_languages) diff --git a/oslo_i18n/tests/test_handler.py b/oslo_i18n/tests/test_handler.py deleted file mode 100644 index b0c678e..0000000 --- a/oslo_i18n/tests/test_handler.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -import mock -from oslotest import base as test_base -import six - -from oslo_i18n import _message -from oslo_i18n import log as i18n_log -from oslo_i18n.tests import fakes - -LOG = logging.getLogger(__name__) - - -class TranslationHandlerTestCase(test_base.BaseTestCase): - - def setUp(self): - super(TranslationHandlerTestCase, self).setUp() - - self.stream = six.StringIO() - self.destination_handler = logging.StreamHandler(self.stream) - self.translation_handler = i18n_log.TranslationHandler('zh_CN') - self.translation_handler.setTarget(self.destination_handler) - - self.logger = logging.getLogger('localehander_logger') - self.logger.setLevel(logging.DEBUG) - self.logger.addHandler(self.translation_handler) - - def test_set_formatter(self): - formatter = 'some formatter' - self.translation_handler.setFormatter(formatter) - self.assertEqual(formatter, self.translation_handler.target.formatter) - - @mock.patch('gettext.translation') - def test_emit_translated_message(self, mock_translation): - log_message = 'A message to be logged' - log_message_translation = 'A message to be logged in Chinese' - translations = {log_message: log_message_translation} - translations_map = {'zh_CN': translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - msg = _message.Message(log_message) - - self.logger.info(msg) - self.assertIn(log_message_translation, self.stream.getvalue()) - - @mock.patch('gettext.translation') - def test_emit_translated_message_with_args(self, mock_translation): - log_message = 'A message to be logged %s' - log_message_translation = 'A message to be logged in Chinese %s' - log_arg = 'Arg to be logged' - log_arg_translation = 'An arg to be logged in Chinese' - - translations = {log_message: log_message_translation, - log_arg: log_arg_translation} - translations_map = {'zh_CN': translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - msg = _message.Message(log_message) - arg = _message.Message(log_arg) - - self.logger.info(msg, arg) - self.assertIn(log_message_translation % log_arg_translation, - self.stream.getvalue()) - - @mock.patch('gettext.translation') - def test_emit_translated_message_with_named_args(self, mock_translation): - log_message = 'A message to be logged %(arg1)s $(arg2)s' - log_message_translation = 'Chinese msg to be logged %(arg1)s $(arg2)s' - log_arg_1 = 'Arg1 to be logged' - log_arg_1_translation = 'Arg1 to be logged in Chinese' - log_arg_2 = 'Arg2 to be logged' - log_arg_2_translation = 'Arg2 to be logged in Chinese' - - translations = {log_message: log_message_translation, - log_arg_1: log_arg_1_translation, - log_arg_2: log_arg_2_translation} - translations_map = {'zh_CN': translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - msg = _message.Message(log_message) - arg_1 = _message.Message(log_arg_1) - arg_2 = _message.Message(log_arg_2) - - self.logger.info(msg, {'arg1': arg_1, 'arg2': arg_2}) - translation = log_message_translation % {'arg1': log_arg_1_translation, - 'arg2': log_arg_2_translation} - self.assertIn(translation, self.stream.getvalue()) diff --git a/oslo_i18n/tests/test_lazy.py b/oslo_i18n/tests/test_lazy.py deleted file mode 100644 index 049d51a..0000000 --- a/oslo_i18n/tests/test_lazy.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base as test_base - -from oslo_i18n import _lazy - - -class LazyTest(test_base.BaseTestCase): - - def setUp(self): - super(LazyTest, self).setUp() - self._USE_LAZY = _lazy.USE_LAZY - - def tearDown(self): - _lazy.USE_LAZY = self._USE_LAZY - super(LazyTest, self).tearDown() - - def test_enable_lazy(self): - _lazy.USE_LAZY = False - _lazy.enable_lazy() - self.assertTrue(_lazy.USE_LAZY) - - def test_disable_lazy(self): - _lazy.USE_LAZY = True - _lazy.enable_lazy(False) - self.assertFalse(_lazy.USE_LAZY) diff --git a/oslo_i18n/tests/test_locale_dir_variable.py b/oslo_i18n/tests/test_locale_dir_variable.py deleted file mode 100644 index 26321c1..0000000 --- a/oslo_i18n/tests/test_locale_dir_variable.py +++ /dev/null @@ -1,32 +0,0 @@ -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base as test_base -import testscenarios.testcase - -from oslo_i18n import _locale - - -class LocaleDirVariableTest(testscenarios.testcase.WithScenarios, - test_base.BaseTestCase): - - scenarios = [ - ('simple', {'domain': 'simple', 'expected': 'SIMPLE_LOCALEDIR'}), - ('with_dot', {'domain': 'one.two', 'expected': 'ONE_TWO_LOCALEDIR'}), - ('with_dash', {'domain': 'one-two', 'expected': 'ONE_TWO_LOCALEDIR'}), - ] - - def test_make_variable_name(self): - var = _locale.get_locale_dir_variable_name(self.domain) - self.assertEqual(self.expected, var) diff --git a/oslo_i18n/tests/test_logging.py b/oslo_i18n/tests/test_logging.py deleted file mode 100644 index 07e5c71..0000000 --- a/oslo_i18n/tests/test_logging.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from oslotest import base as test_base - -from oslo_i18n import _factory - - -class LogLevelTranslationsTest(test_base.BaseTestCase): - - def test_info(self): - self._test('info') - - def test_warning(self): - self._test('warning') - - def test_error(self): - self._test('error') - - def test_critical(self): - self._test('critical') - - def _test(self, level): - with mock.patch.object(_factory.TranslatorFactory, - '_make_translation_func') as mtf: - tf = _factory.TranslatorFactory('domain') - getattr(tf, 'log_%s' % level) - mtf.assert_called_with('domain-log-%s' % level) diff --git a/oslo_i18n/tests/test_message.py b/oslo_i18n/tests/test_message.py deleted file mode 100644 index ba7851f..0000000 --- a/oslo_i18n/tests/test_message.py +++ /dev/null @@ -1,687 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import unicode_literals - -import logging -import warnings - -import mock -from oslotest import base as test_base -import six -import testtools - -from oslo_i18n import _message -from oslo_i18n.tests import fakes -from oslo_i18n.tests import utils - -LOG = logging.getLogger(__name__) - - -class MessageTestCase(test_base.BaseTestCase): - """Unit tests for locale Message class.""" - - def test_message_id_and_message_text(self): - message = _message.Message('1') - self.assertEqual('1', message.msgid) - self.assertEqual('1', message) - message = _message.Message('1', msgtext='A') - self.assertEqual('1', message.msgid) - self.assertEqual('A', message) - - def test_message_is_unicode(self): - message = _message.Message('some %s') % 'message' - self.assertIsInstance(message, six.text_type) - - @mock.patch('locale.getdefaultlocale') - @mock.patch('gettext.translation') - def test_create_message_non_english_default_locale(self, - mock_translation, - mock_getdefaultlocale): - msgid = 'A message in English' - es_translation = 'A message in Spanish' - - es_translations = {msgid: es_translation} - translations_map = {'es': es_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - mock_getdefaultlocale.return_value = ('es',) - - message = _message.Message(msgid) - - # The base representation of the message is in Spanish, as well as - # the default translation, since the default locale was Spanish. - self.assertEqual(es_translation, message) - self.assertEqual(es_translation, message.translate()) - - def test_translate_returns_unicode(self): - message = _message.Message('some %s') % 'message' - self.assertIsInstance(message.translate(), six.text_type) - - def test_mod_with_named_parameters(self): - msgid = ("%(description)s\nCommand: %(cmd)s\n" - "Exit code: %(exit_code)s\nStdout: %(stdout)r\n" - "Stderr: %(stderr)r %%(something)s") - params = {'description': 'test1', - 'cmd': 'test2', - 'exit_code': 'test3', - 'stdout': 'test4', - 'stderr': 'test5', - 'something': 'trimmed'} - - result = _message.Message(msgid) % params - - expected = msgid % params - self.assertEqual(result, expected) - self.assertEqual(result.translate(), expected) - - def test_multiple_mod_with_named_parameter(self): - msgid = ("%(description)s\nCommand: %(cmd)s\n" - "Exit code: %(exit_code)s\nStdout: %(stdout)r\n" - "Stderr: %(stderr)r") - params = {'description': 'test1', - 'cmd': 'test2', - 'exit_code': 'test3', - 'stdout': 'test4', - 'stderr': 'test5'} - - # Run string interpolation the first time to make a new Message - first = _message.Message(msgid) % params - - # Run string interpolation on the new Message, to replicate - # one of the error paths with some Exception classes we've - # implemented in OpenStack. We should receive a second Message - # object, but the translation results should be the same. - # - # The production code that triggers this problem does something - # like: - # - # msg = _('there was a problem %(name)s') % {'name': 'some value'} - # LOG.error(msg) - # raise BadExceptionClass(msg) - # - # where BadExceptionClass does something like: - # - # class BadExceptionClass(Exception): - # def __init__(self, msg, **kwds): - # super(BadExceptionClass, self).__init__(msg % kwds) - # - expected = first % {} - - # Base message id should be the same - self.assertEqual(first.msgid, expected.msgid) - - # Preserved arguments should be the same - self.assertEqual(first.params, expected.params) - - # Should have different objects - self.assertIsNot(expected, first) - - # Final translations should be the same - self.assertEqual(expected.translate(), first.translate()) - - def test_mod_with_named_parameters_no_space(self): - msgid = ("Request: %(method)s http://%(server)s:" - "%(port)s%(url)s with headers %(headers)s") - params = {'method': 'POST', - 'server': 'test1', - 'port': 1234, - 'url': 'test2', - 'headers': {'h1': 'val1'}} - - result = _message.Message(msgid) % params - - expected = msgid % params - self.assertEqual(result, expected) - self.assertEqual(result.translate(), expected) - - def test_mod_with_dict_parameter(self): - msgid = "Test that we can inject a dictionary %s" - params = {'description': 'test1'} - - result = _message.Message(msgid) % params - - expected = msgid % params - self.assertEqual(expected, result) - self.assertEqual(expected, result.translate()) - - def test_mod_with_wrong_field_type_in_trans(self): - msgid = "Correct type %(arg1)s" - params = {'arg1': 'test1'} - with mock.patch('gettext.translation') as trans: - # Set up ugettext to return the original message with the - # correct format string. - trans.return_value.ugettext.return_value = msgid - # Build a message and give it some parameters. - result = _message.Message(msgid) % params - # Now set up ugettext to return the translated version of - # the original message, with a bad format string. - wrong_type = u'Wrong type %(arg1)d' - if six.PY3: - trans.return_value.gettext.return_value = wrong_type - else: - trans.return_value.ugettext.return_value = wrong_type - trans_result = result.translate() - expected = msgid % params - self.assertEqual(expected, trans_result) - - def test_mod_with_wrong_field_type(self): - msgid = "Test that we handle unused args %(arg1)d" - params = {'arg1': 'test1'} - - with testtools.ExpectedException(TypeError): - _message.Message(msgid) % params - - def test_mod_with_missing_arg(self): - msgid = "Test that we handle missing args %(arg1)s %(arg2)s" - params = {'arg1': 'test1'} - - with testtools.ExpectedException(KeyError, '.*arg2.*'): - _message.Message(msgid) % params - - def test_mod_with_integer_parameters(self): - msgid = "Some string with params: %d" - params = [0, 1, 10, 24124] - - messages = [] - results = [] - for param in params: - messages.append(msgid % param) - results.append(_message.Message(msgid) % param) - - for message, result in zip(messages, results): - self.assertEqual(type(result), _message.Message) - self.assertEqual(result.translate(), message) - - # simulate writing out as string - result_str = '%s' % result.translate() - self.assertEqual(result_str, message) - self.assertEqual(result, message) - - def test_mod_copies_parameters(self): - msgid = "Found object: %(current_value)s" - changing_dict = {'current_value': 1} - # A message created with some params - result = _message.Message(msgid) % changing_dict - # The parameters may change - changing_dict['current_value'] = 2 - # Even if the param changes when the message is - # translated it should use the original param - self.assertEqual(result.translate(), 'Found object: 1') - - def test_mod_deep_copies_parameters(self): - msgid = "Found list: %(current_list)s" - changing_list = list([1, 2, 3]) - params = {'current_list': changing_list} - # Apply the params - result = _message.Message(msgid) % params - # Change the list - changing_list.append(4) - # Even though the list changed the message - # translation should use the original list - self.assertEqual(result.translate(), "Found list: [1, 2, 3]") - - def test_mod_deep_copies_param_nodeep_param(self): - msgid = "Value: %s" - params = utils.NoDeepCopyObject(5) - # Apply the params - result = _message.Message(msgid) % params - self.assertEqual(result.translate(), "Value: 5") - - def test_mod_deep_copies_param_nodeep_dict(self): - msgid = "Values: %(val1)s %(val2)s" - params = {'val1': 1, 'val2': utils.NoDeepCopyObject(2)} - # Apply the params - result = _message.Message(msgid) % params - self.assertEqual(result.translate(), "Values: 1 2") - - # Apply again to make sure other path works as well - params = {'val1': 3, 'val2': utils.NoDeepCopyObject(4)} - result = _message.Message(msgid) % params - self.assertEqual(result.translate(), "Values: 3 4") - - def test_mod_returns_a_copy(self): - msgid = "Some msgid string: %(test1)s %(test2)s" - message = _message.Message(msgid) - m1 = message % {'test1': 'foo', 'test2': 'bar'} - m2 = message % {'test1': 'foo2', 'test2': 'bar2'} - - self.assertIsNot(message, m1) - self.assertIsNot(message, m2) - self.assertEqual(m1.translate(), - msgid % {'test1': 'foo', 'test2': 'bar'}) - self.assertEqual(m2.translate(), - msgid % {'test1': 'foo2', 'test2': 'bar2'}) - - def test_mod_with_none_parameter(self): - msgid = "Some string with params: %s" - message = _message.Message(msgid) % None - self.assertEqual(msgid % None, message) - self.assertEqual(msgid % None, message.translate()) - - def test_mod_with_missing_parameters(self): - msgid = "Some string with params: %s %s" - test_me = lambda: _message.Message(msgid) % 'just one' - # Just like with strings missing parameters raise TypeError - self.assertRaises(TypeError, test_me) - - def test_mod_with_extra_parameters(self): - msgid = "Some string with params: %(param1)s %(param2)s" - params = {'param1': 'test', - 'param2': 'test2', - 'param3': 'notinstring'} - - result = _message.Message(msgid) % params - - expected = msgid % params - self.assertEqual(result, expected) - self.assertEqual(result.translate(), expected) - - # Make sure unused params still there - self.assertEqual(result.params.keys(), params.keys()) - - def test_add_disabled(self): - msgid = "A message" - test_me = lambda: _message.Message(msgid) + ' some string' - self.assertRaises(TypeError, test_me) - - def test_radd_disabled(self): - msgid = "A message" - test_me = lambda: utils.SomeObject('test') + _message.Message(msgid) - self.assertRaises(TypeError, test_me) - - @mock.patch('gettext.translation') - def test_translate(self, mock_translation): - en_message = 'A message in the default locale' - es_translation = 'A message in Spanish' - message = _message.Message(en_message) - - es_translations = {en_message: es_translation} - translations_map = {'es': es_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - self.assertEqual(es_translation, message.translate('es')) - - @mock.patch('gettext.translation') - def test_translate_message_from_unicoded_object(self, mock_translation): - en_message = 'A message in the default locale' - es_translation = 'A message in Spanish' - message = _message.Message(en_message) - es_translations = {en_message: es_translation} - translations_map = {'es': es_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - # Here we are not testing the Message object directly but the result - # of unicoding() an object whose unicode representation is a Message - obj = utils.SomeObject(message) - unicoded_obj = six.text_type(obj) - - self.assertEqual(es_translation, unicoded_obj.translate('es')) - - @mock.patch('gettext.translation') - def test_translate_multiple_languages(self, mock_translation): - en_message = 'A message in the default locale' - es_translation = 'A message in Spanish' - zh_translation = 'A message in Chinese' - message = _message.Message(en_message) - - es_translations = {en_message: es_translation} - zh_translations = {en_message: zh_translation} - translations_map = {'es': es_translations, - 'zh': zh_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - self.assertEqual(es_translation, message.translate('es')) - self.assertEqual(zh_translation, message.translate('zh')) - self.assertEqual(en_message, message.translate(None)) - self.assertEqual(en_message, message.translate('en')) - self.assertEqual(en_message, message.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_param(self, mock_translation): - message_with_params = 'A message: %s' - es_translation = 'A message in Spanish: %s' - param = 'A Message param' - - translations = {message_with_params: es_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - msg = msg % param - - default_translation = message_with_params % param - expected_translation = es_translation % param - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('gettext.translation') - @mock.patch('oslo_i18n._message.LOG') - def test_translate_message_bad_translation(self, - mock_log, - mock_translation): - message_with_params = 'A message: %s' - es_translation = 'A message in Spanish: %s %s' - param = 'A Message param' - - translations = {message_with_params: es_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - msg = _message.Message(message_with_params) - msg = msg % param - default_translation = message_with_params % param - - self.assertEqual(default_translation, msg.translate('es')) - - self.assertEqual(1, len(w)) - # Note(gibi): in python 3.4 str.__repr__ does not put the unicode - # marker 'u' in front of the string representations so the test - # removes that to have the same result in python 2.7 and 3.4 - self.assertEqual("Failed to insert replacement values into " - "translated message A message in Spanish: %s %s " - "(Original: 'A message: %s'): " - "not enough arguments for format string", - str(w[0].message).replace("u'", "'")) - - mock_log.debug.assert_called_with(('Failed to insert replacement ' - 'values into translated message ' - '%s (Original: %r): %s'), - es_translation, - message_with_params, - mock.ANY) - - @mock.patch('gettext.translation') - @mock.patch('locale.getdefaultlocale', return_value=('es', '')) - @mock.patch('oslo_i18n._message.LOG') - def test_translate_message_bad_default_translation(self, - mock_log, - mock_local, - mock_translation): - message_with_params = 'A message: %s' - es_translation = 'A message in Spanish: %s %s' - param = 'A Message param' - - translations = {message_with_params: es_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - msg = msg % param - self.assertEqual(1, len(w)) - # Note(gibi): in python 3.4 str.__repr__ does not put the unicode - # marker 'u' in front of the string representations so the test - # removes that to have the same result in python 2.7 and 3.4 - self.assertEqual("Failed to insert replacement values into " - "translated message A message in Spanish: %s %s " - "(Original: 'A message: %s'): " - "not enough arguments for format string", - str(w[0].message).replace("u'", "'")) - - mock_log.debug.assert_called_with(('Failed to insert replacement ' - 'values into translated message ' - '%s (Original: %r): %s'), - es_translation, - message_with_params, - mock.ANY) - mock_log.reset_mock() - - default_translation = message_with_params % param - self.assertEqual(default_translation, msg) - self.assertFalse(mock_log.warning.called) - - @mock.patch('gettext.translation') - def test_translate_message_with_object_param(self, mock_translation): - message_with_params = 'A message: %s' - es_translation = 'A message in Spanish: %s' - param = 'A Message param' - param_translation = 'A Message param in Spanish' - - translations = {message_with_params: es_translation, - param: param_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - param_msg = _message.Message(param) - - # Here we are testing translation of a Message with another object - # that can be translated via its unicode() representation, this is - # very common for instance when modding an Exception with a Message - obj = utils.SomeObject(param_msg) - msg = msg % obj - - default_translation = message_with_params % param - expected_translation = es_translation % param_translation - - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_param_from_unicoded_obj(self, - mock_translation): - message_with_params = 'A message: %s' - es_translation = 'A message in Spanish: %s' - param = 'A Message param' - - translations = {message_with_params: es_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - msg = msg % param - - default_translation = message_with_params % param - expected_translation = es_translation % param - - obj = utils.SomeObject(msg) - unicoded_obj = six.text_type(obj) - - self.assertEqual(expected_translation, unicoded_obj.translate('es')) - self.assertEqual(default_translation, unicoded_obj.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_message_parameter(self, mock_translation): - message_with_params = 'A message with param: %s' - es_translation = 'A message with param in Spanish: %s' - message_param = 'A message param' - es_param_translation = 'A message param in Spanish' - - translations = {message_with_params: es_translation, - message_param: es_param_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - msg_param = _message.Message(message_param) - msg = msg % msg_param - - default_translation = message_with_params % message_param - expected_translation = es_translation % es_param_translation - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_message_parameters(self, mock_translation): - message_with_params = 'A message with params: %s %s' - es_translation = 'A message with params in Spanish: %s %s' - message_param = 'A message param' - es_param_translation = 'A message param in Spanish' - another_message_param = 'Another message param' - another_es_param_translation = 'Another message param in Spanish' - - translations = {message_with_params: es_translation, - message_param: es_param_translation, - another_message_param: another_es_param_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - param_1 = _message.Message(message_param) - param_2 = _message.Message(another_message_param) - msg = msg % (param_1, param_2) - - default_translation = message_with_params % (message_param, - another_message_param) - expected_translation = es_translation % (es_param_translation, - another_es_param_translation) - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_named_parameters(self, mock_translation): - message_with_params = 'A message with params: %(param)s' - es_translation = 'A message with params in Spanish: %(param)s' - message_param = 'A Message param' - es_param_translation = 'A message param in Spanish' - - translations = {message_with_params: es_translation, - message_param: es_param_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - msg_param = _message.Message(message_param) - msg = msg % {'param': msg_param} - - default_translation = message_with_params % {'param': message_param} - expected_translation = es_translation % {'param': es_param_translation} - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('locale.getdefaultlocale') - @mock.patch('gettext.translation') - def test_translate_message_non_default_locale(self, - mock_translation, - mock_getdefaultlocale): - message_with_params = 'A message with params: %(param)s' - es_translation = 'A message with params in Spanish: %(param)s' - zh_translation = 'A message with params in Chinese: %(param)s' - fr_translation = 'A message with params in French: %(param)s' - - message_param = 'A Message param' - es_param_translation = 'A message param in Spanish' - zh_param_translation = 'A message param in Chinese' - fr_param_translation = 'A message param in French' - - es_translations = {message_with_params: es_translation, - message_param: es_param_translation} - zh_translations = {message_with_params: zh_translation, - message_param: zh_param_translation} - fr_translations = {message_with_params: fr_translation, - message_param: fr_param_translation} - - translator = fakes.FakeTranslations.translator({'es': es_translations, - 'zh': zh_translations, - 'fr': fr_translations}) - mock_translation.side_effect = translator - mock_getdefaultlocale.return_value = ('es',) - - msg = _message.Message(message_with_params) - msg_param = _message.Message(message_param) - msg = msg % {'param': msg_param} - - es_translation = es_translation % {'param': es_param_translation} - zh_translation = zh_translation % {'param': zh_param_translation} - fr_translation = fr_translation % {'param': fr_param_translation} - - # Because sys.getdefaultlocale() was Spanish, - # the default translation will be to Spanish - self.assertEqual(es_translation, msg) - self.assertEqual(es_translation, msg.translate()) - self.assertEqual(es_translation, msg.translate('es')) - - # Translation into other locales still works - self.assertEqual(zh_translation, msg.translate('zh')) - self.assertEqual(fr_translation, msg.translate('fr')) - - -class TranslateMsgidTest(test_base.BaseTestCase): - - @mock.patch('gettext.translation') - def test_contextual(self, translation): - lang = mock.Mock() - translation.return_value = lang - trans = mock.Mock() - trans.return_value = 'translated' - lang.gettext = trans - lang.ugettext = trans - result = _message.Message._translate_msgid( - ('context', 'message'), - domain='domain', - has_contextual_form=True, - has_plural_form=False, - ) - self.assertEqual('translated', result) - trans.assert_called_with( - 'context' + _message.CONTEXT_SEPARATOR + 'message' - ) - - @mock.patch('gettext.translation') - def test_contextual_untranslatable(self, translation): - msg_with_context = 'context' + _message.CONTEXT_SEPARATOR + 'message' - lang = mock.Mock() - translation.return_value = lang - trans = mock.Mock() - trans.return_value = msg_with_context - lang.gettext = trans - lang.ugettext = trans - result = _message.Message._translate_msgid( - ('context', 'message'), - domain='domain', - has_contextual_form=True, - has_plural_form=False, - ) - self.assertEqual('message', result) - trans.assert_called_with(msg_with_context) - - @mock.patch('gettext.translation') - def test_plural(self, translation): - lang = mock.Mock() - translation.return_value = lang - trans = mock.Mock() - trans.return_value = 'translated' - lang.ngettext = trans - lang.ungettext = trans - result = _message.Message._translate_msgid( - ('single', 'plural', -1), - domain='domain', - has_contextual_form=False, - has_plural_form=True, - ) - self.assertEqual('translated', result) - trans.assert_called_with( - 'single', 'plural', -1, - ) - - @mock.patch('gettext.translation') - def test_contextual_and_plural(self, translation): - self.assertRaises( - ValueError, - _message.Message._translate_msgid, - 'nothing', - domain='domain', - has_contextual_form=True, - has_plural_form=True, - ) diff --git a/oslo_i18n/tests/test_public_api.py b/oslo_i18n/tests/test_public_api.py deleted file mode 100644 index d419105..0000000 --- a/oslo_i18n/tests/test_public_api.py +++ /dev/null @@ -1,44 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""A few tests that use the public API to ensure the imports work. -""" - -import unittest - -import mock - -import oslo_i18n -from oslo_i18n import _lazy - - -class PublicAPITest(unittest.TestCase): - - def test_create_factory(self): - oslo_i18n.TranslatorFactory('domain') - - def test_install(self): - with mock.patch('six.moves.builtins'): - oslo_i18n.install('domain') - - def test_get_available_languages(self): - oslo_i18n.get_available_languages('domains') - - def test_toggle_lazy(self): - original = _lazy.USE_LAZY - try: - oslo_i18n.enable_lazy(True) - oslo_i18n.enable_lazy(False) - finally: - oslo_i18n.enable_lazy(original) - - def test_translate(self): - oslo_i18n.translate(u'string') diff --git a/oslo_i18n/tests/test_translate.py b/oslo_i18n/tests/test_translate.py deleted file mode 100644 index 335b28c..0000000 --- a/oslo_i18n/tests/test_translate.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import unicode_literals - -import mock -from oslotest import base as test_base - -from oslo_i18n import _message -from oslo_i18n import _translate -from oslo_i18n.tests import fakes -from oslo_i18n.tests import utils - - -class TranslateTest(test_base.BaseTestCase): - - @mock.patch('gettext.translation') - def test_translate(self, mock_translation): - en_message = 'A message in the default locale' - es_translation = 'A message in Spanish' - message = _message.Message(en_message) - - es_translations = {en_message: es_translation} - translations_map = {'es': es_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - # translate() works on msgs and on objects whose unicode reps are msgs - obj = utils.SomeObject(message) - self.assertEqual(es_translation, _translate.translate(message, 'es')) - self.assertEqual(es_translation, _translate.translate(obj, 'es')) diff --git a/oslo_i18n/tests/utils.py b/oslo_i18n/tests/utils.py deleted file mode 100644 index a6ad6c3..0000000 --- a/oslo_i18n/tests/utils.py +++ /dev/null @@ -1,42 +0,0 @@ -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - - -class SomeObject(object): - - def __init__(self, message): - self.message = message - - def __unicode__(self): - return self.message - # alias for Python 3 - __str__ = __unicode__ - - -class NoDeepCopyObject(object): - - def __init__(self, value): - self.value = value - - if six.PY3: - def __str__(self): - return str(self.value) - else: - def __unicode__(self): - return unicode(self.value) - - def __deepcopy__(self, memo): - raise TypeError('Deep Copy not supported') diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 8340453..0000000 --- a/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -pbr>=1.6 # Apache-2.0 -Babel>=2.3.4 # BSD -six>=1.9.0 # MIT diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index eacf7c9..0000000 --- a/setup.cfg +++ /dev/null @@ -1,51 +0,0 @@ -[metadata] -name = oslo.i18n -summary = Oslo i18n library -description-file = - README.rst -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = http://wiki.openstack.org/wiki/Oslo#oslo.i18n -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - -[files] -packages = - oslo_i18n - -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 - -[upload_sphinx] -upload-dir = doc/build/html - -[compile_catalog] -directory = oslo_i18n/locale -domain = oslo_i18n - -[update_catalog] -domain = oslo_i18n -output_dir = oslo_i18n/locale -input_file = oslo_i18n/locale/oslo_i18n.pot - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext _C:1c,2 _P:1,2 -mapping_file = babel.cfg -output_file = oslo_i18n/locale/oslo_i18n.pot - -[pbr] -warnerrors = True - -[wheel] -universal = 1 diff --git a/setup.py b/setup.py deleted file mode 100644 index 782bb21..0000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=1.8'], - pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 80bdbbb..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,15 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -hacking<0.11,>=0.10.0 - - -sphinx!=1.3b1,<1.3,>=1.2.1 # BSD -oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 - -mock>=2.0 # BSD -oslotest>=1.10.0 # Apache-2.0 -coverage>=3.6 # Apache-2.0 - -# for pre-release tests -oslo.config>=3.12.0 # Apache-2.0 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index b4c7c32..0000000 --- a/tox.ini +++ /dev/null @@ -1,38 +0,0 @@ -[tox] -minversion = 1.6 -envlist = py34,py27,pep8 - -[testenv] -deps = -r{toxinidir}/test-requirements.txt -commands = python setup.py testr --slowest --testr-args='{posargs}' - -[testenv:pep8] -commands = flake8 - -[testenv:venv] -commands = {posargs} - -[testenv:docs] -commands = python setup.py build_sphinx - -[testenv:cover] -commands = python setup.py test --coverage --coverage-package-name=oslo_i18n --testr-args='{posargs}' - -[flake8] -# E123, E125 skipped as they are invalid PEP-8. - -show-source = True -ignore = E123,E125 -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,__init__.py - -[hacking] -import_exceptions = - oslo_i18n._i18n._ - -[testenv:pip-missing-reqs] -# do not install test-requirements as that will pollute the virtualenv for -# determining missing packages -# this also means that pip-missing-reqs must be installed separately, outside -# of the requirements.txt files -deps = pip_missing_reqs -commands = pip-missing-reqs -d --ignore-module=oslo_i18n* --ignore-file=oslo_i18n/tests/* --ignore-file=tests/ oslo_i18n