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