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 output = ''
67
68
69 keystart = 7*4+16*len(keys)
70
71 valuestart = keystart + len(msgids)
72 koffsets = []
73 voffsets = []
74
75
76 for offset1, len1, offset2, len2 in offsets:
77 koffsets += [len1, offset1 + keystart]
78 voffsets += [len2, offset2 + valuestart]
79 offsets = koffsets + voffsets
80 output = struct.pack("Iiiiiii",
81 0x950412deL,
82 0,
83 len(keys),
84 7*4,
85 7*4+len(keys)*8,
86 0, 0)
87 output += array.array("i", offsets).tostring()
88 output += msgids
89 output += msgstrs
90 return output
91
92
93 -def make(filename, outfile):
94 """Generate the binary message catalog."""
95
96 MESSAGES.clear()
97
98 MSGID = 1
99 MSGSTR = 2
100
101
102 if filename.endswith('.po'):
103 infile = filename
104 else:
105 infile = filename + '.po'
106 if outfile is None:
107 outfile = os.path.splitext(infile)[0] + '.mo'
108
109 try:
110 lines = open(infile).readlines()
111 except IOError, msg:
112 print >> sys.stderr, msg
113 sys.exit(1)
114
115 section = None
116 fuzzy = 0
117
118
119 lno = 0
120 msgid = msgstr = ''
121 for line in lines:
122 lno += 1
123
124 if line[0] == '#' and section == MSGSTR:
125 add(msgid, msgstr, fuzzy)
126 section = None
127 fuzzy = 0
128
129 if line[:2] == '#,' and line.find('fuzzy'):
130 fuzzy = 1
131
132 if line[0] == '#':
133 continue
134
135 if line.startswith('msgid'):
136 if section == MSGSTR:
137 add(msgid, msgstr, fuzzy)
138 section = MSGID
139 line = line[5:]
140 msgid = msgstr = ''
141
142 elif line.startswith('msgstr'):
143 section = MSGSTR
144 line = line[6:]
145
146 line = line.strip()
147 if not line:
148 continue
149
150 line = eval(line)
151 if section == MSGID:
152 msgid += line
153 elif section == MSGSTR:
154 msgstr += line
155 else:
156 print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
157 'before:'
158 print >> sys.stderr, line
159 sys.exit(1)
160
161 if section == MSGSTR:
162 add(msgid, msgstr, fuzzy)
163
164
165 output = generate()
166
167 try:
168 open(outfile,"wb").write(output)
169 except IOError,msg:
170 print >> sys.stderr, msg
171
172
174 try:
175 opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
176 ['help', 'version', 'output-file='])
177 except getopt.error, msg:
178 usage(1, msg)
179
180 outfile = None
181
182 for opt, arg in opts:
183 if opt in ('-h', '--help'):
184 usage(0)
185 elif opt in ('-V', '--version'):
186 print >> sys.stderr, "msgfmt.py", __version__
187 sys.exit(0)
188 elif opt in ('-o', '--output-file'):
189 outfile = arg
190
191 if not args:
192 print >> sys.stderr, 'No input file given'
193 print >> sys.stderr, "Try `msgfmt --help' for more information."
194 return
195
196 for filename in args:
197 make(filename, outfile)
198
199
200 if __name__ == '__main__':
201 main()
202