2
# Copyright (C) 2004,2005 by SICEm S.L.
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.
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.
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.
20
This script makes easy all the boring steps to use gettext with a python
23
For localization you need to:
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
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
34
To use this script you need to:
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
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.
47
from distutils.dep_util import newer
50
from os.path import join, splitext, basename, exists, isdir
51
from optparse import OptionParser
53
from shutil import copyfile
57
def __init__(self, po_dir, pot_file, mo_file, lang_dir):
58
# where to put the po files (one for each language)
61
# name of the pot (po template) file (it is stored in the cwd)
62
self.pot_file = pot_file
64
# name of the mo file (one for each directory)
65
self.mo_file = mo_file
67
# name of the directory where the mo files are stored
68
self.lang_dir = lang_dir
70
def get_languages(self):
71
"""Gives a list of all the languages that have translation"""
73
for lang in glob(join(self.po_dir, '*.po')):
74
languages.append(splitext(basename(lang))[0])
78
def _list_files(self, directory, recurse=True, ext="py"):
79
files = glob(join(directory, "*." + ext))
81
dirs = [join(directory, filename) for filename \
82
in os.listdir(directory)
83
if isdir(join(directory, filename))]
85
files += self._list_files(d, recurse, ext)
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
94
for dirname in directories:
95
files += self._list_files(dirname, recurse)
97
cmd = 'xgettext -k_ -kN_ -o %s %s' % (self.pot_file, ' '.join(files))
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
107
if not exists(self.pot_file):
108
print 'ERROR: You need to generate the pot file before adding '\
110
'Use the command pot for that'
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')
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
120
for lang_file in glob(join(self.po_dir, '*.po')):
121
cmd = 'msgmerge -U %s %s' % (lang_file, self.pot_file)
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
131
if not exists(self.lang_dir):
132
os.mkdir(self.lang_dir)
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'))
142
# Skip files which are not modified
143
if not newer(src, dst):
145
cmd = 'msgfmt -o %s %s' % (dst, src)
150
if __name__ == '__main__':
151
usage = """usage: %prog [options] command
153
where command can be one of:
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
163
parser = OptionParser(usage)
164
parser.add_option('--po-dir',
168
help='directory to store the po files')
169
parser.add_option('--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',
177
default='prewikka.mo',
178
help='name of the mo file')
179
parser.add_option('--lang-dir',
183
help='directory to store the mo files')
185
options, args = parser.parse_args()
189
print '\nERROR: You should provide one command'
192
langadmin = LangAdmin(options.po_dir, options.pot_file, options.mo_file,
195
command = args.pop(0)
196
if command == 'list':
197
langs = langadmin.get_languages()
198
print ' '.join(langs)
200
elif command == 'pot':
203
print '\nERROR: The pot command needs at least one directory to '\
204
'look for .py files with translatable strings'
206
langadmin.generate_pot_file(True, args)
208
elif command == 'add':
211
print '\nERROR: You need to specify one and only one language '\
214
langadmin.add_language(args[0])
216
elif command == 'merge':
217
langadmin.merge_translations()
219
elif command == 'mo':
220
langadmin.generate_mo_files()
224
print '\nERROR: Unknown command'