1. mst
  2. ooo340

Commits

Ivo Hinkelmann  committed 5579094

txtl10n: #i113008# #i113125# Support of help tree files and single txt files in the L10N process

  • Participants
  • Parent commits 075ba3b
  • Branches default

Comments (0)

Files changed (5)

File l10ntools/scripts/tool/const.py

View file
  • Ignore whitespace
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org.  If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+# Pseudo const
+class _const:
+    class ConstError(TypeError): pass
+    def __setattr__(self, name, value):
+        if self.__dict__.has_key(name):
+            raise self.ConstError, "Can't rebind const(%s)"%name
+        self.__dict__[name] = value
+
+import sys
+sys.modules[__name__] = _const()
+
+

File l10ntools/scripts/tool/l10ntool.py

View file
  • Ignore whitespace
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org.  If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+from optparse import OptionParser
+from sdf import SdfData
+import sys
+import os
+import shutil
+
+class abstractL10nTool:
+    _options            = {}
+    _args               = ""
+    _resource_type      = "" 
+    _source_language    = "en-US"
+   
+    ##### Implement these abstract methods
+
+    ##### Nameing scheme for the output files
+    def get_outputfile_format_str(self):
+        # filename,fileNoExt,language,extension,pathPrefix,pathPostFix,path
+        #return "{path}/{fileNoExt}_{language}.{extension}"
+        return self._options.pattern
+
+    ################################# Merge single files ###########################################
+
+    ##### Merge a single file
+    def merge_file(self, inputfilename, outputfilename, parsed_file_ref, lang, is_forced_lang, sdfdata):
+        pass
+
+    ##### Helper for parse-once-use-often like parsing a xml file is needed implement it here
+    def parse_file(self, filename):
+        return None
+
+    ################### Merge one big file containing all strings in all languages #################
+    def merge_one_big_file(self, inputfile, outputfilename, parsed_file_ref, lang, sdfdata):
+        pass
+
+    ################### Extract a single File ######################################################
+    def extract_file(self, inputfile):
+        pass
+    
+    ################################################################################################
+    
+    def format_outputfile(self, filename, language):
+        extension = filename[filename.rfind('.')+1:]
+        file = filename[:filename.rfind('.')]
+        return self.get_outputfile_format_str().replace('[', '{').replace(']','}').format(
+               filename=filename, fileNoExt=file, language=language, extension=extension, path_prefix=self._options.path_prefix,
+               path_postfix=self._options.path_postfix, path=self.get_path())
+
+    def get_path(self):
+        if self._options.outputfile.find('/') == -1:
+            return ""
+        else:
+            return self._options.outputfile[:self._options.outputfile.rfind('/')]
+            
+    def merge(self,  sdfdata):
+        langset,forcedset, foundset = set(), set() , set()
+
+        if self._options.languages:       
+            langset = set(self._options.languages)  
+        if self._options.forcedlanguages: 
+            forcedset = set(self._options.forcedlanguages) 
+        if sdfdata.get_languages_found_in_sdf(): 
+            foundset = sdfdata.get_languages_found_in_sdf() 
+    
+        if self.has_multi_inputfiles(): 
+            filelist = self.read_inputfile_list()
+        else:
+            filelist = self._options.inputfile
+            
+        for inputfile in filelist:
+            ref = self.parse_file(inputfile)
+            # Don't write that files if there is no l10n present
+            if ((langset & foundset) - forcedset):  # all langs given and found in sdf without enforced 
+                [self.merge_file(inputfile,self.format_outputfile(inputfile, lang), ref, lang, False, sdfdata) for lang in ((langset & foundset) - forcedset)]
+            # Always write those files even if there is no l10n available
+            if forcedset: # all enforced langs
+                [self.merge_file(inputfile, self.format_outputfile(inputfile, lang), ref, lang, True, sdfdata)  for lang in forcedset]
+            # In case a big file have to be written
+            if ((langset & foundset) | forcedset): # all langs given ,found in sdf and enforced ones
+                self.merge_one_big_file(inputfile, self.format_outputfile(inputfile, lang), ref, ((langset & foundset) | forcedset), sdfdata)
+    
+    def has_multi_inputfiles(self): 
+        return self._options.inputfile[0] == '@'
+
+    def copy_file(self, inputfilename, outputfilename):
+        try:
+            shutil.copy(inputfilename, outputfilename)
+        except IOError:
+            print "ERROR: Can not copy file '" + inputfilename + "' to " + "'" + outputfilename + "'"
+            sys.exit(-1)
+    
+    def extract(self):
+        try:
+            f = open(self._options.outputfile, "w+")
+            f.write(self.extract_file(self._options.inputfile))
+        except IOError:
+            print "ERROR: Can not write file " + self._options.outputfile
+        else:
+            f.close()
+            
+    # Parse the common options
+    def parse_options(self):
+        parser = OptionParser()
+        parser.add_option("-i", "--inputfile",       dest="inputfile",       metavar="FILE", help="resource file to read"         )
+        parser.add_option("-o", "--outputfile",      dest="outputfile",      metavar="FILE", help="extracted sdf or merged file"  )
+        parser.add_option("-m", "--inputsdffile",    dest="input_sdf_file",  metavar="FILE", help="merge this sdf file"           )
+        parser.add_option("-x", "--pathprefix",      dest="path_prefix",     metavar="PATH", help=""                              )
+        parser.add_option("-y", "--pathpostfix",     dest="path_postfix",    metavar="PATH", help=""                              )
+        parser.add_option("-p", "--projectname",     dest="project_name",    metavar="NAME", help=""                              )
+        parser.add_option("-r", "--projectroot",     dest="project_root",    metavar="PATH", help=""                              )
+        parser.add_option("-f", "--forcedlanguages", dest="forcedlanguages", metavar="ISOCODE[,ISOCODE]", help="Always merge those langs even if no l10n is available for those langs" )
+        parser.add_option("-l", "--languages",       dest="languages",       metavar="ISOCODE[,ISOCODE]", help="Merge those langs if l10n is found for each")
+        parser.add_option("-s", "--pattern",         dest="pattern",         metavar="", help=""                                  )        
+        parser.add_option("-q", "--quiet",           action="store_true",    dest="quietmode", help="",default=False)
+        (self._options, self.args) = parser.parse_args()
+        
+        # -l "de,pr,pt-BR" => [ "de" , "pt" , "pt-BR" ]
+        parse_complex_arg = lambda arg: arg.split(",")
+        
+        if self._options.forcedlanguages: 
+            self._options.forcedlanguages = parse_complex_arg(self._options.forcedlanguages) 
+        if self._options.languages:       
+            self._options.languages = parse_complex_arg(self._options.languages) 
+        self.test_options()
+        
+    def __init__(self):
+        self.parse_options()
+        if self._options.input_sdf_file != None and len(self._options.input_sdf_file):
+            sdfdata = SdfData(self._options.input_sdf_file)
+            sdfdata.read()
+            self.merge(sdfdata)
+        else:
+            self.extract()
+
+    def make_dirs(self, filename):
+        dir = filename[:filename.rfind('/')]
+        if os.path.exists(dir):
+            if os.path.isfile(dir):
+                print "ERROR: There is a file '"+dir+"' where I want create a directory"
+                sys.exit(-1)
+            else:
+                return
+        else:
+            try:
+                print "DBG: make_dir " + str(dir)
+                os.makedirs(dir)
+            except IOError:
+                print "Error: Can not create dir " + dir
+                sys.exit(-1)
+            
+    def test_options(self):
+        opt = self._options
+        is_valid = lambda x: x != None and len(x) > 0
+        return  is_valid(opt.project_root) and is_valid(opt.project_name) and is_valid(opt.languages) and \
+                ( is_valid(opt.inputfile) and (( is_valid(opt.path_prefix) and is_valid(opt.path_postfix) ) or is_valid(opt.outputfile)) and \
+                ( ( is_valid(opt.input_sdf_file) and ( is_valid(opt.outputfile) or  ( is_valid(opt.path_prefix) and is_valid(opt.path_postfix) ) or \
+                ( is_valid(opt.inputfile) and is_valid(opt.outputFile)) ))))
+        print "Strange options ..."
+        sys.exit( -1 )
+                     
+    def read_inputfile_list(self):
+        if self.has_multi_inputfiles():
+            lines = []
+            try:
+                f = open(self._options.inputfile[1:], "r")
+                lines = [line.strip('\n') for line in f.readlines()]
+            except IOError:
+                print "ERROR: Can not read file list " + self._options.inputfile[2:]
+                sys.exit(-1)
+            else:
+                f.close()
+            return lines
+        
+    def get_filename_string(self, inputfile):
+        absfile = os.path.realpath(os.path.abspath(inputfile))
+        absroot = os.path.realpath(os.path.abspath(self._options.project_root)) 
+        return absfile[len(absroot)+1:].replace('/','\\')
+    

