# HG changeset patch # User palgarvio # Date 1180651497 0 # Node ID bd45ff4254857a97cec23c2e7185f1dccd6e97a4 # Parent 7d37639a741162f4e69c58afd2c17b6acf9268f0 Added line-wrap support for `write_po`. Fixed bug on the distutils frontend regarding the `keywords`. diff --git a/babel/catalog/frontend.py b/babel/catalog/frontend.py --- a/babel/catalog/frontend.py +++ b/babel/catalog/frontend.py @@ -15,6 +15,7 @@ from distutils import log from distutils.cmd import Command +from distutils.errors import DistutilsOptionError from optparse import OptionParser import os import sys @@ -60,28 +61,49 @@ 'do not include msgid "" entry in header'), ('output-file=', 'o', 'name of the output file'), + ('width=', 'w', + 'set output line width. Default: 76'), + ('no-wrap', None, + 'do not break long message lines, longer than the output ' + 'line width, into several lines.') ] - boolean_options = ['no-default-keywords', 'no-location', 'omit-header'] + boolean_options = [ + 'no-default-keywords', 'no-location', 'omit-header', 'no-wrap' + ] def initialize_options(self): self.charset = 'utf-8' - self.keywords = DEFAULT_KEYWORDS.copy() + self.keywords = self._keywords = DEFAULT_KEYWORDS.copy() self.no_default_keywords = False self.no_location = False self.omit_header = False self.output_file = None self.input_dirs = None + self.width = None + self.no_wrap = False def finalize_options(self): if not self.input_dirs: self.input_dirs = dict.fromkeys([k.split('.',1)[0] for k in self.distribution.packages ]).keys() + if self.no_default_keywords and not self.keywords: + raise DistutilsOptionError, \ + 'you must specify new keywords if you disable the default ones' if self.no_default_keywords: - self.keywords = {} + self._keywords = {} if isinstance(self.keywords, basestring): - new_keywords = parse_keywords(self.keywords.split()) - self.keywords.update(new_keywords) + self._keywords.update(parse_keywords(self.keywords.split())) + self.keywords = self._keywords + if self.no_wrap and self.width: + raise DistutilsOptionError, \ + "'--no-wrap' and '--width' are mutually exclusive." + elif self.no_wrap and not self.width: + self.width = 0 + elif not self.no_wrap and not self.width: + self.width = 76 + elif self.width and not self.no_wrap: + self.width = int(self.width) def run(self): outfile = open(self.output_file, 'w') @@ -96,7 +118,7 @@ write_po(outfile, messages, project=self.distribution.get_name(), version=self.distribution.get_version(), charset=self.charset, no_location=self.no_location, - omit_header=self.omit_header) + omit_header=self.omit_header, width=self.width) log.info('writing PO file to %s' % self.output_file) finally: outfile.close() @@ -131,6 +153,12 @@ help='do not include msgid "" entry in header') parser.add_option('-o', '--output', dest='output', help='path to the output POT file') + parser.add_option('-w', '--width', dest='width', type='int', + help="set output line width. Default: 76") + parser.add_option('--no-wrap', dest='no_wrap', default=False, + action = 'store_true', help='do not break long message ' + 'lines, longer than the output line width, into several ' + 'lines.') options, args = parser.parse_args(argv[1:]) if not args: parser.error('incorrect number of arguments') @@ -148,6 +176,13 @@ keywords = {} if options.keywords: keywords.update(parse_keywords(options.keywords)) + + if options.width and options.no_wrap: + parser.error("'--no-wrap' and '--width' are mutually exclusive.") + elif not options.width and not options.no_wrap: + options.width = 76 + elif not options.width and options.no_wrap: + options.width = 0 try: messages = [] @@ -160,7 +195,7 @@ funcname, message, None)) write_po(outfile, messages, charset=options.charset, no_location=options.no_location, - omit_header=options.omit_header) + omit_header=options.omit_header, width=options.width) finally: if options.output: outfile.close() diff --git a/babel/catalog/pofile.py b/babel/catalog/pofile.py --- a/babel/catalog/pofile.py +++ b/babel/catalog/pofile.py @@ -19,7 +19,7 @@ """ # TODO: line wrapping - +from textwrap import wrap from datetime import date, datetime import re try: @@ -195,7 +195,7 @@ if messages: yield pack() -def write_po(fileobj, messages, project='PROJECT', version='VERSION', +def write_po(fileobj, messages, project='PROJECT', version='VERSION', width=76, charset='utf-8', no_location=False, omit_header=False): r"""Write a ``gettext`` PO (portable object) file to the given file-like object. @@ -268,18 +268,53 @@ for msgid in msgids: if not no_location: - for filename, lineno in locations[msgid]: - fileobj.write('#: %s:%s\n' % (filename, lineno)) + locs = [ + u' %s:%s' % (fname, lineno) for + fname, lineno in locations[msgid] + ] + if width > 0: + wrapped = wrap(u''.join(locs), width, break_long_words=False) + else: + wrapped = locs + for line in wrapped: + fileobj.write(u'#: %s\n' % line.strip()) flags = msgflags[msgid] if flags: fileobj.write('#%s\n' % ', '.join([''] + list(flags))) if type(msgid) is tuple: assert len(msgid) == 2 - fileobj.write('msgid %s\n' % normalize(msgid[0], charset)) - fileobj.write('msgid_plural %s\n' % normalize(msgid[1], charset)) + if width > 0: + wrapped = wrap(msgid[0], width, break_long_words=False) + else: + wrapped = [msgid[0]] + if len(wrapped) == 1: + fileobj.write('msgid ') + else: + fileobj.write('msgid ""\n') + for line in wrapped: + fileobj.write('%s\n' % normalize(line, charset)) + if width > 0: + wrapped = wrap(msgid[1], width, break_long_words=False) + else: + wrapped = [msgid[1]] + if len(wrapped) == 1: + fileobj.write('msgid_plural ') + else: + fileobj.write('msgid_plural ""\n') + for line in wrapped: + fileobj.write('%s\n' % normalize(line, charset)) fileobj.write('msgstr[0] ""\n') fileobj.write('msgstr[1] ""\n') else: - fileobj.write('msgid %s\n' % normalize(msgid, charset)) + if width > 0: + wrapped = wrap(msgid, width, break_long_words=False) + else: + wrapped = [msgid] + if len(wrapped) == 1: + fileobj.write('msgid ') + else: + fileobj.write('msgid ""\n') + for line in wrapped: + fileobj.write('%s\n' % normalize(line, charset)) fileobj.write('msgstr ""\n') fileobj.write('\n')