summaryrefslogtreecommitdiffstats
path: root/openstack/common
diff options
context:
space:
mode:
authorLuis A. Garcia <luis@linux.vnet.ibm.com>2013-07-19 22:18:59 +0000
committerLuis A. Garcia <luis@linux.vnet.ibm.com>2013-07-30 19:40:14 +0000
commit319888102f970b09255025d1b7bd9326c0446fa1 (patch)
tree55ab7af72807887243b51b82182a7db587e17d92 /openstack/common
parentf58c936582a17cffcdcdb5bf624f24d574abaf0a (diff)
downloadoslo-319888102f970b09255025d1b7bd9326c0446fa1.tar.gz
oslo-319888102f970b09255025d1b7bd9326c0446fa1.tar.xz
oslo-319888102f970b09255025d1b7bd9326c0446fa1.zip
Add common methods required to allow translation of REST API responses
REST API responses (particularly errors) are always returned to consumers in the locale of the operating system. This change adds common methods that will be required by other components in the process of translating the API responses to a locale requested by the API consumer. The patch set includes the following changes: 1) An installer for the lazy _() function is provided. Services that want to use the Message class to do delayed translation will just have to set the new 'lazy' flag in the existing gettext.install(). 2) A method to retrieve all available languages in a given translation domain in order to pick one that will be used to translate the response to the user. 3) A utility method to translate a Message. Co-authored-by: Mathew Odden <mrodden@us.ibm.com> Co-authored-by: Ben Nemec <openstack@nemebean.com> This partially implements bp user-locale-api. Change-Id: I27640a3c8b255be51bc6396d238098bd25af61ec
Diffstat (limited to 'openstack/common')
-rw-r--r--openstack/common/gettextutils.py116
1 files changed, 81 insertions, 35 deletions
diff --git a/openstack/common/gettextutils.py b/openstack/common/gettextutils.py
index 635a434..a90b241 100644
--- a/openstack/common/gettextutils.py
+++ b/openstack/common/gettextutils.py
@@ -1,8 +1,8 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Red Hat, Inc.
-# All Rights Reserved.
# 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
@@ -31,17 +31,20 @@ import os
import re
import UserString
+from babel import localedata
import six
_localedir = os.environ.get('oslo'.upper() + '_LOCALEDIR')
_t = gettext.translation('oslo', localedir=_localedir, fallback=True)
+_AVAILABLE_LANGUAGES = []
+
def _(msg):
return _t.ugettext(msg)
-def install(domain):
+def install(domain, lazy=False):
"""Install a _() function using the given translation domain.
Given a translation domain, install a _() function using gettext's
@@ -51,41 +54,45 @@ def install(domain):
overriding the default localedir (e.g. /usr/share/locale) using
a translation-domain-specific environment variable (e.g.
NOVA_LOCALEDIR).
- """
- gettext.install(domain,
- localedir=os.environ.get(domain.upper() + '_LOCALEDIR'),
- unicode=True)
-
-
-"""
-Lazy gettext functionality.
-
-The following is an attempt to introduce a deferred way
-to do translations on messages in OpenStack. We attempt to
-override the standard _() function and % (format string) operation
-to build Message objects that can later be translated when we have
-more information. Also included is an example LogHandler that
-translates Messages to an associated locale, effectively allowing
-many logs, each with their own locale.
-"""
-
-def get_lazy_gettext(domain):
- """Assemble and return a lazy gettext function for a given domain.
-
- Factory method for a project/module to get a lazy gettext function
- for its own translation domain (i.e. nova, glance, cinder, etc.)
+ :param domain: the translation domain
+ :param lazy: indicates whether or not to install the lazy _() function.
+ The lazy _() introduces a way to do deferred translation
+ of messages by installing a _ that builds Message objects,
+ instead of strings, which can then be lazily translated into
+ any available locale.
"""
-
- def _lazy_gettext(msg):
- """Create and return a Message object.
-
- Message encapsulates a string so that we can translate it later when
- needed.
- """
- return Message(msg, domain)
-
- return _lazy_gettext
+ if lazy:
+ # NOTE(mrodden): Lazy gettext functionality.
+ #
+ # The following introduces a deferred way to do translations on
+ # messages in OpenStack. We override the standard _() function
+ # and % (format string) operation to build Message objects that can
+ # later be translated when we have more information.
+ #
+ # Also included below is an example LocaleHandler that translates
+ # Messages to an associated locale, effectively allowing many logs,
+ # each with their own locale.
+
+ def _lazy_gettext(msg):
+ """Create and return a Message object.
+
+ Lazy gettext function for a given domain, it is a factory method
+ for a project/module to get a lazy gettext function for its own
+ translation domain (i.e. nova, glance, cinder, etc.)
+
+ Message encapsulates a string so that we can translate
+ it later when needed.
+ """
+ return Message(msg, domain)
+
+ import __builtin__
+ __builtin__.__dict__['_'] = _lazy_gettext
+ else:
+ localedir = '%s_LOCALEDIR' % domain.upper()
+ gettext.install(domain,
+ localedir=os.environ.get(localedir),
+ unicode=True)
class Message(UserString.UserString, object):
@@ -232,6 +239,45 @@ class Message(UserString.UserString, object):
return UserString.UserString.__getattribute__(self, name)
+def get_available_languages(domain):
+ """Lists the available languages for the given translation domain.
+
+ :param domain: the domain to get languages for
+ """
+ if _AVAILABLE_LANGUAGES:
+ return _AVAILABLE_LANGUAGES
+
+ localedir = '%s_LOCALEDIR' % domain.upper()
+ find = lambda x: gettext.find(domain,
+ localedir=os.environ.get(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
+ _AVAILABLE_LANGUAGES.append('en_US')
+ # NOTE(luisg): Babel <1.0 used a function called list(), which was
+ # renamed to locale_identifiers() in >=1.0, the requirements master list
+ # requires >=0.9.6, uncapped, so defensively work with both. We can remove
+ # this check when the master list updates to >=1.0, and all projects udpate
+ list_identifiers = (getattr(localedata, 'list', None) or
+ getattr(localedata, 'locale_identifiers'))
+ locale_identifiers = list_identifiers()
+ for i in locale_identifiers:
+ if find(i) is not None:
+ _AVAILABLE_LANGUAGES.append(i)
+ return _AVAILABLE_LANGUAGES
+
+
+def get_localized_message(message, user_locale):
+ """Gets a localized version of the given message in the given locale."""
+ if (isinstance(message, Message)):
+ if user_locale:
+ message.locale = user_locale
+ return unicode(message)
+ else:
+ return message
+
+
class LocaleHandler(logging.Handler):
"""Handler that can have a locale associated to translate Messages.