summaryrefslogtreecommitdiffstats
path: root/comm/taskcluster/docker/tb-flatpak/build_desktop_file.py
blob: 65ed76eeb81f746296c57f4a7d907dfea5f589f8 (plain)
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
#!/usr/bin/python3 -u
#  This Source Code Form is subject to the terms of the Mozilla Public
#  License, v. 2.0. If a copy of the MPL was not distributed with this
#  file, You can obtain one at https://mozilla.org/MPL/2.0/.

"""
Build the Flatpak .desktop file. Needs to run in the Python virtualenv
due to dependencies.

python3 /scripts/build_desktop_file.py -o "$WORKSPACE/org.mozilla.Thunderbird.desktop" \
  -t "/scripts/org.mozilla.Thunderbird.desktop.jinja2" \
  -l "$WORKSPACE/l10n-central" \
  -L "$WORKSPACE/shipped-locales" \
  -f "mail/branding/thunderbird/brand.ftl" \
  -f "mail/messenger/flatpak.ftl"
"""

import argparse
import json
import os
import urllib.request
import zipfile
from pathlib import Path
from typing import List, Union

import jinja2
from fluent.runtime.fallback import FluentLocalization, FluentResourceLoader

COMM_L10N_ZIP = "https://hg.mozilla.org/projects/comm-l10n/archive/{rev}.zip"
COMM_L10N_ZIP_PREFIX = "comm-l10n-{rev}"


class FluentTranslator:
    """
    FluentTranslator is an enhanced FluentLocalization
    """

    def __init__(self, l10n_base: Path, locales: List[str], resource_ids: List[str]):
        self._locales = locales
        self._localizations = self._populate(l10n_base, resource_ids)

    @property
    def locales(self):
        return sorted([l for l in self._locales if l != "en-US"])

    def _populate(self, l10n_path, resource_ids):
        loader = FluentResourceLoader(str(l10n_path / "{locale}"))

        rv = {}
        for locale in self._locales:
            rv[locale] = FluentLocalization([locale], resource_ids, loader)

        return rv

    def get_message(self, locale, message_id) -> Union[str, None]:
        rv = self._localizations[locale].format_value(message_id)
        if rv == message_id:
            return None
        return rv


def get_multi_translate(l10n_strings: FluentTranslator):
    def translate_multi(key: str, fluent_id: str):
        for locale in l10n_strings.locales:
            translated = l10n_strings.get_message(locale, fluent_id)
            if translated is not None:
                yield f"{key}[{locale}]={translated}"

    return translate_multi


def build_template(
    output: Path,
    template: Path,
    l10n_base: Path,
    locales: List[str],
    fluent_resources: List[str],
    is_beta: bool,
):
    wmclass = "thunderbird"
    if is_beta:
        wmclass = wmclass + "-beta"
    locales_plus = locales + ["en-US"]
    l10n_strings = FluentTranslator(l10n_base.resolve(), locales_plus, fluent_resources)

    with open(template) as fp:
        jinja_template = jinja2.Template(fp.read())

    translate_multi = get_multi_translate(l10n_strings)
    result = jinja_template.render(
        strings=l10n_strings, translate=translate_multi, wmclass=wmclass
    )

    with open(output, "w") as fp:
        fp.write(result)


def get_extract_members(
    zip_file: zipfile.ZipFile, file_pats: List[str], prefix: str
) -> List[zipfile.ZipInfo]:
    for m in zip_file.infolist():
        for pat in file_pats:
            if m.filename.endswith(pat):
                m.filename = os.path.relpath(m.filename, prefix)
                print(f"Found {m.filename} in strings repo.")
                yield m


def get_strings(l10n_base, rev, fluent_files):
    url = COMM_L10N_ZIP.format(rev=rev)
    temp_file, headers = urllib.request.urlretrieve(url)
    with zipfile.ZipFile(temp_file, "r") as strings_zip:
        to_extract = get_extract_members(
            strings_zip, fluent_files, COMM_L10N_ZIP_PREFIX.format(rev=rev)
        )

        strings_zip.extractall(path=l10n_base, members=to_extract)


def main():
    parser = argparse.ArgumentParser()

    parser.add_argument("-o", dest="output", type=Path, required=True, help="Output file")
    parser.add_argument(
        "-t", dest="template", type=Path, required=True, help="Jinja2 template file"
    )
    parser.add_argument(
        "-l", dest="l10n_base", type=Path, required=True, help="l10n-central root path"
    )
    parser.add_argument(
        "-L", dest="locales_file", type=Path, required=True, help="List of supported locales"
    )
    parser.add_argument(
        "-f", dest="fluent_files", type=str, required=True, action="extend", nargs="+"
    )
    parser.add_argument(
        "--beta",
        dest="is_beta",
        action="store_true",
        default=False,
        help="Mark this build a beta version",
    )

    args = parser.parse_args()

    with open(args.locales_file) as fp:
        locale_data = json.load(fp)
        locales = [l for l in locale_data.keys() if l != "ja-JP-mac"]
        comm_l10n_rev = locale_data.get("en-GB", {}).get("revision")

    get_strings(args.l10n_base, comm_l10n_rev, args.fluent_files)

    build_template(
        args.output, args.template, args.l10n_base, locales, args.fluent_files, args.is_beta
    )


if __name__ == "__main__":
    main()