~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/i18n.py

  • Committer: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
#
 
3
# Copyright (C) 2007 Lukáš Lalinský <lalinsky@gmail.com>
 
4
# Copyright (C) 2007,2009 Alexander Belchenko <bialix@ukr.net>
 
5
# Copyright (C) 2011 Canonical Ltd
 
6
#
 
7
# This program is free software; you can redistribute it and/or modify
 
8
# it under the terms of the GNU General Public License as published by
 
9
# the Free Software Foundation; either version 2 of the License, or
 
10
# (at your option) any later version.
 
11
#
 
12
# This program is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
# GNU General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with this program; if not, write to the Free Software
 
19
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
20
 
 
21
# This module is copied from Bazaar Explorer and modified for bzr.
 
22
 
 
23
"""i18n and l10n support for Bazaar."""
 
24
 
 
25
from __future__ import absolute_import
 
26
 
 
27
import gettext as _gettext
 
28
import os
 
29
import sys
 
30
 
 
31
 
 
32
_translations = None
 
33
 
 
34
 
 
35
def gettext(message):
 
36
    """Translate message. 
 
37
    
 
38
    :returns: translated message as unicode.
 
39
    """
 
40
    install()
 
41
    return _translations.ugettext(message)
 
42
 
 
43
 
 
44
def ngettext(singular, plural, number):
 
45
    """Translate message with plural forms based on `number`.
 
46
 
 
47
    :param singular: English language message in singular form
 
48
    :param plural: English language message in plural form
 
49
    :param number: the number this message should be translated for
 
50
 
 
51
    :returns: translated message as unicode.
 
52
    """
 
53
    install()
 
54
    return _translations.ungettext(singular, plural, number)
 
55
 
 
56
 
 
57
def N_(msg):
 
58
    """Mark message for translation but don't translate it right away."""
 
59
    return msg
 
60
 
 
61
 
 
62
def gettext_per_paragraph(message):
 
63
    """Translate message per paragraph.
 
64
 
 
65
    :returns: concatenated translated message as unicode.
 
66
    """
 
67
    install()
 
68
    paragraphs = message.split(u'\n\n')
 
69
    ugettext = _translations.ugettext
 
70
    # Be careful not to translate the empty string -- it holds the
 
71
    # meta data of the .po file.
 
72
    return u'\n\n'.join(ugettext(p) if p else u'' for p in paragraphs)
 
73
 
 
74
 
 
75
def disable_i18n():
 
76
    """Do not allow i18n to be enabled.  Useful for third party users
 
77
    of bzrlib."""
 
78
    global _translations
 
79
    _translations = _gettext.NullTranslations()
 
80
 
 
81
 
 
82
def installed():
 
83
    """Returns whether translations are in use or not."""
 
84
    return _translations is not None
 
85
 
 
86
 
 
87
def install(lang=None):
 
88
    """Enables gettext translations in bzr."""
 
89
    global _translations
 
90
    if installed():
 
91
        return
 
92
    _translations = install_translations(lang)
 
93
 
 
94
 
 
95
def install_translations(lang=None, domain='bzr', locale_base=None):
 
96
    """Create a gettext translation object.
 
97
    
 
98
    :param lang: language to install.
 
99
    :param domain: translation domain to install.
 
100
    :param locale_base: plugins can specify their own directory.
 
101
 
 
102
    :returns: a gettext translations object to use
 
103
    """
 
104
    if lang is None:
 
105
        lang = _get_current_locale()
 
106
    if lang is not None:
 
107
        languages = lang.split(':')
 
108
    else:
 
109
        languages = None
 
110
    translation = _gettext.translation(
 
111
            domain,
 
112
            localedir=_get_locale_dir(locale_base),
 
113
            languages=languages,
 
114
            fallback=True)
 
115
    return translation
 
116
 
 
117
 
 
118
def add_fallback(fallback):
 
119
    """
 
120
    Add a fallback translations object.  Typically used by plugins.
 
121
 
 
122
    :param fallback: gettext.GNUTranslations object
 
123
    """
 
124
    install()
 
125
    _translations.add_fallback(fallback)
 
126
 
 
127
 
 
128
def uninstall():
 
129
    """Disables gettext translations."""
 
130
    global _translations
 
131
    _translations = None
 
132
 
 
133
 
 
134
def _get_locale_dir(base):
 
135
    """Returns directory to find .mo translations file in, either local or system
 
136
 
 
137
    :param base: plugins can specify their own local directory
 
138
    """
 
139
    if hasattr(sys, 'frozen'):
 
140
        if base is None:
 
141
            base = os.path.dirname(
 
142
                unicode(sys.executable, sys.getfilesystemencoding()))
 
143
        return os.path.join(base, u'locale')
 
144
    else:
 
145
        if base is None:
 
146
            base = os.path.dirname(unicode(__file__, sys.getfilesystemencoding()))
 
147
        dirpath = os.path.realpath(os.path.join(base, u'locale'))
 
148
        if os.path.exists(dirpath):
 
149
            return dirpath
 
150
        else:
 
151
            return '/usr/share/locale'
 
152
 
 
153
 
 
154
def _check_win32_locale():
 
155
    for i in ('LANGUAGE','LC_ALL','LC_MESSAGES','LANG'):
 
156
        if os.environ.get(i):
 
157
            break
 
158
    else:
 
159
        lang = None
 
160
        import locale
 
161
        try:
 
162
            import ctypes
 
163
        except ImportError:
 
164
            # use only user's default locale
 
165
            lang = locale.getdefaultlocale()[0]
 
166
        else:
 
167
            # using ctypes to determine all locales
 
168
            lcid_user = ctypes.windll.kernel32.GetUserDefaultLCID()
 
169
            lcid_system = ctypes.windll.kernel32.GetSystemDefaultLCID()
 
170
            if lcid_user != lcid_system:
 
171
                lcid = [lcid_user, lcid_system]
 
172
            else:
 
173
                lcid = [lcid_user]
 
174
            lang = [locale.windows_locale.get(i) for i in lcid]
 
175
            lang = ':'.join([i for i in lang if i])
 
176
        # set lang code for gettext
 
177
        if lang:
 
178
            os.environ['LANGUAGE'] = lang
 
179
 
 
180
 
 
181
def _get_current_locale():
 
182
    if not os.environ.get('LANGUAGE'):
 
183
        from bzrlib import config
 
184
        lang = config.GlobalStack().get('language')
 
185
        if lang:
 
186
            os.environ['LANGUAGE'] = lang
 
187
            return lang
 
188
    if sys.platform == 'win32':
 
189
        _check_win32_locale()
 
190
    for i in ('LANGUAGE','LC_ALL','LC_MESSAGES','LANG'):
 
191
        lang = os.environ.get(i)
 
192
        if lang:
 
193
            return lang
 
194
    return None
 
195
 
 
196
 
 
197
def load_plugin_translations(domain):
 
198
    """Load the translations for a specific plugin.
 
199
 
 
200
    :param domain: Gettext domain name (usually 'bzr-PLUGINNAME')
 
201
    """
 
202
    locale_base = os.path.dirname(
 
203
        unicode(__file__, sys.getfilesystemencoding()))
 
204
    translation = install_translations(domain=domain,
 
205
        locale_base=locale_base)
 
206
    add_fallback(translation)
 
207
    return translation