File indexing completed on 2024-12-08 13:32:02
0001 # -*- coding: UTF-8 -*- 0002 0003 """ 0004 Generate an XML tree from the input PO files. 0005 0006 Documented in C{doc/user/sieving.docbook}. 0007 0008 @author: Nicolas Ternisien <nicolas.ternisien@gmail.com> 0009 @license: GPLv3 0010 """ 0011 0012 from codecs import open 0013 import locale 0014 import os 0015 from os.path import abspath, basename, dirname, isdir, isfile, join 0016 import sys 0017 0018 from pology import _, n_ 0019 from pology.report import report 0020 from pology.rules import loadRules, Rule 0021 from pology.timeout import TimedOutException 0022 0023 0024 def setup_sieve (p): 0025 0026 p.set_desc(_("@info sieve discription", 0027 "Generate an XML tree from the input PO files." 0028 "\n\n" 0029 "See documentation for the description of the XML format used." 0030 )) 0031 0032 p.add_param("xml", str, 0033 metavar=_("@info sieve parameter value placeholder", "FILE"), 0034 desc=_("@info sieve parameter discription", 0035 "Write the XML tree into a file instead to standard output." 0036 )) 0037 # FIXME: Parameter name out of style. 0038 p.add_param("translatedOnly", bool, defval=False, 0039 desc=_("@info sieve parameter discription", 0040 "Consider only translated messages." 0041 )) 0042 0043 0044 class Sieve (object): 0045 0046 def __init__ (self, params): 0047 0048 self.xmlFile = None # File handle to write XML output 0049 self.filename = "" # File name we are processing 0050 self.translatedOnly = False 0051 0052 0053 # Also output in XML file ? 0054 if params.xml: 0055 xmlPath = params.xml 0056 if os.access(dirname(abspath(xmlPath)), os.W_OK): 0057 self.xmlFile=open(xmlPath, "w", "utf-8") 0058 else: 0059 warning(_("@info", 0060 "Cannot open file '%(file)s'. XML output disabled.", 0061 file=xmlPath)) 0062 0063 self.translatedOnly = params.translatedOnly 0064 0065 0066 self.output('<?xml version="1.0" encoding="UTF-8"?>\n') 0067 self.output('<pos>\n') 0068 0069 self.count = {} 0070 self.count["obs"] = 0 0071 self.count["tot"] = 0 0072 self.count["trn"] = 0 0073 self.count["fuz"] = 0 0074 self.count["unt"] = 0 0075 0076 # Indicators to the caller: 0077 self.caller_sync = False # no need to sync catalogs 0078 self.caller_monitored = False # no need for monitored messages 0079 0080 def process(self, msg, cat): 0081 filename=basename(cat.filename) 0082 0083 # Handle start/end of files for XML output (not needed for text output) 0084 if self.filename!=filename: 0085 if self.filename != "": 0086 self.write_stats() 0087 # close previous 0088 self.output("</po>\n") 0089 0090 self.filename=filename 0091 # open new po 0092 self.output('<po name="%s">\n' % filename) 0093 0094 # Test the add or not of this message 0095 if self.add_message(msg) is False: 0096 return 0097 0098 # Statistics updating 0099 if msg.obsolete: 0100 self.count["obs"] += 1 0101 status = "obsolete" 0102 else: 0103 self.count["tot"] += 1 0104 if msg.translated: 0105 self.count["trn"] += 1 0106 status = "translated" 0107 elif msg.fuzzy: 0108 self.count["fuz"] += 1 0109 status = "fuzzy" 0110 elif msg.untranslated: 0111 self.count["unt"] += 1 0112 status = "untranslated" 0113 0114 # Output writing 0115 self.output("\t<msg>\n") 0116 self.output("\t\t<line>%s</line>\n" % msg.refline) 0117 self.output("\t\t<refentry>%s</refentry>\n" % msg.refentry) 0118 self.output("\t\t<status>%s</status>\n" % status) 0119 self.output("\t\t<msgid><![CDATA[%s]]></msgid>\n" % self.replace_cdata(msg.msgid) ) 0120 self.output("\t\t<msgstr>%s</msgstr>\n" % self.join_plural_form(msg.msgstr) ) 0121 0122 if not msg.msgctxt: 0123 self.output("\t\t<msgctxt></msgctxt>\n") 0124 else: 0125 self.output("\t\t<msgctxt><![CDATA[%s]]></msgctxt>\n" % self.replace_cdata(msg.msgctxt) ) 0126 0127 self.output("\t</msg>\n") 0128 0129 def join_plural_form(self, message_list): 0130 if len(message_list) == 1: 0131 return "<![CDATA[%s]]>" % self.replace_cdata(message_list[0]) 0132 0133 message_str = "" 0134 for msgstr in message_list: 0135 message_str += "<plural><![CDATA[%s]]></plural>" % self.replace_cdata(msgstr) 0136 0137 return message_str 0138 0139 0140 def add_message(self, msg): 0141 if self.translatedOnly is False: 0142 return True 0143 0144 if self.translatedOnly is True and msg.translated is True: 0145 return True 0146 0147 return False 0148 0149 0150 def replace_cdata(self, msg): 0151 return msg.replace("<![CDATA[", "<![CDATA[").replace("]]>", "]]>") 0152 0153 def output(self, content): 0154 if self.xmlFile: 0155 self.xmlFile.write(content) 0156 else: 0157 report(content.rstrip("\n")) 0158 0159 def write_stats(self): 0160 self.output("\t<stats>\n") 0161 self.output("\t\t<obsolete>%s</obsolete>\n" % self.count["obs"]) 0162 self.output("\t\t<total>%s</total>\n" % self.count["tot"]) 0163 self.output("\t\t<translated>%s</translated>\n" % self.count["trn"]) 0164 self.output("\t\t<fuzzy>%s</fuzzy>\n" % self.count["fuz"]) 0165 self.output("\t\t<untranslated>%s</untranslated>\n" % self.count["unt"]) 0166 self.output("\t</stats>\n") 0167 self.count["obs"] = 0 0168 self.count["tot"] = 0 0169 self.count["trn"] = 0 0170 self.count["fuz"] = 0 0171 self.count["unt"] = 0 0172 0173 def finalize (self): 0174 self.write_stats() 0175 self.output("</po>\n") 0176 self.output('</pos>\n') 0177 0178 if self.xmlFile: 0179 # Close last po tag and xml file 0180 self.xmlFile.close() 0181