1
2
3
4
5 """Generate binary message catalog from textual translation description.
6
7 This program converts a textual Uniforum-style message catalog (.po file) into
8 a binary GNU catalog (.mo file). This is essentially the same function as the
9 GNU msgfmt program, however, it is a simpler implementation.
10
11 Usage: msgfmt.py [OPTIONS] filename.po
12
13 Options:
14 -o file
15 --output-file=file
16 Specify the output file to write to. If omitted, output will go to a
17 file named filename.mo (based off the input file name).
18
19 -h
20 --help
21 Print this message and exit.
22
23 -V
24 --version
25 Display version information and exit.
26 """
27
28 import sys
29 import os
30 import getopt
31 import struct
32 import array
33
34 __version__ = '1.1'
35
36 MESSAGES = {}
37
38
40 print >> sys.stderr, __doc__
41 if msg:
42 print >> sys.stderr, msg
43 sys.exit(code)
44
45
46 -def add(msgid, msgstr, fuzzy):
47 """Add a non-fuzzy translation to the dictionary."""
48 if not fuzzy and msgstr:
49 MESSAGES[msgid] = msgstr
50
51
53 """Return the generated output."""
54 keys = MESSAGES.keys()
55
56 keys.sort()
57 offsets = []
58 msgids = msgstrs = ''
59 for msgid in keys:
60
61
62 offsets.append((len(msgids), len(msgid),
63 len(msgstrs), len(MESSAGES[msgid])))
64 msgids += msgid + '\0'
65 msgstrs += MESSAGES[msgid] + '\0'
66
67
68 keystart = 7*4+16*len(keys)
69
70 valuestart = keystart + len(msgids)
71 koffsets = []
72 voffsets = []
73
74
75 for offset1, len1, offset2, len2 in offsets:
76 koffsets += [len1, offset1 + keystart]
77 voffsets += [len2, offset2 + valuestart]
78 offsets = koffsets + voffsets
79 output = struct.pack("Iiiiiii",
80 0x950412deL,
81 0,
82 len(keys),
83 7*4,
84 7*4+len(keys)*8,
85 0, 0)
86 output += array.array("i", offsets).tostring()
87 output += msgids
88 output += msgstrs
89 return output
90
91
92 -def make(filename, outfile):
93 """Generate the binary message catalog."""
94
95 MESSAGES.clear()
96
97 MSGID = 1
98 MSGSTR = 2
99
100
101 if filename.endswith('.po'):
102 infile = filename
103 else:
104 infile = filename + '.po'
105 if outfile is None:
106 outfile = os.path.splitext(infile)[0] + '.mo'
107
108 try:
109 lines = open(infile).readlines()
110 except IOError, msg:
111 print >> sys.stderr, msg
112 sys.exit(1)
113
114 section = None
115 fuzzy = 0
116
117
118 lno = 0
119 msgid = msgstr = ''
120 for line in lines:
121 lno += 1
122
123 if line[0] == '#' and section == MSGSTR:
124 add(msgid, msgstr, fuzzy)
125 section = None
126 fuzzy = 0
127
128 if line[:2] == '#,' and line.find('fuzzy'):
129 fuzzy = 1
130
131 if line[0] == '#':
132 continue
133
134 if line.startswith('msgid'):
135 if section == MSGSTR:
136 add(msgid, msgstr, fuzzy)
137 section = MSGID
138 line = line[5:]
139 msgid = msgstr = ''
140
141 elif line.startswith('msgstr'):
142 section = MSGSTR
143 line = line[6:]
144
145 line = line.strip()
146 if not line:
147 continue
148
149 line = eval(line)
150 if section == MSGID:
151 msgid += line
152 elif section == MSGSTR:
153 msgstr += line
154 else:
155 print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
156 'before:'
157 print >> sys.stderr, line
158 sys.exit(1)
159
160 if section == MSGSTR:
161 add(msgid, msgstr, fuzzy)
162
163
164 output = generate()
165
166 try:
167 open(outfile,"wb").write(output)
168 except IOError,msg:
169 print >> sys.stderr, msg
170
171
173 try:
174 opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
175 ['help', 'version', 'output-file='])
176 except getopt.error, msg:
177 usage(1, msg)
178
179 outfile = None
180
181 for opt, arg in opts:
182 if opt in ('-h', '--help'):
183 usage(0)
184 elif opt in ('-V', '--version'):
185 print >> sys.stderr, "msgfmt.py", __version__
186 sys.exit(0)
187 elif opt in ('-o', '--output-file'):
188 outfile = arg
189
190 if not args:
191 print >> sys.stderr, 'No input file given'
192 print >> sys.stderr, "Try `msgfmt --help' for more information."
193 return
194
195 for filename in args:
196 make(filename, outfile)
197
198
199 if __name__ == '__main__':
200 main()
201