From b960b570a531b64c1f4b096a6a0c62a30c2ef916 Mon Sep 17 00:00:00 2001 From: Bainianzzz <3036349123@qq.com> Date: Wed, 15 Apr 2026 02:12:24 +0800 Subject: [PATCH 1/3] opt: refine questions - add RBTI up to 18 with for options - add en for questions and text (vue-i18n) --- package-lock.json | 644 +++++++++++++++++++++++++++++++++ package.json | 2 + src/data/pets.ts | 253 +++++++------ src/data/questions.ts | 156 ++++++-- src/i18n/index.ts | 16 + src/locales/questions/en-US.ts | 168 +++++++++ src/locales/questions/zh-CN.ts | 168 +++++++++ src/locales/text/en-US.ts | 126 +++++++ src/locales/text/zh-CN.ts | 126 +++++++ src/main.ts | 2 + src/types/index.ts | 14 +- src/views/Quiz.vue | 20 +- src/views/Result.vue | 54 +-- 13 files changed, 1562 insertions(+), 187 deletions(-) create mode 100644 src/i18n/index.ts create mode 100644 src/locales/questions/en-US.ts create mode 100644 src/locales/questions/zh-CN.ts create mode 100644 src/locales/text/en-US.ts create mode 100644 src/locales/text/zh-CN.ts diff --git a/package-lock.json b/package-lock.json index e3eb2b8..a43f7bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "lucide-vue-next": "^1.0.0", "pinia": "^3.0.4", "vue": "^3.5.31", + "vue-i18n": "^11.3.2", "vue-router": "^5.0.4" }, "devDependencies": { @@ -34,6 +35,7 @@ "npm-run-all2": "^8.0.4", "oxlint": "~1.57.0", "prettier": "3.8.1", + "sharp": "^0.34.5", "tailwindcss": "^4.2.2", "typescript": "~6.0.0", "vite": "^7.3.2", @@ -643,6 +645,17 @@ "node": ">=20.19.0" } }, + "node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.7", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", @@ -1236,6 +1249,557 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@intlify/core-base": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.3.2.tgz", + "integrity": "sha512-cgsUaV/dyD6aS49UPgerIblrWeXAZHNaDWqm4LujOGC7IafSyhghGXEiSVvuDYaDPiQTP+tSFSTM1HIu7Yp1nA==", + "license": "MIT", + "dependencies": { + "@intlify/devtools-types": "11.3.2", + "@intlify/message-compiler": "11.3.2", + "@intlify/shared": "11.3.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/devtools-types": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/@intlify/devtools-types/-/devtools-types-11.3.2.tgz", + "integrity": "sha512-q96G2ZZw0FNoXzejbjIf9dbfgz1xyYBZu6ZT4b5TE/55j8d1O9X5jv0k+U+L3fVe7uebPcqRQFD0ffm30i5mJA==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.3.2", + "@intlify/shared": "11.3.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.3.2.tgz", + "integrity": "sha512-d/awyHUkNSaGPxBxT/qlUpfRizxHX9dt55CnW03xx5p1KmMyfYHKupCnvzINX+Na8JR8LAR7y32lPKjoeQGmzA==", + "license": "MIT", + "dependencies": { + "@intlify/shared": "11.3.2", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.3.2.tgz", + "integrity": "sha512-x66fjdH6i+lNYPae5URSQGTjBL68Av6hi09jvC5Ci96iTkwfqrPhCj46aylQZmgMaG89rOZCIKqS7ApC8ZDVjg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "dev": true, @@ -5462,6 +6026,51 @@ "node": ">=10" } }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "dev": true, @@ -5793,6 +6402,14 @@ "typescript": ">=4.8.4" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, "node_modules/type-check": { "version": "0.4.0", "dev": true, @@ -6324,6 +6941,33 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/vue-i18n": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.3.2.tgz", + "integrity": "sha512-gmFrvM+iuf2AH4ygligw/pC7PRJ63AdRNE68E0GPlQ83Mzfyck6g6cRQC3KzkYXr+ZidR91wq+5YBmAMpkgE1A==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.3.2", + "@intlify/devtools-types": "11.3.2", + "@intlify/shared": "11.3.2", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-i18n/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, "node_modules/vue-router": { "version": "5.0.4", "license": "MIT", diff --git a/package.json b/package.json index f3fb18a..20b4f63 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "lucide-vue-next": "^1.0.0", "pinia": "^3.0.4", "vue": "^3.5.31", + "vue-i18n": "^11.3.2", "vue-router": "^5.0.4" }, "devDependencies": { @@ -42,6 +43,7 @@ "npm-run-all2": "^8.0.4", "oxlint": "~1.57.0", "prettier": "3.8.1", + "sharp": "^0.34.5", "tailwindcss": "^4.2.2", "typescript": "~6.0.0", "vite": "^7.3.2", diff --git a/src/data/pets.ts b/src/data/pets.ts index 050e36a..f88c0c9 100644 --- a/src/data/pets.ts +++ b/src/data/pets.ts @@ -3,182 +3,211 @@ import type { RocoPet } from '@/types' const getWikiPortraitUrl = (petName: string): string => `https://wiki.biligame.com/rocom/index.php?title=Special:FilePath/${encodeURIComponent(`页面_宠物_立绘_${petName}_1.png`)}` +const PET_NAME = { + 'pets.INTJ.name': '冥暗幽王', + 'pets.INTP.name': '机械方方', + 'pets.ENTJ.name': '烈火战神', + 'pets.ENTP.name': '瓦斯叮当', + 'pets.INFJ.name': '圣水守护', + 'pets.INFP.name': '魔力猫', + 'pets.ENFJ.name': '迪莫', + 'pets.ENFP.name': '蹦蹦花', + 'pets.ISTJ.name': '罗隐', + 'pets.ISFJ.name': '护主犬', + 'pets.ESTJ.name': '皇家狮鹫', + 'pets.ESFJ.name': '格兰球', + 'pets.ISTP.name': '酷拉', + 'pets.ISFP.name': '雪影娃娃', + 'pets.ESTP.name': '音速犬', + 'pets.ESFP.name': '呱呱', +} + +const isPetNameKey = (nameKey: string) => nameKey in PET_NAME + +const getWikiNameByNameKey = (nameKey: keyof typeof PET_NAME): string => + isPetNameKey(nameKey) ? PET_NAME[nameKey] : '' + +const getWikiPageUrlByNameKey = (nameKey: keyof typeof PET_NAME): string => + `https://wiki.biligame.com/rocom/${encodeURIComponent(getWikiNameByNameKey(nameKey))}` + +const getWikiPortraitUrlByNameKey = (nameKey: keyof typeof PET_NAME): string => getWikiPortraitUrl(getWikiNameByNameKey(nameKey)) + export const pets: RocoPet[] = [ { id: 'pet-intj', - name: '迪莫', + nameKey: 'pets.INTJ.name', mbti: 'INTJ', - title: '永远的伙伴', - stats: { hp: 82, atk: 88, def: 92, spAtk: 110, spDef: 96, speed: 85 }, - description: '图鉴编号 NO001,光系代表精灵,适合作为沉稳策略型人格映射。', - wikiUrl: 'https://wiki.biligame.com/rocom/迪莫', - habitat: '叽叽喳喳台地', - imageUrl: getWikiPortraitUrl('迪莫'), + titleKey: 'pets.INTJ.title', + descriptionKey: 'pets.INTJ.description', + habitatKey: 'pets.INTJ.habitat', + wikiName: getWikiNameByNameKey('pets.INTJ.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.INTJ.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.INTJ.name'), }, { id: 'pet-intp', - name: '菊花梨', + nameKey: 'pets.INTP.name', mbti: 'INTP', - title: '图鉴研究者', - stats: { hp: 76, atk: 70, def: 78, spAtk: 116, spDef: 101, speed: 99 }, - description: '来自精灵图鉴的真实词条,用于表现探索中的分析与推演倾向。', - wikiUrl: 'https://wiki.biligame.com/rocom/菊花梨', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('菊花梨'), + titleKey: 'pets.INTP.title', + descriptionKey: 'pets.INTP.description', + habitatKey: 'pets.INTP.habitat', + wikiName: getWikiNameByNameKey('pets.INTP.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.INTP.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.INTP.name'), }, { id: 'pet-entj', - name: '立方人', + nameKey: 'pets.ENTJ.name', mbti: 'ENTJ', - title: '几何指挥官', - stats: { hp: 95, atk: 112, def: 85, spAtk: 96, spDef: 82, speed: 90 }, - description: '图鉴中的经典精灵形象,映射强组织与高执行的队伍领袖风格。', - wikiUrl: 'https://wiki.biligame.com/rocom/立方人', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('立方人'), + titleKey: 'pets.ENTJ.title', + descriptionKey: 'pets.ENTJ.description', + habitatKey: 'pets.ENTJ.habitat', + wikiName: getWikiNameByNameKey('pets.ENTJ.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ENTJ.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ENTJ.name'), }, { id: 'pet-entp', - name: '龙鱼', + nameKey: 'pets.ENTP.name', mbti: 'ENTP', - title: '灵感破局者', - stats: { hp: 80, atk: 92, def: 74, spAtk: 108, spDef: 76, speed: 118 }, - description: '精灵图鉴词条中高人气宠物,适配灵活应变和创意驱动人格。', - wikiUrl: 'https://wiki.biligame.com/rocom/龙鱼', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('龙鱼'), + titleKey: 'pets.ENTP.title', + descriptionKey: 'pets.ENTP.description', + habitatKey: 'pets.ENTP.habitat', + wikiName: getWikiNameByNameKey('pets.ENTP.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ENTP.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ENTP.name'), }, { id: 'pet-infj', - name: '多灵主', + nameKey: 'pets.INFJ.name', mbti: 'INFJ', - title: '灵魂共鸣', - stats: { hp: 92, atk: 72, def: 88, spAtk: 99, spDef: 114, speed: 79 }, - description: '图鉴收录精灵,多重人格融合感强,适配洞察与共情型人格。', - wikiUrl: 'https://wiki.biligame.com/rocom/多灵主', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('多灵主'), + titleKey: 'pets.INFJ.title', + descriptionKey: 'pets.INFJ.description', + habitatKey: 'pets.INFJ.habitat', + wikiName: getWikiNameByNameKey('pets.INFJ.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.INFJ.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.INFJ.name'), }, { id: 'pet-infp', - name: '小皮球', + nameKey: 'pets.INFP.name', mbti: 'INFP', - title: '柔韧旅者', - stats: { hp: 84, atk: 64, def: 77, spAtk: 106, spDef: 112, speed: 87 }, - description: '来自精灵图鉴的宠物名称,呈现温和而富有想象力的探索方式。', - wikiUrl: 'https://wiki.biligame.com/rocom/小皮球', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('小皮球'), + titleKey: 'pets.INFP.title', + descriptionKey: 'pets.INFP.description', + habitatKey: 'pets.INFP.habitat', + wikiName: getWikiNameByNameKey('pets.INFP.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.INFP.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.INFP.name'), }, { id: 'pet-enfj', - name: '健猫教练', + nameKey: 'pets.ENFJ.name', mbti: 'ENFJ', - title: '团队教练', - stats: { hp: 90, atk: 86, def: 83, spAtk: 104, spDef: 100, speed: 98 }, - description: '图鉴中具备鲜明协作氛围的精灵名,映射高同理与引导能力。', - wikiUrl: 'https://wiki.biligame.com/rocom/健猫教练', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('健猫教练'), + titleKey: 'pets.ENFJ.title', + descriptionKey: 'pets.ENFJ.description', + habitatKey: 'pets.ENFJ.habitat', + wikiName: getWikiNameByNameKey('pets.ENFJ.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ENFJ.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ENFJ.name'), }, { id: 'pet-enfp', - name: '酷拉', + nameKey: 'pets.ENFP.name', mbti: 'ENFP', - title: '节奏点燃者', - stats: { hp: 78, atk: 84, def: 70, spAtk: 96, spDef: 74, speed: 122 }, - description: '来自图鉴词条,风格张扬灵活,适配高外向与高创造型人格。', - wikiUrl: 'https://wiki.biligame.com/rocom/酷拉', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('酷拉'), + titleKey: 'pets.ENFP.title', + descriptionKey: 'pets.ENFP.description', + habitatKey: 'pets.ENFP.habitat', + wikiName: getWikiNameByNameKey('pets.ENFP.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ENFP.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ENFP.name'), }, { id: 'pet-istj', - name: '鳗尾兽', + nameKey: 'pets.ISTJ.name', mbti: 'ISTJ', - title: '秩序守线', - stats: { hp: 102, atk: 95, def: 118, spAtk: 62, spDef: 101, speed: 54 }, - description: '图鉴精灵名,用于表现流程优先、稳定推进的执行人格。', - wikiUrl: 'https://wiki.biligame.com/rocom/鳗尾兽', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('鳗尾兽'), + titleKey: 'pets.ISTJ.title', + descriptionKey: 'pets.ISTJ.description', + habitatKey: 'pets.ISTJ.habitat', + wikiName: getWikiNameByNameKey('pets.ISTJ.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ISTJ.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ISTJ.name'), }, { id: 'pet-isfj', - name: '闪电鳗鱼', + nameKey: 'pets.ISFJ.name', mbti: 'ISFJ', - title: '守护支援', - stats: { hp: 96, atk: 68, def: 104, spAtk: 82, spDef: 112, speed: 66 }, - description: '引用精灵图鉴中的命名,强调稳定、谨慎与持续辅助能力。', - wikiUrl: 'https://wiki.biligame.com/rocom/闪电鳗鱼', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('闪电鳗鱼'), + titleKey: 'pets.ISFJ.title', + descriptionKey: 'pets.ISFJ.description', + habitatKey: 'pets.ISFJ.habitat', + wikiName: getWikiNameByNameKey('pets.ISFJ.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ISFJ.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ISFJ.name'), }, { id: 'pet-estj', - name: '彩蝶鲨', + nameKey: 'pets.ESTJ.name', mbti: 'ESTJ', - title: '阵地统筹', - stats: { hp: 108, atk: 116, def: 109, spAtk: 55, spDef: 88, speed: 60 }, - description: '图鉴真实精灵名,映射重目标和高纪律性的决策风格。', - wikiUrl: 'https://wiki.biligame.com/rocom/彩蝶鲨', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('彩蝶鲨'), + titleKey: 'pets.ESTJ.title', + descriptionKey: 'pets.ESTJ.description', + habitatKey: 'pets.ESTJ.habitat', + wikiName: getWikiNameByNameKey('pets.ESTJ.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ESTJ.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ESTJ.name'), }, { id: 'pet-esfj', - name: '卷毛鸭', + nameKey: 'pets.ESFJ.name', mbti: 'ESFJ', - title: '协同应援', - stats: { hp: 88, atk: 72, def: 84, spAtk: 94, spDef: 102, speed: 92 }, - description: '取自精灵图鉴的角色,用于表达高社交和团队情绪连接。', - wikiUrl: 'https://wiki.biligame.com/rocom/卷毛鸭', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('卷毛鸭'), + titleKey: 'pets.ESFJ.title', + descriptionKey: 'pets.ESFJ.description', + habitatKey: 'pets.ESFJ.habitat', + wikiName: getWikiNameByNameKey('pets.ESFJ.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ESFJ.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ESFJ.name'), }, { id: 'pet-istp', - name: '熔岩布丁', + nameKey: 'pets.ISTP.name', mbti: 'ISTP', - title: '冷静操作手', - stats: { hp: 83, atk: 120, def: 86, spAtk: 68, spDef: 79, speed: 111 }, - description: '图鉴中常见的实战派精灵名,适配快速判断和极简执行。', - wikiUrl: 'https://wiki.biligame.com/rocom/熔岩布丁', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('熔岩布丁'), + titleKey: 'pets.ISTP.title', + descriptionKey: 'pets.ISTP.description', + habitatKey: 'pets.ISTP.habitat', + wikiName: getWikiNameByNameKey('pets.ISTP.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ISTP.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ISTP.name'), }, { id: 'pet-isfp', - name: '怒目怂猫', + nameKey: 'pets.ISFP.name', mbti: 'ISFP', - title: '感性漫游', - stats: { hp: 86, atk: 89, def: 75, spAtk: 91, spDef: 84, speed: 108 }, - description: '来自精灵图鉴,映射自由探索与审美驱动的行动偏好。', - wikiUrl: 'https://wiki.biligame.com/rocom/怒目怂猫', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('怒目怂猫'), + titleKey: 'pets.ISFP.title', + descriptionKey: 'pets.ISFP.description', + habitatKey: 'pets.ISFP.habitat', + wikiName: getWikiNameByNameKey('pets.ISFP.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ISFP.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ISFP.name'), }, { id: 'pet-estp', - name: '海豹船长', + nameKey: 'pets.ESTP.name', mbti: 'ESTP', - title: '前线破局', - stats: { hp: 91, atk: 124, def: 78, spAtk: 72, spDef: 73, speed: 119 }, - description: '精灵图鉴命名中的高机动角色,适配强行动和临场突破风格。', - wikiUrl: 'https://wiki.biligame.com/rocom/海豹船长', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('海豹船长'), + titleKey: 'pets.ESTP.title', + descriptionKey: 'pets.ESTP.description', + habitatKey: 'pets.ESTP.habitat', + wikiName: getWikiNameByNameKey('pets.ESTP.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ESTP.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ESTP.name'), }, { id: 'pet-esfp', - name: '绅士鸡', + nameKey: 'pets.ESFP.name', mbti: 'ESFP', - title: '舞台焦点', - stats: { hp: 82, atk: 98, def: 71, spAtk: 102, spDef: 77, speed: 124 }, - description: '来自精灵图鉴的代表形象,强调表现力和氛围带动能力。', - wikiUrl: 'https://wiki.biligame.com/rocom/绅士鸡', - habitat: '图鉴记录区域', - imageUrl: getWikiPortraitUrl('绅士鸡'), + titleKey: 'pets.ESFP.title', + descriptionKey: 'pets.ESFP.description', + habitatKey: 'pets.ESFP.habitat', + wikiName: getWikiNameByNameKey('pets.ESFP.name'), + wikiUrl: getWikiPageUrlByNameKey('pets.ESFP.name'), + imageUrl: getWikiPortraitUrlByNameKey('pets.ESFP.name'), }, ] diff --git a/src/data/questions.ts b/src/data/questions.ts index 35675e6..f66b5f7 100644 --- a/src/data/questions.ts +++ b/src/data/questions.ts @@ -3,98 +3,182 @@ import type { Question } from '@/types' export const questions: Question[] = [ { id: 1, - text: '你第一次进入轻风山地时,更想先做什么?', + textKey: 'questions.q1.text', options: [ - { text: '和路过训练师聊天套情报', weights: { E: 2, N: 1 } }, - { text: '先观察地形和可采集资源', weights: { I: 2, S: 1 } }, + { textKey: 'questions.q1.options.a', weights: { E: 2 } }, + { textKey: 'questions.q1.options.b', weights: { E: 1 } }, + { textKey: 'questions.q1.options.c', weights: { I: 1 } }, + { textKey: 'questions.q1.options.d', weights: { I: 2 } }, ], }, { id: 2, - text: '遇到遗迹机关谜题,你会怎么处理?', + textKey: 'questions.q2.text', options: [ - { text: '先按直觉尝试激活组合', weights: { N: 2, P: 1 } }, - { text: '记录线索并按顺序推演', weights: { S: 1, J: 2 } }, + { textKey: 'questions.q2.options.a', weights: { E: 2 } }, + { textKey: 'questions.q2.options.b', weights: { E: 1 } }, + { textKey: 'questions.q2.options.c', weights: { I: 1 } }, + { textKey: 'questions.q2.options.d', weights: { I: 2 } }, ], }, { id: 3, - text: '队友想临时改路线去抓稀有宠物,你会?', + textKey: 'questions.q3.text', options: [ - { text: '支持,临场变化更有惊喜', weights: { P: 2, E: 1 } }, - { text: '先看是否影响主线目标', weights: { J: 2, T: 1 } }, + { textKey: 'questions.q3.options.a', weights: { E: 2 } }, + { textKey: 'questions.q3.options.b', weights: { E: 1 } }, + { textKey: 'questions.q3.options.c', weights: { I: 1 } }, + { textKey: 'questions.q3.options.d', weights: { I: 2 } }, ], }, { id: 4, - text: '在营地分配补给时你更看重?', + textKey: 'questions.q4.text', options: [ - { text: '每个人都能安心继续探索', weights: { F: 2, I: 1 } }, - { text: '按战斗贡献优先分配效率最高', weights: { T: 2, J: 1 } }, + { textKey: 'questions.q4.options.a', weights: { E: 2 } }, + { textKey: 'questions.q4.options.b', weights: { E: 1 } }, + { textKey: 'questions.q4.options.c', weights: { I: 1 } }, + { textKey: 'questions.q4.options.d', weights: { I: 2 } }, ], }, { id: 5, - text: '面对未知天气区域,你会?', + textKey: 'questions.q5.text', options: [ - { text: '凭经验快速试探边界', weights: { S: 1, P: 2 } }, - { text: '先推测气候规律再行动', weights: { N: 2, J: 1 } }, + { textKey: 'questions.q5.options.a', weights: { E: 2 } }, + { textKey: 'questions.q5.options.b', weights: { E: 1 } }, + { textKey: 'questions.q5.options.c', weights: { I: 1 } }, + { textKey: 'questions.q5.options.d', weights: { I: 2 } }, ], }, { id: 6, - text: '你更喜欢哪种探索节奏?', + textKey: 'questions.q6.text', options: [ - { text: '高频互动、一路触发事件', weights: { E: 2, P: 1 } }, - { text: '沉浸探索、稳步推进地图', weights: { I: 2, J: 1 } }, + { textKey: 'questions.q6.options.a', weights: { S: 2 } }, + { textKey: 'questions.q6.options.b', weights: { S: 1 } }, + { textKey: 'questions.q6.options.c', weights: { N: 1 } }, + { textKey: 'questions.q6.options.d', weights: { N: 2 } }, ], }, { id: 7, - text: '发现疑似隐藏剧情 NPC 时,你倾向?', + textKey: 'questions.q7.text', options: [ - { text: '先感受角色动机再选择对话', weights: { F: 2, N: 1 } }, - { text: '先确认奖励与任务收益', weights: { T: 2, S: 1 } }, + { textKey: 'questions.q7.options.a', weights: { S: 2 } }, + { textKey: 'questions.q7.options.b', weights: { S: 1 } }, + { textKey: 'questions.q7.options.c', weights: { N: 1 } }, + { textKey: 'questions.q7.options.d', weights: { N: 2 } }, ], }, { id: 8, - text: '打 Boss 前准备环节你会?', + textKey: 'questions.q8.text', options: [ - { text: '预设站位和技能循环', weights: { J: 2, T: 1 } }, - { text: '保留弹性,视局势临时应变', weights: { P: 2, N: 1 } }, + { textKey: 'questions.q8.options.a', weights: { S: 2 } }, + { textKey: 'questions.q8.options.b', weights: { S: 1 } }, + { textKey: 'questions.q8.options.c', weights: { N: 1 } }, + { textKey: 'questions.q8.options.d', weights: { N: 2 } }, ], }, { id: 9, - text: '当队伍出现分歧时你更可能?', + textKey: 'questions.q9.text', options: [ - { text: '主动发言推动大家达成共识', weights: { E: 2, F: 1 } }, - { text: '先独立思考后给关键建议', weights: { I: 2, T: 1 } }, + { textKey: 'questions.q9.options.a', weights: { S: 2 } }, + { textKey: 'questions.q9.options.b', weights: { S: 1 } }, + { textKey: 'questions.q9.options.c', weights: { N: 1 } }, + { textKey: 'questions.q9.options.d', weights: { N: 2 } }, ], }, { id: 10, - text: '在精灵培养上你更偏好?', + textKey: 'questions.q10.text', options: [ - { text: '依据数值和克制关系精细养成', weights: { S: 2, T: 1 } }, - { text: '根据主题与故事构建队伍', weights: { N: 2, F: 1 } }, + { textKey: 'questions.q10.options.a', weights: { T: 2 } }, + { textKey: 'questions.q10.options.b', weights: { T: 1 } }, + { textKey: 'questions.q10.options.c', weights: { F: 1 } }, + { textKey: 'questions.q10.options.d', weights: { F: 2 } }, ], }, { id: 11, - text: '地图开荒时你习惯?', + textKey: 'questions.q11.text', options: [ - { text: '先清主干线,再补支线', weights: { J: 2, S: 1 } }, - { text: '哪里有趣就先去哪里', weights: { P: 2, E: 1 } }, + { textKey: 'questions.q11.options.a', weights: { T: 2 } }, + { textKey: 'questions.q11.options.b', weights: { T: 1 } }, + { textKey: 'questions.q11.options.c', weights: { F: 1 } }, + { textKey: 'questions.q11.options.d', weights: { F: 2 } }, ], }, { id: 12, - text: '结算时你更在意哪件事?', + textKey: 'questions.q12.text', options: [ - { text: '团队是否玩得开心、彼此认可', weights: { F: 2, E: 1 } }, - { text: '策略是否有效、目标是否达成', weights: { T: 2, I: 1 } }, + { textKey: 'questions.q12.options.a', weights: { T: 2 } }, + { textKey: 'questions.q12.options.b', weights: { T: 1 } }, + { textKey: 'questions.q12.options.c', weights: { F: 1 } }, + { textKey: 'questions.q12.options.d', weights: { F: 2 } }, + ], + }, + { + id: 13, + textKey: 'questions.q13.text', + options: [ + { textKey: 'questions.q13.options.a', weights: { T: 2 } }, + { textKey: 'questions.q13.options.b', weights: { T: 1 } }, + { textKey: 'questions.q13.options.c', weights: { F: 1 } }, + { textKey: 'questions.q13.options.d', weights: { F: 2 } }, + ], + }, + { + id: 14, + textKey: 'questions.q14.text', + options: [ + { textKey: 'questions.q14.options.a', weights: { J: 2 } }, + { textKey: 'questions.q14.options.b', weights: { J: 1 } }, + { textKey: 'questions.q14.options.c', weights: { P: 1 } }, + { textKey: 'questions.q14.options.d', weights: { P: 2 } }, + ], + }, + { + id: 15, + textKey: 'questions.q15.text', + options: [ + { textKey: 'questions.q15.options.a', weights: { J: 2 } }, + { textKey: 'questions.q15.options.b', weights: { J: 1 } }, + { textKey: 'questions.q15.options.c', weights: { P: 1 } }, + { textKey: 'questions.q15.options.d', weights: { P: 2 } }, + ], + }, + { + id: 16, + textKey: 'questions.q16.text', + options: [ + { textKey: 'questions.q16.options.a', weights: { J: 2 } }, + { textKey: 'questions.q16.options.b', weights: { J: 1 } }, + { textKey: 'questions.q16.options.c', weights: { P: 1 } }, + { textKey: 'questions.q16.options.d', weights: { P: 2 } }, + ], + }, + { + id: 17, + textKey: 'questions.q17.text', + options: [ + { textKey: 'questions.q17.options.a', weights: { J: 2 } }, + { textKey: 'questions.q17.options.b', weights: { J: 1 } }, + { textKey: 'questions.q17.options.c', weights: { P: 1 } }, + { textKey: 'questions.q17.options.d', weights: { P: 2 } }, + ], + }, + { + id: 18, + textKey: 'questions.q18.text', + options: [ + { textKey: 'questions.q18.options.a', weights: { J: 2 } }, + { textKey: 'questions.q18.options.b', weights: { J: 1 } }, + { textKey: 'questions.q18.options.c', weights: { P: 1 } }, + { textKey: 'questions.q18.options.d', weights: { P: 2 } }, ], }, ] diff --git a/src/i18n/index.ts b/src/i18n/index.ts new file mode 100644 index 0000000..d86df57 --- /dev/null +++ b/src/i18n/index.ts @@ -0,0 +1,16 @@ +import { createI18n } from 'vue-i18n' + +import enUSQuestions from '@/locales/questions/en-US' +import zhCNQuestions from '@/locales/questions/zh-CN' +import enUSText from '@/locales/text/en-US' +import zhCNText from '@/locales/text/zh-CN' + +export const i18n = createI18n({ + legacy: false, + locale: navigator.language.toLowerCase().startsWith('zh') ? 'zh-CN' : 'en-US', + fallbackLocale: 'zh-CN', + messages: { + 'zh-CN': { ...zhCNText, ...zhCNQuestions }, + 'en-US': { ...enUSText, ...enUSQuestions }, + }, +}) diff --git a/src/locales/questions/en-US.ts b/src/locales/questions/en-US.ts new file mode 100644 index 0000000..9522519 --- /dev/null +++ b/src/locales/questions/en-US.ts @@ -0,0 +1,168 @@ +const enUSQuestions = { + questions: { + q1: { + text: 'On your first day at the Magic Academy, you arrive at a lively plaza. You will:', + options: { + a: 'Greet people enthusiastically and proactively look for adventure partners.', + b: 'Join the crowd and naturally jump into interesting conversations.', + c: 'Avoid the crowded center and explore nearby buildings and shops alone first.', + d: 'Feel drained by the crowd and quickly find a quiet corner to recharge.', + }, + }, + q2: { + text: 'You are incredibly lucky and catch an extremely rare spirit in the wild. You tend to:', + options: { + a: 'Run back to town and show your new partner in a busy area immediately.', + b: 'Contact close friends with a magic communicator and share the joy right away.', + c: 'Keep it as a secret trump card and study its traits in private.', + d: 'Stay in a quiet camp and spend the whole day bonding with it alone.', + }, + }, + q3: { + text: 'The academy is holding its annual grand festival. Your state is:', + options: { + a: 'Excitedly moving through every booth and joining all games and battles.', + b: 'Enjoying the lively vibe with a few familiar friends.', + c: 'Sitting in a side rest area, quietly watching the celebration with a drink.', + d: 'Feeling the festival is too noisy, so you find a quiet rooftop to watch fireworks alone.', + }, + }, + q4: { + text: 'When your expedition meets an unfamiliar mage team in the wild, you will:', + options: { + a: 'Approach openly and exchange danger intel and supply info.', + b: 'Smile and wave politely, then respond warmly if they start talking.', + c: 'Stay alert, nod politely, and pass by quickly.', + d: 'Hide early or detour to avoid any unnecessary interaction.', + }, + }, + q5: { + text: 'What is your usual training atmosphere with your spirit like?', + options: { + a: 'Full of laughter and challenges with many people, like a big magic meetup.', + b: 'Train with one or two skilled partners and exchange practical insights.', + c: 'Find an open space with only you and your spirit, and ignore passersby.', + d: 'Train in a fully hidden mountain or cave, immersed in your own world.', + }, + }, + q6: { + text: 'When learning a brand-new advanced spell, you usually:', + options: { + a: 'Follow the spellbook steps strictly and make every movement precise.', + b: 'Repeat the standard pattern until it becomes reliable muscle memory.', + c: 'After understanding the principle, explore its origin and links to other spells.', + d: 'After grasping the basics, immediately try to improve or reinvent it.', + }, + }, + q7: { + text: 'Exploring a foggy unknown forest, you rely more on:', + options: { + a: 'A detailed parchment map, compass, and physical marks left by predecessors.', + b: 'Careful observation of footprints, broken branches, and subtle sounds.', + c: 'Your first instinct: go where the path feels right.', + d: 'A strange glimmer or mysterious premonition that pulls you off the main route.', + }, + }, + q8: { + text: 'When choosing a long-term partner spirit, you value most:', + options: { + a: 'Its base stats, growth values, and currently learned practical spells.', + b: 'Physical traits (sharp claws, hard shell) and direct combat value.', + c: 'Its unique aura and appearance that fits your personal aesthetics.', + d: 'Its future potential, ancient lore, and a sense of destined soul resonance.', + }, + }, + q9: { + text: 'When you find a damaged magic scroll in ruins, your first focus is:', + options: { + a: 'Which formulas can be used in battle now or sold for a high price.', + b: 'Its material and preservation status to judge immediate practical value.', + c: 'The adventure story of the mage who once wrote it.', + d: 'Its role as a key to lost continental history and ancient mysteries.', + }, + }, + q10: { + text: 'Your spirit is injured and defeated in an important battle. Your first reaction is:', + options: { + a: 'Calmly review the battle and analyze timing and matchup mistakes.', + b: 'Take it to treatment immediately and restore stamina efficiently for the next battle.', + c: 'Feel a little guilty and comfort it with its favorite food.', + d: 'Hold it tightly right away, feeling deep pain and self-blame.', + }, + }, + q11: { + text: 'The academy is forming an elite team against dangerous creatures. Who should lead?', + options: { + a: 'The strongest and most experienced mage with the highest success rate.', + b: 'A very calm, clear-minded person who allocates resources rationally.', + c: 'A friendly person who cares for emotions and keeps morale light.', + d: 'A highly empathetic person who unites everyone and leaves no one behind.', + }, + }, + q12: { + text: 'You find a lost, badly injured “danger-type” spirit in the wild. You will:', + options: { + a: 'Control it and call academy guards immediately due to potential risk.', + b: 'Keep a safe distance and leave some healing potion when safe.', + c: 'See it as a pitiful life and try to soothe it with gentle magic.', + d: 'Approach despite risk and heal it with everything you have.', + }, + }, + q13: { + text: 'A teammate’s low-level mistake puts your team in danger. You will:', + options: { + a: 'Point out the exact mistake seriously and reinforce expedition rules.', + b: 'Take command fast, patch the strategy, then review rationally after.', + c: 'Confirm everyone is safe first, then comfort the teammate gently.', + d: 'Take part of the blame yourself to protect your teammate’s dignity.', + }, + }, + q14: { + text: 'Before exploring a new high-difficulty map on the weekend, you will:', + options: { + a: 'Plan an exact route and prepare antidotes, rations, and counter tools.', + b: 'Check map intel roughly and bring enough basic recovery items.', + c: 'Bring only essentials and gather resources along the way.', + d: 'Head out almost empty, enjoying improvisation in unknown environments.', + }, + }, + q15: { + text: 'Facing many academy daily quests (herbs, letters, etc.), you usually:', + options: { + a: 'Use a daily schedule and clear all quests early with full checklist satisfaction.', + b: 'At least finish the highest-reward quests before resting each day.', + c: 'Do them casually if you happen to pass quest targets.', + d: 'Often forget quests after being distracted by scenery or rare spirits.', + }, + }, + q16: { + text: 'How are items arranged in your spatial magic backpack?', + options: { + a: 'Strictly sorted by type and tier; you can find anything instantly.', + b: 'Roughly categorized (combat on one side, daily items on another).', + c: 'Usually messy; only organize with one-click sort when it is totally full.', + d: 'Always chaotic; you rely on mysterious muscle memory to find items.', + }, + }, + q17: { + text: 'When making a spirit training plan, you tend to:', + options: { + a: 'Create a strict timetable and diet plan, then execute it every day.', + b: 'Set a clear phase goal (for example, this week target) and advance steadily.', + c: 'Skip fixed plans and observe natural growth through real battles.', + d: 'Arrange everything freely by mood and weather of the day.', + }, + }, + q18: { + text: 'Facing a sudden ambush by a powerful creature, your reaction is:', + options: { + a: 'Recall and execute the rehearsed defense plan and standard formation perfectly.', + b: 'Assess power gap quickly and decide to fight with standard tactics or retreat.', + c: 'Scan surroundings for cliffs, rocks, and terrain advantages.', + d: 'Rely on extreme on-the-spot reflexes and improvise miracles in chaos.', + }, + }, + }, +} + +export default enUSQuestions diff --git a/src/locales/questions/zh-CN.ts b/src/locales/questions/zh-CN.ts new file mode 100644 index 0000000..e7cd464 --- /dev/null +++ b/src/locales/questions/zh-CN.ts @@ -0,0 +1,168 @@ +const zhCNQuestions = { + questions: { + q1: { + text: '魔法学院新生报到第一天,来到热闹的广场,你会?', + options: { + a: '热情地向周围人打招呼,主动寻觅志同道合的探险伙伴。', + b: '走到人群中看热闹,如果有有趣的谈话就顺理成章地加入。', + c: '避开拥挤的中心区域,独自先去熟悉周围的建筑和商铺。', + d: '觉得人太多有些消耗精力,迅速穿过广场寻找安静的角落休息。', + }, + }, + q2: { + text: '你在野外极其幸运地捕捉到了一只极为罕见的精灵,你更倾向于?', + options: { + a: '立刻跑回镇上,在人群密集的区域向大家展示你的新搭档。', + b: '马上用魔法通讯装置联络好朋友,分享这份喜悦。', + c: '将其作为秘密底牌,暂时不告诉别人,暗中研究它的特性。', + d: '独自留在静谧的营地里,花一整天时间安静地与它培养感情。', + }, + }, + q3: { + text: '魔法学院正在举办一年一度的盛大庆典,你的状态是?', + options: { + a: '兴致勃勃地穿梭在各个摊位,参与所有的狂欢与对战游戏。', + b: '和几个熟悉的朋友结伴游玩,享受热闹的氛围。', + c: '坐在边缘地带的休息区,喝着饮料安静地看着大家狂欢。', + d: '觉得庆典过于吵闹,找个高处无人打扰的屋顶独自看烟火。', + }, + }, + q4: { + text: '在野外探险遇到其他素不相识的魔法师队伍,你会?', + options: { + a: '大方地迎上前去,主动交流前方的危险情报和物资储备。', + b: '给予友善的微笑并挥手致意,如果对方搭话就热情回应。', + c: '保持基本的警惕,礼貌地点头示意后快速交错而过。', + d: '提前隐蔽起来或主动绕路,完全不想产生任何不必要的交集。', + }, + }, + q5: { + text: '你的精灵训练场通常是怎样的氛围?', + options: { + a: '充满欢声笑语,大家互相挑战,是一场大型的魔法交流会。', + b: '邀请一两把好手共同练习,互相探讨魔法心得。', + c: '找一块空地,只有你和你的精灵,偶尔有路人经过也不在意。', + d: '绝对隐秘的深山或洞穴,完全沉浸在自己的训练世界里。', + }, + }, + q6: { + text: '学习一门全新的高阶魔法时,你通常?', + options: { + a: '严格按照魔法书上的图解步骤,力求施法动作分毫不差。', + b: '反复练习标准范式,直到形成绝对可靠的肌肉记忆。', + c: '听懂原理后,总想探究这门魔法的起源以及与其他魔法的联系。', + d: '刚学个大概,就忍不住尝试加入自己的理解去改良或创造新效果。', + }, + }, + q7: { + text: '在一片迷雾笼罩的未知森林中探险,你更依赖?', + options: { + a: '手中详细的羊皮纸地图、指南针和前人留下的实体标记。', + b: '仔细观察地上的脚印、折断的树枝和周围细微的声音。', + c: '相信自己的第一直觉,觉得哪条路“感觉”对就走哪条。', + d: '被远处一阵奇异的微光或某种莫名的预感吸引,直接偏离主路。', + }, + }, + q8: { + text: '挑选长期陪伴你的搭档精灵时,你最看重?', + options: { + a: '它的基础属性面板、成长数值和目前已经掌握的实用魔法。', + b: '它外表的生理特征(如锋利的爪子或坚硬的甲壳)带来的实战价值。', + c: '它身上散发的独特气质,以及符合你个人审美的外观。', + d: '它未来的无限潜能、背后的古老传说,以及你们灵魂共鸣的宿命感。', + }, + }, + q9: { + text: '面对在遗迹中发现的一本残破魔法卷轴,你首先关注的是?', + options: { + a: '上面具体记载了哪些能立刻用于实战或者卖出高价的配方。', + b: '检查卷轴的材质和保存状态,评估它在当下的实际用途。', + c: '想象当初写下这卷轴的魔法师经历了怎样的冒险故事。', + d: '认为这是解开整个大陆失落历史和远古谜团的一把核心钥匙。', + }, + }, + q10: { + text: '你的精灵在重要的对战中受伤战败,你的第一反应是?', + options: { + a: '冷静复盘战局,分析属性克制问题和魔法释放的时机失误。', + b: '立刻带它去治疗点,用最高效的方式恢复它的体力以便再战。', + c: '感到有些内疚,用它最喜欢的食物来安抚它失落的情绪。', + d: '立刻上前紧紧抱住它,为它受到的伤害感到十分心疼和自责。', + }, + }, + q11: { + text: '学院需要组建一支对抗危险生物的精英小队,你会推荐谁当队长?', + options: { + a: '魔法实力最强、实战经验最丰富、能绝对保证任务成功率的人。', + b: '极其冷静、头脑清晰,能合理分配每一份资源和战利品的人。', + c: '性格随和、能照顾到大家情绪,让队伍氛围保持轻松的人。', + d: '极具同理心、能把大家团结在一起,不抛弃任何一个队员的人。', + }, + }, + q12: { + text: '在野外发现了一只迷路且受重伤的“危险系别”精灵,你会?', + options: { + a: '考虑到它潜在的破坏力,将其控制住并立刻呼叫学院守卫。', + b: '保持安全距离,在不危及自身的前提下留下一点恢复药剂。', + c: '觉得它此刻只是个可怜的生命,尝试用温和的魔法安抚它。', + d: '不顾危险直接靠近它并全力为它疗伤,坚信没有精灵是天生邪恶的。', + }, + }, + q13: { + text: '当你的探险队友因为低级失误导致你们陷入险境时,你会?', + options: { + a: '严肃指出失误的具体原因,强调探险规则,确保下次绝不再犯。', + b: '迅速接管指挥权,改变战术以弥补漏洞,事后再进行理性复盘。', + c: '先确定大家是否安全,然后温和地安慰队友不要过于自责。', + d: '主动把责任揽到自己身上(比如“是我没提醒你”),保护队友的自尊。', + }, + }, + q14: { + text: '周末前往新的高难度地图探索前,你会?', + options: { + a: '提前规划好精确路线,准备好对应环境的解药、干粮和克制道具。', + b: '大致查阅一下地图情报,确保带够了基础的恢复品就出发。', + c: '只带上常用的几样东西,决定在探索过程中边走边收集资源。', + d: '背包空空就跑过去,觉得利用野外未知环境即兴发挥才是探险的乐趣。', + }, + }, + q15: { + text: '面对一堆需要完成的魔法学院日常委托(采药、送信等),你通常?', + options: { + a: '每天按时间表列出清单,早早地全部做完,享受全部打钩的快感。', + b: '至少保证在每天休息前,把收益最高的几个委托稳定完成。', + c: '走到哪里算哪里,如果路上刚好碰到任务目标就顺手做一下。', + d: '经常因为被路边好看的风景或稀有精灵吸引,而彻底忘掉委托。', + }, + }, + q16: { + text: '在你的空间魔法背包里,物品的摆放是怎样的?', + options: { + a: '药水、装备、材料严格按照种类、等级分门别类,闭着眼都能找到。', + b: '大致有个分类(战斗用的放一边,生活用的放另一边)。', + c: '平时乱塞,只有当背包彻底满了装不下时,才会按一下“一键整理”。', + d: '永远是一团乱麻,全凭神奇的肌肉记忆在千百件杂物中翻找需要的道具。', + }, + }, + q17: { + text: '制定精灵的培育计划时,你倾向于?', + options: { + a: '制定极度严格的训练时间表和饮食计划,每天雷打不动地执行。', + b: '设定一个清晰的阶段性目标(例如“本周达到一定水平”),稳步推进。', + c: '没有固定计划,带它去实战中转转,看看它自然成长的方向。', + d: '完全看自己和精灵当天的心情、天气状态,极其随性地安排一天。', + }, + }, + q18: { + text: '面对突如其来的强大生物伏击,你的反应是?', + options: { + a: '迅速回忆并完美执行之前反复演练过的防御预案和标准阵型。', + b: '快速评估敌我实力差距,果断决定是按常规战术迎敌还是撤退。', + c: '视线立刻扫向四周,寻找悬崖、落石等可以利用的地形环境。', + d: '依靠极其变态的临场反应,随手抓起能用的东西或魔法,在混乱中创造奇迹。', + }, + }, + }, +} + +export default zhCNQuestions diff --git a/src/locales/text/en-US.ts b/src/locales/text/en-US.ts new file mode 100644 index 0000000..437e761 --- /dev/null +++ b/src/locales/text/en-US.ts @@ -0,0 +1,126 @@ +const enUSText = { + quiz: { + badgeTitle: 'Roco Personality Mirror', + progressLabel: 'Question {current} / {total}', + }, + result: { + completed: 'Assessment Complete', + restart: 'Restart Quiz', + portraitSource: 'Artwork source: Roco Kingdom World WIKI bestiary entry', + personality: 'Nature', + habitat: 'Habitat', + viewWiki: 'View Wiki', + shareToMoments: 'Share to Moments (copy link)', + githubStar: 'Like it? Give us a Star on GitHub', + copySuccess: 'Share text and link copied', + copyFailed: 'Copy failed, please copy the URL manually', + shareText: 'I got {mbti} in Roco Personality Mirror, and my spirit partner is {petName}!', + personalities: ['Adamant', 'Bold', 'Calm', 'Jolly', 'Relaxed', 'Careful', 'Brave', 'Gentle'], + }, + fallbackPet: { + name: 'Starsea Sentinel', + title: 'Default Personality Mirror', + description: 'Fallback result data for exceptional cases only.', + habitat: 'Starsea Nexus', + }, + pets: { + INTJ: { + name: 'Nether Dark Sovereign', + title: 'Architect', + description: 'Ruler of the shadow realm. Strategic, independent, and calm with strong big-picture control.', + habitat: 'Chatter Plateau', + }, + INTP: { + name: 'Mecha Cubic', + title: 'Logician', + description: 'Full of tech spirit. Obsessed with underlying mechanisms, rational and highly creative.', + habitat: 'Dex Archive Zone', + }, + ENTJ: { + name: 'Blazing War Deity', + title: 'Commander', + description: 'A burning war god. Born leader with power, confidence, and decisive execution.', + habitat: 'Dex Archive Zone', + }, + ENTP: { + name: 'Gas Dingdang', + title: 'Debater', + description: 'Always floating and shifting. Highly agile mind with unpredictable ideas.', + habitat: 'Dex Archive Zone', + }, + INFJ: { + name: 'Sacred Water Guardian', + title: 'Advocate', + description: 'Incarnation of pure water. Deep inner world, steadfast belief, and silent healing.', + habitat: 'Dex Archive Zone', + }, + INFP: { + name: 'Magic Cat', + title: 'Mediator', + description: 'Beloved by the forest. Gentle, natural, and dreamy with a rich inner world.', + habitat: 'Dex Archive Zone', + }, + ENFJ: { + name: 'Dimo', + title: 'Protagonist', + description: 'A light-element icon. Sunny and inspiring, the emotional pillar of a team.', + habitat: 'Dex Archive Zone', + }, + ENFP: { + name: 'Bouncy Bloom', + title: 'Campaigner', + description: 'Always bouncing. Curious, energetic, and full of personal charm.', + habitat: 'Dex Archive Zone', + }, + ISTJ: { + name: 'Luo Yin', + title: 'Logistician', + description: 'Solid as a rock. Reliable and practical, always defending order.', + habitat: 'Dex Archive Zone', + }, + ISFJ: { + name: 'Guardian Hound', + title: 'Defender', + description: 'Absolutely loyal. Warm, caring, and quietly dependable.', + habitat: 'Dex Archive Zone', + }, + ESTJ: { + name: 'Royal Gryphon', + title: 'Executive', + description: 'Majestic royal mount. Highly disciplined and tradition-driven with strong execution.', + habitat: 'Dex Archive Zone', + }, + ESFJ: { + name: 'Gran Ball', + title: 'Consul', + description: 'A national-level support unit. Warm-hearted and dedicated to helping teammates.', + habitat: 'Dex Archive Zone', + }, + ISTP: { + name: 'Kula', + title: 'Virtuoso', + description: 'A lone electric mage. Cool-headed, agile, practical, and calm in crisis.', + habitat: 'Dex Archive Zone', + }, + ISFP: { + name: 'Snowshade Doll', + title: 'Adventurer', + description: 'A spirit of ice and snow. Cool outside, warm inside, with artistic freedom.', + habitat: 'Dex Archive Zone', + }, + ESTP: { + name: 'Sonic Hound', + title: 'Entrepreneur', + description: 'Fast as lightning. Action-driven, challenge-seeking, and battle-focused.', + habitat: 'Dex Archive Zone', + }, + ESFP: { + name: 'Guagua', + title: 'Entertainer', + description: 'A carefree martial artist who brings joy and loves self-expression.', + habitat: 'Dex Archive Zone', + }, + }, +} + +export default enUSText diff --git a/src/locales/text/zh-CN.ts b/src/locales/text/zh-CN.ts new file mode 100644 index 0000000..4310293 --- /dev/null +++ b/src/locales/text/zh-CN.ts @@ -0,0 +1,126 @@ +const zhCNText = { + quiz: { + badgeTitle: '洛克世界人格镜像', + progressLabel: '第 {current} / {total} 题', + }, + result: { + completed: '鉴定完成', + restart: '重新测试', + portraitSource: '立绘来源:洛克王国世界 WIKI 精灵图鉴词条', + personality: '性格', + habitat: '栖息地', + viewWiki: '查看 Wiki 资料', + shareToMoments: '分享到朋友圈(复制链接)', + githubStar: '觉得不错?来 GitHub 点个 Star', + copySuccess: '已复制分享文案与链接', + copyFailed: '复制失败,请手动复制地址栏链接', + shareText: '我在洛克世界人格镜像测出了 {mbti},本命精灵是 {petName}!', + personalities: ['固执', '大胆', '冷静', '开朗', '悠闲', '慎重', '勇敢', '温和'], + }, + fallbackPet: { + name: '星海守望兽', + title: '默认人格镜像', + description: '默认结果数据,仅用于异常兜底展示。', + habitat: '星海中枢', + }, + pets: { + INTJ: { + name: '冥暗幽王', + title: '建筑师', + description: '幽暗空间的统御者。深谋远虑,极其独立,拥有强大的全局掌控力与冷静的头脑。', + habitat: '叽叽喳喳台地', + }, + INTP: { + name: '机械方方', + title: '逻辑学家', + description: '充满科技感。热衷于探索事物运行的底层逻辑和机制,理性、专注且充满创造性。', + habitat: '图鉴记录区域', + }, + ENTJ: { + name: '烈火战神', + title: '指挥官', + description: '燃烧的战神。天生的领袖,充满力量、自信与决断力,能够带领团队冲锋陷阵。', + habitat: '图鉴记录区域', + }, + ENTP: { + name: '瓦斯叮当', + title: '辩论家', + description: '永远在漂浮摇摆。思维极度跳跃,灵活多变,不按常理出牌,总有让人意想不到的点子。', + habitat: '图鉴记录区域', + }, + INFJ: { + name: '圣水守护', + title: '提倡者', + description: '纯净之水的化身。内心深邃,拥有坚定的信仰,默默治愈和守护着整个水之源头。', + habitat: '图鉴记录区域', + }, + INFP: { + name: '魔力猫', + title: '调停者', + description: '森林的宠儿。亲近自然,温柔随性,不喜争斗,内心有着自己丰富且梦幻的小世界。', + habitat: '图鉴记录区域', + }, + ENFJ: { + name: '迪莫', + title: '主人公', + description: '光系的代表。充满阳光与感染力,总是用正能量指引同伴,是团队中的精神支柱。', + habitat: '图鉴记录区域', + }, + ENFP: { + name: '蹦蹦花', + title: '竞选者', + description: '永远在跳跃。活力四射,对世界上的一切充满好奇,热情洋溢且极具个人魅力。', + habitat: '图鉴记录区域', + }, + ISTJ: { + name: '罗隐', + title: '物流师', + description: '坚如磐石。极其可靠、务实,遵循规则与秩序,是无论面对什么冲击都不退缩的坚实后盾。', + habitat: '图鉴记录区域', + }, + ISFJ: { + name: '护主犬', + title: '守卫者', + description: '绝对忠诚。默默付出,总是优先考虑主人的安危,温暖、体贴且值得信赖。', + habitat: '图鉴记录区域', + }, + ESTJ: { + name: '皇家狮鹫', + title: '总经理', + description: '威风凛凛的皇家坐骑。极度自律,尊重传统,执行力极强,维护着天空的秩序。', + habitat: '图鉴记录区域', + }, + ESFJ: { + name: '格兰球', + title: '执政官', + description: '国民级辅助。热心肠,总是积极地为大家提供催眠、寄生等战术支援,极具奉献精神。', + habitat: '图鉴记录区域', + }, + ISTP: { + name: '酷拉', + title: '鉴赏家', + description: '孤傲的电系法师。外表高冷,行动敏捷,崇尚实用主义,能在危机中迅速做出冷静反应。', + habitat: '图鉴记录区域', + }, + ISFP: { + name: '雪影娃娃', + title: '探险家', + description: '冰雪中的精灵。外冷内热,有着独特的审美和艺术气质,喜欢按照自己的节奏自由生活。', + habitat: '图鉴记录区域', + }, + ESTP: { + name: '音速犬', + title: '企业家', + description: '风驰电掣。绝对的行动派,追求速度、激情与挑战,喜欢在实战中解决问题。', + habitat: '图鉴记录区域', + }, + ESFP: { + name: '呱呱', + title: '表演者', + description: '逍遥的武术家。天生的乐天派,喜欢展现自我(比如挖宝、修行),总能给周围带来欢乐。', + habitat: '图鉴记录区域', + }, + }, +} + +export default zhCNText diff --git a/src/main.ts b/src/main.ts index 8999d8a..29ab4db 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,12 +2,14 @@ import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' +import { i18n } from './i18n' import router from './router' import './style.css' const app = createApp(App) app.use(createPinia()) +app.use(i18n) app.use(router) app.mount('#app') diff --git a/src/types/index.ts b/src/types/index.ts index da33687..4d621f4 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -11,21 +11,21 @@ export interface PetStats { export interface RocoPet { id: string - name: string + nameKey: string mbti: string - title: string - stats: PetStats - description: string + titleKey: string + descriptionKey: string + habitatKey: string + wikiName: string wikiUrl: string - habitat: string imageUrl: string } export interface Question { id: number - text: string + textKey: string options: { - text: string + textKey: string weights: Partial> }[] } diff --git a/src/views/Quiz.vue b/src/views/Quiz.vue index 7157cf0..5c5d0b9 100644 --- a/src/views/Quiz.vue +++ b/src/views/Quiz.vue @@ -3,6 +3,7 @@ import { computed, ref, watch } from 'vue' import { useRouter } from 'vue-router' import { useTransition } from '@vueuse/core' import { Sparkles } from 'lucide-vue-next' +import { useI18n } from 'vue-i18n' import { useQuizStore } from '@/stores/quiz' @@ -12,6 +13,7 @@ defineOptions({ const quizStore = useQuizStore() const router = useRouter() +const { t } = useI18n() const direction = ref<'next' | 'prev'>('next') const progressSource = computed(() => quizStore.progress) @@ -38,19 +40,19 @@ const transitionName = computed(() =>