This file is indexed.

/usr/share/pyshared/translate/convert/po2dtd.py is in translate-toolkit 1.10.0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2002-2009,2012 Zuza Software Foundation
#
# This file is part of translate.
#
# translate is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# translate 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.

"""Converts a Gettext PO file to a UTF-8 encoded Mozilla .dtd file.

.. note: Conversion is either done using a template plus PO file or just
   using the .po file.
"""

import warnings

from translate.storage import dtd
from translate.storage import po
from translate.misc import quote
from translate.convert import accesskey


def dtdwarning(message, category, filename, lineno, line=None):
    return "Warning: %s\n" % message
warnings.formatwarning = dtdwarning


def applytranslation(entity, dtdunit, inputunit, mixedentities):
    """applies the translation for entity in the po unit to the dtd unit"""
    # this converts the po-style string to a dtd-style string
    unquotedstr = inputunit.target
    # check there aren't missing entities...
    if len(unquotedstr.strip()) == 0:
        return
    # handle mixed entities
    for labelsuffix in dtd.labelsuffixes:
        if entity.endswith(labelsuffix):
            if entity in mixedentities:
                unquotedstr, akey = accesskey.extract(unquotedstr)
                break
    else:
        for akeytype in dtd.accesskeysuffixes:
            if entity.endswith(akeytype):
                if entity in mixedentities:
                    label, unquotedstr = accesskey.extract(unquotedstr)
                    if not unquotedstr:
                        warnings.warn("Could not find accesskey for %s" % entity)
                    else:
                        original = dtdunit.source
                        # For the sake of diffs we keep the case of the
                        # accesskey the same if we know the translation didn't
                        # change. Casing matters in XUL.
                        if unquotedstr == dtdunit.source and original.lower() == unquotedstr.lower():
                            if original.isupper():
                                unquotedstr = unquotedstr.upper()
                            elif original.islower():
                                unquotedstr = unquotedstr.lower()
    if len(unquotedstr) > 0:
        dtdunit.source = dtd.removeinvalidamps(entity, unquotedstr)


class redtd:
    """this is a convertor class that creates a new dtd based on a template using translations in a po"""

    def __init__(self, dtdfile, android=False):
        self.dtdfile = dtdfile
        self.mixer = accesskey.UnitMixer(dtd.labelsuffixes, dtd.accesskeysuffixes)
        self.android = False

    def convertstore(self, inputstore, includefuzzy=False):
        # translate the strings
        for inunit in inputstore.units:
            # there may be more than one entity due to msguniq merge
            if includefuzzy or not inunit.isfuzzy():
                self.handleinunit(inunit)
        return self.dtdfile

    def handleinunit(self, inunit):
        entities = inunit.getlocations()
        mixedentities = self.mixer.match_entities(entities)
        for entity in entities:
            if entity in self.dtdfile.index:
                # now we need to replace the definition of entity with msgstr
                dtdunit = self.dtdfile.index[entity]  # find the dtd
                applytranslation(entity, dtdunit, inunit, mixedentities)


class po2dtd:
    """this is a convertor class that creates a new dtd file based on a po file without a template"""

    def __init__(self, android=False):
        self.android = android

    def convertcomments(self, inputunit, dtdunit):
        entities = inputunit.getlocations()
        if len(entities) > 1:
            # don't yet handle multiple entities
            dtdunit.comments.append(("conversionnote", '<!-- CONVERSION NOTE - multiple entities -->\n'))
            dtdunit.entity = entities[0]
        elif len(entities) == 1:
            dtdunit.entity = entities[0]
        else:
            # this produces a blank entity, which doesn't write anything out
            dtdunit.entity = ""

        if inputunit.isfuzzy():
            dtdunit.comments.append(("potype", "fuzzy\n"))
        for note in inputunit.getnotes("translator").split("\n"):
            if not note:
                continue
            note = quote.unstripcomment(note)
            if (note.find('LOCALIZATION NOTE') == -1) or (note.find('GROUP') == -1):
                dtdunit.comments.append(("comment", note))
        # msgidcomments are special - they're actually localization notes
        msgidcomment = inputunit._extract_msgidcomments()
        if msgidcomment:
            locnote = quote.unstripcomment("LOCALIZATION NOTE (" + dtdunit.entity + "): " + msgidcomment)
            dtdunit.comments.append(("locnote", locnote))

    def convertstrings(self, inputunit, dtdunit):
        if inputunit.istranslated():
            unquoted = inputunit.target
        else:
            unquoted = inputunit.source
        dtdunit.source = dtd.removeinvalidamps(dtdunit.entity, unquoted)

    def convertunit(self, inputunit):
        dtdunit = dtd.dtdunit()
        self.convertcomments(inputunit, dtdunit)
        self.convertstrings(inputunit, dtdunit)
        return dtdunit

    def convertstore(self, inputstore, includefuzzy=False):
        outputstore = dtd.dtdfile(android=self.android)
        self.currentgroups = []
        for inputunit in inputstore.units:
            if includefuzzy or not inputunit.isfuzzy():
                dtdunit = self.convertunit(inputunit)
                if dtdunit is not None:
                    outputstore.addunit(dtdunit)
        return outputstore


def convertdtd(inputfile, outputfile, templatefile, includefuzzy=False):
    inputstore = po.pofile(inputfile)

    # Some of the DTD files used for Firefox Mobile are actually completely
    # different with different escaping and quoting rules. The best way to
    # identify them seems to be on their file path in the tree (based on code
    # in compare-locales).
    android_dtd = False
    header_comment = u""
    input_header = inputstore.header()
    if input_header:
        header_comment = input_header.getnotes("developer")
        if "embedding/android" in header_comment or "mobile/android/base" in header_comment:
            android_dtd = True

    if templatefile is None:
        convertor = po2dtd(android=android_dtd)
    else:
        templatestore = dtd.dtdfile(templatefile, android=android_dtd)
        convertor = redtd(templatestore, android=android_dtd)
    outputstore = convertor.convertstore(inputstore, includefuzzy)
    outputfile.write(str(outputstore))
    return 1


def main(argv=None):
    # handle command line options
    from translate.convert import convert
    formats = {"po": ("dtd", convertdtd), ("po", "dtd"): ("dtd", convertdtd)}
    parser = convert.ConvertOptionParser(formats, usetemplates=True, description=__doc__)
    parser.add_fuzzy_option()
    parser.run(argv)


if __name__ == '__main__':
    main()