~ubuntu-branches/ubuntu/trusty/heat/trusty-security

« back to all changes in this revision

Viewing changes to heat/openstack/common/gettextutils.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2013-10-03 09:43:04 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20131003094304-k2c4qcsfn7cv6eos
Tags: 2013.2~rc1-0ubuntu1
* New upstream release.
* debian/control: Dropped python-d2to1 build dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 
27
27
import copy
28
28
import gettext
29
 
import logging.handlers
 
29
import logging
30
30
import os
31
31
import re
32
 
import UserString
 
32
try:
 
33
    import UserString as _userString
 
34
except ImportError:
 
35
    import collections as _userString
33
36
 
34
37
from babel import localedata
35
38
import six
37
40
_localedir = os.environ.get('heat'.upper() + '_LOCALEDIR')
38
41
_t = gettext.translation('heat', localedir=_localedir, fallback=True)
39
42
 
40
 
_AVAILABLE_LANGUAGES = []
 
43
_AVAILABLE_LANGUAGES = {}
 
44
USE_LAZY = False
 
45
 
 
46
 
 
47
def enable_lazy():
 
48
    """Convenience function for configuring _() to use lazy gettext
 
49
 
 
50
    Call this at the start of execution to enable the gettextutils._
 
51
    function to use lazy gettext functionality. This is useful if
 
52
    your project is importing _ directly instead of using the
 
53
    gettextutils.install() way of importing the _ function.
 
54
    """
 
55
    global USE_LAZY
 
56
    USE_LAZY = True
41
57
 
42
58
 
43
59
def _(msg):
44
 
    return _t.ugettext(msg)
 
60
    if USE_LAZY:
 
61
        return Message(msg, 'heat')
 
62
    else:
 
63
        if six.PY3:
 
64
            return _t.gettext(msg)
 
65
        return _t.ugettext(msg)
45
66
 
46
67
 
