diff --git a/README.md b/README.md index 2ca0754..fa4a767 100644 --- a/README.md +++ b/README.md @@ -78,3 +78,16 @@ As for why a typical database is not used, this is because: Post route in the url is directly mapped to the filesystem, eg: `https:///post/path/to/post` -> `cec/path/to/post.md` + +### Internationalization (i18n) + +This project uses [inlang](https://inlang.com/) with `paraglide.js` for i18n. +Translation files are stored in `src/messages/[lang].json`, where `lang` is the target language. + +Currently supported languages: `zh-tw`, `en`, `ja` + +To add a translation, follow the steps below: +1. Add your target language in `tnfshcec.inlang/settings.json`, under the `languageTags` array (ex:`de`). +2. Copy one of the translation files in `src/messages/[lang].json`, renaming it to your target language. +3. Do the translations in the file you copied. +4. Update the languages listed above (the README). diff --git a/package-lock.json b/package-lock.json index 52bbe00..9116355 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "tnfshcec-web", "version": "0.0.1", + "hasInstallScript": true, "dependencies": { "@auth/sveltekit": "^0.3.6", "@cartamd/plugin-code": "^3.0.1", @@ -24,6 +25,8 @@ }, "devDependencies": { "@iconify-json/mdi": "^1.1.54", + "@inlang/paraglide-js": "1.0.0-prerelease.17", + "@inlang/paraglide-js-adapter-vite": "^1.0.1", "@melt-ui/pp": "^0.1.2", "@melt-ui/svelte": "^0.61.1", "@sveltejs/adapter-node": "^1.3.1", @@ -694,6 +697,226 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/@inlang/detect-json-formatting": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@inlang/detect-json-formatting/-/detect-json-formatting-1.0.0.tgz", + "integrity": "sha512-o0jeI8U4TgNlsPwI0y92jld8/18Loh2KEgHCYCJ42rCOdxFrA8R60cydlEd2/6jkdHFn5DxKj8rOyiKv3z9uOw==", + "dev": true, + "dependencies": { + "guess-json-indent": "2.0.0" + } + }, + "node_modules/@inlang/json-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@inlang/json-types/-/json-types-1.1.0.tgz", + "integrity": "sha512-n6vS6AqETsCFbV4TdBvR/EH57waVXzKsMqeUQ+eH2Q6NUATfKhfLabgNms2A+QV3aedH/hLtb1pRmjl2ykBVZg==", + "dev": true, + "peerDependencies": { + "@sinclair/typebox": "^0.31.0" + } + }, + "node_modules/@inlang/language-tag": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@inlang/language-tag/-/language-tag-1.2.0.tgz", + "integrity": "sha512-AwKNPYPgJrhM9ebEYQvcG5PGM4v79jMPlsv2bUYEhEZzMpwIJKQo4t7P7EekMhO086sXOmeTu410Lm8abX/2Yw==", + "dev": true, + "peerDependencies": { + "@sinclair/typebox": "^0.31.0" + } + }, + "node_modules/@inlang/message": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@inlang/message/-/message-2.0.0.tgz", + "integrity": "sha512-RPFcbega2Cnxi78d08O7SbuXyuhEqsB819QjgloNTXWtlBFwVDkF87xAMIZN37hpM6JZzMaYv2O1ipyncU3Ccg==", + "dev": true, + "dependencies": { + "@inlang/language-tag": "*" + }, + "peerDependencies": { + "@sinclair/typebox": "^0.31.0" + } + }, + "node_modules/@inlang/message-lint-rule": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@inlang/message-lint-rule/-/message-lint-rule-1.4.0.tgz", + "integrity": "sha512-imOvpxKFP2ESaWTI5W5aQiW1ukvXMvGa4KhVknssfA1ZkCkVu2EDM4aGxw11U5Rli4QQ70bxztUvfLVhd3J84A==", + "dev": true, + "dependencies": { + "@inlang/json-types": "*", + "@inlang/language-tag": "*", + "@inlang/message": "*", + "@inlang/project-settings": "*", + "@inlang/translatable": "*" + }, + "peerDependencies": { + "@sinclair/typebox": "^0.31.17" + } + }, + "node_modules/@inlang/module": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@inlang/module/-/module-1.2.0.tgz", + "integrity": "sha512-Z91zJUgliX+ddfRK+Ce4aZYlMjeNwZJOMmJ2dEUgg2cfqIFRB+gDsC5gLEY5LTkZspf/XUHoECTpK8ErVVYF5w==", + "dev": true, + "dependencies": { + "@inlang/message-lint-rule": "*", + "@inlang/plugin": "*" + }, + "peerDependencies": { + "@sinclair/typebox": "^0.31.17" + } + }, + "node_modules/@inlang/paraglide-js": { + "version": "1.0.0-prerelease.17", + "resolved": "https://registry.npmjs.org/@inlang/paraglide-js/-/paraglide-js-1.0.0-prerelease.17.tgz", + "integrity": "sha512-m3RaPFB9KMTIvXeHPq58w4u6gHFmNtlQmJOuyKAdYjZEvh3xNx8aUuPbgnjZ1dg2GrJ2w64lNK4LlYWrHRGOFA==", + "dev": true, + "dependencies": { + "@inlang/detect-json-formatting": "1.0.0", + "@inlang/sdk": "0.19.0", + "@lix-js/fs": "0.4.0", + "commander": "11.1.0", + "consola": "3.2.3", + "dedent": "1.5.1", + "isomorphic-git": "1.24.5", + "json5": "2.2.3", + "posthog-node": "3.1.3" + }, + "bin": { + "paraglide-js": "bin/run.js" + } + }, + "node_modules/@inlang/paraglide-js-adapter-unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inlang/paraglide-js-adapter-unplugin/-/paraglide-js-adapter-unplugin-1.0.1.tgz", + "integrity": "sha512-Ana7ysAf/dAhtLOnJuasWhwjkMCPoK7ccVyd3YkI+3Ee3qMLJ+3jSWYKn3C/ZkE+wf9oJubiBbGqpYqGFerd6Q==", + "dev": true, + "dependencies": { + "@inlang/paraglide-js": "1.0.0-prerelease.14", + "@inlang/sdk": "0.19.0", + "unplugin": "1.5.1" + } + }, + "node_modules/@inlang/paraglide-js-adapter-unplugin/node_modules/@inlang/paraglide-js": { + "version": "1.0.0-prerelease.14", + "resolved": "https://registry.npmjs.org/@inlang/paraglide-js/-/paraglide-js-1.0.0-prerelease.14.tgz", + "integrity": "sha512-hnxy9bc3SPISH03ZKvB+Ttg4Mh48fN+dReX3dSbmCBYCaz9wtg/6m+kxJXmQAuHdUkapvNeaFUdiLDNUneFsUw==", + "dev": true, + "dependencies": { + "@inlang/detect-json-formatting": "1.0.0", + "@inlang/sdk": "0.19.0", + "@lix-js/fs": "0.4.0", + "commander": "11.1.0", + "consola": "3.2.3", + "dedent": "1.5.1", + "isomorphic-git": "1.24.5", + "json5": "2.2.3", + "posthog-node": "3.1.3" + }, + "bin": { + "paraglide-js": "bin/run.js" + } + }, + "node_modules/@inlang/paraglide-js-adapter-unplugin/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@inlang/paraglide-js-adapter-vite": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inlang/paraglide-js-adapter-vite/-/paraglide-js-adapter-vite-1.0.1.tgz", + "integrity": "sha512-Hxn+fiyBPXyiaoQw9Zuv/fGrfnyjoaz2ONLg90OH3K+8rl3uOqPVRWck3uKP4W9BWVMkNQlQVBXcPIfIKpzJdg==", + "dev": true, + "dependencies": { + "@inlang/paraglide-js-adapter-unplugin": "1.0.1" + } + }, + "node_modules/@inlang/paraglide-js/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@inlang/plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@inlang/plugin/-/plugin-2.4.0.tgz", + "integrity": "sha512-4+T7ZfuqcW4GFp3G+Vb+RTlYF8kKPY/BH0BcvOV2HX5B9UzgyC+dpXiI3TRQTUj7vz0yqp4K+onsaehPb2NGvw==", + "dev": true, + "dependencies": { + "@inlang/json-types": "*", + "@inlang/language-tag": "*", + "@inlang/message": "*", + "@inlang/project-settings": "*", + "@inlang/translatable": "*", + "@lix-js/fs": "*" + }, + "peerDependencies": { + "@sinclair/typebox": "^0.31.17" + } + }, + "node_modules/@inlang/project-settings": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@inlang/project-settings/-/project-settings-2.2.0.tgz", + "integrity": "sha512-M1D150KYiYoyiHhQp627zhvo/w/M1B11ROEu2u7Jn9005mKEWZS1DDlEOsLuNRl5doHSPHfkGa9qItMtrqr0dA==", + "dev": true, + "dependencies": { + "@inlang/json-types": "*", + "@inlang/language-tag": "*" + }, + "peerDependencies": { + "@sinclair/typebox": "^0.31.0" + } + }, + "node_modules/@inlang/result": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@inlang/result/-/result-1.1.0.tgz", + "integrity": "sha512-zLGroi9EUiHuOjUOaglUVTFO7EWdo2OARMJLBO1Q5Ga/xJmSQb6XS1lhqEXBFAjgFarfEMX5YEJWWALogYV3wA==", + "dev": true + }, + "node_modules/@inlang/sdk": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@inlang/sdk/-/sdk-0.19.0.tgz", + "integrity": "sha512-8dS7MJt1RfvejkIW4OzSkenCTiH7XRHvmQgMtzWQBvS/BMmEVTWtt2W+5uLV4t6HYjqedf+lHwBAgdiOHp7/Yg==", + "dev": true, + "dependencies": { + "@inlang/json-types": "1.1.0", + "@inlang/language-tag": "1.2.0", + "@inlang/message": "2.0.0", + "@inlang/message-lint-rule": "1.4.0", + "@inlang/module": "1.2.0", + "@inlang/plugin": "2.4.0", + "@inlang/project-settings": "2.2.0", + "@inlang/result": "1.1.0", + "@inlang/translatable": "1.2.0", + "@lix-js/fs": "0.4.0", + "@sinclair/typebox": "^0.31.17", + "dedent": "1.5.1", + "deepmerge-ts": "^5.1.0", + "solid-js": "1.6.12", + "throttle-debounce": "5.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@inlang/translatable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@inlang/translatable/-/translatable-1.2.0.tgz", + "integrity": "sha512-Od/nBm3qigfSpYJKu/Isg0rb34ohZApNk+fOtmZ0vBZXsTBzKaYFW0SeBVqwociRCr1tj40N659Ky+RoyLcv8A==", + "dev": true, + "dependencies": { + "@inlang/language-tag": "*" + }, + "peerDependencies": { + "@sinclair/typebox": "^0.31.0" + } + }, "node_modules/@internationalized/date": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.0.tgz", @@ -751,6 +974,15 @@ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, + "node_modules/@lix-js/fs": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@lix-js/fs/-/fs-0.4.0.tgz", + "integrity": "sha512-IOno98FwY+TPinwXzg5dx6xkCwyBCvkv6DMAQjI1Us4rvI9zObfjXd4E2VIGyT7vfUhpXIs4KXmne+onkCDzsg==", + "dev": true, + "dependencies": { + "js-base64": "^3.7.5" + } + }, "node_modules/@melt-ui/pp": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@melt-ui/pp/-/pp-0.1.2.tgz", @@ -967,6 +1199,12 @@ } } }, + "node_modules/@sinclair/typebox": { + "version": "0.31.28", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.31.28.tgz", + "integrity": "sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ==", + "dev": true + }, "node_modules/@speed-highlight/core": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.2.tgz", @@ -1391,9 +1629,9 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "bin": { "acorn": "bin/acorn" }, @@ -1497,6 +1735,18 @@ "node": ">=8" } }, + "node_modules/async-lock": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.0.tgz", + "integrity": "sha512-coglx5yIWuetakm3/1dsX9hxCNox22h7+V80RQOu2XUUMidtArxKoZoOtHUPuR84SycKTXzgGzAUR5hJxujyJQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "node_modules/autoprefixer": { "version": "10.4.14", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", @@ -1530,6 +1780,17 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", @@ -1742,6 +2003,12 @@ "node": ">= 6" } }, + "node_modules/clean-git-ref": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==", + "dev": true + }, "node_modules/code-red": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", @@ -1780,6 +2047,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -1810,6 +2089,15 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/cookie": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", @@ -1818,6 +2106,18 @@ "node": ">= 0.6" } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1856,6 +2156,12 @@ "node": ">=4" } }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1872,6 +2178,35 @@ } } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1886,6 +2221,24 @@ "node": ">=0.10.0" } }, + "node_modules/deepmerge-ts": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz", + "integrity": "sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==", + "dev": true, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -1926,6 +2279,12 @@ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "dev": true }, + "node_modules/diff3": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", + "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==", + "dev": true + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2462,6 +2821,40 @@ "tabbable": "^6.2.0" } }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -2628,6 +3021,15 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/guess-json-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/guess-json-indent/-/guess-json-indent-2.0.0.tgz", + "integrity": "sha512-3Tm6R43KhtZWEVSHZnFmYMV9+gf3Vu0HXNNYtPVk2s7o8eGwYlJPHrjLtYw/7HBc10YxV+bfzKMuOf24z5qFng==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2946,6 +3348,40 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/isomorphic-git": { + "version": "1.24.5", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.24.5.tgz", + "integrity": "sha512-07M4YscftHZJIuw7xZhgWkdFvVjHSBJBsIwWXkxgFCivhb0l8mGNchM7nO2hU27EKSIf0sT4gJivEgLGohWbzA==", + "dev": true, + "dependencies": { + "async-lock": "^1.1.0", + "clean-git-ref": "^2.0.1", + "crc-32": "^1.2.0", + "diff3": "0.0.3", + "ignore": "^5.1.4", + "minimisted": "^2.0.0", + "pako": "^1.0.10", + "pify": "^4.0.1", + "readable-stream": "^3.4.0", + "sha.js": "^2.4.9", + "simple-get": "^4.0.1" + }, + "bin": { + "isogit": "cli.cjs" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/isomorphic-git/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/jiti": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", @@ -2963,6 +3399,12 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/js-base64": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", + "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==", + "dev": true + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2986,6 +3428,18 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -3274,6 +3728,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -3283,6 +3758,18 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -3322,6 +3809,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minimisted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", + "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -3534,6 +4030,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3848,6 +4350,19 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/posthog-node": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-3.1.3.tgz", + "integrity": "sha512-UaOOoWEUYTcaaDe1w0fgHW/sXvFr3RO0l7yI7RUDzkZNZCfwXNO9r3pc14d1EtNppF/SHBrV5hNiZZATpf/vUw==", + "dev": true, + "dependencies": { + "axios": "^1.6.0", + "rusha": "^0.8.14" + }, + "engines": { + "node": ">=15.0.0" + } + }, "node_modules/preact": { "version": "10.11.3", "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz", @@ -3988,6 +4503,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4068,6 +4589,20 @@ "pify": "^2.3.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4197,6 +4732,12 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rusha": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", + "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==", + "dev": true + }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -4208,6 +4749,26 @@ "node": ">=6" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/sander": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", @@ -4264,6 +4825,19 @@ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4291,6 +4865,51 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/sirv": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", @@ -4313,6 +4932,15 @@ "node": ">=8" } }, + "node_modules/solid-js": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.12.tgz", + "integrity": "sha512-JFqRobfG3q5r1l4RYVOAukk6+FWtHpXGIjgh/GEsHKweN/kK+iHOtzUALE6+P5t/jIcSNeGiVitX8gmJg+cYvQ==", + "dev": true, + "dependencies": { + "csstype": "^3.1.0" + } + }, "node_modules/sorcery": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz", @@ -4350,6 +4978,15 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4739,6 +5376,15 @@ "node": ">=0.8" } }, + "node_modules/throttle-debounce": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz", + "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -4929,15 +5575,15 @@ } }, "node_modules/unplugin": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.5.0.tgz", - "integrity": "sha512-9ZdRwbh/4gcm1JTOkp9lAkIDrtOyOxgHmY7cjuwI8L/2RTikMcVG25GsZwNAgRuap3iDw2jeq7eoqtAsz5rW3A==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.5.1.tgz", + "integrity": "sha512-0QkvG13z6RD+1L1FoibQqnvTwVBXvS4XSPwAyinVgoOCl2jAgwzdUKmEj05o4Lt8xwQI85Hb6mSyYkcAGwZPew==", "dev": true, "dependencies": { - "acorn": "^8.10.0", + "acorn": "^8.11.2", "chokidar": "^3.5.3", "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.5.0" + "webpack-virtual-modules": "^0.6.0" } }, "node_modules/unplugin-icons": { @@ -5175,9 +5821,9 @@ } }, "node_modules/webpack-virtual-modules": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", - "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz", + "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==", "dev": true }, "node_modules/which": { diff --git a/package.json b/package.json index cb57386..99f55be 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "private": true, "scripts": { "dev": "vite dev", - "build": "vite build", + "build": "npm run build:i18n && vite build", + "build:i18n": "paraglide-js compile --project ./tnfshcec.inlang", "preview": "vite preview", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", @@ -28,6 +29,8 @@ }, "devDependencies": { "@iconify-json/mdi": "^1.1.54", + "@inlang/paraglide-js": "1.0.0-prerelease.17", + "@inlang/paraglide-js-adapter-vite": "^1.0.1", "@melt-ui/pp": "^0.1.2", "@melt-ui/svelte": "^0.61.1", "@sveltejs/adapter-node": "^1.3.1", diff --git a/src/app.d.ts b/src/app.d.ts index a71c5f4..55d11cf 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,12 +1,15 @@ import "unplugin-icons/types/svelte"; import { DefaultSession } from "@auth/core"; +import type { AvailableLanguageTag } from "$paraglide/runtime"; // See https://kit.svelte.dev/docs/types#app // for information about these interfaces declare global { namespace App { // interface Error {} - // interface Locals {} + interface Locals { + lang: AvailableLanguageTag; + } // interface PageData {} // interface Platform {} interface PostData { diff --git a/src/app.html b/src/app.html index 771d084..290162e 100644 --- a/src/app.html +++ b/src/app.html @@ -1,5 +1,5 @@ - - + + diff --git a/src/hooks.server.ts b/src/hooks.server.ts index b4e61b4..415b8a8 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,12 +1,15 @@ import { SvelteKitAuth } from "@auth/sveltekit"; import GitHub from "@auth/core/providers/github"; import { env } from "$env/dynamic/private"; +import { detectLanguage } from "$lib/stores/i18n"; +import { sequence } from "@sveltejs/kit/hooks"; +import type { Handle } from "@sveltejs/kit"; const admins = env.ADMINS?.split(",") .map((s) => s.trim()) .filter((s) => s); -export const handle = SvelteKitAuth({ +const auth = SvelteKitAuth({ providers: [ GitHub({ clientId: env.GITHUB_ID, @@ -33,3 +36,20 @@ export const handle = SvelteKitAuth({ } } }); + +const locale: Handle = async ({ event, resolve }) => { + const lang = detectLanguage(event.url, event.request); + + event.locals.lang = lang; + + return resolve(event, { + transformPageChunk({ done, html }) { + // Only do it at the very end of the rendering process + if (done) { + return html.replace("%lang%", lang); + } + } + }); +}; + +export const handle = sequence(auth, locale); diff --git a/src/lib/components/TableOfContents/TableOfContents.svelte b/src/lib/components/TableOfContents/TableOfContents.svelte index 0e5d482..6cfba37 100644 --- a/src/lib/components/TableOfContents/TableOfContents.svelte +++ b/src/lib/components/TableOfContents/TableOfContents.svelte @@ -1,10 +1,14 @@ -

On This Page

+

{$m.post_tableOfContents()}