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