Skip to content

Commit 8cf36f0

Browse files
authored
Do not use Cockpit manifest for storing supported languages (#1121)
## Problem - Continue with dropping the Cockpit dependency ## Solution - Do not use the Cockpit manifest for storing the list of supported languages - Use a separate `languages.json` file instead of the `manifest.json` - Import the JSON file directly into the JS code - The workflow is not changed, the update script just generates a different file - The change is backward compatible, works with both Cockpit and the new server ## Testing - Updated unit tests - Tested manually, the language selection still works fine
1 parent f143990 commit 8cf36f0

File tree

13 files changed

+66
-130
lines changed

13 files changed

+66
-130
lines changed

.github/workflows/weblate-merge-po.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
if: steps.check_changes.outputs.po_updated == 'true'
9393
working-directory: ./agama
9494
run: |
95-
web/share/update-manifest.py web/src/manifest.json
95+
web/share/update-languages.py > web/src/languages.json
9696
# use a unique branch to avoid possible conflicts with already existing branches
9797
git checkout -b "po_merge_${GITHUB_RUN_ID}"
9898
git commit -a -m "Update web PO files"$'\n\n'"Agama-weblate commit: `git -C ../agama-weblate rev-parse HEAD`"

web/cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"language": "en",
44
"allowCompoundWords": false,
55
"ignorePaths": [
6+
"src/languages.json",
67
"src/lib/cockpit.js",
78
"src/lib/cockpit-po-plugin.js",
89
"src/manifest.json",

web/package/cockpit-agama.changes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
-------------------------------------------------------------------
2+
Wed Mar 27 12:41:11 UTC 2024 - Ladislav Slezák <[email protected]>
3+
4+
- Dropping Cockpit dependency:
5+
- Do not use Cockpit gettext functionality
6+
(gh#openSUSE/agama#1118)
7+
- Do not store the list of supported languages to the Cockpit
8+
manifest file (gh#openSUSE/agama#1121)
9+
110
-------------------------------------------------------------------
211
Tue Mar 19 14:15:30 UTC 2024 - José Iván López González <[email protected]>
312

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919
# To contact SUSE LLC about this file by physical or electronic mail, you may
2020
# find current contact information at www.suse.com.
2121

22+
#
23+
# This script generates the list of supported languages in JSON format.
24+
#
25+
2226
from argparse import ArgumentParser
2327
from langtable import language_name
2428
from pathlib import Path
2529
import json
26-
import re
2730
import subprocess
28-
31+
import sys
2932

3033
class Locale:
3134
language: str
@@ -76,20 +79,15 @@ def language(self):
7679
return self.path.stem
7780

7881

79-
class Manifest:
80-
""" This class takes care of updating the manifest file"""
82+
class Languages:
83+
""" This class takes care of generating the supported languages file"""
8184

82-
def __init__(self, path: Path):
83-
self.path = path
84-
self.__read__()
85-
86-
def __read__(self):
87-
with open(self.path) as file:
88-
self.content = json.load(file)
85+
def __init__(self):
86+
self.content = dict()
8987

9088
def update(self, po_files, lang2territory: str, threshold: int):
9189
"""
92-
Updates the list of locales in the manifest file
90+
Generate the list of supported locales
9391
9492
It does not write the changes to file system. Use the write() function
9593
for that.
@@ -111,46 +109,43 @@ def update(self, po_files, lang2territory: str, threshold: int):
111109
if locale.territory is None:
112110
print(
113111
"could not find a territory for '{language}'"
114-
.format(language=locale.language)
112+
.format(language=locale.language),
113+
file=sys.stderr
115114
)
116115
elif po_file.coverage() < threshold:
117116
print(
118117
"not enough coverage for '{language}' ({coverage}%)"
119118
.format(
120119
language=locale.code(),
121-
coverage=po_file.coverage())
120+
coverage=po_file.coverage()),
121+
file=sys.stderr
122122
)
123123
else:
124124
supported.append(locale)
125125

126126
languages = [loc.language for loc in supported]
127-
self.content["locales"] = dict()
128127
for locale in supported:
129128
include_territory = languages.count(locale.language) > 1
130-
self.content["locales"][locale.code()] = locale.name(
131-
include_territory)
129+
self.content[locale.code()] = locale.name(include_territory)
132130

133-
def write(self):
134-
with open(self.path, "w+") as file:
135-
json.dump(self.content, file, indent=4, ensure_ascii=False)
131+
def dump(self):
132+
json.dump(self.content, sys.stdout, indent=4, ensure_ascii=False,
133+
sort_keys=True)
136134

137135

138-
def update_manifest(args):
139-
"""Command to update the manifest.json file"""
140-
manifest = Manifest(Path(args.manifest))
136+
def update_languages(args):
137+
"""Print the supported languages in JSON format"""
138+
languages = Languages()
141139
paths = [path for path in Path(args.po_directory).glob("*.po")]
142140
with open(args.territories) as file:
143141
lang2territory = json.load(file)
144-
manifest.update(paths, lang2territory, args.threshold)
145-
manifest.write()
142+
languages.update(paths, lang2territory, args.threshold)
143+
languages.dump()
146144

147145

148146
if __name__ == "__main__":
149-
parser = ArgumentParser(prog="locales.py")
150-
parser.set_defaults(func=update_manifest)
151-
parser.add_argument(
152-
"manifest", type=str, help="Path to the manifest file",
153-
)
147+
parser = ArgumentParser(prog="update-languages.py")
148+
parser.set_defaults(func=update_languages)
154149
parser.add_argument(
155150
"--po-directory", type=str, help="Directory containing the po files",
156151
default="web/po"

web/src/components/l10n/InstallerLocaleSwitcher.jsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,20 @@ import { FormSelect, FormSelectOption, Popover } from "@patternfly/react-core";
2626
import { Icon } from "../layout";
2727
import { _ } from "~/i18n";
2828
import { useInstallerL10n } from "~/context/installerL10n";
29-
import cockpit from "~/lib/cockpit";
29+
import supportedLanguages from "~/languages.json";
3030

3131
export default function InstallerLocaleSwitcher() {
3232
const { language, changeLanguage } = useInstallerL10n();
3333
const [selected, setSelected] = useState(null);
34-
const languages = cockpit.manifests.agama?.locales || [];
3534

3635
const onChange = useCallback((_event, value) => {
3736
setSelected(value);
3837
changeLanguage(value);
3938
}, [setSelected, changeLanguage]);
4039

4140
// sort by the language code to maintain consistent order
42-
const options = Object.keys(languages).sort()
43-
.map(id => <FormSelectOption key={id} value={id} label={languages[id]} />);
41+
const options = Object.keys(supportedLanguages).sort()
42+
.map(id => <FormSelectOption key={id} value={id} label={supportedLanguages[id]} />);
4443

4544
// TRANSLATORS: help text for the language selector in the sidebar,
4645
// %s will be replaced by the "Localization" page link

web/src/components/l10n/InstallerLocaleSwitcher.test.jsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,10 @@ import InstallerLocaleSwitcher from "./InstallerLocaleSwitcher";
2727
const mockLanguage = "es-es";
2828
let mockChangeLanguageFn;
2929

30-
jest.mock("~/lib/cockpit", () => ({
31-
gettext: term => term,
32-
manifests: {
33-
agama: {
34-
locales: {
35-
"de-de": "Deutsch",
36-
"en-us": "English (US)",
37-
"es-es": "Español"
38-
}
39-
}
40-
}
30+
jest.mock("~/languages.json", () => ({
31+
"de-de": "Deutsch",
32+
"en-us": "English (US)",
33+
"es-es": "Español"
4134
}));
4235

4336
jest.mock("~/context/installerL10n", () => ({

web/src/context/installerL10n.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { useCancellablePromise, locationReload, setLocationSearch } from "~/util
2727
import cockpit from "../lib/cockpit";
2828
import { useInstallerClient } from "./installer";
2929
import agama from "~/agama";
30+
import supportedLanguages from "~/languages.json";
3031

3132
const L10nContext = React.createContext(null);
3233

@@ -154,7 +155,7 @@ function navigatorLanguages() {
154155
* @return {string|undefined} Undefined if none of the given languages is supported.
155156
*/
156157
function findSupportedLanguage(languages) {
157-
const supported = Object.keys(cockpit.manifests.agama?.locales || {});
158+
const supported = Object.keys(supportedLanguages);
158159

159160
for (const candidate of languages) {
160161
const [language, country] = candidate.split("-");

web/src/context/installerL10n.test.jsx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,14 @@ const client = {
4040
onDisconnect: jest.fn()
4141
};
4242

43+
jest.mock("~/languages.json", () => ({
44+
"es-ar": "Español (Argentina)",
45+
"cs-cz": "čeština",
46+
"en-us": "English (US)",
47+
"es-es": "Español"
48+
}));
49+
4350
jest.mock("~/lib/cockpit", () => ({
44-
gettext: term => term,
45-
manifests: {
46-
agama: {
47-
locales: {
48-
"es-ar": "Español (Argentina)",
49-
"cs-cz": "čeština",
50-
"en-us": "English (US)",
51-
"es-es": "Español"
52-
}
53-
}
54-
},
5551
spawn: jest.fn().mockResolvedValue()
5652
}));
5753

web/src/languages.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"ca-es": "Català",
3+
"de-de": "Deutsch",
4+
"en-us": "English",
5+
"es-es": "Español",
6+
"fr-fr": "Français",
7+
"id-id": "Indonesia",
8+
"ja-jp": "日本語",
9+
"nl-nl": "Nederlands",
10+
"sv-se": "Svenska",
11+
"zh-Hans": "中文"
12+
}

web/src/lib/webpack-manifests-handler.js

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)