summaryrefslogtreecommitdiffstats
path: root/docs/release/scripts/build/msgfmt.py
blob: deb02ae32b23e2421fe4074d29cfc9d458593543 (plain) (blame)
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
generated by cgit v1.2.3 (git 2.39.1) at 2025-05-06 04:51:21 +0000
 


lass="s1">'latin-1'

    # Parse the catalog
    for lno, l in enumerate(lines):
        l = l.decode(encoding)
        # If we get a comment line after a msgstr, this is a new entry
        if l[0] == '#' and section == STR:
            add(msgid, msgstr, fuzzy)
            section = None
            fuzzy = 0
        # Record a fuzzy mark
        if l[:2] == '#,' and 'fuzzy' in l:
            fuzzy = 1
        # Skip comments
        if l[0] == '#':
            continue
        # Now we are in a msgid section, output previous section
        if l.startswith('msgid') and not l.startswith('msgid_plural'):
            if section == STR:
                add(msgid, msgstr, fuzzy)
                if not msgid:
                    # See whether there is an encoding declaration
                    p = HeaderParser()
                    charset = p.parsestr(msgstr.decode(encoding)).get_content_charset()
                    if charset:
                        encoding = charset
            section = ID
            l = l[5:]
            msgid = msgstr = b''
            is_plural = False
            if l.strip() == '""':
                # Check if next line is msgstr. If so, this is a multiline msgid.
                if lines[lno+1].decode(encoding).startswith('msgstr'):
                    # If this is the first empty msgid and is followed by msgstr, this is the header, which may contain the encoding declaration.
                    # Otherwise this file is not valid
                    if empty > 1:
                        print("Found multiple empty msgids on line " + str(lno) + ", not valid!")
                    empty += 1
        # This is a message with plural forms
        elif l.startswith('msgid_plural'):
            if section != ID:
                print('msgid_plural not preceded by msgid on %s:%d' % (infile, lno),
                      file=sys.stderr)
                sys.exit(1)
            l = l[12:]
            msgid += b'\0' # separator of singular and plural
            is_plural = True
        # Now we are in a msgstr section
        elif l.startswith('msgstr'):
            section = STR
            if l.startswith('msgstr['):
                if not is_plural:
                    print('plural without msgid_plural on %s:%d' % (infile, lno),
                          file=sys.stderr)
                    sys.exit(1)
                l = l.split(']', 1)[1]
                if msgstr:
                    msgstr += b'\0' # Separator of the various plural forms
            else:
                if (l[6:].strip() == '""') and (empty == 1) and (not header_attempted):
                    header = ""
                    # parse up until next empty line = end of header
                    hdrno = lno
                    while(hdrno < len(lines)-1):
                        # This is a roundabout way to strip non-ASCII unicode characters from the header.
                        # As we are only parsing out the encoding, we don't need any unicode chars in it.
                        l = lines[hdrno+1].decode('unicode_escape').encode('ascii','ignore').decode(encoding)
                        if l.strip():
                            header += decode_escapes(dequote(l.strip()))
                        else:
                            break
                        hdrno += 1
                    # See whether there is an encoding declaration
                    if(hdrno > lno):
                        p = HeaderParser()
                        charset = p.parsestr(str(header)).get_content_charset()
                        header_attempted = True
                        if charset:
                            encoding = charset
                if is_plural:
                    print('indexed msgstr required for plural on  %s:%d' % (infile, lno),
                          file=sys.stderr)
                    sys.exit(1)
                l = l[6:]
        # Skip empty lines
        l = l.strip()
        if not l:
            continue
        l = decode_escapes(dequote(l)) # strip quotes and replace newlines if present
        if section == ID:
            msgid += l.encode(encoding)
        elif section == STR:
            msgstr += l.encode(encoding)
        else:
            print('Syntax error on %s:%d' % (infile, lno), \
                  'before:', file=sys.stderr)
            print(l, file=sys.stderr)
            sys.exit(1)
    # Add last entry
    if section == STR:
        add(msgid, msgstr, fuzzy)

    # Compute output
    output = generate()

    try:
        open(outfile,"wb").write(output)
    except IOError as msg:
        print(msg, file=sys.stderr)



def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
                                   ['help', 'version', 'output-file='])
    except getopt.error as msg:
        usage(1, msg)

    outfile = None
    # parse options
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            usage(0)
        elif opt in ('-V', '--version'):
            print("msgfmt.py", __version__)
            sys.exit(0)
        elif opt in ('-o', '--output-file'):
            outfile = arg
    # do it
    if not args:
        print('No input file given', file=sys.stderr)
        print("Try `msgfmt --help' for more information.", file=sys.stderr)
        return

    for filename in args:
        make(filename, outfile)


if __name__ == '__main__':
    main()