File l10ntools/scripts/tool/sdf.py

View file
  • Ignore whitespace
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org.  If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+class MyOrderedDict(dict):
+    _keylist        = []
+    _valuelist      = []
+    
+    def __init__(self, defaults={}):
+        dict.__init__(self)
+        for n,v in defaults.items():
+            self[n] = v
+
+    def __setitem__(self, key, value):
+        self._keylist.append(key)
+        self._valuelist.append(value)
+        return dict.__setitem__(self, key, value)
+        
+    def __delattr__(self, key):
+        self._keylist.__delattr__(key)
+        self._valuelist.__delattr__(dict[key])
+        return dict.__delattr__(self, key)
+
+    def __delitem__(self, key):
+        self._keylist.__delitem__(key)
+        self._valuelist.__delitem__(dict[key])
+        return dict.__delitem__(self, key)
+        
+    def __iter(self):
+        return zip(self._keylist, self._valuelist)
+    
+    def __iterkeys__(self):
+        return self._keylist
+    
+    def __iteritems__(self):
+        return self._valuelist
+    
+    def items(self):
+        return zip(self._keylist,self._valuelist)
+
+    def keys(self):
+        return self._keylist
+
+    def __keysattr__(self):
+        return self._keylist
+    
+    def pop(self, key):
+        self._keylist.pop(key)
+        self._valuelist.pop(key)
+        return dict.__pop__(self, key)
+    
+    def popitem(self):
+        raise NotImplementedError("popitem")
+    
+    def clear(self):
+        self._keylist.clear()
+        self._valuelist.clear()
+        return dict.clear()
+        
+    def copy(self):
+        newobj            = MyOrderedDict(self)
+        newobj._keylist   = self._keylist
+        newobj._valuelist = self._valuelist
+        return newobj
+        
+class SdfData:
+    _filename        = "";
+    _dict            = MyOrderedDict()
+    _languages_found = [];
+    
+    def __init__ (self, filename=""):
+        self._filename = filename
+    
+    def __getitem__(self, key):
+        if self._dict.has_key(key):
+            return self._dict[key]
+        else:
+            return None
+    
+    def has_key(self, key):
+        return self._dict.has_key(key)
+    
+    def __setitem__(self, key, value):
+        self._dict[key] = value
+    
+    def get_languages_found_in_sdf(self):
+        return set(self._languages_found)
+
+    def read(self):
+        try:
+            f = open(self._filename, "r")
+            lines = [line.rstrip('\n') for line in f.readlines()] 
+        except IOError:
+            print "ERROR: Trying to read "+ self._filename
+            raise
+        else:
+            f.close()
+        for line in lines:        
+            entity = SdfEntity()
+            entity.set_properties(line)
+            self._dict[entity.get_id()] = entity
+            self._languages_found.append(entity.langid)
+
+    def write(self, filename):
+        try:
+            f = open(filename, "w+") 
+            for value in self._dict.itervalues():
+                #f.write( repr(value)+"\n" )
+                f.write(value + "\n")
+        except IOError:
+            print "ERROR: Trying to write " + filename
+            raise
+        else:
+            f.close()
+
+import sys
+class SdfEntity: 
+    # Sdf format columns
+    project         = ""
+    source_file     = ""
+    dummy1          = ""
+    resource_type   = ""
+    gid             = ""
+    lid             = ""
+    helpid          = ""
+    platform        = ""
+    dummy2          = ""
+    langid          = ""
+    text            = ""
+    helptext        = ""
+    quickhelptext   = ""
+    title           = ""
+    date            = ""
+    
+    import const
+    const._PROJECT_POS         = 0
+    const._SOURCE_FILE_POS     = 1
+    const._DUMMY1_POS          = 2
+    const._RESOURCE_TYPE_POS   = 3
+    const._GID_POS             = 4
+    const._LID_POS             = 5
+    const._HELPID_POS          = 6
+    const._PLATFORM_POS        = 7
+    const._DUMMY2_POS          = 8
+    const._LANGID_POS          = 9
+    const._TEXT_POS            = 10
+    const._HELPTEXT_POS        = 11
+    const._QUICKHELPTEXT_POS   = 12
+    const._TITLE_POS           = 13
+    const._DATE_POS            = 14
+        
+    def __init__(self, project="", source_file="", dummy1="", resource_type="", gid="", lid="", helpid="", platform="", dummy2="", langid="", 
+                       text="", helptext="", quickhelptext="", title="", date="2002-02-02 02:02:02"):
+        self.project        = project;
+        self.source_file    = source_file;
+        self.dummy1         = dummy1;
+        self.resource_type  = resource_type;
+        self.gid            = gid;
+        self.lid            = lid;
+        self.helpid         = helpid;
+        self.platform       = platform;
+        self.dummy2         = dummy2;
+        self.langid         = langid;
+        self.text           = text;
+        self.helptext       = helptext;
+        self.quickhelptext  = quickhelptext;
+        self.title          = title;
+        self.date           = date;
+
+    def set_properties(self, line):
+        splitted = line.split("\t")
+        if len(splitted) == 15:
+            self.project        = splitted[ self.const._PROJECT_POS ]             
+            self.source_file    = splitted[ self.const._SOURCE_FILE_POS ]     
+            self.dummy1         = splitted[ self.const._DUMMY1_POS ]         
+            self.resource_type  = splitted[ self.const._RESOURCE_TYPE_POS ] 
+            self.gid            = splitted[ self.const._GID_POS ]             
+            self.lid            = splitted[ self.const._LID_POS ]             
+            self.helpid         = splitted[ self.const._HELPID_POS ]         
+            self.platform       = splitted[ self.const._PLATFORM_POS ]         
+            self.dummy2         = splitted[ self.const._DUMMY2_POS ]         
+            self.langid         = splitted[ self.const._LANGID_POS ]         
+            self.text           = splitted[ self.const._TEXT_POS ]             
+            self.helptext       = splitted[ self.const._HELPTEXT_POS ]         
+            self.quickhelptext  = splitted[ self.const._QUICKHELPTEXT_POS ] 
+            self.title          = splitted[ self.const._TITLE_POS ]         
+            self.date           = splitted[ self.const._DATE_POS ]            
+
+    def get_file_id(self):
+        return self.project + "\\" + self.source_file
+    
+    def get_resource_path(self):
+            return self.source_file[0:self.source_file.rfind( "\\" )-1]
+    
+    def __str__(self):
+        return ''.join([self.project, "\t", self.source_file, "\t", self.dummy1, "\t", self.resource_type, "\t" , 
+            self.gid, "\t", self.lid, "\t", self.helpid, "\t", self.platform, "\t", self.dummy2, "\t" , self.langid, 
+            "\t", self.text, "\t", self.helptext, "\t", self.quickhelptext, "\t" , self.title, "\t", self.date ])
+    
+    def get_id(self):
+        return ''.join([self.project, self.gid, self.lid, self.source_file, self.resource_type, self.platform, self.helpid, self.langid])

