1import os 2import sys 3 4from pyramid.interfaces import ( 5 ILocaleNegotiator, 6 ITranslationDirectories, 7 ) 8 9from pyramid.exceptions import ConfigurationError 10from pyramid.path import package_path 11from pyramid.util import action_method 12 13class I18NConfiguratorMixin(object): 14 @action_method 15 def set_locale_negotiator(self, negotiator): 16 """ 17 Set the :term:`locale negotiator` for this application. The 18 :term:`locale negotiator` is a callable which accepts a 19 :term:`request` object and which returns a :term:`locale 20 name`. The ``negotiator`` argument should be the locale 21 negotiator implementation or a :term:`dotted Python name` 22 which refers to such an implementation. 23 24 Later calls to this method override earlier calls; there can 25 be only one locale negotiator active at a time within an 26 application. See :ref:`activating_translation` for more 27 information. 28 29 .. note:: 30 31 Using the ``locale_negotiator`` argument to the 32 :class:`pyramid.config.Configurator` constructor can be used to 33 achieve the same purpose. 34 """ 35 def register(): 36 self._set_locale_negotiator(negotiator) 37 intr = self.introspectable('locale negotiator', None, 38 self.object_description(negotiator), 39 'locale negotiator') 40 intr['negotiator'] = negotiator 41 self.action(ILocaleNegotiator, register, introspectables=(intr,)) 42 43 def _set_locale_negotiator(self, negotiator): 44 locale_negotiator = self.maybe_dotted(negotiator) 45 self.registry.registerUtility(locale_negotiator, ILocaleNegotiator) 46 47 @action_method 48 def add_translation_dirs(self, *specs): 49 """ Add one or more :term:`translation directory` paths to the 50 current configuration state. The ``specs`` argument is a 51 sequence that may contain absolute directory paths 52 (e.g. ``/usr/share/locale``) or :term:`asset specification` 53 names naming a directory path (e.g. ``some.package:locale``) 54 or a combination of the two. 55 56 Example: 57 58 .. code-block:: python 59 60 config.add_translation_dirs('/usr/share/locale', 61 'some.package:locale') 62 63 Later calls to ``add_translation_dir`` insert directories into the 64 beginning of the list of translation directories created by earlier 65 calls. This means that the same translation found in a directory 66 added later in the configuration process will be found before one 67 added earlier in the configuration process. However, if multiple 68 specs are provided in a single call to ``add_translation_dirs``, the 69 directories will be inserted into the beginning of the directory list 70 in the order they're provided in the ``*specs`` list argument (items 71 earlier in the list trump ones later in the list). 72 """ 73 directories = [] 74 introspectables = [] 75 76 for spec in specs[::-1]: # reversed 77 package_name, filename = self._split_spec(spec) 78 if package_name is None: # absolute filename 79 directory = filename 80 else: 81 __import__(package_name) 82 package = sys.modules[package_name] 83 directory = os.path.join(package_path(package), filename) 84 85 if not os.path.isdir(os.path.realpath(directory)): 86 raise ConfigurationError('"%s" is not a directory' % 87 directory) 88 intr = self.introspectable('translation directories', directory, 89 spec, 'translation directory') 90 intr['directory'] = directory 91 intr['spec'] = spec 92 introspectables.append(intr) 93 directories.append(directory) 94 95 def register(): 96 for directory in directories: 97 98 tdirs = self.registry.queryUtility(ITranslationDirectories) 99 if tdirs is None: 100 tdirs = [] 101 self.registry.registerUtility(tdirs, 102 ITranslationDirectories) 103 104 tdirs.insert(0, directory) 105 106 self.action(None, register, introspectables=introspectables) 107 108