xref: /aoo42x/main/l10ntools/scripts/tool/l10ntool.py (revision cdf0e10c)
1*cdf0e10cSrcweir#*************************************************************************
2*cdf0e10cSrcweir#
3*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir#
5*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir#
7*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir#
9*cdf0e10cSrcweir# This file is part of OpenOffice.org.
10*cdf0e10cSrcweir#
11*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir# only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir#
15*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir#
21*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir# version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir# <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir# for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir#
26*cdf0e10cSrcweir#*************************************************************************
27*cdf0e10cSrcweir
28*cdf0e10cSrcweirfrom optparse import OptionParser
29*cdf0e10cSrcweirfrom sdf import SdfData
30*cdf0e10cSrcweirfrom pseudo import PseudoSet
31*cdf0e10cSrcweir
32*cdf0e10cSrcweirimport sys
33*cdf0e10cSrcweirimport os
34*cdf0e10cSrcweirimport shutil
35*cdf0e10cSrcweir
36*cdf0e10cSrcweirclass AbstractL10nTool:
37*cdf0e10cSrcweir    _options            = {}
38*cdf0e10cSrcweir    _args               = ""
39*cdf0e10cSrcweir    _resource_type      = ""
40*cdf0e10cSrcweir    _source_language    = "en-US"
41*cdf0e10cSrcweir
42*cdf0e10cSrcweir    ##### Implement these abstract methods
43*cdf0e10cSrcweir
44*cdf0e10cSrcweir    ##### Nameing scheme for the output files
45*cdf0e10cSrcweir    def get_outputfile_format_str(self):
46*cdf0e10cSrcweir        # filename,fileNoExt,language,extension,pathPrefix,pathPostFix,path
47*cdf0e10cSrcweir        #return "{path}/{fileNoExt}_{language}.{extension}"
48*cdf0e10cSrcweir        return self._options.pattern
49*cdf0e10cSrcweir
50*cdf0e10cSrcweir    ################################# Merge single files ###########################################
51*cdf0e10cSrcweir
52*cdf0e10cSrcweir    ##### Merge a single file
53*cdf0e10cSrcweir    def merge_file(self, inputfilename, outputfilename, parsed_file_ref, lang, is_forced_lang, sdfdata):
54*cdf0e10cSrcweir        pass
55*cdf0e10cSrcweir
56*cdf0e10cSrcweir    ##### Helper for parse-once-use-often like parsing a xml file is needed implement it here
57*cdf0e10cSrcweir    def parse_file(self, filename):
58*cdf0e10cSrcweir        return None
59*cdf0e10cSrcweir
60*cdf0e10cSrcweir    ################### Merge one big file containing all strings in all languages #################
61*cdf0e10cSrcweir    def merge_one_big_file(self, inputfile, outputfilename, parsed_file_ref, lang, sdfdata):
62*cdf0e10cSrcweir        pass
63*cdf0e10cSrcweir
64*cdf0e10cSrcweir    ################### Extract a single File ######################################################
65*cdf0e10cSrcweir    def extract_file(self, inputfile):
66*cdf0e10cSrcweir        pass
67*cdf0e10cSrcweir
68*cdf0e10cSrcweir    ################################################################################################
69*cdf0e10cSrcweir
70*cdf0e10cSrcweir    def format_outputfile(self, filename, language):
71*cdf0e10cSrcweir        extension = filename[filename.rfind('.')+1:]
72*cdf0e10cSrcweir        file = filename[:filename.rfind('.')]
73*cdf0e10cSrcweir        # Python 2.3.x friendly
74*cdf0e10cSrcweir        return self.get_outputfile_format_str().replace('[', '%(').replace(']',')s') % \
75*cdf0e10cSrcweir                { 'filename': filename, 'fileNoExt': file, 'language': language, 'extension': extension, 'path_prefix': self._options.path_prefix,
76*cdf0e10cSrcweir                  'path_postfix': self._options.path_postfix, 'path': self.get_path() }
77*cdf0e10cSrcweir
78*cdf0e10cSrcweir        #return self.get_outputfile_format_str().replace('[', '{').replace(']','}').format(
79*cdf0e10cSrcweir        #       filename=filename, fileNoExt=file, language=language, extension=extension, path_prefix=self._options.path_prefix,
80*cdf0e10cSrcweir        #       path_postfix=self._options.path_postfix, path=self.get_path())
81*cdf0e10cSrcweir
82*cdf0e10cSrcweir    def get_path(self):
83*cdf0e10cSrcweir        if self._options.outputfile.find('/') == -1:
84*cdf0e10cSrcweir            return ""
85*cdf0e10cSrcweir        else:
86*cdf0e10cSrcweir            return self._options.outputfile[:self._options.outputfile.rfind('/')]
87*cdf0e10cSrcweir
88*cdf0e10cSrcweir    def merge(self,  sdfdata):
89*cdf0e10cSrcweir        langset,forcedset, foundset = PseudoSet(), PseudoSet() , PseudoSet()
90*cdf0e10cSrcweir
91*cdf0e10cSrcweir        if self._options.languages:
92*cdf0e10cSrcweir            langset = PseudoSet(self._options.languages)
93*cdf0e10cSrcweir        if self._options.forcedlanguages:
94*cdf0e10cSrcweir            forcedset = PseudoSet(self._options.forcedlanguages)
95*cdf0e10cSrcweir        if sdfdata.get_languages_found_in_sdf():
96*cdf0e10cSrcweir            foundset = sdfdata.get_languages_found_in_sdf()
97*cdf0e10cSrcweir
98*cdf0e10cSrcweir        if self.has_multi_inputfiles():
99*cdf0e10cSrcweir            filelist = self.read_inputfile_list()
100*cdf0e10cSrcweir        else:
101*cdf0e10cSrcweir            filelist = self._options.inputfile
102*cdf0e10cSrcweir
103*cdf0e10cSrcweir        for inputfile in filelist:
104*cdf0e10cSrcweir            ref = self.parse_file(inputfile)
105*cdf0e10cSrcweir            # Don't write that files if there is no l10n present
106*cdf0e10cSrcweir            if ((langset & foundset) - forcedset):  # all langs given and found in sdf without enforced
107*cdf0e10cSrcweir                [self.merge_file(inputfile,self.format_outputfile(inputfile, lang), ref, lang, False, sdfdata) for lang in ((langset & foundset) - forcedset)]
108*cdf0e10cSrcweir            # Always write those files even if there is no l10n available
109*cdf0e10cSrcweir            if forcedset: # all enforced langs
110*cdf0e10cSrcweir                [self.merge_file(inputfile, self.format_outputfile(inputfile, lang), ref, lang, True, sdfdata)  for lang in forcedset]
111*cdf0e10cSrcweir            # In case a big file have to be written
112*cdf0e10cSrcweir            if ((langset & foundset) | forcedset): # all langs given ,found in sdf and enforced ones
113*cdf0e10cSrcweir                self.merge_one_big_file(inputfile, self.format_outputfile(inputfile, lang), ref, ((langset & foundset) | forcedset), sdfdata)
114*cdf0e10cSrcweir
115*cdf0e10cSrcweir    def has_multi_inputfiles(self):
116*cdf0e10cSrcweir        return self._options.inputfile[0] == '@'
117*cdf0e10cSrcweir
118*cdf0e10cSrcweir    def copy_file(self, inputfilename, outputfilename):
119*cdf0e10cSrcweir        try:
120*cdf0e10cSrcweir            os.remove(outputfilename)
121*cdf0e10cSrcweir        except:
122*cdf0e10cSrcweir            pass
123*cdf0e10cSrcweir
124*cdf0e10cSrcweir        try:
125*cdf0e10cSrcweir            os.remove(outputfilename)
126*cdf0e10cSrcweir        except:
127*cdf0e10cSrcweir            pass
128*cdf0e10cSrcweir
129*cdf0e10cSrcweir        try:
130*cdf0e10cSrcweir            shutil.copy(inputfilename, outputfilename)
131*cdf0e10cSrcweir        except IOError:
132*cdf0e10cSrcweir            print "ERROR: Can not copy file '" + inputfilename + "' to " + "'" + outputfilename + "'"
133*cdf0e10cSrcweir            sys.exit(-1)
134*cdf0e10cSrcweir
135*cdf0e10cSrcweir    def extract(self):
136*cdf0e10cSrcweir        try:
137*cdf0e10cSrcweir            f = open(self._options.outputfile, "w+")
138*cdf0e10cSrcweir            f.write(self.extract_file(self._options.inputfile))
139*cdf0e10cSrcweir        except IOError:
140*cdf0e10cSrcweir            print "ERROR: Can not write file " + self._options.outputfile
141*cdf0e10cSrcweir        else:
142*cdf0e10cSrcweir            f.close()
143*cdf0e10cSrcweir
144*cdf0e10cSrcweir    # Parse the common options
145*cdf0e10cSrcweir    def parse_options(self):
146*cdf0e10cSrcweir        parser = OptionParser()
147*cdf0e10cSrcweir        parser.add_option("-i", "--inputfile",       dest="inputfile",       metavar="FILE", help="resource file to read"         )
148*cdf0e10cSrcweir        parser.add_option("-o", "--outputfile",      dest="outputfile",      metavar="FILE", help="extracted sdf or merged file"  )
149*cdf0e10cSrcweir        parser.add_option("-m", "--inputsdffile",    dest="input_sdf_file",  metavar="FILE", help="merge this sdf file"           )
150*cdf0e10cSrcweir        parser.add_option("-x", "--pathprefix",      dest="path_prefix",     metavar="PATH", help=""                              )
151*cdf0e10cSrcweir        parser.add_option("-y", "--pathpostfix",     dest="path_postfix",    metavar="PATH", help=""                              )
152*cdf0e10cSrcweir        parser.add_option("-p", "--projectname",     dest="project_name",    metavar="NAME", help=""                              )
153*cdf0e10cSrcweir        parser.add_option("-r", "--projectroot",     dest="project_root",    metavar="PATH", help=""                              )
154*cdf0e10cSrcweir        parser.add_option("-f", "--forcedlanguages", dest="forcedlanguages", metavar="ISOCODE[,ISOCODE]", help="Always merge those langs even if no l10n is available for those langs" )
155*cdf0e10cSrcweir        parser.add_option("-l", "--languages",       dest="languages",       metavar="ISOCODE[,ISOCODE]", help="Merge those langs if l10n is found for each")
156*cdf0e10cSrcweir        parser.add_option("-s", "--pattern",         dest="pattern",         metavar="", help=""                                  )
157*cdf0e10cSrcweir        parser.add_option("-q", "--quiet",           action="store_true",    dest="quietmode", help="",default=False)
158*cdf0e10cSrcweir        (self._options, self.args) = parser.parse_args()
159*cdf0e10cSrcweir
160*cdf0e10cSrcweir        # -l "de,pr,pt-BR" => [ "de" , "pt" , "pt-BR" ]
161*cdf0e10cSrcweir        parse_complex_arg = lambda arg: arg.split(",")
162*cdf0e10cSrcweir
163*cdf0e10cSrcweir        if self._options.forcedlanguages:
164*cdf0e10cSrcweir            self._options.forcedlanguages = parse_complex_arg(self._options.forcedlanguages)
165*cdf0e10cSrcweir        if self._options.languages:
166*cdf0e10cSrcweir            self._options.languages = parse_complex_arg(self._options.languages)
167*cdf0e10cSrcweir        self.test_options()
168*cdf0e10cSrcweir
169*cdf0e10cSrcweir    def __init__(self):
170*cdf0e10cSrcweir        self.parse_options()
171*cdf0e10cSrcweir        if self._options.input_sdf_file != None and len(self._options.input_sdf_file):
172*cdf0e10cSrcweir            sdfdata = SdfData(self._options.input_sdf_file)
173*cdf0e10cSrcweir            sdfdata.read()
174*cdf0e10cSrcweir            self.merge(sdfdata)
175*cdf0e10cSrcweir        else:
176*cdf0e10cSrcweir            self.extract()
177*cdf0e10cSrcweir
178*cdf0e10cSrcweir    def make_dirs(self, filename):
179*cdf0e10cSrcweir        dir = filename[:filename.rfind('/')]
180*cdf0e10cSrcweir        if os.path.exists(dir):
181*cdf0e10cSrcweir            if os.path.isfile(dir):
182*cdf0e10cSrcweir                print "ERROR: There is a file '"+dir+"' where I want create a directory"
183*cdf0e10cSrcweir                sys.exit(-1)
184*cdf0e10cSrcweir            else:
185*cdf0e10cSrcweir                return
186*cdf0e10cSrcweir        else:
187*cdf0e10cSrcweir            try:
188*cdf0e10cSrcweir                os.makedirs(dir)
189*cdf0e10cSrcweir            except IOError:
190*cdf0e10cSrcweir                print "Error: Can not create dir " + dir
191*cdf0e10cSrcweir                sys.exit(-1)
192*cdf0e10cSrcweir
193*cdf0e10cSrcweir    def test_options(self):
194*cdf0e10cSrcweir        opt = self._options
195*cdf0e10cSrcweir        is_valid = lambda x: x != None and len(x) > 0
196*cdf0e10cSrcweir        return  is_valid(opt.project_root) and is_valid(opt.project_name) and is_valid(opt.languages) and \
197*cdf0e10cSrcweir                ( is_valid(opt.inputfile) and (( is_valid(opt.path_prefix) and is_valid(opt.path_postfix) ) or is_valid(opt.outputfile)) and \
198*cdf0e10cSrcweir                ( ( is_valid(opt.input_sdf_file) and ( is_valid(opt.outputfile) or  ( is_valid(opt.path_prefix) and is_valid(opt.path_postfix) ) or \
199*cdf0e10cSrcweir                ( is_valid(opt.inputfile) and is_valid(opt.outputFile)) ))))
200*cdf0e10cSrcweir        print "Strange options ..."
201*cdf0e10cSrcweir        sys.exit( -1 )
202*cdf0e10cSrcweir
203*cdf0e10cSrcweir    def read_inputfile_list(self):
204*cdf0e10cSrcweir        if self.has_multi_inputfiles():
205*cdf0e10cSrcweir            lines = []
206*cdf0e10cSrcweir            try:
207*cdf0e10cSrcweir                f = open(self._options.inputfile[1:], "r")
208*cdf0e10cSrcweir                lines = [line.strip('\n') for line in f.readlines()]
209*cdf0e10cSrcweir            except IOError:
210*cdf0e10cSrcweir                print "ERROR: Can not read file list " + self._options.inputfile[2:]
211*cdf0e10cSrcweir                sys.exit(-1)
212*cdf0e10cSrcweir            else:
213*cdf0e10cSrcweir                f.close()
214*cdf0e10cSrcweir            return lines
215*cdf0e10cSrcweir
216*cdf0e10cSrcweir    def get_filename_string(self, inputfile):
217*cdf0e10cSrcweir        absfile = os.path.realpath(os.path.abspath(inputfile))
218*cdf0e10cSrcweir        absroot = os.path.realpath(os.path.abspath(self._options.project_root))
219*cdf0e10cSrcweir        return absfile[len(absroot)+1:].replace('/','\\')
220*cdf0e10cSrcweir
221