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[", "&lt;![CDATA[").replace("]]>", "]]&gt;")
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