File l10ntools/scripts/tool/xhtex.py

View file
  • Ignore whitespace
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org.  If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+from l10ntool import abstractL10nTool
+from sdf import SdfEntity
+import sys
+import xml.dom.minidom
+
+class xhtex(abstractL10nTool):
+    _resource_type = "xht" 
+    _sdfdata       = ()
+    _lang          = ""
+   
+    # Extract methods
+    def extract_topic(self, list, inputfile):
+        topics = []
+        for elem in list:                        
+            if elem.childNodes[0].nodeType == elem.TEXT_NODE:
+                topics.append(self.prepare_sdf_line(id=elem.getAttribute("id").strip(), text=elem.childNodes[0].data, inputfile=inputfile))            
+        return topics
+            
+    def extract_title(self, list, inputfile):
+        titles = []
+        for elem in list:
+            titles.append(self.prepare_sdf_line(id=elem.getAttribute("id").strip(), text=elem.getAttribute("title").strip(), inputfile=inputfile))
+        return titles
+    
+    # Merge methods
+    def merge_topic(self, list, sdfdata, lang, inputfilename, dom):
+        for elem in list:
+            if elem.childNodes[0].nodeType == elem.TEXT_NODE and elem.getAttribute("id").strip():
+                obj = self.prepare_sdf_line(inputfile=inputfilename, lang=lang, id=elem.getAttribute("id").strip())
+                if sdfdata[obj.get_id()]:
+                    elem.childNodes[0].data = str(sdfdata[obj.get_id()].text)  
+                
+    def merge_title(self, list, sdfdata, lang, inputfilename):
+        for elem in list:
+            obj = self.prepare_sdf_line(inputfile=inputfilename, lang=lang, id=elem.getAttribute("id").strip())
+            if elem.getAttribute("id").strip() and sdfdata[obj.get_id()]: 
+                elem.setAttribute("title", str(sdfdata[obj.get_id()].text))
+
+    # L10N tool       
+    def __init__(self):
+        abstractL10nTool.__init__(self)
+        
+    def parse_file(self, filename):
+        document = ""
+        try:
+            f = open(filename, "r+")
+            document = f.read()
+        except IOError:
+            print "ERROR: Can not read file " + filename
+            sys.exit(-1)
+        else:
+            f.close()
+        return xml.dom.minidom.parseString(document)
+
+        
+    def merge_file(self, inputfilename, outputfilename, parsed_file_ref, lang,is_forced_lang, sdfdata):
+        if lang == "en-US":             
+            mod_outputfilename = outputfilename.replace("_en-US",'')            
+            self.copy_file(inputfilename, mod_outputfilename)
+            return
+        dom = parsed_file_ref.cloneNode(True)
+        #dom = self.parse_file(inputfilename)    # in case cloneNode is buggy just parse it always
+                
+        self.merge_topic(dom.getElementsByTagName("topic"), sdfdata, lang, inputfilename, dom)
+        self.merge_title(dom.getElementsByTagName("node"), sdfdata, lang, inputfilename)
+        self.merge_title(dom.getElementsByTagName("help_section"), sdfdata, lang, inputfilename)
+        self.make_dirs(outputfilename)
+        try:
+            f = open(outputfilename, "w+")
+            str = dom.toxml()
+            f.write(str)
+        except IOError:
+            print "ERROR: Can not write file " + outputfilename
+            sys.exit(-1)
+        else:
+            f.close()
+    
+    ##### Helper for parse-once-use-often like parsing a xml file is needed implement it here
+    def parse_file(self, filename):
+        document = ""
+        try:
+            f = open(filename,"r+")
+            document = f.read()
+        except IOError:
+            print "ERROR: Can not read file " + filename
+        else:
+            f.close()        
+        return xml.dom.minidom.parseString(document)
+    
+    ##### Extract a single File
+    def extract_file(self, inputfile):
+        sdf_data = []
+        dom = self.parse_file(inputfile)        
+        sdf_data.extend(self.extract_topic(dom.getElementsByTagName("topic"), inputfile))
+        sdf_data.extend(self.extract_title(dom.getElementsByTagName("help_section"), inputfile))
+        sdf_data.extend(self.extract_title(dom.getElementsByTagName("node"), inputfile))        
+        return ''.join([str(line)+"\n" for line in sdf_data])                      
+
+    def prepare_sdf_line(self, inputfile="", lang="" , id="" , text=""):
+        if lang == "":
+            lang = self._source_language
+        return SdfEntity(project=self._options.project_name, source_file=self.get_filename_string(inputfile),
+                         resource_type=self._resource_type, gid=id, lid="", langid=lang,text=text)
+        
+run = xhtex()
+ 

