1 | #!/usr/bin/env python |
---|
2 | import sys |
---|
3 | import string |
---|
4 | import xmllib |
---|
5 | |
---|
6 | class TranslatableStringParser(xmllib.XMLParser): |
---|
7 | def __init__(self): |
---|
8 | xmllib.XMLParser.__init__(self) |
---|
9 | self.filename = None |
---|
10 | self.strings = {} |
---|
11 | self.data = "" |
---|
12 | def add_string(self, string): |
---|
13 | if string == "": |
---|
14 | return |
---|
15 | if self.strings.has_key(string): |
---|
16 | self.strings[string].append((self.filename, |
---|
17 | self.lineno)) |
---|
18 | else: |
---|
19 | self.strings[string] = [(self.filename, self.lineno)] |
---|
20 | |
---|
21 | def read_file(self, filename): |
---|
22 | self.reset() |
---|
23 | self.filename = filename |
---|
24 | fp = open(filename, "r") |
---|
25 | data = fp.read(8192) |
---|
26 | while data: |
---|
27 | self.feed(data) |
---|
28 | data = fp.read(8192) |
---|
29 | fp.close() |
---|
30 | |
---|
31 | def syntax_error(self, message): |
---|
32 | sys.stderr.write("%s:%d: %s\n" % (self.filename, self.lineno, |
---|
33 | message)) |
---|
34 | sys.exit(1) |
---|
35 | |
---|
36 | def unknown_starttag(self, tag, attrs): |
---|
37 | self.data = "" |
---|
38 | def handle_data(self, data): |
---|
39 | self.data = self.data + data |
---|
40 | |
---|
41 | def translate_this_string(self): |
---|
42 | self.add_string(self.data) |
---|
43 | |
---|
44 | # this list should include all tags for which translation should occur |
---|
45 | end_label = translate_this_string |
---|
46 | end_title = translate_this_string |
---|
47 | end_text = translate_this_string |
---|
48 | end_format = translate_this_string |
---|
49 | end_copyright = translate_this_string |
---|
50 | end_comments = translate_this_string |
---|
51 | end_preview_text = translate_this_string |
---|
52 | end_tooltip = translate_this_string |
---|
53 | def end_items(self): |
---|
54 | for item in string.split(self.data, '\n'): |
---|
55 | self.add_string(item) |
---|
56 | |
---|
57 | def output_pot(self, filename): |
---|
58 | strings = self.strings.keys() |
---|
59 | strings.sort() |
---|
60 | fp = open(filename, "w") |
---|
61 | fp.write('# SOME DESCRIPTIVE TITLE\n') |
---|
62 | for str in strings: |
---|
63 | pos = map(lambda x: "%s:%d" % x, self.strings[str]) |
---|
64 | length = 80 |
---|
65 | for p in pos: |
---|
66 | if length + len(p) > 74: |
---|
67 | fp.write('\n#:') |
---|
68 | length = 2 |
---|
69 | fp.write(' ') |
---|
70 | fp.write(p) |
---|
71 | length = length + 1 + len(p) |
---|
72 | fp.write('\n') |
---|
73 | if '\n' in str: |
---|
74 | fp.write('msgid ""\n') |
---|
75 | lines = string.split(str, '\n') |
---|
76 | lines = map(lambda x: |
---|
77 | '"%s\\n"\n' % (x,), |
---|
78 | lines[:-1]) + \ |
---|
79 | ['"%s"\n' % (lines[-1],)] |
---|
80 | fp.writelines(lines) |
---|
81 | else: |
---|
82 | fp.write('msgid "%s"\n' % (str,)) |
---|
83 | fp.write('msgstr ""\n') |
---|
84 | |
---|
85 | def output_c(self, filename): |
---|
86 | strings = self.strings.keys() |
---|
87 | strings.sort() |
---|
88 | fp = open(filename, "w") |
---|
89 | fp.write('/* SOME DESCRIPTIVE TITLE */\n') |
---|
90 | fp.write('/* This file is intended to be parsed by xgettext.\n') |
---|
91 | fp.write(' * It is not intended to be compiled.\n') |
---|
92 | fp.write(' */\n\n') |
---|
93 | fp.write('#if 0\n') |
---|
94 | fp.write('void some_function_name() {\n') |
---|
95 | for str in strings: |
---|
96 | pos = map(lambda x: "%s:%d" % x, self.strings[str]) |
---|
97 | fp.write('\n /*') |
---|
98 | length = 4 |
---|
99 | for p in pos: |
---|
100 | if length + len(p) > 74: |
---|
101 | fp.write('\n *') |
---|
102 | length = 4 |
---|
103 | fp.write(' ') |
---|
104 | fp.write(p) |
---|
105 | length = length + 1 + len(p) |
---|
106 | fp.write(' */\n') |
---|
107 | if '\n' in str: |
---|
108 | fp.write(' _(""\n') |
---|
109 | lines = string.split(str, '\n') |
---|
110 | lines = map(lambda x: |
---|
111 | ' "%s\\n"\n' % (x,), |
---|
112 | lines[:-1]) + \ |
---|
113 | [' "%s");\n' % (lines[-1],)] |
---|
114 | fp.writelines(lines) |
---|
115 | else: |
---|
116 | fp.write(' _("%s");\n' % (str,)) |
---|
117 | fp.write('}\n') |
---|
118 | fp.write('#endif\n') |
---|
119 | |
---|
120 | if __name__ == '__main__': |
---|
121 | import getopt |
---|
122 | |
---|
123 | options, args = getopt.getopt(sys.argv[1:], "cpo:vh", |
---|
124 | ["c", "pot", "output=","version","help"]) |
---|
125 | output = '' |
---|
126 | format = None |
---|
127 | for opt, optarg in options: |
---|
128 | if opt in ('-v', '--version'): |
---|
129 | print "libglade xgettext 0.0" |
---|
130 | sys.exit(0) |
---|
131 | if opt in ('-h', '--help'): |
---|
132 | print "Usage: libglade-xgettext [-c] [-p] [-o FILE] GLADEFILES" |
---|
133 | print "" |
---|
134 | print " -c, --c Force C output format" |
---|
135 | print " -p, --pot Force POT output format" |
---|
136 | print " -o, --output=FILE Output file name" |
---|
137 | print " GLADEFILES Glade XML input files" |
---|
138 | print "" |
---|
139 | print "This application creates a file of strings to be translated." |
---|
140 | print "It can output either a standard POT file (the default) or" |
---|
141 | print "output a C file that can be parsed by xgettext. The C output" |
---|
142 | print "is implicitly turned on if the output filename ends in .c" |
---|
143 | sys.exit(0) |
---|
144 | if opt in ('-c', '--c'): |
---|
145 | format = "C" |
---|
146 | elif opt in ('-p', '--pot'): |
---|
147 | format = "pot" |
---|
148 | elif opt in ('-o', '--output'): |
---|
149 | output = optarg |
---|
150 | if not format: |
---|
151 | if len(output) > 2 and output[-2:] == '.c': |
---|
152 | format = "C" |
---|
153 | else: |
---|
154 | format = "pot" |
---|
155 | if not output: |
---|
156 | output = "/dev/stdout" |
---|
157 | if not args: |
---|
158 | sys.stderr.write("No input files given.\n") |
---|
159 | sys.exit(1) |
---|
160 | p = TranslatableStringParser() |
---|
161 | for file in args: |
---|
162 | p.read_file(file) |
---|
163 | if format == 'C': |
---|
164 | p.output_c(output) |
---|
165 | else: |
---|
166 | p.output_pot(output) |
---|