47
68
def install(domain, lazy=False):
86
107
            """
87
108
            return Message(msg, domain)
88
109
 
89
 
        import __builtin__
90
 
        __builtin__.__dict__['_'] = _lazy_gettext
 
110
        from six import moves
 
111
        moves.builtins.__dict__['_'] = _lazy_gettext
91
112
    else:
92
113
        localedir = '%s_LOCALEDIR' % domain.upper()
93
 
        gettext.install(domain,
94
 
                        localedir=os.environ.get(localedir),
95
 
                        unicode=True)
96
 
 
97
 
 
98
 
class Message(UserString.UserString, object):
 
114
        if six.PY3:
 
115
            gettext.install(domain,
 
116
                            localedir=os.environ.get(localedir))
 
117
        else:
 
118
            gettext.install(domain,
 
119
                            localedir=os.environ.get(localedir),
 
120
                            unicode=True)
 
121
 
 
122
 
 
123
class Message(_userString.UserString, object):
99
124
    """Class used to encapsulate translatable messages."""
100
125
    def __init__(self, msg, domain):
101
126
        # _msg is the gettext msgid and should never change
102
127
        self._msg = msg
103
128
        self._left_extra_msg = ''
104
129
        self._right_extra_msg = ''
 
130
        self._locale = None
105
131
        self.params = None
106
 
        self.locale = None
107
132
        self.domain = domain
108
133
 
109
134
    @property
123
148
                                       localedir=localedir,
124
149
                                       fallback=True)
125
150
 
 
151
        if six.PY3:
 
152
            ugettext = lang.gettext
 
153
        else:
 
154
            ugettext = lang.ugettext
 
155
 
126
156
        full_msg = (self._left_extra_msg +
127
 
                    lang.ugettext(self._msg) +
 
157
                    ugettext(self._msg) +
128
158
                    self._right_extra_msg)
129
159
 
130
160
        if self.params is not None:
132
162
 
133
163
        return six.text_type(full_msg)
134
164
 
 
165
    @property
 
166
    def locale(self):
 
167
        return self._locale
 
168
 
 
169
    @locale.setter
 
170
    def locale(self, value):
 
171
        self._locale = value
 
172
        if not self.params:
 
173
            return
 
174
 
 
175
        # This Message object may have been constructed with one or more
 
176
        # Message objects as substitution parameters, given as a single
 
177
        # Message, or a tuple or Map containing some, so when setting the
 
178
        # locale for this Message we need to set it for those Messages too.
 
179
        if isinstance(self.params, Message):
 
180
            self.params.locale = value
 
181
            return
 
182
        if isinstance(self.params, tuple):
 
183
            for param in self.params:
 
184
                if isinstance(param, Message):
 
185
                    param.locale = value
 
186
            return
 
187
        if isinstance(self.params, dict):
 
188
            for param in self.params.values():
 
189
                if isinstance(param, Message):
 
190
                    param.locale = value
 
191
 
135
192
    def _save_dictionary_parameter(self, dict_param):
136
193
        full_msg = self.data
137
194
        # look for %(blah) fields in string;
138
195
        # ignore %% and deal with the
139
196
        # case where % is first character on the line
140
 
        keys = re.findall('(?:[^%]|^)%\((\w*)\)[a-z]', full_msg)
 
197
        keys = re.findall('(?:[^%]|^)?%\((\w*)\)[a-z]', full_msg)
141
198
 
142
199
        # if we don't find any %(blah) blocks but have a %s
143
200
        if not keys and re.findall('(?:[^%]|^)%[a-z]', full_msg):
150
207
                    params[key] = copy.deepcopy(dict_param[key])
151
208
                except TypeError:
152
209
                    # cast uncopyable thing to unicode string
153
 
                    params[key] = unicode(dict_param[key])
 
210
                    params[key] = six.text_type(dict_param[key])
154
211
 
155
212
        return params
156
213
 
169
226
            try:
170
227
                self.params = copy.deepcopy(other)
171
228
            except TypeError:
172
 
                self.params = unicode(other)
 
229
                self.params = six.text_type(other)
173
230
 
174
231
        return self
175
232
 
178
235
        return self.data
179
236
 
180
237
    def __str__(self):
 
238
        if six.PY3:
 
239
            return self.__unicode__()
181
240
        return self.data.encode('utf-8')
182
241
 
183
242
    def __getstate__(self):
184
243
        to_copy = ['_msg', '_right_extra_msg', '_left_extra_msg',
185
 
                   'domain', 'params', 'locale']
 
244
                   'domain', 'params', '_locale']
186
245
        new_dict = self.__dict__.fromkeys(to_copy)
187
246
        for attr in to_copy:
188
247
            new_dict[attr] = copy.deepcopy(self.__dict__[attr])
236
295
        if name in ops:
237
296
            return getattr(self.data, name)
238
297
        else:
239
 
            return UserString.UserString.__getattribute__(self, name)
 
298
            return _userString.UserString.__getattribute__(self, name)
240
299
 
241
300
 
242
301
def get_available_languages(domain):
244
303
 
245
304
    :param domain: the domain to get languages for
246
305
    """
247
 
    if _AVAILABLE_LANGUAGES:
248
 
        return _AVAILABLE_LANGUAGES
 
306
    if domain in _AVAILABLE_LANGUAGES:
 
307
        return copy.copy(_AVAILABLE_LANGUAGES[domain])
249
308
 
250
309
    localedir = '%s_LOCALEDIR' % domain.upper()
251
310
    find = lambda x: gettext.find(domain,
254
313
 
255
314
    # NOTE(mrodden): en_US should always be available (and first in case
256
315
    # order matters) since our in-line message strings are en_US
257
 
    _AVAILABLE_LANGUAGES.append('en_US')
 
316
    language_list = ['en_US']
258
317
    # NOTE(luisg): Babel <1.0 used a function called list(), which was
259
318
    # renamed to locale_identifiers() in >=1.0, the requirements master list
260
319
    # requires >=0.9.6, uncapped, so defensively work with both. We can remove
264
323
    locale_identifiers = list_identifiers()
265
324
    for i in locale_identifiers:
266
325
        if find(i) is not None:
267
 
            _AVAILABLE_LANGUAGES.append(i)
268
 
    return _AVAILABLE_LANGUAGES
 
326
            language_list.append(i)
 
327
    _AVAILABLE_LANGUAGES[domain] = language_list
 
328
    return copy.copy(language_list)
269
329
 
270
330
 
271
331
def get_localized_message(message, user_locale):
272
332
    """Gets a localized version of the given message in the given locale."""
273
 
    if (isinstance(message, Message)):
 
333
    if isinstance(message, Message):
274
334
        if user_locale:
275
335
            message.locale = user_locale
276
 
        return unicode(message)
 
336
        return six.text_type(message)
277
337
    else:
278
338
        return message
279
339