File l10ntools/scripts/tool/xtxex.py

View file
  • Ignore whitespace
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org.  If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+from l10ntool import abstractL10nTool
+from sdf import SdfEntity
+import sys
+import shutil 
+
+class xtxex(abstractL10nTool):
+    _resource_type       = "xtx" 
+       
+    def __init__(self):
+        abstractL10nTool.__init__(self)
+        
+    def merge_file(self, inputfilename, outputfilename, parsed_file_ref, lang, is_forced_lang, sdfdata): 
+        # Special handling for en-US files
+        if lang == "en-US":             
+            mod_outputfilename = outputfilename.replace("_en-US",'')
+            self.copy_file(inputfilename, mod_outputfilename)
+            return      
+        # merge usual lang
+        sdfline = self.prepare_sdf_line(inputfilename,lang)
+        if sdfdata.has_key(sdfline.get_id()):
+            line = sdfdata[sdfline.get_id()].text.replace("\\n", '\n')
+            self.make_dirs(outputfilename)
+            try:
+                f = open(outputfilename, "w+")
+                f.write(line)
+            except IOError:
+                print "ERROR: Can not write file " + outputfilename
+                sys.exit(-1)
+            else:
+                f.close()
+            return        
+        # no sdf data found then copy en-US source file
+        if is_forced_lang:
+            self.copy_file(inputfilename, outputfilename)
+               
+    ##### Extract a single File
+    def extract_file(self, inputfile):
+        lines = []
+        try:
+            f = open(inputfile, "r")
+            lines = f.readlines()
+        except IOError:
+            print "ERROR: Can not open file " + inputfile
+            sys.exit(-1)
+        else:
+            f.close()
+        # remove legal header
+        lines = [line for line in lines if len(line) > 0 and not line[0] == '#']        
+        # escape all returns
+        lines = [line.replace('\n', "\\n") for line in lines]
+        line = ''.join(lines)
+        sdf_entity = self.prepare_sdf_line(inputfile);
+        sdf_entity.text = line
+        return str(sdf_entity)
+    
+    def prepare_sdf_line(self, inputfile="", lang=""):
+        if lang == "":
+            lang = self._source_language
+        return SdfEntity(project=self._options.project_name, source_file=self.get_filename_string(inputfile),
+                          resource_type=self._resource_type, gid="none", lid="none", langid=lang,text="")
+         
+run = xtxex()