1
##############################################################################
3
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
13
##############################################################################
14
"""Translation Domain Message Export and Import Filters
16
$Id: filters.py 38178 2005-08-30 21:50:19Z mj $
18
__docformat__ = 'restructuredtext'
21
from types import StringTypes
22
from zope.interface import implements
24
from zope.i18n.interfaces import IMessageExportFilter, IMessageImportFilter
25
from zope.app.i18n.interfaces import ILocalTranslationDomain
28
class ParseError(Exception):
29
def __init__(self, state, lineno):
30
Exception.__init__(self, state, lineno)
35
return "state %s, line %s" % (self.state, self.lineno)
38
class GettextExportFilter(object):
40
implements(IMessageExportFilter)
41
__used_for__ = ILocalTranslationDomain
44
def __init__(self, domain):
47
def exportMessages(self, languages):
48
'See IMessageExportFilter'
49
domain = self.domain.domain
51
if isinstance(languages, StringTypes):
53
elif len(languages) == 1:
54
language = languages[0]
57
'Only one language at a time is supported for gettext export.')
60
dt = time.localtime(dt)
61
dt = time.strftime('%Y/%m/%d %H:%M', dt)
62
output = _file_header %(dt, language.encode('UTF-8'),
63
domain.encode('UTF-8'))
65
for msgid in self.domain.getMessageIds():
66
msgstr = self.domain.translate(msgid, target_language=language)
67
msgstr = msgstr.encode('UTF-8')
68
msgid = msgid.encode('UTF-8')
69
output += _msg_template %(msgid, msgstr)
75
class GettextImportFilter(object):
77
implements(IMessageImportFilter)
78
__used_for__ = ILocalTranslationDomain
81
def __init__(self, domain):
84
def importMessages(self, languages, file):
85
'See IMessageImportFilter'
87
if isinstance(languages, StringTypes):
89
elif len(languages) == 1:
90
language = languages[0]
93
'Only one language at a time is supported for gettext export.')
95
result = parseGetText(file.readlines())[3]
96
headers = parserHeaders(''.join(result[('',)][1]))
98
charset = extractCharset(headers['content-type'])
99
for msg in result.items():
100
msgid = unicode(''.join(msg[0]), charset)
101
msgid = msgid.replace('\\n', '\n')
102
msgstr = unicode(''.join(msg[1][1]), charset)
103
msgstr = msgstr.replace('\\n', '\n')
104
self.domain.addMessage(msgid, msgstr, language)
108
def extractCharset(header):
109
charset = header.split('charset=')[-1]
110
return charset.lower()
113
def parserHeaders(headers_text):
115
for line in headers_text.split('\\n'):
116
name = line.split(':')[0]
117
value = ''.join(line.split(':')[1:])
118
headers[name.lower()] = value
123
def parseGetText(content):
124
# The regular expressions
125
com = re.compile('^#.*')
126
msgid = re.compile(r'^ *msgid *"(.*?[^\\]*)"')
127
msgstr = re.compile(r'^ *msgstr *"(.*?[^\\]*)"')
128
re_str = re.compile(r'^ *"(.*?[^\\])"')
129
blank = re.compile(r'^\s*$')
134
COM, MSGID, MSGSTR = [], [], []
135
while pointer < len(content):
136
line = content[pointer]
137
#print 'STATE:', state
138
#print 'LINE:', line, content[pointer].strip()
140
COM, MSGID, MSGSTR = [], [], []
142
COM.append(line.strip())
144
pointer = pointer + 1
145
elif msgid.match(line):
146
MSGID.append(msgid.match(line).group(1))
148
pointer = pointer + 1
149
elif blank.match(line):
150
pointer = pointer + 1
152
raise ParseError(0, pointer + 1)
155
COM.append(line.strip())
157
pointer = pointer + 1
158
elif msgid.match(line):
159
MSGID.append(msgid.match(line).group(1))
161
pointer = pointer + 1
162
elif blank.match(line):
163
pointer = pointer + 1
165
raise ParseError(1, pointer + 1)
169
COM.append(line.strip())
171
pointer = pointer + 1
172
elif re_str.match(line):
173
MSGID.append(re_str.match(line).group(1))
175
pointer = pointer + 1
176
elif msgstr.match(line):
177
MSGSTR.append(msgstr.match(line).group(1))
179
pointer = pointer + 1
180
elif blank.match(line):
181
pointer = pointer + 1
183
raise ParseError(2, pointer + 1)
186
if com.match(line) or msgid.match(line):
187
# print "\nEn", language, "detected", MSGID
188
trans[tuple(MSGID)] = (COM, MSGSTR)
190
elif re_str.match(line):
191
MSGSTR.append(re_str.match(line).group(1))
193
pointer = pointer + 1
194
elif blank.match(line):
195
pointer = pointer + 1
197
raise ParseError(3, pointer + 1)
199
# the last also goes in
201
trans[tuple(MSGID)] = (COM, MSGSTR)
203
return COM, MSGID, MSGSTR, trans
209
"Project-Id-Version: Zope 3\\n"
210
"PO-Revision-Date: %s\\n"
211
"Last-Translator: Zope 3 Gettext Export Filter\\n"
212
"Zope-Language: %s\\n"
214
"MIME-Version: 1.0\\n"
215
"Content-Type: text/plain; charset=UTF-8\\n"
216
"Content-Transfer-Encoding: 8bit\\n"