Edgewall Software

Ticket #7497: plugin_i18n_support-domain_functions.patch

File plugin_i18n_support-domain_functions.patch, 11.0 KB (added by cboos, 4 years ago)

Same as previous patch, with a new helper function domain_functions to ease the setup of plugins.

  • setup.py

     
    7373        'Genshi>=0.5' 
    7474    ], 
    7575    extras_require = { 
    76         'Babel': ['Babel>=0.9.3'], 
     76        'Babel': ['Babel>=0.9.4'], 
    7777        'Pygments': ['Pygments>=0.6'], 
    7878        'reST': ['docutils>=0.3'], 
    7979        'SilverCity': ['SilverCity>=0.9.4'], 
  • trac/web/api.py

     
    369369                    from trac.web.chrome import Chrome 
    370370                    from trac.util import translation 
    371371                    if hasattr(self, 'locale'): 
    372                         translation.activate(self.locale) 
     372                        translation.activate(self.locale, env.path) 
    373373                    try: 
    374374                        data = Chrome(env).render_template(self, template, 
    375375                                                           data, 'text/html') 
  • trac/web/chrome.py

     
    2626 
    2727from genshi import Markup 
    2828from genshi.builder import tag, Element 
    29 from genshi.filters import Translator 
     29from genshi.filters import Translator, setup_i18n 
    3030from genshi.input import HTML, ParseError 
    3131from genshi.core import Attrs, START 
    3232from genshi.output import DocType 
     
    293293        'classes': presentation.classes, 
    294294        'date': datetime.date, 
    295295        'datetime': datetime.datetime, 
     296        'dgettext': translation.dgettext, 
     297        'dngettext': translation.dngettext, 
    296298        'first_last': presentation.first_last, 
    297299        'get_reporter_id': get_reporter_id, 
    298300        'gettext': translation.gettext, 
     
    660662        """ 
    661663        if not self.templates: 
    662664            def _template_loaded(template): 
    663                 template.filters.insert(0, Translator(translation.gettext)) 
     665                translator = Translator(translation.get_translations()) 
     666                setup_i18n(template, translator) 
    664667 
    665668            self.templates = TemplateLoader(self.get_all_templates_dirs(), 
    666669                                            auto_reload=self.auto_reload, 
  • trac/web/main.py

     
    164164        try: 
    165165            try: 
    166166                try: 
    167                     translation.activate(req.locale) 
     167                    translation.activate(req.locale, self.env.path) 
    168168 
    169169                    # Select the component that should handle the request 
    170170                    chosen_handler = None 
  • trac/util/translation.py

     
    1414"""Utilities for text translation with gettext.""" 
    1515 
    1616import re 
     17import sys  
    1718try: 
    1819    import threading 
    1920except ImportError: 
     
    5758    from babel.support import LazyProxy, Translations 
    5859    from gettext import NullTranslations 
    5960 
    60     _current = threading.local() 
     61    class TranslationsProxy(object): 
     62        """Delegate Translations calls to the currently active Translations. 
    6163 
    62     def gettext(string, **kwargs): 
    63         def _gettext(): 
    64             trans = get_translations().ugettext(string) 
    65             return kwargs and trans % kwargs or trans 
    66         if not hasattr(_current, 'translations'): 
    67             return LazyProxy(_gettext) 
    68         return _gettext() 
    69     _ = gettext 
     64        If there's none, wrap those calls in LazyProxy objects. 
     65        """ 
    7066 
    71     def ngettext(singular, plural, num, **kwargs): 
    72         kwargs = kwargs.copy() 
    73         kwargs.setdefault('num', num) 
    74         def _ngettext(): 
    75             trans = get_translations().ungettext(singular, plural, num) 
    76             return trans % kwargs 
    77         if not hasattr(_current, 'translations'): 
    78             return LazyProxy(_ngettext) 
    79         return _ngettext() 
     67        def __init__(self): 
     68            self._current = threading.local() 
     69            self._null_translations = NullTranslations() 
     70            self._plugin_domains = {} 
    8071 
    81     def tgettext(string, **kwargs): 
    82         def _tgettext(): 
    83             trans = get_translations().ugettext(string) 
    84             return kwargs and _tag_kwargs(trans, kwargs) or trans 
    85         if not hasattr(_current, 'translations'): 
    86             return LazyProxy(_tgettext) 
    87         return _tgettext() 
    88     tag_ = tgettext 
     72        # Public API 
    8973 
    90     def tngettext(singular, plural, num, **kwargs): 
    91         kwargs = kwargs.copy() 
    92         kwargs.setdefault('num', num) 
    93         def _tngettext(): 
    94             trans = get_translations().ungettext(singular, plural, num) 
    95             return _tag_kwargs(trans, kwargs) 
    96         if not hasattr(_current, 'translations'): 
    97             return LazyProxy(_tngettext) 
    98         return _tngettext() 
     74        def add_domain(self, domain, env_path, locales_dir): 
     75            if env_path not in self._plugin_domains: 
     76                self._plugin_domains[env_path] = [] 
     77            self._plugin_domains[env_path].append((domain, locales_dir)) 
    9978 
    100     def activate(locale): 
    101         locale_dir = pkg_resources.resource_filename(__name__, '../locale') 
    102         _current.translations = Translations.load(locale_dir, locale) 
     79        def activate(self, locale, env_path=None): 
     80            locale_dir = pkg_resources.resource_filename(__name__, '../locale') 
     81            t = Translations.load(locale_dir, locale) 
     82            if env_path: 
     83                for domain, dirname in self._plugin_domains.get(env_path, []): 
     84                    t.add(Translations.load(dirname, locale, domain)) 
     85            self._current.translations = t 
     86          
     87        def deactivate(self): 
     88            del self._current.translations 
     89     
     90        @property 
     91        def active(self): 
     92            return getattr(self._current, 'translations',  
     93                           self._null_translations) 
    10394 
    104     _null_translations = NullTranslations() 
     95        @property 
     96        def isactive(self): 
     97            return hasattr(self._current, 'translations') 
    10598 
    106     def get_translations(): 
    107         return getattr(_current, 'translations', _null_translations) 
     99        # Delegated methods 
    108100 
     101        def __getattr__(self, name): 
     102            return getattr(self.active, name) 
     103 
     104        def gettext(self, string, **kwargs): 
     105            def _gettext(): 
     106                trans = self.active.ugettext(string) 
     107                return kwargs and trans % kwargs or trans 
     108            if not self.isactive: 
     109                return LazyProxy(_gettext) 
     110            return _gettext() 
     111 
     112        def dgettext(self, domain, string, **kwargs): 
     113            def _dgettext(): 
     114                trans = self.active.dugettext(domain, string) 
     115                return kwargs and trans % kwargs or trans 
     116            if not self.isactive: 
     117                return LazyProxy(_dgettext) 
     118            return _dgettext() 
     119 
     120        def ngettext(self, singular, plural, num, **kwargs): 
     121            kwargs = kwargs.copy() 
     122            kwargs.setdefault('num', num) 
     123            def _ngettext(): 
     124                trans = self.active.ungettext(singular, plural, num) 
     125                return trans % kwargs 
     126            if not self.isactive: 
     127                return LazyProxy(_ngettext) 
     128            return _ngettext() 
     129 
     130        def dngettext(self, domain, singular, plural, num, **kwargs): 
     131            kwargs = kwargs.copy() 
     132            kwargs.setdefault('num', num) 
     133            def _dngettext(): 
     134                trans = self.active.dungettext(domain, singular, plural, num) 
     135                return trans % kwargs 
     136            if not self.isactive: 
     137                return LazyProxy(_dngettext) 
     138            return _dngettext() 
     139 
     140        def tgettext(self, string, **kwargs): 
     141            def _tgettext(): 
     142                trans = self.active.ugettext(string) 
     143                return kwargs and _tag_kwargs(trans, kwargs) or trans 
     144            if not self.isactive: 
     145                return LazyProxy(_tgettext) 
     146            return _tgettext() 
     147 
     148        def dtgettext(self, domain, string, **kwargs): 
     149            def _dtgettext(): 
     150                trans = self.active.dugettext(domain, string) 
     151                return kwargs and _tag_kwargs(trans, kwargs) or trans 
     152            if not self.isactive: 
     153                return LazyProxy(_dtgettext) 
     154            return _dtgettext() 
     155 
     156        def tngettext(self, singular, plural, num, **kwargs): 
     157            kwargs = kwargs.copy() 
     158            kwargs.setdefault('num', num) 
     159            def _tngettext(): 
     160                trans = self.active.ungettext(singular, plural, num) 
     161                return _tag_kwargs(trans, kwargs) 
     162            if not self.isactive: 
     163                return LazyProxy(_tngettext) 
     164            return _tngettext() 
     165 
     166        def dtngettext(self, domain, singular, plural, num, **kwargs): 
     167            kwargs = kwargs.copy() 
     168            def _dtngettext(): 
     169                trans = self.active.dungettext(domain, singular, plural, num) 
     170                if '%(num)' in trans: 
     171                    kwargs.update(num=num) 
     172                return kwargs and _tag_kwargs(trans, kwargs) or trans 
     173            if not self.isactive: 
     174                return LazyProxy(_dtngettext) 
     175            return _dtngettext() 
     176 
     177     
     178    translations = TranslationsProxy() 
     179 
     180    def domain_functions(domain, *symbols): 
     181        _symbols = { 
     182          'gettext': translations.dgettext, 
     183          '_': translations.dgettext, 
     184          'ngettext': translations.dngettext, 
     185          'tgettext': translations.dtgettext, 
     186          'tag_': translations.dtgettext, 
     187          'tngettext': translations.dtngettext, 
     188          'add_domain': translations.add_domain, 
     189          } 
     190        def wrapdomain(symbol): 
     191            if symbol == 'N_': 
     192                return gettext_noop 
     193            return lambda *args, **kw: _symbols[symbol](domain, *args, **kw) 
     194        return [wrapdomain(s) for s in symbols] 
     195 
     196    gettext = translations.gettext  
     197    _ = gettext  
     198    dgettext = translations.dgettext  
     199    ngettext = translations.ngettext  
     200    dngettext = translations.dngettext  
     201    tgettext = translations.tgettext  
     202    tag_ = tgettext  
     203    dtgettext = translations.dtgettext  
     204    tngettext = translations.tngettext  
     205    dtngettext = translations.dtngettext  
     206     
    109207    def deactivate(): 
    110         del _current.translations 
     208        translations.deactivate() 
    111209 
     210    def activate(locale, env_path=None): 
     211        translations.activate(locale, env_path) 
     212 
     213    def add_domain(domain, env_path, locale_dir): 
     214        translations.add_domain(domain, env_path, locale_dir) 
     215 
     216    def get_translations(): 
     217        return translations 
     218 
    112219    def get_available_locales(): 
    113220        """Return a list of locale identifiers of the locales for which 
    114221        translations are available. 
     
    129236    def deactivate(): 
    130237        pass 
    131238 
     239    def add_domain(domain, env_path, locale_dir): 
     240        pass 
     241 
    132242    def get_translations(): 
    133243        return [] 
    134244