diff --git a/src/GZCTF/ClientApp/package.json b/src/GZCTF/ClientApp/package.json index 52d19c30f..6aa1af2d8 100644 --- a/src/GZCTF/ClientApp/package.json +++ b/src/GZCTF/ClientApp/package.json @@ -8,7 +8,7 @@ "lint": "oxlint --fix && eslint", "build": "tsc && vite build", "preview": "vite preview", - "prettier": "prettier --write src", + "prettier": "prettier --write src --write plugins --write *.mjs --write *.mts", "genapi": "swagger-typescript-api -p http://localhost:55000/openapi/v1.json -t template -o src --module-name-first-tag --sort-routes" }, "dependencies": { @@ -39,6 +39,7 @@ "fast-average-color": "^9.4.0", "i18next": "^24.1.0", "i18next-browser-languagedetector": "^8.0.2", + "i18next-resources-to-backend": "^1.2.1", "katex": "^0.16.15", "lz-string": "^1.5.0", "marked": "^15.0.4", @@ -91,7 +92,6 @@ "typescript": "5.7.2", "vite": "^6.0.3", "vite-plugin-banner": "^0.8.0", - "vite-plugin-i18next-loader": "^3.0.0", "vite-plugin-optimize-css-modules": "^1.2.0", "vite-plugin-pages": "^0.32.4", "vite-plugin-prismjs": "^0.0.11", diff --git a/src/GZCTF/ClientApp/plugins/vite-i18n-virtual-manifest.ts b/src/GZCTF/ClientApp/plugins/vite-i18n-virtual-manifest.ts new file mode 100644 index 000000000..6017f7959 --- /dev/null +++ b/src/GZCTF/ClientApp/plugins/vite-i18n-virtual-manifest.ts @@ -0,0 +1,110 @@ +import crypto from 'crypto' +import fs from 'fs' +import path from 'path' +import { createLogger } from 'vite' +import type { Plugin } from 'vite' + +export default function i18nVirtualManifest(): Plugin { + let manifest: Record = {} + let contents: Record = {} + const logger = createLogger() + let localesDir: string + let outputDir: string + + const reloadResources = () => { + const newManifest: Record = {} + const newContents: Record = {} + + try { + fs.readdirSync(localesDir) + .filter(function (file) { + return fs.statSync(path.join(localesDir, file)).isDirectory() + }) + .forEach((lang) => { + const langDir = path.join(localesDir, lang) + const files = fs.readdirSync(langDir).filter((file) => file.endsWith('.json')) + + const merged = files.reduce((acc, file) => { + const key = file.replace('.json', '') + const filePath = path.join(langDir, file) + const content = JSON.parse(fs.readFileSync(filePath, 'utf-8')) + return { ...acc, [key]: content } + }, {}) + + const contentString = JSON.stringify(merged) + const hash = crypto.createHash('md5').update(contentString).digest('hex').slice(0, 8) + const outputFileName = `${lang}.${hash}.json` + + newManifest[lang.toLowerCase()] = outputFileName + newContents[outputFileName] = merged + }) + + manifest = newManifest + contents = newContents + } catch (e) { + logger.error(`Error reading locales directory: ${e}`) + } + } + + return { + name: 'vite-i18n-virtual-manifest', + + configResolved(config) { + localesDir = path.resolve(config.root, path.join('src', 'locales')) + outputDir = config.build.assetsDir + }, + + buildStart() { + reloadResources() + + // emit files only in production mode + if (process.env.NODE_ENV === 'production') { + Object.keys(contents).forEach((file) => { + this.emitFile({ + type: 'asset', + fileName: path.join(outputDir, file), + source: JSON.stringify(contents[file]), + }) + }) + } + + this.addWatchFile(localesDir) + }, + + configureServer(server) { + // handle requests for i18n resources like `/static/${file}` + server.middlewares.use((req, res, next) => { + if (!req.url?.startsWith('/static/')) { + return next() + } + + const file = req.url.slice('/static/'.length) + const content = contents[file] + + if (!content) { + res.statusCode = 404 + res.end('File not found') + return + } + + res.setHeader('Content-Type', 'application/json') + res.end(JSON.stringify(content)) + }) + + // watch for changes in locales directory + server.watcher.add(localesDir).on('change', (file) => { + if (file.endsWith('.json') && file.includes('locales')) reloadResources() + }) + }, + + resolveId(id) { + if (id === 'virtual:i18n-manifest') return id + return null + }, + + load(id) { + if (id !== 'virtual:i18n-manifest') return null + return `export default ${JSON.stringify(manifest)}` + }, + } +} diff --git a/src/GZCTF/ClientApp/pnpm-lock.yaml b/src/GZCTF/ClientApp/pnpm-lock.yaml index 3c36a6286..ec6614bdf 100644 --- a/src/GZCTF/ClientApp/pnpm-lock.yaml +++ b/src/GZCTF/ClientApp/pnpm-lock.yaml @@ -92,6 +92,9 @@ importers: i18next-browser-languagedetector: specifier: ^8.0.2 version: 8.0.2 + i18next-resources-to-backend: + specifier: ^1.2.1 + version: 1.2.1 katex: specifier: ^0.16.15 version: 0.16.15 @@ -243,9 +246,6 @@ importers: vite-plugin-banner: specifier: ^0.8.0 version: 0.8.0 - vite-plugin-i18next-loader: - specifier: ^3.0.0 - version: 3.0.0(vite@6.0.3(@types/node@22.10.2)(sass-embedded@1.81.0)(sugarss@4.0.1(postcss@8.4.49))(yaml@2.6.1)) vite-plugin-optimize-css-modules: specifier: ^1.2.0 version: 1.2.0(vite@6.0.3(@types/node@22.10.2)(sass-embedded@1.81.0)(sugarss@4.0.1(postcss@8.4.49))(yaml@2.6.1)) @@ -361,10 +361,6 @@ packages: '@bufbuild/protobuf@2.2.3': resolution: {integrity: sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==} - '@colors/colors@1.5.0': - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} - '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} @@ -637,10 +633,6 @@ packages: resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} engines: {node: '>=18.18'} - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -914,10 +906,6 @@ packages: cpu: [x64] os: [win32] - '@sindresorhus/is@4.6.0': - resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} - engines: {node: '>=10'} - '@trivago/prettier-plugin-sort-imports@5.2.0': resolution: {integrity: sha512-yEIJ7xMKYQwyNRjxSdi4Gs37iszikAjxfky+3hu9bn24u8eHLJNDMAoOTyowp8p6EpSl8IQMdkfBx+WnJTttsw==} engines: {node: '>18.12'} @@ -1060,29 +1048,14 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ansi-escapes@7.0.0: - resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} - engines: {node: '>=18'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1193,14 +1166,6 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - chroma-js@3.1.2: resolution: {integrity: sha512-IJnETTalXbsLx1eKEgx19d5L6SRM7cH4vINw/99p/M11HCuXGRWL+6YmCm7FWFGIo6dtWuQoQi1dc5yQ7ESIHg==} @@ -1208,21 +1173,9 @@ packages: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} - cli-highlight@2.1.11: - resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} - engines: {node: '>=8.0.0', npm: '>=5.0.0'} - hasBin: true - - cli-table3@0.6.5: - resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} - engines: {node: 10.* || >= 12.*} - client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1363,10 +1316,6 @@ packages: domutils@3.1.0: resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} - dot-prop@9.0.0: - resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} - engines: {node: '>=18'} - dry-uninstall@0.3.0: resolution: {integrity: sha512-b8h94RVpETWkVV59x62NsY++79bM7Si6Dxq7a4iVxRcJU3ZJJ4vaiC7wUZwM8WDK0ySRL+i+T/1SMAzbJLejYA==} @@ -1374,9 +1323,6 @@ packages: resolution: {integrity: sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==} engines: {node: '>= 0.4'} - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - echarts-for-react@3.0.2: resolution: {integrity: sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==} peerDependencies: @@ -1410,12 +1356,6 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - emojilib@2.4.0: - resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==} - entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -1424,10 +1364,6 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1635,10 +1571,6 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - foreground-child@3.3.0: - resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} - engines: {node: '>=14'} - form-data@4.0.1: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} @@ -1686,11 +1618,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@11.0.0: - resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} - engines: {node: 20 || >=22} - hasBin: true - globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -1743,9 +1670,6 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - highlight.js@10.7.3: - resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -1776,6 +1700,9 @@ packages: i18next-browser-languagedetector@8.0.2: resolution: {integrity: sha512-shBvPmnIyZeD2VU5jVGIOWP7u9qNG3Lj7mpaiPFpbJ3LVfHZJvVzKR4v1Cb91wAOFpNw442N+LGPzHOHsten2g==} + i18next-resources-to-backend@1.2.1: + resolution: {integrity: sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw==} + i18next@24.1.0: resolution: {integrity: sha512-suKlX82AlptkMUO5YRfaAeH4FQyyKvR66jNaubTMiyPPMx7INU6PXAiy3PGULc0q6K+t9nxmDf/TRj9KjAivmw==} peerDependencies: @@ -1926,10 +1853,6 @@ packages: resolution: {integrity: sha512-x4WH0BWmrMmg4oHHl+duwubhrvczGlyuGAZu3nvrf0UXOfPu8IhZObFEr7DE/iv01YgVZrsOiRcqw2srkKEDIA==} engines: {node: '>= 0.4'} - jackspeak@4.0.2: - resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} - engines: {node: 20 || >=22} - javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} @@ -2008,10 +1931,6 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - lru-cache@11.0.2: - resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} - engines: {node: 20 || >=22} - lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -2030,12 +1949,6 @@ packages: peerDependencies: marked: '>=4 <16' - marked-terminal@7.2.1: - resolution: {integrity: sha512-rQ1MoMFXZICWNsKMiiHwP/Z+92PLKskTPXj+e7uwXmuMPkNn7iTqC+IvDekVm1MPeC9wYQeLxeFaOvudRR/XbQ==} - engines: {node: '>=16.0.0'} - peerDependencies: - marked: '>=1 <15' - marked@15.0.4: resolution: {integrity: sha512-TCHvDqmb3ZJ4PWG7VEGVgtefA5/euFmsIhxtD0XsBxI39gUSKL81mIRFdt0AiNQozUahd4ke98ZdirExd/vSEw==} engines: {node: '>= 18'} @@ -2069,10 +1982,6 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - minimatch@10.0.1: - resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} - engines: {node: 20 || >=22} - minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2080,19 +1989,12 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - mlly@1.7.3: resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.8: resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2101,10 +2003,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - node-emoji@2.2.0: - resolution: {integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==} - engines: {node: '>=18'} - node-fetch-h2@2.3.0: resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} engines: {node: 4.x || >=6.0.0} @@ -2185,9 +2083,6 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -2200,15 +2095,6 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse5-htmlparser2-tree-adapter@6.0.1: - resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} - - parse5@5.1.1: - resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} - - parse5@6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -2220,10 +2106,6 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@2.0.0: - resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} - engines: {node: 20 || >=22} - path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -2696,17 +2578,9 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - size-sensor@1.0.2: resolution: {integrity: sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==} - skin-tone@2.0.0: - resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==} - engines: {node: '>=8'} - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2723,10 +2597,6 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - string.prototype.matchall@4.0.11: resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} engines: {node: '>= 0.4'} @@ -2750,10 +2620,6 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -2781,10 +2647,6 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - supports-hyperlinks@3.1.0: - resolution: {integrity: sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==} - engines: {node: '>=14.18'} - supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -2817,13 +2679,6 @@ packages: tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} - thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - - thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -2844,10 +2699,6 @@ packages: peerDependencies: typescript: '>=4.2.0' - ts-deepmerge@7.0.2: - resolution: {integrity: sha512-akcpDTPuez4xzULo5NwuoKwYRtjQJ9eoNfBACiBMaXwNAx7B1PKfe5wqUFJuW5uKzQ68YjDFwPaWHDG1KnFGsA==} - engines: {node: '>=14.13.1'} - tsconfck@3.1.4: resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==} engines: {node: ^18 || >=20} @@ -2910,10 +2761,6 @@ packages: undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - unicode-emoji-modifier-base@1.0.0: - resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==} - engines: {node: '>=4'} - universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} @@ -2991,11 +2838,6 @@ packages: vite-plugin-banner@0.8.0: resolution: {integrity: sha512-JpDWDYxtrsytuvUOJCgJcTkBb6XM8yPOidjRtB6F5SW1JSzDd/Y+PD/44wR6ovWKXhSUiyDRqPvx7mMf8+8ELg==} - vite-plugin-i18next-loader@3.0.0: - resolution: {integrity: sha512-1XiAp+mu5p5xQ3Am9iS5F+2utYhTM32zkJEQ6tlCI73A4hvkfeTX9wXm/V1BByg882mPbGcGiDvzoiofZfkM4g==} - peerDependencies: - vite: '>=3.1.6' - vite-plugin-optimize-css-modules@1.2.0: resolution: {integrity: sha512-5kOEVyif9qSoLAQDmN6nXW2fgz66oLXGlapKwY7u8nPVaVoyabkioQqf90s0gFvssCAY2bwBndx5sK7LF+i2rA==} peerDependencies: @@ -3118,10 +2960,6 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - ws@7.5.10: resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} engines: {node: '>=8.3.0'} @@ -3150,18 +2988,10 @@ packages: engines: {node: '>= 14'} hasBin: true - yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -3305,9 +3135,6 @@ snapshots: '@bufbuild/protobuf@2.2.3': optional: true - '@colors/colors@1.5.0': - optional: true - '@emotion/babel-plugin@11.13.5': dependencies: '@babel/helper-module-imports': 7.25.9 @@ -3529,15 +3356,6 @@ snapshots: '@humanwhocodes/retry@0.4.1': {} - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -3776,8 +3594,6 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.28.1': optional: true - '@sindresorhus/is@4.6.0': {} - '@trivago/prettier-plugin-sort-imports@5.2.0(prettier@3.4.2)': dependencies: '@babel/generator': 7.26.3 @@ -3955,22 +3771,12 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ansi-escapes@7.0.0: - dependencies: - environment: 1.1.0 - ansi-regex@5.0.1: {} - ansi-regex@6.1.0: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.1: {} - - any-promise@1.3.0: {} - argparse@2.0.1: {} array-buffer-byte-length@1.0.1: @@ -4120,39 +3926,14 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.3.0: {} - - char-regex@1.0.2: {} - chroma-js@3.1.2: {} clean-css@5.3.3: dependencies: source-map: 0.6.1 - cli-highlight@2.1.11: - dependencies: - chalk: 4.1.2 - highlight.js: 10.7.3 - mz: 2.7.0 - parse5: 5.1.1 - parse5-htmlparser2-tree-adapter: 6.0.1 - yargs: 16.2.0 - - cli-table3@0.6.5: - dependencies: - string-width: 4.2.3 - optionalDependencies: - '@colors/colors': 1.5.0 - client-only@0.0.1: {} - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -4288,10 +4069,6 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 - dot-prop@9.0.0: - dependencies: - type-fest: 4.30.1 - dry-uninstall@0.3.0: optional: true @@ -4301,8 +4078,6 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - eastasianwidth@0.2.0: {} - echarts-for-react@3.0.2(echarts@5.5.1)(react@19.0.0): dependencies: echarts: 5.5.1 @@ -4335,16 +4110,10 @@ snapshots: emoji-regex@8.0.0: {} - emoji-regex@9.2.2: {} - - emojilib@2.4.0: {} - entities@4.5.0: {} env-paths@2.2.1: {} - environment@1.1.0: {} - error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -4656,11 +4425,6 @@ snapshots: dependencies: is-callable: 1.2.7 - foreground-child@3.3.0: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - form-data@4.0.1: dependencies: asynckit: 0.4.0 @@ -4714,15 +4478,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@11.0.0: - dependencies: - foreground-child: 3.3.0 - jackspeak: 4.0.2 - minimatch: 10.0.1 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 2.0.0 - globals@11.12.0: {} globals@14.0.0: {} @@ -4762,8 +4517,6 @@ snapshots: dependencies: function-bind: 1.1.2 - highlight.js@10.7.3: {} - hoist-non-react-statics@3.3.2: dependencies: react-is: 16.13.1 @@ -4802,6 +4555,10 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 + i18next-resources-to-backend@1.2.1: + dependencies: + '@babel/runtime': 7.26.0 + i18next@24.1.0(typescript@5.7.2): dependencies: '@babel/runtime': 7.26.0 @@ -4946,10 +4703,6 @@ snapshots: reflect.getprototypeof: 1.0.8 set-function-name: 2.0.2 - jackspeak@4.0.2: - dependencies: - '@isaacs/cliui': 8.0.2 - javascript-natural-sort@0.7.1: {} js-tokens@4.0.0: {} @@ -5017,8 +4770,6 @@ snapshots: dependencies: js-tokens: 4.0.0 - lru-cache@11.0.2: {} - lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -5033,17 +4784,6 @@ snapshots: dependencies: marked: 15.0.4 - marked-terminal@7.2.1(marked@15.0.4): - dependencies: - ansi-escapes: 7.0.0 - ansi-regex: 6.1.0 - chalk: 5.3.0 - cli-highlight: 2.1.11 - cli-table3: 0.6.5 - marked: 15.0.4 - node-emoji: 2.2.0 - supports-hyperlinks: 3.1.0 - marked@15.0.4: {} math-intrinsics@1.0.0: {} @@ -5065,10 +4805,6 @@ snapshots: dependencies: mime-db: 1.52.0 - minimatch@10.0.1: - dependencies: - brace-expansion: 2.0.1 - minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -5077,8 +4813,6 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minipass@7.1.2: {} - mlly@1.7.3: dependencies: acorn: 8.14.0 @@ -5088,23 +4822,10 @@ snapshots: ms@2.1.3: {} - mz@2.7.0: - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - nanoid@3.3.8: {} natural-compare@1.4.0: {} - node-emoji@2.2.0: - dependencies: - '@sindresorhus/is': 4.6.0 - char-regex: 1.0.2 - emojilib: 2.4.0 - skin-tone: 2.0.0 - node-fetch-h2@2.3.0: dependencies: http2-client: 1.3.5 @@ -5210,8 +4931,6 @@ snapshots: dependencies: p-limit: 3.1.0 - package-json-from-dist@1.0.1: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -5225,25 +4944,12 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse5-htmlparser2-tree-adapter@6.0.1: - dependencies: - parse5: 6.0.1 - - parse5@5.1.1: {} - - parse5@6.0.1: {} - path-exists@4.0.0: {} path-key@3.1.1: {} path-parse@1.0.7: {} - path-scurry@2.0.0: - dependencies: - lru-cache: 11.0.2 - minipass: 7.1.2 - path-type@4.0.0: {} path2d@0.2.2: @@ -5717,14 +5423,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - signal-exit@4.1.0: {} - size-sensor@1.0.2: {} - skin-tone@2.0.0: - dependencies: - unicode-emoji-modifier-base: 1.0.0 - source-map-js@1.2.1: {} source-map@0.5.7: {} @@ -5737,12 +5437,6 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - string.prototype.matchall@4.0.11: dependencies: call-bind: 1.0.8 @@ -5790,10 +5484,6 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - strip-json-comments@3.1.1: {} style-to-js@1.1.16: @@ -5819,11 +5509,6 @@ snapshots: has-flag: 4.0.0 optional: true - supports-hyperlinks@3.1.0: - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 - supports-preserve-symlinks-flag@1.0.0: {} swagger-schema-official@2.0.0-bab6bed: {} @@ -5877,14 +5562,6 @@ snapshots: tabbable@6.2.0: {} - thenify-all@1.6.0: - dependencies: - thenify: 3.3.1 - - thenify@3.3.1: - dependencies: - any-promise: 1.3.0 - tiny-invariant@1.3.3: {} to-regex-range@5.0.1: @@ -5904,8 +5581,6 @@ snapshots: dependencies: typescript: 5.7.2 - ts-deepmerge@7.0.2: {} - tsconfck@3.1.4(typescript@5.7.2): optionalDependencies: typescript: 5.7.2 @@ -5970,8 +5645,6 @@ snapshots: undici-types@6.20.0: {} - unicode-emoji-modifier-base@1.0.0: {} - universalify@0.2.0: {} update-browserslist-db@1.1.1(browserslist@4.24.3): @@ -6034,16 +5707,6 @@ snapshots: vite-plugin-banner@0.8.0: {} - vite-plugin-i18next-loader@3.0.0(vite@6.0.3(@types/node@22.10.2)(sass-embedded@1.81.0)(sugarss@4.0.1(postcss@8.4.49))(yaml@2.6.1)): - dependencies: - dot-prop: 9.0.0 - glob: 11.0.0 - js-yaml: 4.1.0 - marked: 15.0.4 - marked-terminal: 7.2.1(marked@15.0.4) - ts-deepmerge: 7.0.2 - vite: 6.0.3(@types/node@22.10.2)(sass-embedded@1.81.0)(sugarss@4.0.1(postcss@8.4.49))(yaml@2.6.1) - vite-plugin-optimize-css-modules@1.2.0(vite@6.0.3(@types/node@22.10.2)(sass-embedded@1.81.0)(sugarss@4.0.1(postcss@8.4.49))(yaml@2.6.1)): dependencies: vite: 6.0.3(@types/node@22.10.2)(sass-embedded@1.81.0)(sugarss@4.0.1(postcss@8.4.49))(yaml@2.6.1) @@ -6170,12 +5833,6 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - ws@7.5.10: {} y18n@5.0.8: {} @@ -6186,20 +5843,8 @@ snapshots: yaml@2.6.1: {} - yargs-parser@20.2.9: {} - yargs-parser@21.1.1: {} - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - yargs@17.7.2: dependencies: cliui: 8.0.1 diff --git a/src/GZCTF/ClientApp/src/main.tsx b/src/GZCTF/ClientApp/src/main.tsx index 7026ecc20..6ba86b0bb 100644 --- a/src/GZCTF/ClientApp/src/main.tsx +++ b/src/GZCTF/ClientApp/src/main.tsx @@ -1,15 +1,25 @@ import { App } from '@App' import i18n from 'i18next' import LanguageDetector from 'i18next-browser-languagedetector' +import resourcesToBackend from 'i18next-resources-to-backend' import ReactDOM from 'react-dom/client' import { initReactI18next } from 'react-i18next' import { BrowserRouter } from 'react-router' -import resources from 'virtual:i18next-loader' +import manifest from 'virtual:i18n-manifest' import { convertLanguage } from '@Utils/I18n' i18n .use(LanguageDetector) .use(initReactI18next) + .use( + // implement by custom vite plugin, see plugins/vite-i18n-virtual-manifest.ts + resourcesToBackend(async (lang: string, _: string) => { + const file = manifest[lang.toLowerCase()] + if (!file) return {} + const response = await fetch(`/static/${file}`) + return response.json() + }) + ) .init({ fallbackLng: convertLanguage, interpolation: { @@ -18,14 +28,6 @@ i18n detection: { convertDetectedLanguage: convertLanguage, }, - resources: Object.fromEntries( - Object.entries(resources).map(([lang, res]) => [ - lang, - { - translation: res, - }, - ]) - ), }) const app = ReactDOM.createRoot(document.getElementById('root')!) diff --git a/src/GZCTF/ClientApp/src/vite-env.d.ts b/src/GZCTF/ClientApp/src/vite-env.d.ts index d6f88a626..ca419fea2 100644 --- a/src/GZCTF/ClientApp/src/vite-env.d.ts +++ b/src/GZCTF/ClientApp/src/vite-env.d.ts @@ -11,8 +11,8 @@ interface ImportMeta { readonly env: ImportMetaEnv } -declare module 'virtual:i18next-loader' { - declare const resources: import('i18next').Resource +declare module 'virtual:i18n-manifest' { + declare const manifest: Record - export default resources + export default manifest } diff --git a/src/GZCTF/ClientApp/vite.config.mts b/src/GZCTF/ClientApp/vite.config.mts index 485437f75..1bb35f7c8 100644 --- a/src/GZCTF/ClientApp/vite.config.mts +++ b/src/GZCTF/ClientApp/vite.config.mts @@ -3,12 +3,12 @@ import react from '@vitejs/plugin-react' import process from 'process' import { defineConfig, loadEnv } from 'vite' import banner from 'vite-plugin-banner' -import i18nextLoader from 'vite-plugin-i18next-loader' import { optimizeCssModules } from 'vite-plugin-optimize-css-modules' import Pages from 'vite-plugin-pages' import { prismjsPlugin } from 'vite-plugin-prismjs' import webfontDownload from 'vite-plugin-webfont-dl' import tsconfigPaths from 'vite-tsconfig-paths' +import i18nVirtualManifest from './plugins/vite-i18n-virtual-manifest' export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd()) @@ -83,11 +83,7 @@ export default defineConfig(({ mode }) => { languages: 'all', css: true, }), - i18nextLoader({ - paths: ['./src/locales'], - include: ['**/*.json'], - namespaceResolution: 'basename', - }), + i18nVirtualManifest(), optimizeCssModules(), ], }