1
by Pierre Chifflier
Import upstream version 0.9.10 |
1 |
#!/usr/bin/env python
|
2 |
# Copyright (C) 2004,2005 by SICEm S.L.
|
|
3 |
#
|
|
4 |
# This program is free software; you can redistribute it and/or
|
|
5 |
# modify it under the terms of the GNU Lesser General Public License
|
|
6 |
# as published by the Free Software Foundation; either version 2
|
|
7 |
# of the License, or (at your option) any later version.
|
|
8 |
#
|
|
9 |
# This program is distributed in the hope that it will be useful,
|
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 |
# GNU General Public License for more details.
|
|
13 |
#
|
|
14 |
# You should have received a copy of the GNU Lesser General Public License
|
|
15 |
# along with this program; if not, write to the Free Software
|
|
16 |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
17 |
||
18 |
||
19 |
"""
|
|
20 |
This script makes easy all the boring steps to use gettext with a python
|
|
21 |
application.
|
|
22 |
||
23 |
For localization you need to:
|
|
24 |
||
25 |
1 Mark the strings in the source code as translatable
|
|
26 |
2 Use xgettext to get a pot file from it
|
|
27 |
3 Use a copy of this pot file for every language you want to have
|
|
28 |
translations
|
|
29 |
4 Translate these po files
|
|
30 |
5 Use msgmerge every time you change the source code and the strings you
|
|
31 |
need to translate change
|
|
32 |
6 Generate the mo binary files for every po file you have
|
|
33 |
||
34 |
To use this script you need to:
|
|
35 |
||
36 |
- have a directory where you put the po files: the PO_DIR
|
|
37 |
- have a directory where you put the mo files: the LANG_DIR
|
|
38 |
- choose a name for the pot file: the POT_FILE
|
|
39 |
- choose a name for the mo files: the MO_FILE
|
|
40 |
||
41 |
Note that you have only one POT_FILE but you have one po file in the PO_DIR for
|
|
42 |
every language you have translations. Then you have a MO_FILE for every po file
|
|
43 |
and they are stored in LANG_DIR/lang/LC_MESSAGES/ where lang is the language
|
|
44 |
this MO_FILE belongs to.
|
|
45 |
"""
|
|
46 |
||
47 |
from distutils.dep_util import newer |
|
48 |
from glob import glob |
|
49 |
import os |
|
50 |
from os.path import join, splitext, basename, exists, isdir |
|
51 |
from optparse import OptionParser |
|
52 |
import sys |
|
53 |
from shutil import copyfile |
|
54 |
||
55 |
class LangAdmin: |
|
56 |
||
57 |
def __init__(self, po_dir, pot_file, mo_file, lang_dir): |
|
58 |
# where to put the po files (one for each language)
|
|
59 |
self.po_dir = po_dir |
|
60 |
||
61 |
# name of the pot (po template) file (it is stored in the cwd)
|
|
62 |
self.pot_file = pot_file |
|
63 |
||
64 |
# name of the mo file (one for each directory)
|
|
65 |
self.mo_file = mo_file |
|
66 |
||
67 |
# name of the directory where the mo files are stored
|
|
68 |
self.lang_dir = lang_dir |
|
69 |
||
70 |
def get_languages(self): |
|
71 |
"""Gives a list of all the languages that have translation"""
|
|
72 |
languages = [] |
|
73 |
for lang in glob(join(self.po_dir, '*.po')): |
|
74 |
languages.append(splitext(basename(lang))[0]) |
|
75 |
||
76 |
return languages |
|
77 |
||
78 |
def _list_files(self, directory, recurse=True, ext="py"): |
|
79 |
files = glob(join(directory, "*." + ext)) |
|
80 |
if recurse: |
|
81 |
dirs = [join(directory, filename) for filename \ |
|
82 |
in os.listdir(directory) |
|
83 |
if isdir(join(directory, filename))] |
|
84 |
for d in dirs: |
|
85 |
files += self._list_files(d, recurse, ext) |
|
86 |
return files |
|
87 |
||
88 |
def generate_pot_file(self, recurse=True, directories=[]): |
|
89 |
"""Get all the python files in the directories parameter and create
|
|
90 |
a pot file using xgettext. If the recurse parameter is True it search
|
|
91 |
for more .py files in the subdirectories of the directories list
|
|
92 |
"""
|
|
93 |
files = [] |
|
94 |
for dirname in directories: |
|
95 |
files += self._list_files(dirname, recurse) |
|
96 |
||
97 |
cmd = 'xgettext -k_ -kN_ -o %s %s' % (self.pot_file, ' '.join(files)) |
|
98 |
print cmd |
|
99 |
os.system(cmd) |
|
100 |
||
101 |
def add_language(self, lang): |
|
102 |
"""Create another language by copying the self.pot_file into the
|
|
103 |
self.po_dir using the lang parameter for its name. You need to fill at
|
|
104 |
least the charset property of the prolog of this new file if you don't
|
|
105 |
want the other commands to fail
|
|
106 |
"""
|
|
107 |
if not exists(self.pot_file): |
|
108 |
print 'ERROR: You need to generate the pot file before adding '\ |
|
109 |
'any language.\n' \ |
|
110 |
'Use the command pot for that'
|
|
111 |
sys.exit(1) |
|
112 |
copyfile(self.pot_file, join(self.po_dir, lang+'.po')) |
|
113 |
print 'Please fill the prolog information of the file', \ |
|
114 |
join(self.po_dir, lang+'.po') |
|
115 |
||
116 |
def merge_translations(self): |
|
117 |
"""Merge the new self.pot_file with the existing po files in the
|
|
118 |
self.po_dir directory using the command msgmerge
|
|
119 |
"""
|
|
120 |
for lang_file in glob(join(self.po_dir, '*.po')): |
|
121 |
cmd = 'msgmerge -U %s %s' % (lang_file, self.pot_file) |
|
122 |
print cmd |
|
123 |
os.system(cmd) |
|
124 |
||
125 |
def generate_mo_files(self, verbose=True): |
|
126 |
"""For every po file in the self.po_dir directory generates a
|
|
127 |
self.mo_file using msgfmt. It guess the language name from the po file
|
|
128 |
and creates the directories needed under self.lang_dir to put the final
|
|
129 |
self.mo_file in the right place
|
|
130 |
"""
|
|
131 |
if not exists(self.lang_dir): |
|
132 |
os.mkdir(self.lang_dir) |
|
133 |
||
134 |
for lang in self.get_languages(): |
|
135 |
src = join(self.po_dir, lang+'.po') |
|
136 |
dst = join(self.lang_dir, lang, 'LC_MESSAGES', self.mo_file) |
|
137 |
if not exists(join(self.lang_dir, lang, 'LC_MESSAGES')): |
|
138 |
if not exists(join(self.lang_dir, lang)): |
|
139 |
os.mkdir(join(self.lang_dir, lang)) |
|
140 |
os.mkdir(join(self.lang_dir, lang, 'LC_MESSAGES')) |
|
141 |
||
142 |
# Skip files which are not modified
|
|
143 |
if not newer(src, dst): |
|
144 |
continue
|
|
145 |
cmd = 'msgfmt -o %s %s' % (dst, src) |
|
146 |
if verbose: |
|
147 |
print 'running', cmd |
|
148 |
os.system(cmd) |
|
149 |
||
150 |
if __name__ == '__main__': |
|
151 |
usage = """usage: %prog [options] command |
|
152 |
|
|
153 |
where command can be one of:
|
|
154 |
||
155 |
list List all the languages supported
|
|
156 |
add LANG Add the language LANG
|
|
157 |
pot DIRS Get the translatable strings for every file in DIRS that
|
|
158 |
is a .py file and creates the .pot file from them
|
|
159 |
merge Merge all the languages files with the POT file
|
|
160 |
mo Create a .mo file for every .po file and put it in the right
|
|
161 |
place"""
|
|
162 |
||
163 |
parser = OptionParser(usage) |
|
164 |
parser.add_option('--po-dir', |
|
165 |
action='store', |
|
166 |
dest='po_dir', |
|
167 |
default='po', |
|
168 |
help='directory to store the po files') |
|
169 |
parser.add_option('--pot-file', |
|
170 |
action='store', |
|
171 |
dest='pot_file', |
|
172 |
default='prewikka.pot', |
|
173 |
help='name of the pot (po template) file. It is stored in the cwd') |
|
174 |
parser.add_option('--mo-file', |
|
175 |
action='store', |
|
176 |
dest='mo_file', |
|
177 |
default='prewikka.mo', |
|
178 |
help='name of the mo file') |
|
179 |
parser.add_option('--lang-dir', |
|
180 |
action='store', |
|
181 |
dest='lang_dir', |
|
182 |
default='locale', |
|
183 |
help='directory to store the mo files') |
|
184 |
||
185 |
options, args = parser.parse_args() |
|
186 |
||
187 |
if len(args) == 0: |
|
188 |
parser.print_help() |
|
189 |
print '\nERROR: You should provide one command' |
|
190 |
sys.exit(1) |
|
191 |
||
192 |
langadmin = LangAdmin(options.po_dir, options.pot_file, options.mo_file, |
|
193 |
options.lang_dir) |
|
194 |
||
195 |
command = args.pop(0) |
|
196 |
if command == 'list': |
|
197 |
langs = langadmin.get_languages() |
|
198 |
print ' '.join(langs) |
|
199 |
||
200 |
elif command == 'pot': |
|
201 |
if len(args) == 0: |
|
202 |
parser.print_help() |
|
203 |
print '\nERROR: The pot command needs at least one directory to '\ |
|
204 |
'look for .py files with translatable strings'
|
|
205 |
sys.exit(1) |
|
206 |
langadmin.generate_pot_file(True, args) |
|
207 |
||
208 |
elif command == 'add': |
|
209 |
if len(args) != 1: |
|
210 |
parser.print_help() |
|
211 |
print '\nERROR: You need to specify one and only one language '\ |
|
212 |
'to add'
|
|
213 |
sys.exit(1) |
|
214 |
langadmin.add_language(args[0]) |
|
215 |
||
216 |
elif command == 'merge': |
|
217 |
langadmin.merge_translations() |
|
218 |
||
219 |
elif command == 'mo': |
|
220 |
langadmin.generate_mo_files() |
|
221 |
||
222 |
else: |
|
223 |
parser.print_help() |
|
224 |
print '\nERROR: Unknown command' |
|
225 |
sys.exit(1) |