root/Zope2/TranslationService/trunk/Domain.py

Revision 49431, 4.9 kB (checked in by madarche, 3 years ago)

- Fixed _findEncoding encoding search : "latin9" is an unknow python encoding

while "iso-8859-15" is.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 # (C) Copyright 2002-2006 Nuxeo SAS <http://nuxeo.com>
2 # Author: Florent Guillaume <fg@nuxeo.com>
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 2 as published
6 # by the Free Software Foundation.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
16 # 02111-1307, USA.
17 #
18 # $Id$
19
20 import re
21
22 import Globals
23 from DocumentTemplate.DT_Util import ustr
24 from OFS.SimpleItem import SimpleItem
25
26 NAME_RE = r"[a-zA-Z][a-zA-Z0-9_]*"
27 _interp_regex = re.compile(r'(?<!\$)(\$(?:%(n)s|{%(n)s}))' % {'n': NAME_RE})
28 _get_var_regex = re.compile(r'%(n)s' % {'n': NAME_RE})
29 _charset_regex = re.compile(
30     r'text/[0-9a-z]+\s*;\s*charset=([-_0-9a-z]+)(?:(?:\s*;)|\Z)',
31     re.IGNORECASE)
32
33
34 def _findEncoding():
35     encoding = 'iso-8859-15'
36     get_request = getattr(Globals, 'get_request', None)
37     if get_request is None:
38         request = None
39     else:
40         request = get_request()
41     if request is not None:
42         ct = request.RESPONSE.headers.get('content-type')
43         if ct:
44             match = _charset_regex.match(ct)
45             if match:
46                 encoding = match.group(1)
47     return encoding
48
49
50 class Domain(SimpleItem):
51     """Translation domain."""
52     # Inherit from a Persistent base class to be able to lookup placefully.
53
54     meta_type = 'Placeful Domain' # XXX unused
55
56     # __implements__ =  IDomain
57
58     def __init__(self, domain):
59         self._domain = domain
60
61     def getMessageCatalog(self, lang=None):
62         """Get the message catalog implementing this domain."""
63         raise NotImplementedError
64
65     def noTranslation(self, mapping=None, default=None, **kw):
66         """Return the correct value when there is no translation."""
67         if default is None:
68             # In Zope 2.6, we have to return None to use the default
69             return None
70         else:
71             # In Zope 2.7, we cannot return None but we have the default
72             return self._interpolate(default, mapping)
73
74     #
75     # IDomain API
76     #
77
78     def translate(self, msgid, mapping=None, context=None,
79                   target_language=None, default=None):
80         """Translate a msgid, maybe doing ${keyword} substitution.
81
82         msgid is the message id to be translated.
83         mapping is a set of mapping to be applied on ${keywords}.
84         """
85         # msgid can be '${name} was born in ${country}'.
86         # mapping can be {'country': 'Antarctica', 'name': 'Lomax'}.
87         # context must be adaptable to IUserPreferredLanguages.
88
89         mc = self.getMessageCatalog(lang=target_language)
90         text = mc.queryMessage(msgid, default=default)
91         if text is None:
92             # No default was passed, and msgid has no translation.
93             # We'll get what's in between the tags where the translate
94             # has been invoked within the template
95             if default is None:
96                 default = msgid
97             res = self.noTranslation(mapping=mapping, default=default)
98         else:
99             res = self._interpolate(text, mapping)
100         # Make sure we always return unicode
101         if not isinstance(res, unicode):
102             # This can happen if a non-unicode default is passed
103             res = unicode(res, 'iso-8859-15')
104         return res
105
106     #
107     # Internal
108     #
109
110     def _interpolate(self, text, mapping):
111         """Interpolate ${keyword} substitutions."""
112         if not mapping:
113             return text
114
115         # Find all the spots we want to substitute.
116         to_replace = _interp_regex.findall(text)
117
118         # Now substitute with the variables in mapping.
119         encoding = None
120         for string in to_replace:
121             var = _get_var_regex.findall(string)[0]
122             if mapping.has_key(var):
123                 subst = ustr(mapping[var])
124                 try:
125                     text = text.replace(string, subst)
126                 except UnicodeError:
127                     # The string subst contains high-bit chars.
128                     # Assume it's encoded in the output encoding.
129                     # (This will be the case if Localizer was used.)
130                     if encoding is None:
131                         encoding = _findEncoding()
132                     subst = unicode(subst, encoding, 'ignore')
133                     text = text.replace(string, subst)
134
135         return text
136
137
138 class DummyDomain(Domain):
139     def translate(self, *args, **kw):
140         return self.noTranslation(**kw)
141     def getSelectedLanguage(self):
142         return 'en'
143     def getDefaultLanguage(self):
144         return 'en'
145     def getSupportedLanguages(self):
146         return ('en',)
Note: See TracBrowser for help on using the browser.