1a0428e9eSAndrew Rist#************************************************************** 2a0428e9eSAndrew Rist# 3a0428e9eSAndrew Rist# Licensed to the Apache Software Foundation (ASF) under one 4a0428e9eSAndrew Rist# or more contributor license agreements. See the NOTICE file 5a0428e9eSAndrew Rist# distributed with this work for additional information 6a0428e9eSAndrew Rist# regarding copyright ownership. The ASF licenses this file 7a0428e9eSAndrew Rist# to you under the Apache License, Version 2.0 (the 8a0428e9eSAndrew Rist# "License"); you may not use this file except in compliance 9a0428e9eSAndrew Rist# with the License. You may obtain a copy of the License at 10a0428e9eSAndrew Rist# 11a0428e9eSAndrew Rist# http://www.apache.org/licenses/LICENSE-2.0 12a0428e9eSAndrew Rist# 13a0428e9eSAndrew Rist# Unless required by applicable law or agreed to in writing, 14a0428e9eSAndrew Rist# software distributed under the License is distributed on an 15a0428e9eSAndrew Rist# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16a0428e9eSAndrew Rist# KIND, either express or implied. See the License for the 17a0428e9eSAndrew Rist# specific language governing permissions and limitations 18a0428e9eSAndrew Rist# under the License. 19a0428e9eSAndrew Rist# 20a0428e9eSAndrew Rist#************************************************************** 21cdf0e10cSrcweir 22cdf0e10cSrcweirfrom optparse import OptionParser 23cdf0e10cSrcweirfrom sdf import SdfData 24cdf0e10cSrcweirfrom pseudo import PseudoSet 25cdf0e10cSrcweir 26cdf0e10cSrcweirimport sys 27cdf0e10cSrcweirimport os 28cdf0e10cSrcweirimport shutil 29cdf0e10cSrcweir 30cdf0e10cSrcweirclass AbstractL10nTool: 31cdf0e10cSrcweir _options = {} 32cdf0e10cSrcweir _args = "" 33ae54856bSPedro Giffuni _resource_type = "" 34cdf0e10cSrcweir _source_language = "en-US" 35ae54856bSPedro Giffuni 36cdf0e10cSrcweir ##### Implement these abstract methods 37cdf0e10cSrcweir 38cdf0e10cSrcweir ##### Nameing scheme for the output files 39cdf0e10cSrcweir def get_outputfile_format_str(self): 40cdf0e10cSrcweir # filename,fileNoExt,language,extension,pathPrefix,pathPostFix,path 41cdf0e10cSrcweir #return "{path}/{fileNoExt}_{language}.{extension}" 42cdf0e10cSrcweir return self._options.pattern 43cdf0e10cSrcweir 44cdf0e10cSrcweir ################################# Merge single files ########################################### 45cdf0e10cSrcweir 46cdf0e10cSrcweir ##### Merge a single file 47cdf0e10cSrcweir def merge_file(self, inputfilename, outputfilename, parsed_file_ref, lang, is_forced_lang, sdfdata): 48cdf0e10cSrcweir pass 49cdf0e10cSrcweir 50cdf0e10cSrcweir ##### Helper for parse-once-use-often like parsing a xml file is needed implement it here 51cdf0e10cSrcweir def parse_file(self, filename): 52cdf0e10cSrcweir return None 53cdf0e10cSrcweir 54cdf0e10cSrcweir ################### Merge one big file containing all strings in all languages ################# 55cdf0e10cSrcweir def merge_one_big_file(self, inputfile, outputfilename, parsed_file_ref, lang, sdfdata): 56cdf0e10cSrcweir pass 57cdf0e10cSrcweir 58cdf0e10cSrcweir ################### Extract a single File ###################################################### 59cdf0e10cSrcweir def extract_file(self, inputfile): 60cdf0e10cSrcweir pass 61ae54856bSPedro Giffuni 62cdf0e10cSrcweir ################################################################################################ 63ae54856bSPedro Giffuni 64cdf0e10cSrcweir def format_outputfile(self, filename, language): 65cdf0e10cSrcweir extension = filename[filename.rfind('.')+1:] 66cdf0e10cSrcweir file = filename[:filename.rfind('.')] 67cdf0e10cSrcweir # Python 2.3.x friendly 68cdf0e10cSrcweir return self.get_outputfile_format_str().replace('[', '%(').replace(']',')s') % \ 69cdf0e10cSrcweir { 'filename': filename, 'fileNoExt': file, 'language': language, 'extension': extension, 'path_prefix': self._options.path_prefix, 70cdf0e10cSrcweir 'path_postfix': self._options.path_postfix, 'path': self.get_path() } 71cdf0e10cSrcweir 72cdf0e10cSrcweir #return self.get_outputfile_format_str().replace('[', '{').replace(']','}').format( 73cdf0e10cSrcweir # filename=filename, fileNoExt=file, language=language, extension=extension, path_prefix=self._options.path_prefix, 74cdf0e10cSrcweir # path_postfix=self._options.path_postfix, path=self.get_path()) 75cdf0e10cSrcweir 76cdf0e10cSrcweir def get_path(self): 77cdf0e10cSrcweir if self._options.outputfile.find('/') == -1: 78cdf0e10cSrcweir return "" 79cdf0e10cSrcweir else: 80cdf0e10cSrcweir return self._options.outputfile[:self._options.outputfile.rfind('/')] 81ae54856bSPedro Giffuni 82cdf0e10cSrcweir def merge(self, sdfdata): 83cdf0e10cSrcweir langset,forcedset, foundset = PseudoSet(), PseudoSet() , PseudoSet() 84cdf0e10cSrcweir 85ae54856bSPedro Giffuni if self._options.languages: 86ae54856bSPedro Giffuni langset = PseudoSet(self._options.languages) 87ae54856bSPedro Giffuni if self._options.forcedlanguages: 88ae54856bSPedro Giffuni forcedset = PseudoSet(self._options.forcedlanguages) 89ae54856bSPedro Giffuni if sdfdata.get_languages_found_in_sdf(): 90ae54856bSPedro Giffuni foundset = sdfdata.get_languages_found_in_sdf() 91ae54856bSPedro Giffuni 92ae54856bSPedro Giffuni if self.has_multi_inputfiles(): 93cdf0e10cSrcweir filelist = self.read_inputfile_list() 94cdf0e10cSrcweir else: 95cdf0e10cSrcweir filelist = self._options.inputfile 96ae54856bSPedro Giffuni 97cdf0e10cSrcweir for inputfile in filelist: 98cdf0e10cSrcweir ref = self.parse_file(inputfile) 99cdf0e10cSrcweir # Don't write that files if there is no l10n present 100ae54856bSPedro Giffuni if ((langset & foundset) - forcedset): # all langs given and found in sdf without enforced 101cdf0e10cSrcweir [self.merge_file(inputfile,self.format_outputfile(inputfile, lang), ref, lang, False, sdfdata) for lang in ((langset & foundset) - forcedset)] 102cdf0e10cSrcweir # Always write those files even if there is no l10n available 103cdf0e10cSrcweir if forcedset: # all enforced langs 104cdf0e10cSrcweir [self.merge_file(inputfile, self.format_outputfile(inputfile, lang), ref, lang, True, sdfdata) for lang in forcedset] 105cdf0e10cSrcweir # In case a big file have to be written 106cdf0e10cSrcweir if ((langset & foundset) | forcedset): # all langs given ,found in sdf and enforced ones 107cdf0e10cSrcweir self.merge_one_big_file(inputfile, self.format_outputfile(inputfile, lang), ref, ((langset & foundset) | forcedset), sdfdata) 108ae54856bSPedro Giffuni 109ae54856bSPedro Giffuni def has_multi_inputfiles(self): 110cdf0e10cSrcweir return self._options.inputfile[0] == '@' 111cdf0e10cSrcweir 112cdf0e10cSrcweir def copy_file(self, inputfilename, outputfilename): 113ae54856bSPedro Giffuni try: 114cdf0e10cSrcweir os.remove(outputfilename) 115cdf0e10cSrcweir except: 116ae54856bSPedro Giffuni pass 117cdf0e10cSrcweir 118cdf0e10cSrcweir try: 119cdf0e10cSrcweir os.remove(outputfilename) 120cdf0e10cSrcweir except: 121cdf0e10cSrcweir pass 122cdf0e10cSrcweir 123cdf0e10cSrcweir try: 124cdf0e10cSrcweir shutil.copy(inputfilename, outputfilename) 125cdf0e10cSrcweir except IOError: 126*7d9fa7c3SPedro Giffuni print("ERROR: Can not copy file '" + inputfilename + "' to " + "'" + outputfilename + "'") 127cdf0e10cSrcweir sys.exit(-1) 128ae54856bSPedro Giffuni 129cdf0e10cSrcweir def extract(self): 130cdf0e10cSrcweir try: 131cdf0e10cSrcweir f = open(self._options.outputfile, "w+") 132cdf0e10cSrcweir f.write(self.extract_file(self._options.inputfile)) 133cdf0e10cSrcweir except IOError: 134*7d9fa7c3SPedro Giffuni print("ERROR: Can not write file " + self._options.outputfile) 135cdf0e10cSrcweir else: 136cdf0e10cSrcweir f.close() 137ae54856bSPedro Giffuni 138cdf0e10cSrcweir # Parse the common options 139cdf0e10cSrcweir def parse_options(self): 140cdf0e10cSrcweir parser = OptionParser() 141cdf0e10cSrcweir parser.add_option("-i", "--inputfile", dest="inputfile", metavar="FILE", help="resource file to read" ) 142cdf0e10cSrcweir parser.add_option("-o", "--outputfile", dest="outputfile", metavar="FILE", help="extracted sdf or merged file" ) 143cdf0e10cSrcweir parser.add_option("-m", "--inputsdffile", dest="input_sdf_file", metavar="FILE", help="merge this sdf file" ) 144cdf0e10cSrcweir parser.add_option("-x", "--pathprefix", dest="path_prefix", metavar="PATH", help="" ) 145cdf0e10cSrcweir parser.add_option("-y", "--pathpostfix", dest="path_postfix", metavar="PATH", help="" ) 146cdf0e10cSrcweir parser.add_option("-p", "--projectname", dest="project_name", metavar="NAME", help="" ) 147cdf0e10cSrcweir parser.add_option("-r", "--projectroot", dest="project_root", metavar="PATH", help="" ) 148cdf0e10cSrcweir parser.add_option("-f", "--forcedlanguages", dest="forcedlanguages", metavar="ISOCODE[,ISOCODE]", help="Always merge those langs even if no l10n is available for those langs" ) 149cdf0e10cSrcweir parser.add_option("-l", "--languages", dest="languages", metavar="ISOCODE[,ISOCODE]", help="Merge those langs if l10n is found for each") 150ae54856bSPedro Giffuni parser.add_option("-s", "--pattern", dest="pattern", metavar="", help="" ) 151cdf0e10cSrcweir parser.add_option("-q", "--quiet", action="store_true", dest="quietmode", help="",default=False) 152cdf0e10cSrcweir (self._options, self.args) = parser.parse_args() 153ae54856bSPedro Giffuni 154cdf0e10cSrcweir # -l "de,pr,pt-BR" => [ "de" , "pt" , "pt-BR" ] 155cdf0e10cSrcweir parse_complex_arg = lambda arg: arg.split(",") 156ae54856bSPedro Giffuni 157ae54856bSPedro Giffuni if self._options.forcedlanguages: 158ae54856bSPedro Giffuni self._options.forcedlanguages = parse_complex_arg(self._options.forcedlanguages) 159ae54856bSPedro Giffuni if self._options.languages: 160ae54856bSPedro Giffuni self._options.languages = parse_complex_arg(self._options.languages) 161cdf0e10cSrcweir self.test_options() 162ae54856bSPedro Giffuni 163cdf0e10cSrcweir def __init__(self): 164cdf0e10cSrcweir self.parse_options() 165cdf0e10cSrcweir if self._options.input_sdf_file != None and len(self._options.input_sdf_file): 166cdf0e10cSrcweir sdfdata = SdfData(self._options.input_sdf_file) 167cdf0e10cSrcweir sdfdata.read() 168cdf0e10cSrcweir self.merge(sdfdata) 169cdf0e10cSrcweir else: 170cdf0e10cSrcweir self.extract() 171cdf0e10cSrcweir 172cdf0e10cSrcweir def make_dirs(self, filename): 173cdf0e10cSrcweir dir = filename[:filename.rfind('/')] 174cdf0e10cSrcweir if os.path.exists(dir): 175cdf0e10cSrcweir if os.path.isfile(dir): 176*7d9fa7c3SPedro Giffuni print("ERROR: There is a file '"+dir+"' where I want create a directory") 177cdf0e10cSrcweir sys.exit(-1) 178cdf0e10cSrcweir else: 179cdf0e10cSrcweir return 180cdf0e10cSrcweir else: 181cdf0e10cSrcweir try: 182cdf0e10cSrcweir os.makedirs(dir) 183cdf0e10cSrcweir except IOError: 184*7d9fa7c3SPedro Giffuni print("Error: Can not create dir " + dir) 185cdf0e10cSrcweir sys.exit(-1) 186ae54856bSPedro Giffuni 187cdf0e10cSrcweir def test_options(self): 188cdf0e10cSrcweir opt = self._options 189cdf0e10cSrcweir is_valid = lambda x: x != None and len(x) > 0 190cdf0e10cSrcweir return is_valid(opt.project_root) and is_valid(opt.project_name) and is_valid(opt.languages) and \ 191cdf0e10cSrcweir ( is_valid(opt.inputfile) and (( is_valid(opt.path_prefix) and is_valid(opt.path_postfix) ) or is_valid(opt.outputfile)) and \ 192cdf0e10cSrcweir ( ( is_valid(opt.input_sdf_file) and ( is_valid(opt.outputfile) or ( is_valid(opt.path_prefix) and is_valid(opt.path_postfix) ) or \ 193cdf0e10cSrcweir ( is_valid(opt.inputfile) and is_valid(opt.outputFile)) )))) 194*7d9fa7c3SPedro Giffuni print("Strange options ...") 195cdf0e10cSrcweir sys.exit( -1 ) 196ae54856bSPedro Giffuni 197cdf0e10cSrcweir def read_inputfile_list(self): 198cdf0e10cSrcweir if self.has_multi_inputfiles(): 199cdf0e10cSrcweir lines = [] 200cdf0e10cSrcweir try: 201cdf0e10cSrcweir f = open(self._options.inputfile[1:], "r") 202cdf0e10cSrcweir lines = [line.strip('\n') for line in f.readlines()] 203cdf0e10cSrcweir except IOError: 204*7d9fa7c3SPedro Giffuni print("ERROR: Can not read file list " + self._options.inputfile[2:]) 205cdf0e10cSrcweir sys.exit(-1) 206cdf0e10cSrcweir else: 207cdf0e10cSrcweir f.close() 208cdf0e10cSrcweir return lines 209ae54856bSPedro Giffuni 210cdf0e10cSrcweir def get_filename_string(self, inputfile): 211cdf0e10cSrcweir absfile = os.path.realpath(os.path.abspath(inputfile)) 212ae54856bSPedro Giffuni absroot = os.path.realpath(os.path.abspath(self._options.project_root)) 213cdf0e10cSrcweir return absfile[len(absroot)+1:].replace('/','\\') 214