~ubuntu-branches/ubuntu/hardy/prewikka/hardy

« back to all changes in this revision

Viewing changes to langadmin.py

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Chifflier
  • Date: 2007-04-11 14:41:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070411144109-2hh7zx3amwd27b4l
Tags: upstream-0.9.10
ImportĀ upstreamĀ versionĀ 0.9.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)