Fix regression that broke loading translations from .po files in the working directory

This commit is contained in:
Kovid Goyal 2011-07-21 00:12:14 -06:00
parent 629da2b324
commit ca1367048d
2 changed files with 83 additions and 24 deletions

View File

@ -1,20 +1,39 @@
#! /usr/bin/env python #! /usr/bin/env python
# Written by Martin v. Loewis <loewis@informatik.hu-berlin.de> # Written by Martin v. Loewis <loewis@informatik.hu-berlin.de>
# Modified by Kovid Goyal <kovid@kovidgoyal.net>
"""Generate binary message catalog from textual translation description. """Generate binary message catalog from textual translation description.
This program converts a textual Uniforum-style message catalog (.po file) into This program converts a textual Uniforum-style message catalog (.po file) into
a binary GNU catalog (.mo file). This is essentially the same function as the a binary GNU catalog (.mo file). This is essentially the same function as the
GNU msgfmt program, however, it is a simpler implementation. GNU msgfmt program, however, it is a simpler implementation.
Usage: msgfmt.py [OPTIONS] filename.po
Options:
-o file
--output-file=file
Specify the output file to write to. If omitted, output will go to a
file named filename.mo (based off the input file name).
-h
--help
Print this message and exit.
-V
--version
Display version information and exit.
""" """
import sys import sys
import os import os
import getopt
import struct import struct
import array import array
__version__ = "1.2" __version__ = "1.1"
MESSAGES = {}
def usage(code, msg=''): def usage(code, msg=''):
print >> sys.stderr, __doc__ print >> sys.stderr, __doc__
@ -23,16 +42,16 @@ def usage(code, msg=''):
sys.exit(code) sys.exit(code)
def add(id, str, fuzzy):
def add(id, str, fuzzy, MESSAGES):
"Add a non-fuzzy translation to the dictionary." "Add a non-fuzzy translation to the dictionary."
global MESSAGES
if not fuzzy and str: if not fuzzy and str:
MESSAGES[id] = str MESSAGES[id] = str
def generate():
def generate(MESSAGES):
"Return the generated output." "Return the generated output."
global MESSAGES
keys = MESSAGES.keys() keys = MESSAGES.keys()
# the keys are sorted in the .mo file # the keys are sorted in the .mo file
keys.sort() keys.sort()
@ -44,6 +63,7 @@ def generate(MESSAGES):
offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id]))) offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id])))
ids += id + '\0' ids += id + '\0'
strs += MESSAGES[id] + '\0' strs += MESSAGES[id] + '\0'
output = ''
# The header is 7 32-bit unsigned integers. We don't use hash tables, so # The header is 7 32-bit unsigned integers. We don't use hash tables, so
# the keys start right after the index tables. # the keys start right after the index tables.
# translated string. # translated string.
@ -71,9 +91,7 @@ def generate(MESSAGES):
return output return output
def make(filename, outfile): def make(filename, outfile):
MESSAGES = {}
ID = 1 ID = 1
STR = 2 STR = 2
@ -101,7 +119,7 @@ def make(filename, outfile):
lno += 1 lno += 1
# If we get a comment line after a msgstr, this is a new entry # If we get a comment line after a msgstr, this is a new entry
if l[0] == '#' and section == STR: if l[0] == '#' and section == STR:
add(msgid, msgstr, fuzzy, MESSAGES) add(msgid, msgstr, fuzzy)
section = None section = None
fuzzy = 0 fuzzy = 0
# Record a fuzzy mark # Record a fuzzy mark
@ -111,15 +129,38 @@ def make(filename, outfile):
if l[0] == '#': if l[0] == '#':
continue continue
# Now we are in a msgid section, output previous section # Now we are in a msgid section, output previous section
if l.startswith('msgid'): if l.startswith('msgid') and not l.startswith('msgid_plural'):
if section == STR: if section == STR:
add(msgid, msgstr, fuzzy, MESSAGES) add(msgid, msgstr, fuzzy)
section = ID section = ID
l = l[5:] l = l[5:]
msgid = msgstr = '' msgid = msgstr = ''
is_plural = False
# This is a message with plural forms
elif l.startswith('msgid_plural'):
if section != ID:
print >> sys.stderr, 'msgid_plural not preceeded by msgid on %s:%d' %\
(infile, lno)
sys.exit(1)
l = l[12:]
msgid += '\0' # separator of singular and plural
is_plural = True
# Now we are in a msgstr section # Now we are in a msgstr section
elif l.startswith('msgstr'): elif l.startswith('msgstr'):
section = STR section = STR
if l.startswith('msgstr['):
if not is_plural:
print >> sys.stderr, 'plural without msgid_plural on %s:%d' %\
(infile, lno)
sys.exit(1)
l = l.split(']', 1)[1]
if msgstr:
msgstr += '\0' # Separator of the various plural forms
else:
if is_plural:
print >> sys.stderr, 'indexed msgstr required for plural on %s:%d' %\
(infile, lno)
sys.exit(1)
l = l[6:] l = l[6:]
# Skip empty lines # Skip empty lines
l = l.strip() l = l.strip()
@ -138,22 +179,40 @@ def make(filename, outfile):
sys.exit(1) sys.exit(1)
# Add last entry # Add last entry
if section == STR: if section == STR:
add(msgid, msgstr, fuzzy, MESSAGES) add(msgid, msgstr, fuzzy)
# Compute output # Compute output
output = generate(MESSAGES) output = generate()
try:
outfile.write(output) outfile.write(output)
except IOError,msg:
print >> sys.stderr, msg
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
['help', 'version', 'output-file='])
except getopt.error, msg:
usage(1, msg)
outfile = None
# parse options
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
elif opt in ('-V', '--version'):
print >> sys.stderr, "msgfmt.py", __version__
sys.exit(0)
elif opt in ('-o', '--output-file'):
outfile = arg
# do it
if not args:
print >> sys.stderr, 'No input file given'
print >> sys.stderr, "Try `msgfmt --help' for more information."
return
def main(outfile, args=sys.argv[1:]):
for filename in args: for filename in args:
make(filename, outfile) make(filename, outfile)
return 0
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main(sys.stdout)) main()

View File

@ -71,13 +71,13 @@ def set_translators():
lang = get_lang() lang = get_lang()
if lang: if lang:
buf = iso639 = None buf = iso639 = None
if os.access(lang+'.po', os.R_OK): mpath = get_lc_messages_path(lang)
if os.access(mpath+'.po', os.R_OK):
from calibre.translations.msgfmt import make from calibre.translations.msgfmt import make
buf = cStringIO.StringIO() buf = cStringIO.StringIO()
make(lang+'.po', buf) make(mpath+'.po', buf)
buf = cStringIO.StringIO(buf.getvalue()) buf = cStringIO.StringIO(buf.getvalue())
mpath = get_lc_messages_path(lang)
if mpath is not None: if mpath is not None:
with ZipFile(P('localization/locales.zip', with ZipFile(P('localization/locales.zip',
allow_user_override=False), 'r') as zf: allow_user_override=False), 'r') as zf: