mirror of
https://github.com/gotson/komga.git
synced 2026-05-08 04:22:28 +02:00
i18n support
This commit is contained in:
parent
7e16a710d0
commit
382a851b7d
15 changed files with 730 additions and 10 deletions
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
import {defineConfigWithVueTs, vueTsConfigs} from '@vue/eslint-config-typescript'
|
||||
import formatjs from 'eslint-plugin-formatjs'
|
||||
|
||||
export default defineConfigWithVueTs(
|
||||
{
|
||||
|
|
@ -32,5 +33,20 @@ export default defineConfigWithVueTs(
|
|||
],
|
||||
'vue/multi-word-component-names': 'off',
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
plugins: {
|
||||
formatjs,
|
||||
},
|
||||
rules: {
|
||||
'formatjs/no-offset': 'error',
|
||||
'formatjs/enforce-id': [
|
||||
'error',
|
||||
{
|
||||
idInterpolationPattern: '[sha512:contenthash:base64:6]',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
|
|||
540
next-ui/package-lock.json
generated
540
next-ui/package-lock.json
generated
|
|
@ -16,10 +16,12 @@
|
|||
"openapi-fetch": "^0.14.0",
|
||||
"pinia-plugin-persistedstate": "^4.3.0",
|
||||
"vue": "^3.5.14",
|
||||
"vue-intl": "^6.5.25",
|
||||
"vuetify": "^3.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.27.0",
|
||||
"@formatjs/cli": "^6.7.1",
|
||||
"@mdi/font": "7.4.47",
|
||||
"@tsconfig/node22": "^22.0.2",
|
||||
"@types/node": "^22.15.21",
|
||||
|
|
@ -27,6 +29,7 @@
|
|||
"@vue/eslint-config-typescript": "^14.1.3",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"eslint": "^9.27.0",
|
||||
"eslint-plugin-formatjs": "^5.3.1",
|
||||
"eslint-plugin-vue": "^10.1.0",
|
||||
"npm-run-all2": "^8.0.3",
|
||||
"openapi-typescript": "^7.8.0",
|
||||
|
|
@ -689,6 +692,151 @@
|
|||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/cli": {
|
||||
"version": "6.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/cli/-/cli-6.7.1.tgz",
|
||||
"integrity": "sha512-ULiXbLkbuTyd8f0qaByu1Nuc+jbAOLH1qRAtHZ7waIABQGPBB93OQ2FFtQPgoYoupKOKyNr+PZXR6pOT45E4EQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"formatjs": "bin/formatjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@glimmer/env": "^0.1.7",
|
||||
"@glimmer/reference": "^0.94.0",
|
||||
"@glimmer/syntax": "^0.94.9",
|
||||
"@glimmer/validator": "^0.94.0",
|
||||
"@vue/compiler-core": "^3.5.12",
|
||||
"content-tag": "^3.0.0",
|
||||
"ember-template-recast": "^6.1.5",
|
||||
"vue": "^3.5.12"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@glimmer/env": {
|
||||
"optional": true
|
||||
},
|
||||
"@glimmer/reference": {
|
||||
"optional": true
|
||||
},
|
||||
"@glimmer/syntax": {
|
||||
"optional": true
|
||||
},
|
||||
"@glimmer/validator": {
|
||||
"optional": true
|
||||
},
|
||||
"@vue/compiler-core": {
|
||||
"optional": true
|
||||
},
|
||||
"content-tag": {
|
||||
"optional": true
|
||||
},
|
||||
"ember-template-recast": {
|
||||
"optional": true
|
||||
},
|
||||
"vue": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/ecma402-abstract": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz",
|
||||
"integrity": "sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "2.2.7",
|
||||
"@formatjs/intl-localematcher": "0.6.1",
|
||||
"decimal.js": "^10.4.3",
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/fast-memoize": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz",
|
||||
"integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/icu-messageformat-parser": {
|
||||
"version": "2.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.2.tgz",
|
||||
"integrity": "sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/ecma402-abstract": "2.3.4",
|
||||
"@formatjs/icu-skeleton-parser": "1.8.14",
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/icu-skeleton-parser": {
|
||||
"version": "1.8.14",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.14.tgz",
|
||||
"integrity": "sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/ecma402-abstract": "2.3.4",
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/intl": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-3.1.6.tgz",
|
||||
"integrity": "sha512-tDkXnA4qpIFcDWac8CyVJq6oW8DR7W44QDUBsfXWIIJD/FYYen0QoH46W7XsVMFfPOVKkvbufjboZrrWbEfmww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/ecma402-abstract": "2.3.4",
|
||||
"@formatjs/fast-memoize": "2.2.7",
|
||||
"@formatjs/icu-messageformat-parser": "2.11.2",
|
||||
"intl-messageformat": "10.7.16",
|
||||
"tslib": "^2.8.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/intl-localematcher": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.1.tgz",
|
||||
"integrity": "sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/ts-transformer": {
|
||||
"version": "3.13.34",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/ts-transformer/-/ts-transformer-3.13.34.tgz",
|
||||
"integrity": "sha512-N1n7dA+6dfHn/LDQXrUPOC90Z+7dsDB5cQIJeIysVwGhk8PRyYo2eaotDszZMjQp8+hvs98kJyekn1X7mK1yHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "2.11.2",
|
||||
"@types/json-stable-stringify": "^1.1.0",
|
||||
"@types/node": "^22.0.0",
|
||||
"chalk": "^4.1.2",
|
||||
"json-stable-stringify": "^1.1.1",
|
||||
"tslib": "^2.8.0",
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ts-jest": "^29"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ts-jest": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
||||
|
|
@ -1568,6 +1716,17 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
|
||||
"integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
|
||||
|
|
@ -1581,6 +1740,13 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/json-stable-stringify": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.1.0.tgz",
|
||||
"integrity": "sha512-ESTsHWB72QQq+pjUFIbEz9uSCZppD31YrVkbt2rnUciTYEvcwN6uZIhX5JZeBHqRlFJ41x/7MewCs7E2Qux6Cg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.15.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz",
|
||||
|
|
@ -1591,6 +1757,13 @@
|
|||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/picomatch": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-3.0.2.tgz",
|
||||
"integrity": "sha512-n0i8TD3UDB7paoMMxA3Y65vUncFJXjcUf7lQY7YyKGl6031FNjfsLs6pdLFCy2GNFxItPJG8GvvpbZc2skH7WA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
|
||||
|
|
@ -2406,6 +2579,56 @@
|
|||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.0",
|
||||
"es-define-property": "^1.0.0",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"set-function-length": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bound": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"get-intrinsic": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
|
|
@ -2626,6 +2849,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decimal.js": {
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz",
|
||||
"integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deep-is": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||
|
|
@ -2638,6 +2867,24 @@
|
|||
"resolved": "https://registry.npmjs.org/deep-pick-omit/-/deep-pick-omit-1.2.1.tgz",
|
||||
"integrity": "sha512-2J6Kc/m3irCeqVG42T+SaUMesaK7oGWaedGnQQK/+O0gYc+2SP5bKh/KKTE7d7SJ+GCA9UUE1GRzh6oDe0EnGw=="
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/defu": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
|
||||
|
|
@ -2672,6 +2919,31 @@
|
|||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex-xs": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-2.0.1.tgz",
|
||||
"integrity": "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
|
|
@ -2689,6 +2961,39 @@
|
|||
"resolved": "https://registry.npmjs.org/errx/-/errx-0.1.0.tgz",
|
||||
"integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q=="
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.4",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz",
|
||||
|
|
@ -2804,6 +3109,27 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-formatjs": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-formatjs/-/eslint-plugin-formatjs-5.3.1.tgz",
|
||||
"integrity": "sha512-RYXxDyCIcjzXXiclHhtXTJhRnR+HGyk4fyAke4j7Jtw8kCdVG/0rFeLqsIoJojxEB91+tkt0enX2LmDaXNhfdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "2.11.2",
|
||||
"@formatjs/ts-transformer": "3.13.34",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/picomatch": "^3",
|
||||
"@typescript-eslint/utils": "^8.27.0",
|
||||
"magic-string": "^0.30.0",
|
||||
"picomatch": "2 || 3 || 4",
|
||||
"tslib": "^2.8.0",
|
||||
"unicode-emoji-utils": "^1.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^9.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vue": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.1.0.tgz",
|
||||
|
|
@ -3121,6 +3447,55 @@
|
|||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/giget": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz",
|
||||
|
|
@ -3163,6 +3538,19 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
|
|
@ -3180,6 +3568,45 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/he": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||
|
|
@ -3267,6 +3694,18 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/intl-messageformat": {
|
||||
"version": "10.7.16",
|
||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.16.tgz",
|
||||
"integrity": "sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@formatjs/ecma402-abstract": "2.3.4",
|
||||
"@formatjs/fast-memoize": "2.2.7",
|
||||
"@formatjs/icu-messageformat-parser": "2.11.2",
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
|
|
@ -3325,6 +3764,13 @@
|
|||
"url": "https://github.com/sponsors/mesqueeb"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
|
|
@ -3394,6 +3840,26 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-stable-stringify": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
|
||||
"integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.8",
|
||||
"call-bound": "^1.0.4",
|
||||
"isarray": "^2.0.5",
|
||||
"jsonify": "^0.0.1",
|
||||
"object-keys": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/json-stable-stringify-without-jsonify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
|
||||
|
|
@ -3414,6 +3880,16 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonify": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
|
||||
"integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==",
|
||||
"dev": true,
|
||||
"license": "Public Domain",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
|
|
@ -3552,6 +4028,16 @@
|
|||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/memorystream": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
|
||||
|
|
@ -3818,6 +4304,16 @@
|
|||
"pathe": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ohash": {
|
||||
"version": "2.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
|
||||
|
|
@ -4786,6 +5282,24 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
|
|
@ -5001,7 +5515,6 @@
|
|||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"devOptional": true,
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
|
|
@ -5099,6 +5612,16 @@
|
|||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unicode-emoji-utils": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/unicode-emoji-utils/-/unicode-emoji-utils-1.3.1.tgz",
|
||||
"integrity": "sha512-6PiQxmnlsOsqzZCZz0sykSyMy/r1HiJiOWWXV98+BDva583DU4CtBeyDNsi4wMYUIbjUtMs4RgAuyft0EKLoVw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex-xs": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unimport": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/unimport/-/unimport-4.2.0.tgz",
|
||||
|
|
@ -5674,6 +6197,21 @@
|
|||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-intl": {
|
||||
"version": "6.5.25",
|
||||
"resolved": "https://registry.npmjs.org/vue-intl/-/vue-intl-6.5.25.tgz",
|
||||
"integrity": "sha512-r7mcl9O/sNF+k+pqiHW+Zu2dbxF7XkME4+cQz5JiZTGJAPRMWX1l5WIELE63/CAxV6EU3CfcryE+r98rYidJlA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.26.10",
|
||||
"@formatjs/icu-messageformat-parser": "2.11.2",
|
||||
"@formatjs/intl": "3.1.6",
|
||||
"tslib": "^2.8.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.5.12"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-router": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build --force",
|
||||
"lint": "eslint . --fix",
|
||||
"openapi-generate": "npx tsx ./openapi-generator.mts"
|
||||
"openapi-generate": "npx tsx ./openapi-generator.mts",
|
||||
"i18n-extract": "formatjs extract \"src/**/*.{ts,tsx,vue}\" --ignore=\"**/*.d.ts\" --out-file src/i18n/en.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pinia/colada": "^0.16.1",
|
||||
|
|
@ -21,10 +22,12 @@
|
|||
"openapi-fetch": "^0.14.0",
|
||||
"pinia-plugin-persistedstate": "^4.3.0",
|
||||
"vue": "^3.5.14",
|
||||
"vue-intl": "^6.5.25",
|
||||
"vuetify": "^3.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.27.0",
|
||||
"@formatjs/cli": "^6.7.1",
|
||||
"@mdi/font": "7.4.47",
|
||||
"@tsconfig/node22": "^22.0.2",
|
||||
"@types/node": "^22.15.21",
|
||||
|
|
@ -32,6 +35,7 @@
|
|||
"@vue/eslint-config-typescript": "^14.1.3",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"eslint": "^9.27.0",
|
||||
"eslint-plugin-formatjs": "^5.3.1",
|
||||
"eslint-plugin-vue": "^10.1.0",
|
||||
"npm-run-all2": "^8.0.3",
|
||||
"openapi-typescript": "^7.8.0",
|
||||
|
|
|
|||
4
next-ui/src/components.d.ts
vendored
4
next-ui/src/components.d.ts
vendored
|
|
@ -25,11 +25,11 @@ declare module 'vue' {
|
|||
DialogConfirmEdit: typeof import('./components/dialogs/DialogConfirmEdit.vue')['default']
|
||||
FormUserChangePassword: typeof import('./components/forms/user/FormUserChangePassword.vue')['default']
|
||||
FormUserEdit: typeof import('./components/forms/user/FormUserEdit.vue')['default']
|
||||
FormUserRoles: typeof import('./components/forms/user/FormUserRoles.vue')['default']
|
||||
HelloWorld: typeof import('./components/HelloWorld.vue')['default']
|
||||
LocaleSelector: typeof import('./components/LocaleSelector.vue')['default']
|
||||
LoginForm: typeof import('./components/LoginForm.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
ThemeSelector: typeof import('./components/app/bar/ThemeSelector.vue')['default']
|
||||
ThemeSelector: typeof import('./components/ThemeSelector.vue')['default']
|
||||
}
|
||||
}
|
||||
|
|
|
|||
53
next-ui/src/components/LocaleSelector.vue
Normal file
53
next-ui/src/components/LocaleSelector.vue
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<template>
|
||||
<v-menu>
|
||||
<template #activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
icon="mdi-translate"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<v-list
|
||||
:selected="[currentLocale]"
|
||||
color="primary"
|
||||
>
|
||||
<v-list-subheader
|
||||
title="Translations"
|
||||
class="text-high-emphasis text-uppercase font-weight-black"
|
||||
/>
|
||||
|
||||
<v-list-item
|
||||
v-for="locale in locales"
|
||||
:key="locale.value"
|
||||
:title="locale.title"
|
||||
:value="locale.value"
|
||||
@click="setLocale(locale.value)"
|
||||
/>
|
||||
|
||||
<v-list-item
|
||||
href="https://hosted.weblate.org/projects/komga/webui/"
|
||||
target="_blank"
|
||||
>
|
||||
<v-list-item-title class="font-weight-bold">
|
||||
Help translate
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {availableLocales, currentLocale, setLocale} from '@/utils/locale-helper.ts'
|
||||
|
||||
const locales = Object.entries(availableLocales).map(([k, v]) => ({
|
||||
title: v,
|
||||
value: k,
|
||||
}))
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
|
@ -7,12 +7,16 @@
|
|||
/>
|
||||
</template>
|
||||
|
||||
<v-list>
|
||||
<v-list
|
||||
:selected="[appStore.theme]"
|
||||
color="primary"
|
||||
>
|
||||
<v-list-item
|
||||
v-for="theme in themes"
|
||||
:key="theme.value"
|
||||
:prepend-icon="theme.icon"
|
||||
:title="theme.title"
|
||||
:value="theme.value"
|
||||
@click="appStore.theme = theme.value"
|
||||
/>
|
||||
</v-list>
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
</RouterLink>
|
||||
Komga
|
||||
</v-app-bar-title>
|
||||
<LocaleSelector />
|
||||
<ThemeSelector />
|
||||
</v-app-bar>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -28,8 +28,17 @@
|
|||
/>
|
||||
<v-list-item
|
||||
to="/server/settings"
|
||||
title="Settings"
|
||||
/>
|
||||
>
|
||||
<v-list-item-title>
|
||||
{{
|
||||
$formatMessage({
|
||||
description: 'Drawer menu for Server Settings',
|
||||
defaultMessage: 'Settings',
|
||||
id: '9yKJ2S'
|
||||
})
|
||||
}}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
to="/server/ui"
|
||||
title="User Interface"
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<v-text-field
|
||||
v-model="confirmPassword"
|
||||
class="mt-2"
|
||||
:rules="[rules.sameAs(newPassword)]"
|
||||
:rules="[rules.sameAs(newPassword, 'Passwords must be identical')]"
|
||||
label="Confirm password"
|
||||
autocomplete="off"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
|
|
|
|||
10
next-ui/src/i18n/en.json
Normal file
10
next-ui/src/i18n/en.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"9yKJ2S": {
|
||||
"defaultMessage": "Settings",
|
||||
"description": "Drawer menu for Server Settings"
|
||||
},
|
||||
"localename": {
|
||||
"defaultMessage": "English",
|
||||
"description": "The name of the locale, shown in the language selection menu. Must be translated to the language's name"
|
||||
}
|
||||
}
|
||||
10
next-ui/src/i18n/fr.json
Normal file
10
next-ui/src/i18n/fr.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"9yKJ2S": {
|
||||
"defaultMessage": "Réglages",
|
||||
"description": "Drawer menu for Server Settings"
|
||||
},
|
||||
"localename": {
|
||||
"defaultMessage": "Français",
|
||||
"description": "The name of the locale, shown in the language selection menu. Must be translated to the language's name"
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import pinia from '../stores'
|
|||
import router from '../router'
|
||||
import {PiniaColada} from '@pinia/colada'
|
||||
import { PiniaColadaAutoRefetch } from '@pinia/colada-plugin-auto-refetch'
|
||||
import {vueIntl} from '@/plugins/vue-intl.ts'
|
||||
|
||||
// Types
|
||||
import type {App} from 'vue'
|
||||
|
|
@ -21,6 +22,7 @@ export function registerPlugins(app: App) {
|
|||
app
|
||||
.use(vuetify)
|
||||
.use(vuetifyRulesPlugin)
|
||||
.use(vueIntl)
|
||||
// .use(DataLoaderPlugin, {router})
|
||||
.use(router)
|
||||
.use(pinia)
|
||||
|
|
|
|||
10
next-ui/src/plugins/vue-intl.ts
Normal file
10
next-ui/src/plugins/vue-intl.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import {createIntl} from 'vue-intl'
|
||||
import {currentLocale, defaultLocale, loadLocale} from '@/utils/locale-helper.ts'
|
||||
|
||||
const messages = await loadLocale(currentLocale)
|
||||
|
||||
export const vueIntl = createIntl({
|
||||
locale: currentLocale,
|
||||
defaultLocale: defaultLocale,
|
||||
messages
|
||||
})
|
||||
|
|
@ -48,7 +48,7 @@ export const vuetify = createVuetify({
|
|||
export const vuetifyRulesPlugin = createRulesPlugin({
|
||||
aliases: {
|
||||
sameAs: (other?: string, err?: string) => {
|
||||
return (v: unknown) => other === v || err || 'Field must be same'
|
||||
return (v: unknown) => other === v || err || 'Field must have the same value'
|
||||
},
|
||||
},
|
||||
}, vuetify.locale)
|
||||
|
|
|
|||
63
next-ui/src/utils/locale-helper.ts
Normal file
63
next-ui/src/utils/locale-helper.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import {defineMessage} from 'vue-intl'
|
||||
|
||||
export const defaultLocale = 'en'
|
||||
|
||||
const localeName = defineMessage({
|
||||
description: 'The name of the locale, shown in the language selection menu. Must be translated to the language\'s name',
|
||||
defaultMessage: 'English',
|
||||
id: 'localename'
|
||||
})
|
||||
|
||||
/**
|
||||
* Loads messages from a translation file by its locale code.
|
||||
* If the translation file does not exist, loads the `defaultLocale` instead.
|
||||
* @param locale the locale code, e.g. 'fr'
|
||||
*/
|
||||
export async function loadLocale(locale: string) {
|
||||
const localeToLoad = locale in availableLocales ? locale : defaultLocale
|
||||
const { default: messages } = await import(`@/i18n/${localeToLoad}.json`);
|
||||
return messages;
|
||||
}
|
||||
|
||||
async function loadAvailableLocales(): Promise<Record<string, string>> {
|
||||
const localeFiles = import.meta.glob('@/i18n/*.json')
|
||||
const locales: Record<string, string> = {}
|
||||
for (const path in localeFiles) {
|
||||
const matched = path.match(/([A-Za-z0-9-_]+)\./i)
|
||||
if (matched && matched.length > 1) {
|
||||
const locale = matched[1]
|
||||
const messages = await localeFiles[path]!() as Record<string, {defaultMessage: string}>
|
||||
locales[locale!] = messages[localeName.id]!.defaultMessage
|
||||
}
|
||||
}
|
||||
return locales
|
||||
}
|
||||
|
||||
/**
|
||||
* Available locales loaded from translation files.
|
||||
* Key is the locale code (e.g. 'fr')
|
||||
* Value is the locale name in its own locale (e.g. 'Français')
|
||||
*/
|
||||
export const availableLocales = await loadAvailableLocales()
|
||||
|
||||
/**
|
||||
* Gets the saved locale from localStorage.
|
||||
* If the locale is not valid, defaults to 'en'.
|
||||
*/
|
||||
function getLocale(): string {
|
||||
const storageLocale = localStorage.getItem('userLocale') ?? defaultLocale
|
||||
return storageLocale in availableLocales ? storageLocale : defaultLocale
|
||||
}
|
||||
|
||||
export const currentLocale = getLocale()
|
||||
|
||||
/**
|
||||
* Save the locale to localStorage and reloads the window if it has changed.
|
||||
* @param locale the new locale
|
||||
*/
|
||||
export function setLocale(locale: string) {
|
||||
if(locale !== currentLocale) {
|
||||
localStorage.setItem('userLocale', locale)
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue