67 |
# message in a catalog is not translated, tough luck, you get the msgid. |
# message in a catalog is not translated, tough luck, you get the msgid. |
68 |
LANGUAGE_FALLBACKS = list(os.environ.get('LANGUAGE_FALLBACKS', 'en').split(' ')) |
LANGUAGE_FALLBACKS = list(os.environ.get('LANGUAGE_FALLBACKS', 'en').split(' ')) |
69 |
|
|
70 |
|
from UserDict import UserDict |
71 |
|
|
72 |
|
class Registry(UserDict): |
73 |
|
|
74 |
|
def register(self, name, value): |
75 |
|
self[name] = value |
76 |
|
|
77 |
|
catalogRegistry = Registry() |
78 |
|
registerCatalog = catalogRegistry.register |
79 |
|
fbcatalogRegistry = Registry() |
80 |
|
registerFBCatalog = fbcatalogRegistry.register |
81 |
|
|
82 |
class PlacelessTranslationService(Folder): |
class PlacelessTranslationService(Folder): |
83 |
meta_type = title = 'Placeless Translation Service' |
meta_type = title = 'Placeless Translation Service' |
99 |
# domain. So far, we've required the domain argument to .translate() |
# domain. So far, we've required the domain argument to .translate() |
100 |
self._domain = default_domain |
self._domain = default_domain |
101 |
# _catalogs maps (language, domain) to identifiers |
# _catalogs maps (language, domain) to identifiers |
102 |
self._catalogs = {} |
catalogRegistry = {} |
103 |
self._fb_catalogs = {} |
fbcatalogRegistry = {} |
104 |
# What languages to fallback to, if there is no catalog for the |
# What languages to fallback to, if there is no catalog for the |
105 |
# requested language (no fallback on individual messages) |
# requested language (no fallback on individual messages) |
106 |
if fallbacks is None: |
if fallbacks is None: |
109 |
|
|
110 |
def _registerMessageCatalog(self, catalog): |
def _registerMessageCatalog(self, catalog): |
111 |
domain = catalog.getDomain() |
domain = catalog.getDomain() |
112 |
self._catalogs.setdefault((catalog.getLanguage(), domain), []).append(catalog.getIdentifier()) |
catalogRegistry.setdefault((catalog.getLanguage(), domain), []).append(catalog.getIdentifier()) |
113 |
for lang in catalog.getOtherLanguages(): |
for lang in catalog.getOtherLanguages(): |
114 |
self._fb_catalogs.setdefault((lang, domain), []).append(catalog.getIdentifier()) |
fbcatalogRegistry.setdefault((lang, domain), []).append(catalog.getIdentifier()) |
115 |
self._p_changed = 1 |
self._p_changed = 1 |
116 |
|
|
117 |
def _unregister_inner(self, catalog, clist): |
def _unregister_inner(self, catalog, clist): |
124 |
del clist[key] |
del clist[key] |
125 |
|
|
126 |
def _unregisterMessageCatalog(self, catalog): |
def _unregisterMessageCatalog(self, catalog): |
127 |
self._unregister_inner(catalog, self._catalogs) |
self._unregister_inner(catalog, catalogRegistry) |
128 |
self._unregister_inner(catalog, self._fb_catalogs) |
self._unregister_inner(catalog, fbcatalogRegistry) |
129 |
self._p_changed = 1 |
self._p_changed = 1 |
130 |
|
|
131 |
def _load_dir(self, basepath): |
def _load_dir(self, basepath): |
186 |
|
|
187 |
|
|
188 |
def getLanguageName(self, code): |
def getLanguageName(self, code): |
189 |
for (ccode, cdomain), cnames in self._catalogs.items(): |
for (ccode, cdomain), cnames in catalogRegistry.items(): |
190 |
if ccode == code: |
if ccode == code: |
191 |
for cname in cnames: |
for cname in cnames: |
192 |
cat = self._getOb(cname) |
cat = self._getOb(cname) |
198 |
"""Get available languages""" |
"""Get available languages""" |
199 |
if domain is None: |
if domain is None: |
200 |
# no domain, so user wants 'em all |
# no domain, so user wants 'em all |
201 |
langs = self._catalogs.keys() |
langs = catalogRegistry.keys() |
202 |
# uniquify |
# uniquify |
203 |
d = {} |
d = {} |
204 |
for l in langs: |
for l in langs: |
205 |
d[l[0]] = 1 |
d[l[0]] = 1 |
206 |
l = d.keys() |
l = d.keys() |
207 |
else: |
else: |
208 |
l = [k[0] for k in self._catalogs.keys() if k[1] == domain] |
l = [k[0] for k in catalogRegistry.keys() if k[1] == domain] |
209 |
l.sort() |
l.sort() |
210 |
return l |
return l |
211 |
|
|
212 |
def negotiate(self, langs, context): |
def negotiate(self, langs, context): |
213 |
return negotiator.getLanguage(langs, context) |
return negotiator.getLanguage(langs, context) |
214 |
|
|
215 |
def translate(self, domain, msgid, mapping=None, context=None, |
def translate(self, domain, msgid, mapping=None, context=None, |
216 |
target_language=None, default=None): |
target_language=None, default=None): |
217 |
""" |
""" |
218 |
""" |
""" |
226 |
context = context.REQUEST |
context = context.REQUEST |
227 |
except AttributeError: |
except AttributeError: |
228 |
pass |
pass |
229 |
|
|
230 |
if target_language is None: |
if target_language is None: |
231 |
target_language = self.negotiate_language(context, domain) |
target_language = self.negotiate_language(context, domain) |
232 |
|
|
233 |
# Get the translation. Use the specified fallbacks if this fails |
# Get the translation. Use the specified fallbacks if this fails |
234 |
catalog_names = self._catalogs.get((target_language, domain), ()) or \ |
catalog_names = catalogRegistry.get((target_language, domain), ()) or \ |
235 |
self._fb_catalogs.get((target_language, domain), ()) |
fbcatalogRegistry.get((target_language, domain), ()) |
236 |
if not catalog_names: |
if not catalog_names: |
237 |
for language in self._fallbacks: |
for language in self._fallbacks: |
238 |
catalog_names = self._catalogs.get((language, domain), ()) |
catalog_names = catalogRegistry.get((language, domain), ()) |
239 |
if catalog_names: |
if catalog_names: |
240 |
break |
break |
241 |
|
|
242 |
for name in catalog_names: |
for name in catalog_names: |
243 |
catalog = self._getOb(name) |
catalog = self._getOb(name) |
244 |
try: |
try: |
271 |
if context is None: |
if context is None: |
272 |
raise TypeError, 'No destination language' |
raise TypeError, 'No destination language' |
273 |
else: |
else: |
274 |
langs = [m[0] for m in self._catalogs.keys() if m[1] == domain] + \ |
langs = [m[0] for m in catalogRegistry.keys() if m[1] == domain] + \ |
275 |
[m[0] for m in self._fb_catalogs.keys() if m[1] == domain] |
[m[0] for m in fbcatalogRegistry.keys() if m[1] == domain] |
276 |
for fallback in self._fallbacks: |
for fallback in self._fallbacks: |
277 |
if fallback not in langs: |
if fallback not in langs: |
278 |
langs.append(fallback) |
langs.append(fallback) |
289 |
"""Insert the data passed from mapping into the text""" |
"""Insert the data passed from mapping into the text""" |
290 |
|
|
291 |
# If the mapping does not exist, make a "raw translation" without |
# If the mapping does not exist, make a "raw translation" without |
292 |
# interpolation. |
# interpolation. |
293 |
if mapping is None or type(text) not in (StringType, UnicodeType): |
if mapping is None or type(text) not in (StringType, UnicodeType): |
294 |
# silly wabbit! |
# silly wabbit! |
295 |
return text |
return text |