~widelands-dev/widelands/trunk

10790 by The Widelands Bunnybot
Python files require python3 explicitly (CB #4529 / GH #6187)
1
#!/usr/bin/env python3
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
2
# encoding: utf-8
3
9689 by The Widelands Bunnybot
'utils/update_appdata.py' was automatically formatted.
4
import subprocess
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
5
import codecs
6
import json
7
import os.path
10048 by The Widelands Bunnybot
Fix Save Game Window Layout Issues (#5105)
8
import shutil
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
9
import sys
10
7981.3.9 by GunChleoc
Updated documentation.
11
# This script collects translations for the appdata.xml and .desktop files
12
#
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
13
# All non-translatable content for ../xdg/org.widelands.Widelands.appdata.xml is taken from
14
# ../xdg/org.widelands.Widelands.appdata.xml.stub
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
15
# That file contains a SUMMARY_DESCRIPTION_HOOK where the translatable information
16
# is inserted.
8796.1.9 by GunChleoc
List textdomains
17
# A language list and textdomain info is inserted into LANGUAGES_HOOK
8796.1.4 by GunChleoc
Add language tags to appdata.xml
18
#
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
19
# The output is written to ../xdg/org.widelands.Widelands.appdata.xml
7981.3.9 by GunChleoc
Updated documentation.
20
#
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
21
# All non-translatable content for ../xdg/org.widelands.Widelands.desktop is taken from
22
# ../xdg/org.widelands.Widelands.desktop.stub
7981.3.9 by GunChleoc
Updated documentation.
23
# That file contains a GENERIC_NAME_COMMENT_HOOK where the translatable information
24
# is inserted.
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
25
# The output is written to ../xdg/org.widelands.Widelands.desktop
7981.3.9 by GunChleoc
Updated documentation.
26
#
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
27
# All translations are sourced from ../xdg/translations/
10748 by The Widelands Bunnybot
Report all validation errors by update_appdata.py (#6116)
28
#
29
# If used with the --nonet command line option, the validator for the generated
30
# appdata.xml file will be executed with the same, or the equivalent --no-net option.
31
# This skips the downloading of the screenshot images in restricted environments
32
# without network access, such as e.g. flatpak-builder.
7981.3.9 by GunChleoc
Updated documentation.
33
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
34
8201 by GunChleoc
Fetched translations and updated catalogues.
35
print('Updating appdata.xml and .desktop files')
36
print('- Checking files')
37
38
base_path = os.path.abspath(os.path.join(
39
    os.path.dirname(__file__), os.path.pardir))
40
41
appdata_input_filename = os.path.normpath(
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
42
    base_path + '/xdg/org.widelands.Widelands.appdata.xml.stub')
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
43
if (not os.path.isfile(appdata_input_filename)):
8201 by GunChleoc
Fetched translations and updated catalogues.
44
    print('Error: File ' + appdata_input_filename + ' not found.')
45
    sys.exit(1)
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
46
8201 by GunChleoc
Fetched translations and updated catalogues.
47
desktop_input_filename = os.path.normpath(
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
48
    base_path + '/xdg/org.widelands.Widelands.desktop.stub')
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
49
if (not os.path.isfile(desktop_input_filename)):
8201 by GunChleoc
Fetched translations and updated catalogues.
50
    print('Error: File ' + desktop_input_filename + ' not found.')
51
    sys.exit(1)
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
52
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
53
translations_path = os.path.normpath(base_path + '/xdg/translations')
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
54
if (not os.path.isdir(translations_path)):
8201 by GunChleoc
Fetched translations and updated catalogues.
55
    print('Error: Path ' + translations_path + ' not found.')
56
    sys.exit(1)
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
57
8201 by GunChleoc
Fetched translations and updated catalogues.
58
english_source_filename = os.path.normpath(
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
59
    base_path + '/xdg/translations/appdata.json')
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
60
if (not os.path.isfile(english_source_filename)):
8201 by GunChleoc
Fetched translations and updated catalogues.
61
    print('Error: File ' + english_source_filename + ' not found.')
62
    sys.exit(1)
63
8796.1.9 by GunChleoc
List textdomains
64
print('- Reading textdomains:')
65
66
textdomain_path = os.path.normpath(
67
    base_path + '/po')
68
textdomains = []
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
69
textdomain_path_contents = sorted(os.listdir(textdomain_path), key=str.lower)
8796.1.9 by GunChleoc
List textdomains
70
for textdomain in textdomain_path_contents:
8798 by Wideland's Bunnybot
Merged lp:~widelands-dev/widelands/appdata_tweaks:
71
    if os.path.isdir(os.path.normpath(textdomain_path + '/' + textdomain)):
8796.1.9 by GunChleoc
List textdomains
72
        textdomains.append(textdomain)
73
8201 by GunChleoc
Fetched translations and updated catalogues.
74
print('- Reading source from JSON:')
75
76
english_source_file = open(english_source_filename, 'r')
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
77
english_source = json.load(english_source_file)
78
8796.1.6 by GunChleoc
Add translation of name to appdata.
79
name_en = english_source['name']
8201 by GunChleoc
Fetched translations and updated catalogues.
80
tagline_en = english_source['tagline']
81
descriptions_en = english_source['description']
82
generic_name_en = english_source['category']
8796.1.7 by GunChleoc
Add name translations to desktop file
83
desktop_name_en = english_source['name']
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
84
85
english_source_file.close()
86
87
# For appdata.xml
8796.1.6 by GunChleoc
Add translation of name to appdata.
88
names = '  <name>' + name_en + '</name>\n'
8201 by GunChleoc
Fetched translations and updated catalogues.
89
summaries = '  <summary>' + tagline_en + '</summary>\n'
90
descriptions = '  <description>\n'
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
91
for description in descriptions_en:
8201 by GunChleoc
Fetched translations and updated catalogues.
92
    descriptions += '    <p>\n'
93
    descriptions += '      ' + description + '\n'
94
    descriptions += '    </p>\n'
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
95
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
96
# For .desktop
8796.1.7 by GunChleoc
Add name translations to desktop file
97
desktop_names = 'Name=' + desktop_name_en + '\n'
8201 by GunChleoc
Fetched translations and updated catalogues.
98
generic_names = 'GenericName=' + generic_name_en + '\n'
99
comments = 'Comment=' + tagline_en + '\n'
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
100
8201 by GunChleoc
Fetched translations and updated catalogues.
101
print('- Reading translations from JSON:')
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
102
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
103
# Each language's translations live in a separate file, so we list the dir
104
translation_files = sorted(os.listdir(translations_path), key=str.lower)
8796.1.4 by GunChleoc
Add language tags to appdata.xml
105
langcodes = []
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
106
107
for translation_filename in translation_files:
8201 by GunChleoc
Fetched translations and updated catalogues.
108
    # Only json files, and not the template file please
109
    if translation_filename.endswith('.json') and translation_filename != 'appdata.json':
110
        translation_file = open(
111
            translations_path + '/' + translation_filename, 'r')
112
        translation = json.load(translation_file)
113
        lang_code = translation_filename[:-5]
8796.1.4 by GunChleoc
Add language tags to appdata.xml
114
        langcodes.append(lang_code)
8201 by GunChleoc
Fetched translations and updated catalogues.
115
        tagline = translation['tagline']
116
        if tagline != tagline_en:
117
            summaries += "  <summary xml:lang=\"" + lang_code + \
118
                "\">" + tagline + '</summary>\n'  # appdata.xml
119
            comments += 'Comment[' + lang_code + ']=' + \
120
                tagline + '\n'  # .desktop
121
        generic_name = translation['category']
122
        if generic_name != generic_name_en:
123
            # .desktop
124
            generic_names += 'GenericName[' + \
125
                lang_code + ']=' + generic_name + '\n'
9688 by The Widelands Bunnybot
Python 3 compatibility for translation upgrade
126
        if 'name' in translation:
8796.1.7 by GunChleoc
Add name translations to desktop file
127
            desktop_name = translation['name']
128
            if desktop_name != desktop_name_en:
129
                # .desktop
130
                desktop_names += 'Name[' + \
131
                    lang_code + ']=' + desktop_name + '\n'
8798 by Wideland's Bunnybot
Merged lp:~widelands-dev/widelands/appdata_tweaks:
132
        # appdata.xml
9688 by The Widelands Bunnybot
Python 3 compatibility for translation upgrade
133
        if 'name' in translation and translation['name'] != name_en:
8798 by Wideland's Bunnybot
Merged lp:~widelands-dev/widelands/appdata_tweaks:
134
            names += "  <name xml:lang=\"" + lang_code + \
135
                "\">" + translation['name'] + '</name>\n'
8201 by GunChleoc
Fetched translations and updated catalogues.
136
        if translation['description'] != descriptions_en:  # appdata.xml
137
            for description in translation['description']:
138
                descriptions += "    <p xml:lang=\"" + lang_code + "\">\n"
139
                descriptions += '      ' + description + '\n'
140
                descriptions += '    </p>\n'
141
        translation_file.close()
142
descriptions += '  </description>\n'
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
143
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
144
print('- Writing org.widelands.Widelands.appdata.xml')
8201 by GunChleoc
Fetched translations and updated catalogues.
145
input_file = open(appdata_input_filename, 'r')
146
appdata = ''
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
147
148
for line in input_file:
8796.1.4 by GunChleoc
Add language tags to appdata.xml
149
    if line.strip() == 'SUMMARY_DESCRIPTION_HOOK':
8796.1.6 by GunChleoc
Add translation of name to appdata.
150
        appdata += names + summaries + descriptions
8796.1.4 by GunChleoc
Add language tags to appdata.xml
151
    elif line.strip() == 'LANGUAGES_HOOK':
8796.1.9 by GunChleoc
List textdomains
152
        appdata += '  <languages>\n'
8796.1.4 by GunChleoc
Add language tags to appdata.xml
153
        for langcode in langcodes:
154
            appdata += '    <lang>' + langcode + '</lang>\n'
8796.1.9 by GunChleoc
List textdomains
155
        appdata += '  </languages>\n'
156
        for textdomain in textdomains:
157
            appdata += '  <translation type="gettext">' + textdomain + '</translation>\n'
8796.1.4 by GunChleoc
Add language tags to appdata.xml
158
    else:
8201 by GunChleoc
Fetched translations and updated catalogues.
159
        appdata += line
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
160
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
161
input_file.close()
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
162
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
163
appdata_filepath = base_path + '/xdg/org.widelands.Widelands.appdata.xml'
8770.1.1 by GunChleoc
Validate desktop file on translation updates.
164
dest_file = codecs.open(appdata_filepath, encoding='utf-8', mode='w')
7981.3.2 by GunChleoc
Added script + JSON to parse + write appdata translations.
165
dest_file.write(appdata)
166
dest_file.close()
167
8201 by GunChleoc
Fetched translations and updated catalogues.
168
print('- Writing .desktop')
169
desktop = ''
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
170
9689 by The Widelands Bunnybot
'utils/update_appdata.py' was automatically formatted.
171
with open(desktop_input_filename, 'r', encoding='utf-8') as input_file:
172
    for line in input_file:
173
        if line.strip() != 'GENERIC_NAME_COMMENT_HOOK':
174
            desktop += line
175
        else:
176
            desktop += desktop_names + generic_names + comments
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
177
178
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
179
desktop_filepath = base_path + '/xdg/org.widelands.Widelands.desktop'
8770.1.1 by GunChleoc
Validate desktop file on translation updates.
180
dest_file = codecs.open(desktop_filepath, encoding='utf-8', mode='w')
7981.3.3 by GunChleoc
Parse and write translations for .desktop.
181
dest_file.write(desktop)
182
dest_file.close()
183
8201 by GunChleoc
Fetched translations and updated catalogues.
184
print('Done!')
8156.1.3 by GunChleoc
Fixed content rating hierarchy and added validation call to utils/update_appdata.py.
185
8770.1.1 by GunChleoc
Validate desktop file on translation updates.
186
10048 by The Widelands Bunnybot
Fix Save Game Window Layout Issues (#5105)
187
# Validate Appdata
10748 by The Widelands Bunnybot
Report all validation errors by update_appdata.py (#6116)
188
skip_screenshot_check = len(sys.argv) > 1 and sys.argv[1] == '--nonet'
189
10048 by The Widelands Bunnybot
Fix Save Game Window Layout Issues (#5105)
190
if shutil.which('appstreamcli'):
10748 by The Widelands Bunnybot
Report all validation errors by update_appdata.py (#6116)
191
    validate_cmd = ['appstreamcli', 'validate', appdata_filepath]
192
    if skip_screenshot_check:
193
        validate_cmd.insert(2, '--no-net')
194
    appdata_result = subprocess.run(validate_cmd)
10048 by The Widelands Bunnybot
Fix Save Game Window Layout Issues (#5105)
195
elif shutil.which('appstream-util'):
10748 by The Widelands Bunnybot
Report all validation errors by update_appdata.py (#6116)
196
    validate_cmd = ['appstream-util', 'validate-relax', appdata_filepath]
197
    if skip_screenshot_check:
198
        validate_cmd.insert(2, '--nonet')
199
    appdata_result = subprocess.run(validate_cmd)
10048 by The Widelands Bunnybot
Fix Save Game Window Layout Issues (#5105)
200
else:
201
    print('Cannot validate generated appdata file.')
10748 by The Widelands Bunnybot
Report all validation errors by update_appdata.py (#6116)
202
    appdata_result = FileNotFoundError() # dummy object for returncode
203
    appdata_result.returncode = 0
204
205
desktop_result = subprocess.run(['desktop-file-validate', desktop_filepath])
206
207
sys.exit(max(desktop_result.returncode, appdata_result.returncode))