1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
# ##############################################################################
#
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""This module handles the 'i18n' namespace directives.
$Id$
"""
__docformat__ = 'restructuredtext'
import os
from zope.component import getSiteManager
from zope.component import queryUtility
from zope.component.interface import provideInterface
from zope.configuration.fields import Path
from zope.interface import Interface
from zope.i18n import config
from zope.i18n.compile import compile_mo_file
from zope.i18n.gettextmessagecatalog import GettextMessageCatalog
from zope.i18n.testmessagecatalog import TestMessageCatalog
from zope.i18n.translationdomain import TranslationDomain
from zope.i18n.interfaces import ITranslationDomain
class IRegisterTranslationsDirective(Interface):
"""Register translations with the global site manager."""
directory = Path(
title=u"Directory",
description=u"Directory containing the translations",
required=True
)
def allow_language(lang):
if config.ALLOWED_LANGUAGES is None:
return True
return lang in config.ALLOWED_LANGUAGES
def handler(catalogs, name):
""" special handler handling the merging of two message catalogs """
gsm = getSiteManager()
# Try to get an existing domain and add the given catalogs to it
domain = queryUtility(ITranslationDomain, name)
if domain is None:
domain = TranslationDomain(name)
gsm.registerUtility(domain, ITranslationDomain, name=name)
for catalog in catalogs:
domain.addCatalog(catalog)
# make sure we have a TEST catalog for each domain:
domain.addCatalog(TestMessageCatalog(name))
def registerTranslations(_context, directory):
path = os.path.normpath(directory)
domains = {}
# Gettext has the domain-specific catalogs inside the language directory,
# which is exactly the opposite as we need it. So create a dictionary that
# reverses the nesting.
for language in os.listdir(path):
if not allow_language(language):
continue
lc_messages_path = os.path.join(path, language, 'LC_MESSAGES')
if os.path.isdir(lc_messages_path):
# Preprocess files and update or compile the mo files
if config.COMPILE_MO_FILES:
for domain_file in os.listdir(lc_messages_path):
if domain_file.endswith('.po'):
domain = domain_file[:-3]
compile_mo_file(domain, lc_messages_path)
for domain_file in os.listdir(lc_messages_path):
if domain_file.endswith('.mo'):
domain_path = os.path.join(lc_messages_path, domain_file)
domain = domain_file[:-3]
if not domain in domains:
domains[domain] = {}
domains[domain][language] = domain_path
# Now create TranslationDomain objects and add them as utilities
for name, langs in domains.items():
catalogs = []
for lang, file in langs.items():
catalogs.append(GettextMessageCatalog(lang, name, file))
# register the necessary actions directly (as opposed to using
# `zope.component.zcml.utility`) since we need the actual utilities
# in place before the merging can be done...
_context.action(
discriminator = None,
callable = handler,
args = (catalogs, name))
# also register the interface for the translation utilities
provides = ITranslationDomain
_context.action(
discriminator = None,
callable = provideInterface,
args = (provides.__module__ + '.' + provides.getName(), provides))
|