Michael Merickel
2018-10-26 4149922e64aecf2a213f8efb120cd2d61fed3eb7
commit | author | age
0c29cf 1 from pyramid.interfaces import ILocaleNegotiator, ITranslationDirectories
5bf23f 2
CM 3 from pyramid.exceptions import ConfigurationError
0c1c58 4 from pyramid.path import AssetResolver
52fde9 5
d579f2 6 from pyramid.config.actions import action_method
0c29cf 7
5bf23f 8
CM 9 class I18NConfiguratorMixin(object):
10     @action_method
11     def set_locale_negotiator(self, negotiator):
12         """
13         Set the :term:`locale negotiator` for this application.  The
14         :term:`locale negotiator` is a callable which accepts a
15         :term:`request` object and which returns a :term:`locale
16         name`.  The ``negotiator`` argument should be the locale
17         negotiator implementation or a :term:`dotted Python name`
18         which refers to such an implementation.
19
20         Later calls to this method override earlier calls; there can
21         be only one locale negotiator active at a time within an
22         application.  See :ref:`activating_translation` for more
23         information.
24
012b97 25         .. note::
M 26
27            Using the ``locale_negotiator`` argument to the
28            :class:`pyramid.config.Configurator` constructor can be used to
29            achieve the same purpose.
5bf23f 30         """
0c29cf 31
5bf23f 32         def register():
CM 33             self._set_locale_negotiator(negotiator)
0c29cf 34
MM 35         intr = self.introspectable(
36             'locale negotiator',
37             None,
38             self.object_description(negotiator),
39             'locale negotiator',
40         )
3b5ccb 41         intr['negotiator'] = negotiator
CM 42         self.action(ILocaleNegotiator, register, introspectables=(intr,))
5bf23f 43
CM 44     def _set_locale_negotiator(self, negotiator):
45         locale_negotiator = self.maybe_dotted(negotiator)
46         self.registry.registerUtility(locale_negotiator, ILocaleNegotiator)
47
a78b58 48     @action_method
d009c0 49     def add_translation_dirs(self, *specs, **kw):
5bf23f 50         """ Add one or more :term:`translation directory` paths to the
CM 51         current configuration state.  The ``specs`` argument is a
52         sequence that may contain absolute directory paths
53         (e.g. ``/usr/share/locale``) or :term:`asset specification`
54         names naming a directory path (e.g. ``some.package:locale``)
55         or a combination of the two.
56
57         Example:
58
59         .. code-block:: python
60
61            config.add_translation_dirs('/usr/share/locale',
62                                        'some.package:locale')
63
c13745 64         The translation directories are defined as a list in which
MM 65         translations defined later have precedence over translations defined
66         earlier.
67
d009c0 68         By default, consecutive calls to ``add_translation_dirs`` will add
MM 69         directories to the start of the list. This means later calls to
70         ``add_translation_dirs`` will have their translations trumped by
71         earlier calls. If you explicitly need this call to trump an earlier
72         call then you may set ``override`` to ``True``.
73
c13745 74         If multiple specs are provided in a single call to
MM 75         ``add_translation_dirs``, the directories will be inserted in the
76         order they're provided (earlier items are trumped by later items).
77
d009c0 78         .. versionchanged:: 1.8
c13745 79
d009c0 80            The ``override`` parameter was added to allow a later call
MM 81            to ``add_translation_dirs`` to override an earlier call, inserting
82            folders at the beginning of the translation directory list.
0c1c58 83
5bf23f 84         """
3b5ccb 85         introspectables = []
d009c0 86         override = kw.pop('override', False)
MM 87         if kw:
88             raise TypeError('invalid keyword arguments: %s', sorted(kw.keys()))
5bf23f 89
3b5ccb 90         def register():
b24aeb 91             directories = []
MM 92             resolver = AssetResolver(self.package_name)
93
0c1c58 94             # defer spec resolution until register to allow for asset
MM 95             # overrides to take place in an earlier config phase
d009c0 96             for spec in specs:
0c1c58 97                 # the trailing slash helps match asset overrides for folders
MM 98                 if not spec.endswith('/'):
99                     spec += '/'
100                 asset = resolver.resolve(spec)
101                 directory = asset.abspath()
102                 if not asset.isdir():
0c29cf 103                     raise ConfigurationError(
MM 104                         '"%s" is not a directory' % directory
105                     )
106                 intr = self.introspectable(
107                     'translation directories',
108                     directory,
109                     spec,
110                     'translation directory',
111                 )
0c1c58 112                 intr['directory'] = directory
MM 113                 intr['spec'] = spec
114                 introspectables.append(intr)
115                 directories.append(directory)
5bf23f 116
b24aeb 117             tdirs = self.registry.queryUtility(ITranslationDirectories)
MM 118             if tdirs is None:
119                 tdirs = []
120                 self.registry.registerUtility(tdirs, ITranslationDirectories)
d009c0 121             if override:
MM 122                 tdirs.extend(directories)
123             else:
124                 for directory in reversed(directories):
125                     tdirs.insert(0, directory)
5bf23f 126
3b5ccb 127         self.action(None, register, introspectables=introspectables)