Internationalization (i18n) - Enable French locale

Our project should now enable its internationalization.
This patchset add the french locale to the project but also
refactors the codebase to following the oslo_i18n recommendations.

DocImpact
Implements: blueprint support-translation

Change-Id: I0e4fbf05d16afb5e25bac78438c640f147c754b1
This commit is contained in:
Vincent Françoise 2015-12-11 18:02:19 +01:00
parent 7c72d6f912
commit bd29e2e79f
18 changed files with 614 additions and 54 deletions

View File

@ -52,3 +52,6 @@ commands =
[testenv:wheel]
commands = python setup.py bdist_wheel
[hacking]
import_exceptions = watcher._i18n

View File

@ -16,11 +16,31 @@
#
import oslo_i18n
_translators = oslo_i18n.TranslatorFactory(domain='watcher')
oslo_i18n.enable_lazy()
# The domain is the name of the App which is used to generate the folder
# containing the translation files (i.e. the .pot file and the various locales)
DOMAIN = "watcher"
_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"
_C = _translators.contextual_form
# The plural translation function using the name "_P"
_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)

View File

@ -21,8 +21,8 @@ import six
import wsme
from wsme import types as wtypes
from watcher._i18n import _
from watcher.common import exception
from watcher.common.i18n import _
from watcher.common import utils

View File

@ -17,7 +17,7 @@ import jsonpatch
from oslo_config import cfg
import wsme
from watcher.common.i18n import _
from watcher._i18n import _
CONF = cfg.CONF

View File

@ -19,8 +19,8 @@ from oslo_log import log
from keystonemiddleware import auth_token
from watcher._i18n import _
from watcher.common import exception
from watcher.common.i18n import _
from watcher.common import utils
LOG = log.getLogger(__name__)

View File

@ -27,8 +27,8 @@ from oslo_log import log
import six
import webob
from watcher.common.i18n import _
from watcher.common.i18n import _LE
from watcher._i18n import _
from watcher._i18n import _LE
LOG = log.getLogger(__name__)

View File

@ -24,8 +24,8 @@ from wsgiref import simple_server
from oslo_config import cfg
from oslo_log import log as logging
from watcher._i18n import _
from watcher.api import app as api_app
from watcher.common.i18n import _
from watcher import service

View File

@ -24,13 +24,13 @@ import sys
from oslo_config import cfg
from oslo_log import log as logging
from watcher import _i18n
from watcher.applier.manager import ApplierManager
from watcher.common import service
from watcher import i18n
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
_LI = i18n._LI
_LI = _i18n._LI
def main():

View File

@ -23,15 +23,15 @@ import sys
from oslo_config import cfg
from oslo_log import log as logging
from watcher import _i18n
from watcher.common import service
from watcher.decision_engine.manager import DecisionEngineManager
from watcher import i18n
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
_LI = i18n._LI
_LI = _i18n._LI
def main():

View File

@ -27,8 +27,8 @@ from oslo_log import log as logging
import six
from watcher.common.i18n import _
from watcher.common.i18n import _LE
from watcher._i18n import _
from watcher._i18n import _LE
LOG = logging.getLogger(__name__)

View File

@ -24,10 +24,10 @@ import oslo_messaging as messaging
from oslo_service import service
from oslo_utils import importutils
from watcher._i18n import _LE
from watcher._i18n import _LI
from watcher.common import config
from watcher.common import context
from watcher.common.i18n import _LE
from watcher.common.i18n import _LI
from watcher.common import rpc
from watcher.objects import base as objects_base

View File

