Sync gettextutils from oslo

This change brings in new functionality from gettextutils
needed for supporting delayed message translation in
Ceilometer.

Partially implements bp user-locale-api

Change-Id: I541a3fdcef713f9c3b08dd96f78553e7c092162d
This commit is contained in:
Brad Pokorny 2013-08-02 20:06:09 +00:00
parent d9ee2e7704
commit 3019fa75e6

View File

@ -1,8 +1,8 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Red Hat, Inc. # Copyright 2012 Red Hat, Inc.
# All Rights Reserved.
# Copyright 2013 IBM Corp. # Copyright 2013 IBM Corp.
# All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # not use this file except in compliance with the License. You may obtain
@ -31,17 +31,20 @@ import os
import re import re
import UserString import UserString
from babel import localedata
import six import six
_localedir = os.environ.get('ceilometer'.upper() + '_LOCALEDIR') _localedir = os.environ.get('ceilometer'.upper() + '_LOCALEDIR')
_t = gettext.translation('ceilometer', localedir=_localedir, fallback=True) _t = gettext.translation('ceilometer', localedir=_localedir, fallback=True)
_AVAILABLE_LANGUAGES = []
def _(msg): def _(msg):
return _t.ugettext(msg) return _t.ugettext(msg)
def install(domain): def install(domain, lazy=False):
"""Install a _() function using the given translation domain. """Install a _() function using the given translation domain.
Given a translation domain, install a _() function using gettext's 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 overriding the default localedir (e.g. /usr/share/locale) using
a translation-domain-specific environment variable (e.g. a translation-domain-specific environment variable (e.g.
NOVA_LOCALEDIR). NOVA_LOCALEDIR).
: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.
""" """
gettext.install(domain, if lazy:
localedir=os.environ.get(domain.upper() + '_LOCALEDIR'), # NOTE(mrodden): Lazy gettext functionality.
unicode=True) #
# 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
Lazy gettext functionality. for a project/module to get a lazy gettext function for its own
translation domain (i.e. nova, glance, cinder, etc.)
The following is an attempt to introduce a deferred way Message encapsulates a string so that we can translate
to do translations on messages in OpenStack. We attempt to it later when needed.
override the standard _() function and % (format string) operation """
to build Message objects that can later be translated when we have return Message(msg, domain)
more information. Also included is an example LogHandler that
translates Messages to an associated locale, effectively allowing
many logs, each with their own locale.
"""
import __builtin__
def get_lazy_gettext(domain): __builtin__.__dict__['_'] = _lazy_gettext
"""Assemble and return a lazy gettext function for a given domain. else:
localedir = '%s_LOCALEDIR' % domain.upper()
Factory method for a project/module to get a lazy gettext function gettext.install(domain,
for its own translation domain (i.e. nova, glance, cinder, etc.) localedir=os.environ.get(localedir),
""" unicode=True)
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
class Message(UserString.UserString, object): class Message(UserString.UserString, object):
@ -232,6 +239,45 @@ class Message(UserString.UserString, object):
return UserString.UserString.__getattribute__(self, name) 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): class LocaleHandler(logging.Handler):
"""Handler that can have a locale associated to translate Messages. """Handler that can have a locale associated to translate Messages.