pylons.i18n.translation
Covered: 27 lines
Missed: 115 lines
Skipped 56 lines
Percent: 19 %

      1

    """Translation/Localization functions.

      2

      3

    Provides :mod:`gettext` translation functions via an app's

      4

    ``pylons.translator`` and get/set_lang for changing the language

      5

    translated to.

      6

      7

    """

      8

    import os

      9

    from gettext import NullTranslations, translation

     10

     11

    import pylons

     12

     13

    __all__ = ['_', 'add_fallback', 'get_lang', 'gettext', 'gettext_noop',

     14

               'lazy_gettext', 'lazy_ngettext', 'lazy_ugettext', 'lazy_ungettext',

     15

               'ngettext', 'set_lang', 'ugettext', 'ungettext', 'LanguageError',

     16

               'N_']

     17

     18

    class LanguageError(Exception):

     19

        """Exception raised when a problem occurs with changing languages"""

     20

        pass

     21

     22

     23

    class LazyString(object):

     24

        """Has a number of lazily evaluated functions replicating a

     25

        string. Just override the eval() method to produce the actual value.

     26

     27

        This method copied from TurboGears.

     28

     29

        """

     30

        def __init__(self, func, *args, **kwargs):

     31

            self.func = func

     32

            self.args = args

     33

            self.kwargs = kwargs

     34

     35

        def eval(self):

     36

            return self.func(*self.args, **self.kwargs)

     37

     38

        def __unicode__(self):

     39

            return unicode(self.eval())

     40

     41

        def __str__(self):

     42

            return str(self.eval())

     43

     44

        def __mod__(self, other):

     45

            return self.eval() % other

     46

     47

     48

    def lazify(func):

     49

        """Decorator to return a lazy-evaluated version of the original"""

     50

        def newfunc(*args, **kwargs):

     51

            return LazyString(func, *args, **kwargs)

     52

        newfunc.__name__ = 'lazy_%s' % func.__name__

     53

        newfunc.__doc__ = 'Lazy-evaluated version of the %s function\n\n%s' % \

     54

            (func.__name__, func.__doc__)

     55

        return newfunc

     56

     57

     58

    def gettext_noop(value):

     59

        """Mark a string for translation without translating it. Returns

     60

        value.

     61

     62

        Used for global strings, e.g.::

     63

     64

            foo = N_('Hello')

     65

     66

            class Bar:

     67

                def __init__(self):

     68

                    self.local_foo = _(foo)

     69

     70

            h.set_lang('fr')

     71

            assert Bar().local_foo == 'Bonjour'

     72

            h.set_lang('es')

     73

            assert Bar().local_foo == 'Hola'

     74

            assert foo == 'Hello'

     75

     76

        """

     77

        return value

     78

    N_ = gettext_noop

     79

     80

     81

    def gettext(value):

     82

        """Mark a string for translation. Returns the localized string of

     83

        value.

     84

     85

        Mark a string to be localized as follows::

     86

     87

            gettext('This should be in lots of languages')

     88

     89

        """

     90

        return pylons.translator.gettext(value)

     91

    lazy_gettext = lazify(gettext)

     92

     93

     94

    def ugettext(value):

     95

        """Mark a string for translation. Returns the localized unicode

     96

        string of value.

     97

     98

        Mark a string to be localized as follows::

     99

    100

            _('This should be in lots of languages')

    101

    102

        """

    103

        return pylons.translator.ugettext(value)

    104

    _ = ugettext

    105

    lazy_ugettext = lazify(ugettext)

    106

    107

    108

    def ngettext(singular, plural, n):

    109

        """Mark a string for translation. Returns the localized string of

    110

        the pluralized value.

    111

    112

        This does a plural-forms lookup of a message id. ``singular`` is

    113

        used as the message id for purposes of lookup in the catalog, while

    114

        ``n`` is used to determine which plural form to use. The returned

    115

        message is a string.

    116

    117

        Mark a string to be localized as follows::

    118

    119

            ngettext('There is %(num)d file here', 'There are %(num)d files here',

    120

                     n) % {'num': n}

    121

    122

        """

    123

        return pylons.translator.ngettext(singular, plural, n)

    124

    lazy_ngettext = lazify(ngettext)

    125

    126

    127

    def ungettext(singular, plural, n):

    128

        """Mark a string for translation. Returns the localized unicode

    129

        string of the pluralized value.

    130

    131

        This does a plural-forms lookup of a message id. ``singular`` is

    132

        used as the message id for purposes of lookup in the catalog, while

    133

        ``n`` is used to determine which plural form to use. The returned

    134

        message is a Unicode string.

    135

    136

        Mark a string to be localized as follows::

    137

    138

            ungettext('There is %(num)d file here', 'There are %(num)d files here',

    139

                      n) % {'num': n}

    140

    141

        """

    142

        return pylons.translator.ungettext(singular, plural, n)

    143

    lazy_ungettext = lazify(ungettext)

    144

    145

    146

    def _get_translator(lang, **kwargs):

    147

        """Utility method to get a valid translator object from a language

    148

        name"""

    149

        if not lang:

    150

            return NullTranslations()

    151

        if 'pylons_config' in kwargs:

    152

            conf = kwargs.pop('pylons_config')

    153

        else:

    154

            conf = pylons.config.current_conf()

    155

        localedir = os.path.join(conf['pylons.paths']['root'], 'i18n')

    156

        if not isinstance(lang, list):

    157

            lang = [lang]

    158

        try:

    159

            translator = translation(conf['pylons.package'], localedir,

    160

                                     languages=lang, **kwargs)

    161

        except IOError, ioe:

    162

            raise LanguageError('IOError: %s' % ioe)

    163

        translator.pylons_lang = lang

    164

        return translator

    165

    166

    167

    def set_lang(lang, **kwargs):

    168

        """Set the current language used for translations.

    169

    170

        ``lang`` should be a string or a list of strings. If a list of

    171

        strings, the first language is set as the main and the subsequent

    172

        languages are added as fallbacks.

    173

        """

    174

        translator = _get_translator(lang, **kwargs)

    175

        environ = pylons.request.environ

    176

        environ['pylons.pylons'].translator = translator

    177

        if 'paste.registry' in environ:

    178

            environ['paste.registry'].replace(pylons.translator, translator)

    179

    180

    181

    def get_lang():

    182

        """Return the current i18n language used"""

    183

        return getattr(pylons.translator, 'pylons_lang', None)

    184

    185

    186

    def add_fallback(lang, **kwargs):

    187

        """Add a fallback language from which words not matched in other

    188

        languages will be translated to.

    189

    190

        This fallback will be associated with the currently selected

    191

        language -- that is, resetting the language via set_lang() resets

    192

        the current fallbacks.

    193

    194

        This function can be called multiple times to add multiple

    195

        fallbacks.

    196

        """

    197

        return pylons.translator.add_fallback(_get_translator(lang, **kwargs))

    198