@ -24,7 +24,7 @@ import six
import uuid
from watcher.common.i18n import _LW
from watcher._i18n import _LW
UTILS_OPTS = [
cfg.StrOpt('rootwrap_config',

View File

@ -25,16 +25,16 @@ from oslo_log import log
from sqlalchemy.orm.exc import MultipleResultsFound
from sqlalchemy.orm.exc import NoResultFound
from watcher import _i18n
from watcher.common import exception
from watcher.common import utils
from watcher.db import api
from watcher.db.sqlalchemy import models
from watcher import i18n
from watcher.objects.audit import AuditStatus
CONF = cfg.CONF
LOG = log.getLogger(__name__)
_ = i18n._
_ = _i18n._
_FACADE = None

View File

@ -1,31 +0,0 @@
# Copyright 2014 Huawei Crop.
# 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 oslo_i18n import * # noqa
_translators = TranslatorFactory(domain='glance')
# The primary translation function using the well-known name "_"
_ = _translators.primary
# 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

View File

@ -0,0 +1,285 @@
# French translations for python-watcher.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the python-watcher
# project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2015.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: python-watcher 0.21.1.dev32\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2015-12-11 15:29+0100\n"
"PO-Revision-Date: 2015-12-11 15:42+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: fr\n"
"Language-Team: fr <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.1.1\n"
#: watcher/api/controllers/v1/types.py:148
#, python-format
msgid "%s is not JSON serializable"
msgstr ""
#: watcher/api/controllers/v1/types.py:184
#, python-format
msgid "Wrong type. Expected '%(type)s', got '%(value)s'"
msgstr ""
#: watcher/api/controllers/v1/types.py:222
#, python-format
msgid "'%s' is an internal attribute and can not be updated"
msgstr ""
#: watcher/api/controllers/v1/types.py:226
#, python-format
msgid "'%s' is a mandatory attribute and can not be removed"
msgstr ""
#: watcher/api/controllers/v1/types.py:231
msgid "'add' and 'replace' operations needs value"
msgstr ""
#: watcher/api/controllers/v1/utils.py:32
msgid "Limit must be positive"
msgstr ""
#: watcher/api/controllers/v1/utils.py:39
#, python-format
msgid "Invalid sort direction: %s. Acceptable values are 'asc' or 'desc'"
msgstr ""
#: watcher/api/controllers/v1/utils.py:49
#, python-format
msgid "Adding a new attribute (%s) to the root of the resource is not allowed"
msgstr ""
#: watcher/api/middleware/auth_token.py:43
#, python-format
msgid "Cannot compile public API routes: %s"
msgstr ""
#: watcher/api/middleware/parsable_error.py:53
#, python-format
msgid "ErrorDocumentMiddleware received an invalid status %s"
msgstr ""
#: watcher/cmd/api.py:45
#, python-format
msgid "Starting server in PID %s"
msgstr ""
#: watcher/cmd/api.py:50
#, python-format
msgid "serving on 0.0.0.0:%(port)s, view at http://127.0.0.1:%(port)s"
msgstr ""
#: watcher/cmd/api.py:54
#, python-format
msgid "serving on http://%(host)s:%(port)s"
msgstr ""
#: watcher/common/exception.py:58
msgid "An unknown exception occurred."
msgstr ""
#: watcher/common/exception.py:109
msgid "Not authorized."
msgstr ""
#: watcher/common/exception.py:114
msgid "Operation not permitted."
msgstr ""
#: watcher/common/exception.py:118
msgid "Unacceptable parameters."
msgstr ""
#: watcher/common/exception.py:123
#, python-format
msgid "The %(name)s %(id)s could not be found."
msgstr ""
#: watcher/common/exception.py:127
msgid "Conflict."
msgstr ""
#: watcher/common/exception.py:132
#, python-format
msgid "The %(name)s resource %(id)s could not be found."
msgstr ""
#: watcher/common/exception.py:137
#, python-format
msgid "Expected an uuid or int but received %(identity)s."
msgstr ""
#: watcher/common/exception.py:141
#, python-format
msgid "Goal %(goal)s is not defined in Watcher configuration file."
msgstr ""
#: watcher/common/exception.py:147
#, python-format
msgid "%(err)s"
msgstr ""
#: watcher/common/exception.py:151
#, python-format
msgid "Expected a uuid but received %(uuid)s."
msgstr ""
#: watcher/common/exception.py:155
#, python-format
msgid "Expected a logical name but received %(name)s."
msgstr ""
#: watcher/common/exception.py:159
#, python-format
msgid "Expected a logical name or uuid but received %(name)s."
msgstr ""
#: watcher/common/exception.py:163
#, python-format
msgid "AuditTemplate %(audit_template)s could not be found."
msgstr ""
#: watcher/common/exception.py:167
#, python-format
msgid "An audit_template with UUID %(uuid)s or name %(name)s already exists."
msgstr ""
#: watcher/common/exception.py:172
#, python-format
msgid "AuditTemplate %(audit_template)s is referenced by one or multiple audit."
msgstr ""
#: watcher/common/exception.py:177
#, python-format
msgid "Audit %(audit)s could not be found."
msgstr ""
#: watcher/common/exception.py:181
#, python-format
msgid "An audit with UUID %(uuid)s already exists."
msgstr ""
#: watcher/common/exception.py:185
#, python-format
msgid "Audit %(audit)s is referenced by one or multiple action plans."
msgstr ""
#: watcher/common/exception.py:190
msgid "ActionPlan %(action plan)s could not be found."
msgstr ""
#: watcher/common/exception.py:194
#, python-format
msgid "An action plan with UUID %(uuid)s already exists."
msgstr ""
#: watcher/common/exception.py:198
#, python-format
msgid "Action Plan %(action_plan)s is referenced by one or multiple actions."
msgstr ""
#: watcher/common/exception.py:203
#, python-format
msgid "Action %(action)s could not be found."
msgstr ""
#: watcher/common/exception.py:207
#, python-format
msgid "An action with UUID %(uuid)s already exists."
msgstr ""
#: watcher/common/exception.py:211
#, python-format
msgid "Action plan %(action_plan)s is referenced by one or multiple goals."
msgstr ""
#: watcher/common/exception.py:216
msgid "Filtering actions on both audit and action-plan is prohibited."
msgstr ""
#: watcher/common/exception.py:225
#, python-format
msgid "Couldn't apply patch '%(patch)s'. Reason: %(reason)s"
msgstr ""
#: watcher/common/exception.py:286
msgid "'Keystone API endpoint is missing''"
msgstr ""
#: watcher/common/exception.py:290
msgid "The list of hypervisor(s) in the cluster is empty.'"
msgstr ""
#: watcher/common/exception.py:294
msgid "The metrics resource collector is not defined.'"
msgstr ""
#: watcher/common/exception.py:298
msgid "the cluster state is not defined"
msgstr ""
#: watcher/common/exception.py:304
msgid "The VM could not be found."
msgstr ""
#: watcher/common/exception.py:308
msgid "The hypervisor could not be found."
msgstr ""
#: watcher/common/exception.py:312
msgid "The Meta-Action could not be found."
msgstr ""
#: watcher/db/sqlalchemy/api.py:278
msgid "Cannot overwrite UUID for an existing AuditTemplate."
msgstr ""
#: watcher/db/sqlalchemy/api.py:387 watcher/db/sqlalchemy/api.py:587
msgid "Cannot overwrite UUID for an existing Audit."
msgstr ""
#: watcher/db/sqlalchemy/api.py:478
msgid "Cannot overwrite UUID for an existing Action."
msgstr ""
#: watcher/objects/base.py:108
msgid "Invalid version string"
msgstr ""
#: watcher/objects/base.py:299
#, python-format
msgid "Cannot load '%(attrname)s' in the base class"
msgstr ""
#: watcher/objects/base.py:308
msgid "Cannot save anything in the base class"
msgstr ""
#: watcher/objects/base.py:340
#, python-format
msgid "%(objname)s object has no attribute '%(attrname)s'"
msgstr ""
#: watcher/objects/base.py:389
#, python-format
msgid "'%(objclass)s' object has no attribute '%(attrname)s'"
msgstr ""
#: watcher/objects/utils.py:40
msgid "A datetime.datetime is required here"
msgstr ""
#: watcher/objects/utils.py:105
#, python-format
msgid "An object of class %s is required here"
msgstr ""

283
watcher/locale/watcher.pot Normal file
View File

@ -0,0 +1,283 @@
# Translations template for python-watcher.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the python-watcher
# project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2015.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: python-watcher 0.21.1.dev32\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2015-12-11 15:29+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.1.1\n"
#: watcher/api/controllers/v1/types.py:148
#, python-format
msgid "%s is not JSON serializable"
msgstr ""
#: watcher/api/controllers/v1/types.py:184
#, python-format
msgid "Wrong type. Expected '%(type)s', got '%(value)s'"
msgstr ""
#: watcher/api/controllers/v1/types.py:222
#, python-format
msgid "'%s' is an internal attribute and can not be updated"
msgstr ""
#: watcher/api/controllers/v1/types.py:226
#, python-format
msgid "'%s' is a mandatory attribute and can not be removed"
msgstr ""
#: watcher/api/controllers/v1/types.py:231
msgid "'add' and 'replace' operations needs value"
msgstr ""
#: watcher/api/controllers/v1/utils.py:32
msgid "Limit must be positive"
msgstr ""
#: watcher/api/controllers/v1/utils.py:39
#, python-format
msgid "Invalid sort direction: %s. Acceptable values are 'asc' or 'desc'"
msgstr ""
#: watcher/api/controllers/v1/utils.py:49
#, python-format
msgid "Adding a new attribute (%s) to the root of the resource is not allowed"
msgstr ""
#: watcher/api/middleware/auth_token.py:43
#, python-format
msgid "Cannot compile public API routes: %s"
msgstr ""
#: watcher/api/middleware/parsable_error.py:53
#, python-format
msgid "ErrorDocumentMiddleware received an invalid status %s"
msgstr ""
#: watcher/cmd/api.py:45
#, python-format
msgid "Starting server in PID %s"
msgstr ""
#: watcher/cmd/api.py:50
#, python-format
msgid "serving on 0.0.0.0:%(port)s, view at http://127.0.0.1:%(port)s"
msgstr ""
#: watcher/cmd/api.py:54
#, python-format
msgid "serving on http://%(host)s:%(port)s"
msgstr ""
#: watcher/common/exception.py:58
msgid "An unknown exception occurred."
msgstr ""
#: watcher/common/exception.py:109
msgid "Not authorized."
msgstr ""
#: watcher/common/exception.py:114
msgid "Operation not permitted."
msgstr ""
#: watcher/common/exception.py:118
msgid "Unacceptable parameters."
msgstr ""
#: watcher/common/exception.py:123
#, python-format
msgid "The %(name)s %(id)s could not be found."
msgstr ""
#: watcher/common/exception.py:127
msgid "Conflict."
msgstr ""
#: watcher/common/exception.py:132
#, python-format
msgid "The %(name)s resource %(id)s could not be found."
msgstr ""
#: watcher/common/exception.py:137
#, python-format
msgid "Expected an uuid or int but received %(identity)s."
msgstr ""
#: watcher/common/exception.py:141
#, python-format
msgid "Goal %(goal)s is not defined in Watcher configuration file."
msgstr ""
#: watcher/common/exception.py:147
#, python-format
msgid "%(err)s"
msgstr ""
#: watcher/common/exception.py:151
#, python-format
msgid "Expected a uuid but received %(uuid)s."
msgstr ""
#: watcher/common/exception.py:155
#, python-format
msgid "Expected a logical name but received %(name)s."
msgstr ""
#: watcher/common/exception.py:159
#, python-format
msgid "Expected a logical name or uuid but received %(name)s."
msgstr ""
#: watcher/common/exception.py:163
#, python-format
msgid "AuditTemplate %(audit_template)s could not be found."
msgstr ""
#: watcher/common/exception.py:167
#, python-format
msgid "An audit_template with UUID %(uuid)s or name %(name)s already exists."
msgstr ""
#: watcher/common/exception.py:172
#, python-format
msgid "AuditTemplate %(audit_template)s is referenced by one or multiple audit."
msgstr ""
#: watcher/common/exception.py:177
#, python-format
msgid "Audit %(audit)s could not be found."
msgstr ""
#: watcher/common/exception.py:181
#, python-format
msgid "An audit with UUID %(uuid)s already exists."
msgstr ""
#: watcher/common/exception.py:185
#, python-format
msgid "Audit %(audit)s is referenced by one or multiple action plans."
msgstr ""
#: watcher/common/exception.py:190
msgid "ActionPlan %(action plan)s could not be found."
msgstr ""
#: watcher/common/exception.py:194
#, python-format
msgid "An action plan with UUID %(uuid)s already exists."
msgstr ""
#: watcher/common/exception.py:198
#, python-format
msgid "Action Plan %(action_plan)s is referenced by one or multiple actions."
msgstr ""
#: watcher/common/exception.py:203
#, python-format
msgid "Action %(action)s could not be found."
msgstr ""
#: watcher/common/exception.py:207
#, python-format
msgid "An action with UUID %(uuid)s already exists."
msgstr ""
#: watcher/common/exception.py:211
#, python-format
msgid "Action plan %(action_plan)s is referenced by one or multiple goals."
msgstr ""
#: watcher/common/exception.py:216
msgid "Filtering actions on both audit and action-plan is prohibited."
msgstr ""
#: watcher/common/exception.py:225
#, python-format
msgid "Couldn't apply patch '%(patch)s'. Reason: %(reason)s"
msgstr ""
#: watcher/common/exception.py:286
msgid "'Keystone API endpoint is missing''"
msgstr ""
#: watcher/common/exception.py:290
msgid "The list of hypervisor(s) in the cluster is empty.'"
msgstr ""
#: watcher/common/exception.py:294
msgid "The metrics resource collector is not defined.'"
msgstr ""
#: watcher/common/exception.py:298
msgid "the cluster state is not defined"
msgstr ""
#: watcher/common/exception.py:304
msgid "The VM could not be found."
msgstr ""
#: watcher/common/exception.py:308
msgid "The hypervisor could not be found."
msgstr ""
#: watcher/common/exception.py:312
msgid "The Meta-Action could not be found."
msgstr ""
#: watcher/db/sqlalchemy/api.py:278
msgid "Cannot overwrite UUID for an existing AuditTemplate."
msgstr ""
#: watcher/db/sqlalchemy/api.py:387 watcher/db/sqlalchemy/api.py:587
msgid "Cannot overwrite UUID for an existing Audit."
msgstr ""
#: watcher/db/sqlalchemy/api.py:478
msgid "Cannot overwrite UUID for an existing Action."
msgstr ""
#: watcher/objects/base.py:108
msgid "Invalid version string"
msgstr ""
#: watcher/objects/base.py:299
#, python-format
msgid "Cannot load '%(attrname)s' in the base class"
msgstr ""
#: watcher/objects/base.py:308
msgid "Cannot save anything in the base class"
msgstr ""
#: watcher/objects/base.py:340
#, python-format
msgid "%(objname)s object has no attribute '%(attrname)s'"
msgstr ""
#: watcher/objects/base.py:389
#, python-format
msgid "'%(objclass)s' object has no attribute '%(attrname)s'"
msgstr ""
#: watcher/objects/utils.py:40
msgid "A datetime.datetime is required here"
msgstr ""
#: watcher/objects/utils.py:105
#, python-format
msgid "An object of class %s is required here"
msgstr ""

View File

@ -22,9 +22,9 @@ import oslo_messaging as messaging
from oslo_utils import versionutils
import six
from watcher._i18n import _
from watcher._i18n import _LE
from watcher.common import exception
from watcher.common.i18n import _
from watcher.common.i18n import _LE
from watcher.objects import utils as obj_utils

View File

@ -22,7 +22,7 @@ import netaddr
from oslo_utils import timeutils
import six
from watcher.common.i18n import _
from watcher._i18n import _
def datetime_or_none(dt):