1
|
1 # -*- coding: utf-8 -*-
|
|
2 #
|
|
3 # Copyright (C) 2007 Edgewall Software
|
|
4 # All rights reserved.
|
|
5 #
|
|
6 # This software is licensed as described in the file COPYING, which
|
|
7 # you should have received as part of this distribution. The terms
|
|
8 # are also available at http://babel.edgewall.org/wiki/License.
|
|
9 #
|
|
10 # This software consists of voluntary contributions made by many
|
|
11 # individuals. For the exact contribution history, see the revision
|
|
12 # history and logs, available at http://babel.edgewall.org/log/.
|
|
13
|
|
14 """Frontends for the message extraction functionality."""
|
|
15
|
|
16 from distutils import log
|
|
17 from distutils.cmd import Command
|
|
18 from optparse import OptionParser
|
|
19 import os
|
|
20 import sys
|
|
21
|
|
22 from babel import __version__ as VERSION
|
|
23 from babel.catalog.extract import extract_from_dir, KEYWORDS
|
|
24 from babel.catalog.pofile import write_po
|
|
25
|
|
26 __all__ = ['extract_messages', 'main']
|
|
27 __docformat__ = 'restructuredtext en'
|
|
28
|
|
29
|
|
30 class extract_messages(Command):
|
|
31 """Message extraction command for use in ``setup.py`` scripts.
|
|
32
|
|
33 If correctly installed, this command is available to Setuptools-using
|
|
34 setup scripts automatically. For projects using plain old ``distutils``,
|
|
35 the command needs to be registered explicitly in ``setup.py``::
|
|
36
|
|
37 from babel.catalog.frontend import extract_messages
|
|
38
|
|
39 setup(
|
|
40 ...
|
|
41 cmdclass = {'extract_messages': extract_messages}
|
|
42 )
|
|
43
|
|
44 :see: `Integrating new distutils commands <http://docs.python.org/dist/node32.html>`_
|
|
45 :see: `setuptools <http://peak.telecommunity.com/DevCenter/setuptools>`_
|
|
46 """
|
|
47
|
|
48 description = 'extract localizable strings from the project code'
|
|
49 user_options = [
|
|
50 ('charset=', None,
|
|
51 'charset to use in the output file'),
|
|
52 ('keywords=', 'k',
|
|
53 'comma-separated list of keywords to look for in addition to the '
|
|
54 'defaults'),
|
|
55 ('no-location', None,
|
|
56 'do not include location comments with filename and line number'),
|
|
57 ('omit-header', None,
|
|
58 'do not include msgid "" entry in header'),
|
|
59 ('output-file=', None,
|
|
60 'name of the output file'),
|
|
61 ]
|
|
62 boolean_options = ['no-location', 'omit-header']
|
|
63
|
|
64 def initialize_options(self):
|
|
65 self.charset = 'utf-8'
|
|
66 self.keywords = KEYWORDS
|
|
67 self.no_location = False
|
|
68 self.omit_header = False
|
|
69 self.output_file = None
|
|
70 self.input_dirs = None
|
|
71
|
|
72 def finalize_options(self):
|
|
73 if not self.input_dirs:
|
|
74 self.input_dirs = dict.fromkeys([k.split('.',1)[0]
|
|
75 for k in self.distribution.packages
|
|
76 ]).keys()
|
|
77 if isinstance(self.keywords, basestring):
|
|
78 new_keywords = [k.strip() for k in self.keywords.split(',')]
|
|
79 self.keywords = list(KEYWORDS) + new_keywords
|
|
80
|
|
81 def run(self):
|
|
82 outfile = open(self.output_file, 'w')
|
|
83 try:
|
|
84 messages = []
|
|
85 for dirname in self.input_dirs:
|
|
86 log.info('extracting messages from %r' % dirname)
|
|
87 extracted = extract_from_dir(dirname, keywords=self.keywords)
|
|
88 for filename, lineno, funcname, message in extracted:
|
|
89 messages.append((os.path.join(dirname, filename), lineno,
|
|
90 funcname, message))
|
|
91 write_po(outfile, messages, charset=self.charset,
|
|
92 no_location=self.no_location, omit_header=self.omit_header)
|
|
93 log.info('writing PO file to %s' % self.output_file)
|
|
94 finally:
|
|
95 outfile.close()
|
|
96
|
|
97
|
|
98 def main(argv=sys.argv):
|
|
99 """Command-line interface.
|
|
100
|
|
101 This function provides a simple command-line interface to the message
|
|
102 extraction and PO file generation functionality.
|
|
103
|
|
104 :param argv: list of arguments passed on the command-line
|
|
105 """
|
|
106 parser = OptionParser(usage='%prog [options] dirname1 <dirname2> ...',
|
|
107 version='%%prog %s' % VERSION)
|
|
108 parser.add_option('--charset', dest='charset', default='utf-8',
|
|
109 help='charset to use in the output')
|
|
110 parser.add_option('-k', '--keyword', dest='keywords',
|
|
111 default=list(KEYWORDS), action='append',
|
|
112 help='keywords to look for in addition to the defaults. '
|
|
113 'You can specify multiple -k flags on the command '
|
|
114 'line.')
|
|
115 parser.add_option('--no-location', dest='no_location', default=False,
|
|
116 action='store_true',
|
|
117 help='do not include location comments with filename and '
|
|
118 'line number')
|
|
119 parser.add_option('--omit-header', dest='omit_header', default=False,
|
|
120 action='store_true',
|
|
121 help='do not include msgid "" entry in header')
|
|
122 parser.add_option('-o', '--output', dest='output',
|
|
123 help='path to the output POT file')
|
|
124 options, args = parser.parse_args(argv[1:])
|
|
125 if not args:
|
|
126 parser.error('incorrect number of arguments')
|
|
127
|
|
128 if options.output not in (None, '-'):
|
|
129 outfile = open(options.output, 'w')
|
|
130 else:
|
|
131 outfile = sys.stdout
|
|
132
|
|
133 try:
|
|
134 messages = []
|
|
135 for dirname in args:
|
|
136 if not os.path.isdir(dirname):
|
|
137 parser.error('%r is not a directory' % dirname)
|
|
138 extracted = extract_from_dir(dirname, keywords=options.keywords)
|
|
139 for filename, lineno, funcname, message in extracted:
|
|
140 messages.append((os.path.join(dirname, filename), lineno,
|
|
141 funcname, message))
|
|
142 write_po(outfile, messages,
|
|
143 charset=options.charset, no_location=options.no_location,
|
|
144 omit_header=options.omit_header)
|
|
145 finally:
|
|
146 if options.output:
|
|
147 outfile.close()
|
|
148
|
|
149 if __name__ == '__main__':
|
|
150 main()
|