diff --git a/.gitignore b/.gitignore
index 98e8302..a2e3c7b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,10 @@ node_modules/
static/resources/DecimalJs*
static/resources/SortableJS
static/resources/Standalone
+
+# Secrets
+src/
+bin/
+app/
+.run/
+*.tmpl
diff --git a/data/sidebar.yml b/data/sidebar.yml
index 26178c0..5de4b3c 100644
--- a/data/sidebar.yml
+++ b/data/sidebar.yml
@@ -4,7 +4,7 @@
active_id: home
has_new_until_utc: 0
--
+- {}
#- title_key: text.articles
# abs_href: "/articles/"
@@ -56,7 +56,7 @@
active_id: ""
has_new_until_utc: 0
--
+- {}
#- title_key: text.about
# abs_href: "/about"
diff --git a/data/strings/en/home.yml b/data/strings/en/home.yml
index 52ed5ac..7c9e738 100644
--- a/data/strings/en/home.yml
+++ b/data/strings/en/home.yml
@@ -1,12 +1,14 @@
# EN - Home
-head.title: NibblePoker
-head.description: Collection of free and open-source handmade utilities and libraries
- ranging from a simple COM port lister to password remover and autonomous video archivers.
+head:
+ title: NibblePoker
+ description: Collection of free and open-source handmade utilities and libraries
+ ranging from a simple COM port lister to password remover and autonomous video archivers.
-og.title: NibblePoker
-og.description: Collection of free and open-source handmade utilities and libraries
- ranging from a simple COM port lister to password remover and autonomous video archivers.
+og:
+ title: NibblePoker
+ description: Collection of free and open-source handmade utilities and libraries
+ ranging from a simple COM port lister to password remover and autonomous video archivers.
header.title: Homepage
@@ -23,25 +25,32 @@ updates.title: Updates
updates.text.privacy: Updated our privacy policy.
-updates.5.date: March 30 2025
-updates.5.text.1: Complete redesign of the site to use a standardized style.
-updates.5.text.2: Changed some of our VPS providers to HosTeam.
-
-updates.4.date: November 30 2023
-updates.4.text.1: Centralized DNS servers & implemented GeoDNS.
-updates.4.text.2: Added US CDN hosted by ChicagoVPS.
-updates.4.text.3: All other regions use the EU CDN hosted by IONOS.
-
-updates.3.date: November 12 2023
-updates.3.text.1: Other services are back online.
-updates.3.text.2: Changed our host to IONOS.
-updates.3.text.3: Finished all side pages.
-
-updates.2.date: August 15 2023
-updates.2.text.1: The website is back online.
-updates.2.text.2: New and much lighter design.
-updates.2.text.3: Changed our host to HostBrr.
-updates.2.text.4: Added a section for web-based tools.
-
-updates.1.date: September 9 2022
-updates.1.text.1: Changed our host to v6Node.
+updates:
+ 5:
+ date: March 30 2025
+ text:
+ 1: Complete redesign of the site to use a standardized style.
+ 2: Changed some of our VPS providers to HosTeam.
+ 4:
+ date: November 30 2023
+ text:
+ 1: Centralized DNS servers & implemented GeoDNS.
+ 2: Added US CDN hosted by ChicagoVPS.
+ 3: All other regions use the EU CDN hosted by IONOS.
+ 3:
+ date: November 12 2023
+ text:
+ 1: Other services are back online.
+ 2: Changed our host to IONOS.
+ 3: Finished all side pages.
+ 2:
+ date: August 15 2023
+ text:
+ 1: The website is back online.
+ 2: New and much lighter design.
+ 3: Changed our host to HostBrr.
+ 4: Added a section for web-based tools.
+ 1:
+ date: September 9 2022
+ text:
+ 1: Changed our host to v6Node.
diff --git a/data/strings/fr/home.yml b/data/strings/fr/home.yml
index 59da1a6..a536e6b 100644
--- a/data/strings/fr/home.yml
+++ b/data/strings/fr/home.yml
@@ -24,25 +24,32 @@ showcase.title: Vitrine
updates.title: Updates
updates.text.privacy: Mise-à-jour de notre politique de confidentialité.
-updates.5.date: 30 mars 2025
-updates.5.text.1: Refonte complète du site pour utiliser un style standardisé.
-updates.5.text.2: Changements de certains providers de VPS pour HosTeam.
-
-updates.4.date: 30 novembre 2023
-updates.4.text.1: Centralisation des serveurs DNS & implémentation de GeoDNS.
-updates.4.text.2: Ajout d'un CDN pour l'Amérique du Nord hébergé par ChicagoVPS.
-updates.4.text.3: Les autres régions utilisent le CDN Européen hébergé par IONOS.
-
-updates.3.date: 12 novembre 2023
-updates.3.text.1: Les services annexes sont disponibles.
-updates.3.text.2: Changement d'hébergeur vers IONOS.
-updates.3.text.3: Finition des pages annexes.
-
-updates.2.date: 15 août 2023
-updates.2.text.1: Le site internet est à nouveau disponible.
-updates.2.text.2: Mise en place d'un nouveau design plus léger.
-updates.2.text.3: Changement d'hébergeur vers HostBrr.
-updates.2.text.4: Ajout d'une nouvelle section pour les outils.
-
-updates.1.date: 9 septembre 2022
-updates.1.text.1: Changement d'hébergeur vers v6Node.
+updates:
+ 5:
+ date: 30 mars 2025
+ text:
+ 1: Refonte complète du site pour utiliser un style standardisé.
+ 2: Changements de certains providers de VPS pour HosTeam.
+ 4:
+ date: 30 novembre 2023
+ text:
+ 1: Centralisation des serveurs DNS & implémentation de GeoDNS.
+ 2: Ajout d'un CDN pour l'Amérique du Nord hébergé par ChicagoVPS.
+ 3: Les autres régions utilisent le CDN Européen hébergé par IONOS.
+ 3:
+ date: 12 novembre 2023
+ text:
+ 1: Les services annexes sont disponibles.
+ 2: Changement d'hébergeur vers IONOS.
+ 3: Finition des pages annexes.
+ 2:
+ date: 15 août 2023
+ text:
+ 1: Le site internet est à nouveau disponible.
+ 2: Mise en place d'un nouveau design plus léger.
+ 3: Changement d'hébergeur vers HostBrr.
+ 4: Ajout d'une nouvelle section pour les outils.
+ 1:
+ date: 9 septembre 2022
+ text:
+ 1: Changement d'hébergeur vers v6Node.
diff --git a/scripts/package-lock.json b/scripts/package-lock.json
deleted file mode 100644
index e1d0998..0000000
--- a/scripts/package-lock.json
+++ /dev/null
@@ -1,771 +0,0 @@
-{
- "name": "scripts",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "devDependencies": {
- "browserify": "^17.0.1",
- "html-minifier-terser": "^7.2.0",
- "minify": "^10.2.0",
- "rollup": "^4.48.1",
- "sass": "^1.63.6",
- "terser": "^5.19.0",
- "typescript": "^5.1.6"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
- "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/set-array": "^1.2.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/set-array": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
- "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/source-map": {
- "version": "0.3.6",
- "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
- "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
- "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.25",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
- "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@putout/minify": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/@putout/minify/-/minify-2.11.0.tgz",
- "integrity": "sha512-HNOICCQIwKqjz9MZxQimWI8c3PvoehY4qlg5N5/tCWT+JJfZQUiRWQgm6RQ9rP85ReoSO20HShH22naVMpbFog==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/acorn": {
- "version": "8.12.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
- "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/camel-case": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
- "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pascal-case": "^3.1.2",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/clean-css": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
- "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "source-map": "~0.6.0"
- },
- "engines": {
- "node": ">= 10.0"
- }
- },
- "node_modules/commander": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
- "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/css-b64-images": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz",
- "integrity": "sha512-TgQBEdP07adhrDfXvI5o6bHGukKBNMzp2Ngckc/6d09zpjD2gc1Hl3Ca1CKgb8FXjHi88+Phv2Uegs2kTL4zjg==",
- "dev": true,
- "bin": {
- "css-b64-images": "bin/css-b64-images"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/debug": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
- "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/dot-case": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
- "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "no-case": "^3.0.4",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/find-up": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
- "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^7.1.0",
- "path-exists": "^5.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/html-minifier-terser": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz",
- "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "camel-case": "^4.1.2",
- "clean-css": "~5.3.2",
- "commander": "^10.0.0",
- "entities": "^4.4.0",
- "param-case": "^3.0.4",
- "relateurl": "^0.2.7",
- "terser": "^5.15.1"
- },
- "bin": {
- "html-minifier-terser": "cli.js"
- },
- "engines": {
- "node": "^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/immutable": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz",
- "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/jju": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
- "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/locate-path": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
- "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^6.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lower-case": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
- "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.3"
- }
- },
- "node_modules/minify": {
- "version": "10.5.2",
- "resolved": "https://registry.npmjs.org/minify/-/minify-10.5.2.tgz",
- "integrity": "sha512-/7aNrZ7kMe43o0NQUftL/H9QBi15FYEUo7tnw0Nrcc+XsmNS6nP4cIL4iqrNzSzv1rUaHLBxpmYbETKT9dKZiQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@putout/minify": "^2.0.0",
- "clean-css": "^5.0.1",
- "css-b64-images": "~0.2.5",
- "debug": "^4.1.0",
- "find-up": "^6.1.0",
- "html-minifier-terser": "^7.1.0",
- "readjson": "^2.2.2",
- "simport": "^1.2.0",
- "try-catch": "^3.0.0",
- "try-to-catch": "^3.0.0"
- },
- "bin": {
- "minify": "bin/minify.js"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/no-case": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
- "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "lower-case": "^2.0.2",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/p-limit": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
- "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "yocto-queue": "^1.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
- "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/param-case": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
- "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "dot-case": "^3.0.4",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/pascal-case": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
- "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "no-case": "^3.0.4",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/path-exists": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
- "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/readjson": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/readjson/-/readjson-2.2.2.tgz",
- "integrity": "sha512-PdeC9tsmLWBiL8vMhJvocq+OezQ3HhsH2HrN7YkhfYcTjQSa/iraB15A7Qvt7Xpr0Yd2rDNt6GbFwVQDg3HcAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "jju": "^1.4.0",
- "try-catch": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/relateurl": {
- "version": "0.2.7",
- "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
- "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/rollup": {
- "version": "3.29.4",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
- "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=14.18.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/sass": {
- "version": "1.77.8",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz",
- "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chokidar": ">=3.0.0 <4.0.0",
- "immutable": "^4.0.0",
- "source-map-js": ">=0.6.2 <2.0.0"
- },
- "bin": {
- "sass": "sass.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/simport": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/simport/-/simport-1.2.0.tgz",
- "integrity": "sha512-85Bm7pKsqiiQ8rmYCaPDdlXZjJvuW6/k/FY8MTtLFMgU7f8S00CgTHfRtWB6KwSb6ek4p9YyG2enG1+yJbl+CA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "readjson": "^2.2.0",
- "try-to-catch": "^3.0.0"
- },
- "engines": {
- "node": ">=12.2"
- }
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "node_modules/terser": {
- "version": "5.31.6",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz",
- "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "@jridgewell/source-map": "^0.3.3",
- "acorn": "^8.8.2",
- "commander": "^2.20.0",
- "source-map-support": "~0.5.20"
- },
- "bin": {
- "terser": "bin/terser"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/terser/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/try-catch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/try-catch/-/try-catch-3.0.1.tgz",
- "integrity": "sha512-91yfXw1rr/P6oLpHSyHDOHm0vloVvUoo9FVdw8YwY05QjJQG9OT0LUxe2VRAzmHG+0CUOmI3nhxDUMLxDN/NEQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/try-to-catch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/try-to-catch/-/try-to-catch-3.0.1.tgz",
- "integrity": "sha512-hOY83V84Hx/1sCzDSaJA+Xz2IIQOHRvjxzt+F0OjbQGPZ6yLPLArMA0gw/484MlfUkQbCpKYMLX3VDCAjWKfzQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tslib": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
- "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
- "dev": true,
- "license": "0BSD"
- },
- "node_modules/typescript": {
- "version": "5.5.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
- "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/yocto-queue": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz",
- "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- }
- }
-}
diff --git a/website/l10n/__init__.py b/website/l10n/__init__.py
index 5055e65..c8ef047 100644
--- a/website/l10n/__init__.py
+++ b/website/l10n/__init__.py
@@ -1,72 +1,10 @@
-import copy
-from typing import Optional
-from locked_dict.locked_dict import LockedDict
-
-
-class Localizer:
- _langs_data: LockedDict[LockedDict[str, str]]
- _default_lang: str
- _allowed_langs: list[str]
-
- def __init__(self, default_lang: str, allowed_langs: Optional[list[str]]):
- self._langs_data = LockedDict()
- self._default_lang = default_lang
-
- self._allowed_langs = allowed_langs
- if self._allowed_langs is None:
- self._allowed_langs = list()
- self._allowed_langs.append(self._default_lang)
-
- def add_lang(self, lang: str):
- if lang not in self._langs_data.keys():
- self._langs_data[lang] = LockedDict()
-
- def add_domain(self, lang: str, domain: str, domain_data: Optional[dict[str, str]], strip_prefix: bool = False):
- if domain not in self._langs_data[lang].keys():
- self._langs_data[lang][domain] = LockedDict()
-
- if strip_prefix:
- new_domain_data = dict()
- for key, value in domain_data.items():
- if key.startswith(f"{domain}."):
- new_domain_data[key[len(f"{domain}."):]] = value
- domain_data = new_domain_data
-
- self._langs_data[lang][domain].update(domain_data)
-
- def _localize_internal(self, lang: str, domain: str, key: str, args: list[str] = None) -> Optional[str]:
- if lang not in self._allowed_langs:
- return None
-
- if lang not in self._langs_data.keys():
- return None
-
- lang_data = self._langs_data[lang]
- if domain not in lang_data.keys():
- return None
-
- domain_data = lang_data[domain]
- if key not in domain_data.keys():
- return None
-
- localized_text = domain_data[key]
- if args is not None:
- for arg_index, arg_value in enumerate(args):
- localized_text = localized_text.replace(f"%{arg_index}", arg_value)
-
- return localized_text
-
- def localize(self, lang: str, domain: str, key: str, args: list[str] = None) -> str:
- localized_string = None
-
- if localized_string is None:
- localized_string = self._localize_internal(lang, domain, key, args)
-
- if localized_string is None and lang != self._default_lang:
- localized_string = self._localize_internal(self._default_lang, domain, key, args)
-
- if localized_string is None:
- return domain + "." + key
-
- return localized_string
+def flatten_dict(d, parent_key='', separator='.'):
+ items = []
+ for key, value in d.items():
+ new_key = f"{parent_key}{separator}{key}" if parent_key else str(key)
+ if isinstance(value, dict):
+ items.extend(flatten_dict(value, new_key, separator).items())
+ else:
+ items.append((new_key, value))
+ return dict(items)
diff --git a/website/l10n/localizer.py b/website/l10n/localizer.py
new file mode 100644
index 0000000..896e400
--- /dev/null
+++ b/website/l10n/localizer.py
@@ -0,0 +1,76 @@
+from typing import Optional
+
+from locked_dict.locked_dict import LockedDict
+
+from website.l10n import flatten_dict
+
+
+class Localizer:
+ _langs_data: LockedDict[LockedDict[str, str]]
+ _default_lang: str
+ _allowed_langs: list[str]
+
+ def __init__(self, default_lang: str, allowed_langs: Optional[list[str]]):
+ self._langs_data = LockedDict()
+ self._default_lang = default_lang
+
+ self._allowed_langs = allowed_langs
+ if self._allowed_langs is None:
+ self._allowed_langs = list()
+ self._allowed_langs.append(self._default_lang)
+
+ def add_lang(self, lang: str):
+ if lang not in self._langs_data.keys():
+ self._langs_data[lang] = LockedDict()
+
+ def add_domain(self, lang: str, domain: str, domain_data: Optional[dict[str, str]], strip_prefix: bool = False):
+ if domain not in self._langs_data[lang].keys():
+ self._langs_data[lang][domain] = LockedDict()
+
+ if domain_data is not None:
+ domain_data = flatten_dict(domain_data)
+
+ if strip_prefix:
+ new_domain_data = dict()
+ for key, value in domain_data.items():
+ if key.startswith(f"{domain}."):
+ new_domain_data[key[len(f"{domain}."):]] = value
+ domain_data = new_domain_data
+
+ self._langs_data[lang][domain].update(domain_data)
+
+ def _localize_internal(self, lang: str, domain: str, key: str, args: list[str] = None) -> Optional[str]:
+ if lang not in self._allowed_langs:
+ return None
+
+ if lang not in self._langs_data.keys():
+ return None
+
+ lang_data = self._langs_data[lang]
+ if domain not in lang_data.keys():
+ return None
+
+ domain_data = lang_data[domain]
+ if key not in domain_data.keys():
+ return None
+
+ localized_text = domain_data[key]
+ if args is not None:
+ for arg_index, arg_value in enumerate(args):
+ localized_text = localized_text.replace(f"%{arg_index}", arg_value)
+
+ return localized_text
+
+ def localize(self, lang: str, domain: str, key: str, args: list[str] = None) -> str:
+ localized_string = None
+
+ if localized_string is None:
+ localized_string = self._localize_internal(lang, domain, key, args)
+
+ if localized_string is None and lang != self._default_lang:
+ localized_string = self._localize_internal(self._default_lang, domain, key, args)
+
+ if localized_string is None:
+ return domain + "." + key
+
+ return localized_string
diff --git a/website/l10n/utils.py b/website/l10n/utils.py
index ba94234..70521bd 100644
--- a/website/l10n/utils.py
+++ b/website/l10n/utils.py
@@ -5,7 +5,7 @@ from typing import Optional
import yaml
-from . import Localizer
+from .localizer import Localizer
DEFAULT_LANG = "en"
ALLOWED_LANGS = ["en", "fr"]
@@ -123,46 +123,3 @@ def l10n_url_switch(url: str, new_lang: Optional[str] = None) -> str:
url = "/" + new_lang + url
return url.replace("//", "/")
-
-
-# STRINGS = dict()
-# STRINGS[DEFAULT_LANG] = dict()
-# STRINGS["_compile_date"] = "1970-01-01T00:00:00.000000+00:00Z"
-#
-#
-# def reload_strings(strings_file: str) -> None:
-# global STRINGS
-# STRINGS = dict()
-# STRINGS[DEFAULT_LANG] = dict()
-# STRINGS["_compile_date"] = "1970-01-01T00:00:00.000000+00:00Z"
-# STRINGS = json.loads(open(strings_file, "r").read())
-#
-#
-# def localize_internal(string_key: str, language: str, lang_data: dict, fallback: Optional[str]) -> Optional[str]:
-# if language not in ALLOWED_LANGS:
-# return fallback
-#
-# if language not in lang_data.keys():
-# language = DEFAULT_LANG
-#
-# localized_string = lang_data[language].get(string_key)
-# if localized_string is None and language != DEFAULT_LANG:
-# localized_string = lang_data[DEFAULT_LANG].get(string_key)
-#
-# if localized_string is None:
-# return fallback
-# return localized_string
-#
-#
-# def localize(strings_key: str, language: str, extra_lang_data: Optional[dict] = None) -> str:
-# localized_string = None
-#
-# if extra_lang_data is not None:
-# localized_string = localize_internal(strings_key, language, extra_lang_data, None)
-#
-# if localized_string is None:
-# localized_string = localize_internal(strings_key, language, STRINGS, None)
-#
-# if localized_string is None:
-# return f"${strings_key}"
-# return localized_string