diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae3af631..58c53b1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,7 @@ jobs: flag-for-router: ['', '--router'] flag-for-pinia: ['', '--pinia'] flag-for-vitest: ['', '--vitest'] + flag-for-i18n: ['', '--vue-i18n'] # It's quite costly to install Cypress & Playwright even with cache. # Maybe we can split them into another job so that all the projects @@ -68,6 +69,7 @@ jobs: flag-for-e2e: '--cypress' flag-for-eslint: '--eslint' flag-for-devtools: '--devtools' + flag-for-i18n: '--vue-i18n' - node-version: 18 os: macos-latest @@ -79,6 +81,7 @@ jobs: flag-for-e2e: '--cypress' flag-for-eslint: '--eslint' flag-for-devtools: '--devtools' + flag-for-i18n: '--vue-i18n' - node-version: 20 os: ubuntu-latest @@ -90,6 +93,7 @@ jobs: flag-for-e2e: '--cypress' flag-for-eslint: '--eslint' flag-for-devtools: '--devtools' + flag-for-i18n: '--vue-i18n' - node-version: 22 os: ubuntu-latest @@ -101,10 +105,11 @@ jobs: flag-for-e2e: '--cypress' flag-for-eslint: '--eslint' flag-for-devtools: '--devtools' + flag-for-i18n: '--vue-i18n' runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.os == 'windows-latest' }} env: - FEATURE_FLAGS: ${{ matrix.flag-for-ts }} ${{ matrix.flag-for-jsx }} ${{ matrix.flag-for-router }} ${{ matrix.flag-for-pinia }} ${{ matrix.flag-for-vitest }} ${{ matrix.flag-for-e2e }} ${{matrix.flag-for-eslint}} ${{matrix.flag-for-devtools}} + FEATURE_FLAGS: ${{ matrix.flag-for-ts }} ${{ matrix.flag-for-jsx }} ${{ matrix.flag-for-router }} ${{ matrix.flag-for-pinia }} ${{ matrix.flag-for-vitest }} ${{ matrix.flag-for-e2e }} ${{matrix.flag-for-eslint}} ${{matrix.flag-for-devtools}} ${{ matrix.flag-for-i18n }} # Sometimes the Linux runner can't verify Cypress in 30s CYPRESS_VERIFY_TIMEOUT: 60000 steps: diff --git a/__test__/sortDependencies.spec.ts b/__test__/sortDependencies.spec.ts index 29becf4f..9c65287a 100644 --- a/__test__/sortDependencies.spec.ts +++ b/__test__/sortDependencies.spec.ts @@ -20,7 +20,8 @@ describe('sortDependencies', () => { '@vitejs/plugin-vue': '^4.4.0', 'eslint-plugin-cypress': '^2.15.1', 'eslint-plugin-vue': '^9.17.0', - vitest: '^0.34.6' + vitest: '^0.34.6', + 'vue-i18n': '^9.13.1' } } expect(sortDependencies(packageJson)).toStrictEqual({ @@ -40,7 +41,8 @@ describe('sortDependencies', () => { jsdom: '^22.1.0', 'start-server-and-test': '^2.0.1', vite: '^4.4.11', - vitest: '^0.34.6' + vitest: '^0.34.6', + 'vue-i18n': '^9.13.1' } }) }) diff --git a/index.ts b/index.ts index 8e0e55c9..498e69fc 100755 --- a/index.ts +++ b/index.ts @@ -97,7 +97,9 @@ async function init() { 'vue-router': { type: 'boolean' }, router: { type: 'boolean' }, 'vue-devtools': { type: 'boolean' }, - devtools: { type: 'boolean' } + devtools: { type: 'boolean' }, + 'vue-i18n': { type: 'boolean' }, + i18n: { type: 'boolean' } } as const const { values: argv, positionals } = parseArgs({ @@ -121,7 +123,9 @@ async function init() { argv.playwright ?? argv.eslint ?? argv['eslint-with-prettier'] ?? - (argv.devtools || argv['vue-devtools']) + (argv.devtools || argv['vue-devtools']) ?? + argv['vue-i18n'] ?? + argv.i18n ) === 'boolean' let targetDir = positionals[0] @@ -144,6 +148,7 @@ async function init() { needsEslint?: boolean needsPrettier?: boolean needsDevTools?: boolean + needsVueI18n?: boolean } = {} try { @@ -300,6 +305,14 @@ async function init() { initial: false, active: language.defaultToggleOptions.active, inactive: language.defaultToggleOptions.inactive + }, + { + name: 'needsVueI18n', + type: () => (isFeatureFlagsUsed ? null : 'toggle'), + message: language.needsVueI18n.message, + initial: false, + active: language.defaultToggleOptions.active, + inactive: language.defaultToggleOptions.inactive } ], { @@ -326,7 +339,8 @@ async function init() { needsVitest = argv.vitest || argv.tests, needsEslint = argv.eslint || argv['eslint-with-prettier'], needsPrettier = argv['eslint-with-prettier'], - needsDevTools = argv.devtools || argv['vue-devtools'] + needsDevTools = argv.devtools || argv['vue-devtools'], + needsVueI18n = argv['vue-i18n'] || argv.i18n } = result const { needsE2eTesting } = result @@ -475,6 +489,10 @@ async function init() { if (needsDevTools) { render('config/devtools') } + + if (needsVueI18n) { + render('config/vue-i18n') + } // Render code template. // prettier-ignore const codeTemplate = @@ -489,6 +507,8 @@ async function init() { render('entry/pinia') } else if (needsRouter) { render('entry/router') + } else if (needsVueI18n) { + render('entry/i18n') } else { render('entry/default') } @@ -521,7 +541,7 @@ async function init() { // We try to share as many files between TypeScript and JavaScript as possible. // If that's not possible, we put `.ts` version alongside the `.js` one in the templates. // So after all the templates are rendered, we need to clean up the redundant files. - // (Currently it's only `cypress/plugin/index.ts`, but we might add more in the future.) + // (Currently it's only `cypress/plugin/index.js`, but we might add more in the future.) // (Or, we might completely get rid of the plugins folder as Cypress 10 supports `cypress.config.ts`) if (needsTypeScript) { diff --git a/locales/en-US.json b/locales/en-US.json index 8dc45e43..ed0a783f 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -53,6 +53,9 @@ "needsDevTools": { "message": "Add Vue DevTools 7 extension for debugging? (experimental)" }, + "needsVueI18n": { + "message": "Add Vue I18n for internationalization?" + }, "errors": { "operationCancelled": "Operation cancelled" }, diff --git a/locales/fr-FR.json b/locales/fr-FR.json index 6815e766..1f8a36e3 100644 --- a/locales/fr-FR.json +++ b/locales/fr-FR.json @@ -53,6 +53,9 @@ "needsDevTools": { "message": "Ajouter l'extension Vue DevTools 7 pour le débogage\u00a0? (expérimental)" }, + "needsVueI18n": { + "message": "Ajouter Vue I18n pour l'internationalisation\u00a0?" + }, "errors": { "operationCancelled": "Operation annulée" }, diff --git a/locales/tr-TR.json b/locales/tr-TR.json index 26ea693f..8b212bf1 100644 --- a/locales/tr-TR.json +++ b/locales/tr-TR.json @@ -53,6 +53,9 @@ "needsDevTools": { "message": "Hata ayıklama için Vue DevTools 7 eklentisi eklensin mi? (deneysel)" }, + "needsVueI18n": { + "message": "Uluslararasılaştırma için Vue I18n eklensin mi?" + }, "errors": { "operationCancelled": "İşlem iptal edildi" }, diff --git a/locales/zh-Hans.json b/locales/zh-Hans.json index 1e9a0fc0..c91b9bb6 100644 --- a/locales/zh-Hans.json +++ b/locales/zh-Hans.json @@ -53,6 +53,9 @@ "needsDevTools": { "message": "是否引入 Vue DevTools 7 扩展用于调试? (试验阶段)" }, + "needsVueI18n": { + "message": "是否引入 Vue I18n 用于国际化?" + }, "errors": { "operationCancelled": "操作取消" }, diff --git a/locales/zh-Hant.json b/locales/zh-Hant.json index cab9ca21..75417816 100644 --- a/locales/zh-Hant.json +++ b/locales/zh-Hant.json @@ -57,6 +57,9 @@ "needsDevTools": { "message": "是否引入 Vue DevTools 7 擴充元件以協助偵錯?(試驗性功能)" }, + "needsVueI18n": { + "message": "是否引入 Vue I18n 用於國際化?" + }, "errors": { "operationCancelled": "操作取消" }, diff --git a/package.json b/package.json index 9464c950..8bdf1b9b 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,8 @@ "prettier": "^3.3.3", "prompts": "^2.4.2", "vitest": "^2.0.5", - "zx": "^8.1.4" + "zx": "^8.1.4", + "vue-i18n": "^9.13.1" }, "lint-staged": { "*.{js,ts,vue,json}": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 71880ff5..a90e9e29 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,9 @@ importers: vitest: specifier: ^2.0.5 version: 2.0.5(@types/node@20.14.15)(jsdom@24.1.1) + vue-i18n: + specifier: ^9.13.1 + version: 9.13.1(vue@3.4.37(typescript@5.5.3)) zx: specifier: ^8.1.4 version: 8.1.4 @@ -197,6 +200,15 @@ importers: specifier: ^2.0.5 version: 2.0.5(@types/node@20.14.15)(jsdom@24.1.1) + template/config/vue-i18n: + dependencies: + vue: + specifier: ^3.4.34 + version: 3.4.34(typescript@5.5.3) + vue-i18n: + specifier: ^9.2.2 + version: 9.13.1(vue@3.4.34(typescript@5.5.3)) + template/tsconfig/base: devDependencies: '@tsconfig/node20': @@ -785,6 +797,18 @@ packages: '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@intlify/core-base@9.13.1': + resolution: {integrity: sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==} + engines: {node: '>= 16'} + + '@intlify/message-compiler@9.13.1': + resolution: {integrity: sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==} + engines: {node: '>= 16'} + + '@intlify/shared@9.13.1': + resolution: {integrity: sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==} + engines: {node: '>= 16'} + '@jridgewell/gen-mapping@0.3.3': resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} @@ -1088,26 +1112,38 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@vue/compiler-core@3.4.35': - resolution: {integrity: sha512-gKp0zGoLnMYtw4uS/SJRRO7rsVggLjvot3mcctlMXunYNsX+aRJDqqw/lV5/gHK91nvaAAlWFgdVl020AW1Prg==} + '@vue/compiler-core@3.4.33': + resolution: {integrity: sha512-MoIREbkdPQlnGfSKDMgzTqzqx5nmEjIc0ydLVYlTACGBsfvOJ4tHSbZXKVF536n6fB+0eZaGEOqsGThPpdvF5A==} + + '@vue/compiler-core@3.4.34': + resolution: {integrity: sha512-Z0izUf32+wAnQewjHu+pQf1yw00EGOmevl1kE+ljjjMe7oEfpQ+BI3/JNK7yMB4IrUsqLDmPecUrpj3mCP+yJQ==} '@vue/compiler-core@3.4.37': resolution: {integrity: sha512-ZDDT/KiLKuCRXyzWecNzC5vTcubGz4LECAtfGPENpo0nrmqJHwuWtRLxk/Sb9RAKtR9iFflFycbkjkY+W/PZUQ==} - '@vue/compiler-dom@3.4.35': - resolution: {integrity: sha512-pWIZRL76/oE/VMhdv/ovZfmuooEni6JPG1BFe7oLk5DZRo/ImydXijoZl/4kh2406boRQ7lxTYzbZEEXEhj9NQ==} + '@vue/compiler-dom@3.4.33': + resolution: {integrity: sha512-GzB8fxEHKw0gGet5BKlpfXEqoBnzSVWwMnT+dc25wE7pFEfrU/QsvjZMP9rD4iVXHBBoemTct8mN0GJEI6ZX5A==} + + '@vue/compiler-dom@3.4.34': + resolution: {integrity: sha512-3PUOTS1h5cskdOJMExCu2TInXuM0j60DRPpSCJDqOCupCfUZCJoyQmKtRmA8EgDNZ5kcEE7vketamRZfrEuVDw==} '@vue/compiler-dom@3.4.37': resolution: {integrity: sha512-rIiSmL3YrntvgYV84rekAtU/xfogMUJIclUMeIKEtVBFngOL3IeZHhsH3UaFEgB5iFGpj6IW+8YuM/2Up+vVag==} - '@vue/compiler-sfc@3.4.35': - resolution: {integrity: sha512-xacnRS/h/FCsjsMfxBkzjoNxyxEyKyZfBch/P4vkLRvYJwe5ChXmZZrj8Dsed/752H2Q3JE8kYu9Uyha9J6PgA==} + '@vue/compiler-sfc@3.4.33': + resolution: {integrity: sha512-7rk7Vbkn21xMwIUpHQR4hCVejwE6nvhBOiDgoBcR03qvGqRKA7dCBSsHZhwhYUsmjlbJ7OtD5UFIyhP6BY+c8A==} + + '@vue/compiler-sfc@3.4.34': + resolution: {integrity: sha512-x6lm0UrM03jjDXTPZgD9Ad8bIVD1ifWNit2EaWQIZB5CULr46+FbLQ5RpK7AXtDHGjx9rmvC7QRCTjsiGkAwRw==} '@vue/compiler-sfc@3.4.37': resolution: {integrity: sha512-vCfetdas40Wk9aK/WWf8XcVESffsbNkBQwS5t13Y/PcfqKfIwJX2gF+82th6dOpnpbptNMlMjAny80li7TaCIg==} - '@vue/compiler-ssr@3.4.35': - resolution: {integrity: sha512-7iynB+0KB1AAJKk/biENTV5cRGHRdbdaD7Mx3nWcm1W8bVD6QmnH3B4AHhQQ1qZHhqFwzEzMwiytXm3PX1e60A==} + '@vue/compiler-ssr@3.4.33': + resolution: {integrity: sha512-0WveC9Ai+eT/1b6LCV5IfsufBZ0HP7pSSTdDjcuW302tTEgoBw8rHVHKPbGUtzGReUFCRXbv6zQDDgucnV2WzQ==} + + '@vue/compiler-ssr@3.4.34': + resolution: {integrity: sha512-8TDBcLaTrFm5rnF+Qm4BlliaopJgqJ28Nsrc80qazynm5aJO+Emu7y0RWw34L8dNnTRdcVBpWzJxhGYzsoVu4g==} '@vue/compiler-ssr@3.4.37': resolution: {integrity: sha512-TyAgYBWrHlFrt4qpdACh8e9Ms6C/AZQ6A6xLJaWrCL8GCX5DxMzxyeFAEMfU/VFr4tylHm+a2NpfJpcd7+20XA==} @@ -1142,22 +1178,39 @@ packages: typescript: optional: true + '@vue/reactivity@3.4.34': + resolution: {integrity: sha512-ua+Lo+wBRlBEX9TtgPOShE2JwIO7p6BTZ7t1KZVPoaBRfqbC7N3c8Mpzicx173fXxx5VXeU6ykiHo7WgLzJQDA==} + '@vue/reactivity@3.4.37': resolution: {integrity: sha512-UmdKXGx0BZ5kkxPqQr3PK3tElz6adTey4307NzZ3whZu19i5VavYal7u2FfOmAzlcDVgE8+X0HZ2LxLb/jgbYw==} + '@vue/runtime-core@3.4.34': + resolution: {integrity: sha512-PXhkiRPwcPGJ1BnyBZFI96GfInCVskd0HPNIAZn7i3YOmLbtbTZpB7/kDTwC1W7IqdGPkTVC63IS7J2nZs4Ebg==} + '@vue/runtime-core@3.4.37': resolution: {integrity: sha512-MNjrVoLV/sirHZoD7QAilU1Ifs7m/KJv4/84QVbE6nyAZGQNVOa1HGxaOzp9YqCG+GpLt1hNDC4RbH+KtanV7w==} + '@vue/runtime-dom@3.4.34': + resolution: {integrity: sha512-dXqIe+RqFAK2Euak4UsvbIupalrhc67OuQKpD7HJ3W2fv8jlqvI7szfBCsAEcE8o/wyNpkloxB6J8viuF/E3gw==} + '@vue/runtime-dom@3.4.37': resolution: {integrity: sha512-Mg2EwgGZqtwKrqdL/FKMF2NEaOHuH+Ks9TQn3DHKyX//hQTYOun+7Tqp1eo0P4Ds+SjltZshOSRq6VsU0baaNg==} + '@vue/server-renderer@3.4.34': + resolution: {integrity: sha512-GeyEUfMVRZMD/mZcNONEqg7MiU10QQ1DB3O/Qr6+8uXpbwdlmVgQ5Qs1/ZUAFX1X2UUtqMoGrDRbxdWfOJFT7Q==} + peerDependencies: + vue: 3.4.34 + '@vue/server-renderer@3.4.37': resolution: {integrity: sha512-jZ5FAHDR2KBq2FsRUJW6GKDOAG9lUTX8aBEGq4Vf6B/35I9fPce66BornuwmqmKgfiSlecwuOb6oeoamYMohkg==} peerDependencies: vue: 3.4.37 - '@vue/shared@3.4.35': - resolution: {integrity: sha512-hvuhBYYDe+b1G8KHxsQ0diDqDMA8D9laxWZhNAjE83VZb5UDaXl9Xnz7cGdDSyiHM90qqI/CyGMcpBpiDy6VVQ==} + '@vue/shared@3.4.33': + resolution: {integrity: sha512-aoRY0jQk3A/cuvdkodTrM4NMfxco8n55eG4H7ML/CRy7OryHfiqvug4xrCBBMbbN+dvXAetDDwZW9DXWWjBntA==} + + '@vue/shared@3.4.34': + resolution: {integrity: sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A==} '@vue/shared@3.4.37': resolution: {integrity: sha512-nIh8P2fc3DflG8+5Uw8PT/1i17ccFn0xxN/5oE9RfV5SVnd7G0XEFRwakrnNFE/jlS95fpGXDVG5zDETS26nmg==} @@ -3014,6 +3067,10 @@ packages: engines: {node: '>=18'} hasBin: true + postcss@8.4.39: + resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} + engines: {node: ^10 || ^12 || >=14} + postcss@8.4.40: resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==} engines: {node: ^10 || ^12 || >=14} @@ -3557,6 +3614,34 @@ packages: terser: optional: true + vite@5.3.5: + resolution: {integrity: sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + vite@5.4.0: resolution: {integrity: sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==} engines: {node: ^18.0.0 || >=20.0.0} @@ -3633,6 +3718,12 @@ packages: '@vue/composition-api': optional: true + vue-i18n@9.13.1: + resolution: {integrity: sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + vue-router@4.4.3: resolution: {integrity: sha512-sv6wmNKx2j3aqJQDMxLFzs/u/mjA9Z5LCgy6BE0f7yFWMjrPLnS/sPNn8ARY/FXw6byV18EFutn5lTO6+UsV5A==} peerDependencies: @@ -3644,6 +3735,14 @@ packages: peerDependencies: typescript: '>=5.0.0' + vue@3.4.34: + resolution: {integrity: sha512-VZze05HWlA3ItreQ/ka7Sx7PoD0/3St8FEiSlSTVgb6l4hL+RjtP2/8g5WQBzZgyf8WG2f+g1bXzC7zggLhAJA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + vue@3.4.37: resolution: {integrity: sha512-3vXvNfkKTBsSJ7JP+LyR7GBuwQuckbWvuwAid3xbqK9ppsKt/DUvfqgZ48fgOLEfpy1IacL5f8QhUVl77RaI7A==} peerDependencies: @@ -3862,7 +3961,7 @@ snapshots: '@babel/traverse': 7.23.3 '@babel/types': 7.23.3 convert-source-map: 2.0.0 - debug: 4.3.6(supports-color@8.1.1) + debug: 4.3.5 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -4131,7 +4230,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.24.7 '@babel/types': 7.24.6 - debug: 4.3.6(supports-color@8.1.1) + debug: 4.3.5 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -4146,7 +4245,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.6 '@babel/parser': 7.24.7 '@babel/types': 7.24.6 - debug: 4.3.6(supports-color@8.1.1) + debug: 4.3.5 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -4348,6 +4447,18 @@ snapshots: dependencies: '@hapi/hoek': 9.3.0 + '@intlify/core-base@9.13.1': + dependencies: + '@intlify/message-compiler': 9.13.1 + '@intlify/shared': 9.13.1 + + '@intlify/message-compiler@9.13.1': + dependencies: + '@intlify/shared': 9.13.1 + source-map-js: 1.2.0 + + '@intlify/shared@9.13.1': {} + '@jridgewell/gen-mapping@0.3.3': dependencies: '@jridgewell/set-array': 1.1.2 @@ -4696,12 +4807,20 @@ snapshots: '@babel/helper-module-imports': 7.22.15 '@babel/helper-plugin-utils': 7.24.0 '@babel/parser': 7.24.7 - '@vue/compiler-sfc': 3.4.35 + '@vue/compiler-sfc': 3.4.33 + + '@vue/compiler-core@3.4.33': + dependencies: + '@babel/parser': 7.24.7 + '@vue/shared': 3.4.33 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.0 - '@vue/compiler-core@3.4.35': + '@vue/compiler-core@3.4.34': dependencies: '@babel/parser': 7.24.7 - '@vue/shared': 3.4.35 + '@vue/shared': 3.4.34 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.0 @@ -4714,26 +4833,43 @@ snapshots: estree-walker: 2.0.2 source-map-js: 1.2.0 - '@vue/compiler-dom@3.4.35': + '@vue/compiler-dom@3.4.33': + dependencies: + '@vue/compiler-core': 3.4.33 + '@vue/shared': 3.4.33 + + '@vue/compiler-dom@3.4.34': dependencies: - '@vue/compiler-core': 3.4.35 - '@vue/shared': 3.4.35 + '@vue/compiler-core': 3.4.34 + '@vue/shared': 3.4.34 '@vue/compiler-dom@3.4.37': dependencies: '@vue/compiler-core': 3.4.37 '@vue/shared': 3.4.37 - '@vue/compiler-sfc@3.4.35': + '@vue/compiler-sfc@3.4.33': dependencies: '@babel/parser': 7.24.7 - '@vue/compiler-core': 3.4.35 - '@vue/compiler-dom': 3.4.35 - '@vue/compiler-ssr': 3.4.35 - '@vue/shared': 3.4.35 + '@vue/compiler-core': 3.4.33 + '@vue/compiler-dom': 3.4.33 + '@vue/compiler-ssr': 3.4.33 + '@vue/shared': 3.4.33 estree-walker: 2.0.2 magic-string: 0.30.10 - postcss: 8.4.40 + postcss: 8.4.39 + source-map-js: 1.2.0 + + '@vue/compiler-sfc@3.4.34': + dependencies: + '@babel/parser': 7.24.7 + '@vue/compiler-core': 3.4.34 + '@vue/compiler-dom': 3.4.34 + '@vue/compiler-ssr': 3.4.34 + '@vue/shared': 3.4.34 + estree-walker: 2.0.2 + magic-string: 0.30.10 + postcss: 8.4.39 source-map-js: 1.2.0 '@vue/compiler-sfc@3.4.37': @@ -4748,10 +4884,15 @@ snapshots: postcss: 8.4.40 source-map-js: 1.2.0 - '@vue/compiler-ssr@3.4.35': + '@vue/compiler-ssr@3.4.33': dependencies: - '@vue/compiler-dom': 3.4.35 - '@vue/shared': 3.4.35 + '@vue/compiler-dom': 3.4.33 + '@vue/shared': 3.4.33 + + '@vue/compiler-ssr@3.4.34': + dependencies: + '@vue/compiler-dom': 3.4.34 + '@vue/shared': 3.4.34 '@vue/compiler-ssr@3.4.37': dependencies: @@ -4800,9 +4941,9 @@ snapshots: '@vue/language-core@2.0.29(typescript@5.5.3)': dependencies: '@volar/language-core': 2.4.0-alpha.18 - '@vue/compiler-dom': 3.4.35 + '@vue/compiler-dom': 3.4.33 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.4.35 + '@vue/shared': 3.4.33 computeds: 0.0.1 minimatch: 9.0.3 muggle-string: 0.4.1 @@ -4810,15 +4951,31 @@ snapshots: optionalDependencies: typescript: 5.5.3 + '@vue/reactivity@3.4.34': + dependencies: + '@vue/shared': 3.4.34 + '@vue/reactivity@3.4.37': dependencies: '@vue/shared': 3.4.37 + '@vue/runtime-core@3.4.34': + dependencies: + '@vue/reactivity': 3.4.34 + '@vue/shared': 3.4.34 + '@vue/runtime-core@3.4.37': dependencies: '@vue/reactivity': 3.4.37 '@vue/shared': 3.4.37 + '@vue/runtime-dom@3.4.34': + dependencies: + '@vue/reactivity': 3.4.34 + '@vue/runtime-core': 3.4.34 + '@vue/shared': 3.4.34 + csstype: 3.1.3 + '@vue/runtime-dom@3.4.37': dependencies: '@vue/reactivity': 3.4.37 @@ -4826,13 +4983,21 @@ snapshots: '@vue/shared': 3.4.37 csstype: 3.1.3 + '@vue/server-renderer@3.4.34(vue@3.4.34(typescript@5.5.3))': + dependencies: + '@vue/compiler-ssr': 3.4.34 + '@vue/shared': 3.4.34 + vue: 3.4.34(typescript@5.5.3) + '@vue/server-renderer@3.4.37(vue@3.4.37(typescript@5.5.3))': dependencies: '@vue/compiler-ssr': 3.4.37 '@vue/shared': 3.4.37 vue: 3.4.37(typescript@5.5.3) - '@vue/shared@3.4.35': {} + '@vue/shared@3.4.33': {} + + '@vue/shared@3.4.34': {} '@vue/shared@3.4.37': {} @@ -4868,7 +5033,7 @@ snapshots: agent-base@7.1.0: dependencies: - debug: 4.3.6(supports-color@8.1.1) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -5967,7 +6132,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.0 - debug: 4.3.6(supports-color@8.1.1) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -5987,7 +6152,7 @@ snapshots: https-proxy-agent@7.0.5: dependencies: agent-base: 7.1.0 - debug: 4.3.6(supports-color@8.1.1) + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -6745,6 +6910,12 @@ snapshots: optionalDependencies: fsevents: 2.3.2 + postcss@8.4.39: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + postcss@8.4.40: dependencies: nanoid: 3.3.7 @@ -7344,7 +7515,7 @@ snapshots: '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.6) '@babel/plugin-transform-typescript': 7.24.6(@babel/core@7.24.6) '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.24.6) - '@vue/compiler-dom': 3.4.35 + '@vue/compiler-dom': 3.4.33 kolorist: 1.8.0 magic-string: 0.30.10 vite: 5.4.0(@types/node@20.14.15) @@ -7354,12 +7525,21 @@ snapshots: vite@4.5.2(@types/node@20.14.15): dependencies: esbuild: 0.18.20 - postcss: 8.4.40 + postcss: 8.4.39 rollup: 3.29.4 optionalDependencies: '@types/node': 20.14.15 fsevents: 2.3.3 + vite@5.3.5(@types/node@20.14.15): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.39 + rollup: 4.13.2 + optionalDependencies: + '@types/node': 20.14.15 + fsevents: 2.3.3 + vite@5.4.0(@types/node@20.14.15): dependencies: esbuild: 0.21.5 @@ -7387,7 +7567,7 @@ snapshots: tinybench: 2.8.0 tinypool: 1.0.0 tinyrainbow: 1.2.0 - vite: 5.4.0(@types/node@20.14.15) + vite: 5.3.5(@types/node@20.14.15) vite-node: 2.0.5(@types/node@20.14.15) why-is-node-running: 2.3.0 optionalDependencies: @@ -7413,6 +7593,20 @@ snapshots: dependencies: vue: 3.4.37(typescript@5.5.3) + vue-i18n@9.13.1(vue@3.4.34(typescript@5.5.3)): + dependencies: + '@intlify/core-base': 9.13.1 + '@intlify/shared': 9.13.1 + '@vue/devtools-api': 6.6.3 + vue: 3.4.34(typescript@5.5.3) + + vue-i18n@9.13.1(vue@3.4.37(typescript@5.5.3)): + dependencies: + '@intlify/core-base': 9.13.1 + '@intlify/shared': 9.13.1 + '@vue/devtools-api': 6.6.3 + vue: 3.4.37(typescript@5.5.3) + vue-router@4.4.3(vue@3.4.37(typescript@5.5.3)): dependencies: '@vue/devtools-api': 6.6.3 @@ -7425,6 +7619,16 @@ snapshots: semver: 7.5.4 typescript: 5.5.3 + vue@3.4.34(typescript@5.5.3): + dependencies: + '@vue/compiler-dom': 3.4.34 + '@vue/compiler-sfc': 3.4.34 + '@vue/runtime-dom': 3.4.34 + '@vue/server-renderer': 3.4.34(vue@3.4.34(typescript@5.5.3)) + '@vue/shared': 3.4.34 + optionalDependencies: + typescript: 5.5.3 + vue@3.4.37(typescript@5.5.3): dependencies: '@vue/compiler-dom': 3.4.37 diff --git a/scripts/snapshot.mjs b/scripts/snapshot.mjs index b80da8e1..79a963c3 100644 --- a/scripts/snapshot.mjs +++ b/scripts/snapshot.mjs @@ -54,18 +54,22 @@ function fullCombination(arr) { } let flagCombinations = fullCombination(featureFlags) + flagCombinations.push( ['default'], ['devtools', 'router', 'pinia'], ['eslint'], - ['eslint-with-prettier'] + ['eslint-with-prettier'], + ['vue-i18n'], + ['vue-i18n', 'typescript'], + ['vue-i18n', 'router', 'pinia'] ) // `--with-tests` are equivalent of `--vitest --cypress` // Previously it means `--cypress` without `--vitest`. // Here we generate the snapshots only for the sake of easier comparison with older templates. // They may be removed in later releases. -const withTestsFlags = fullCombination(['typescript', 'jsx', 'router', 'pinia']).map((args) => [ +const withTestsFlags = fullCombination(['typescript', 'jsx', 'router', 'pinia', 'vue-i18n']).map((args) => [ ...args, 'with-tests' ]) diff --git a/template/code/typescript-i18n/src/components/HelloWorld.vue b/template/code/typescript-i18n/src/components/HelloWorld.vue new file mode 100644 index 00000000..82912b32 --- /dev/null +++ b/template/code/typescript-i18n/src/components/HelloWorld.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/template/code/typescript-i18n/src/i18n/index.ts b/template/code/typescript-i18n/src/i18n/index.ts new file mode 100644 index 00000000..8082b976 --- /dev/null +++ b/template/code/typescript-i18n/src/i18n/index.ts @@ -0,0 +1,13 @@ +import { createI18n } from 'vue-i18n' +import enUS from './locales/en-US.json' + +type MessageSchema = typeof enUS + +const i18n = createI18n<[MessageSchema], 'en-US'>({ + locale: 'en-US', + messages: { + 'en-US': enUS + } +}) + +export default i18n diff --git a/template/code/typescript-i18n/src/i18n/locales/en-US.json b/template/code/typescript-i18n/src/i18n/locales/en-US.json new file mode 100644 index 00000000..6619b046 --- /dev/null +++ b/template/code/typescript-i18n/src/i18n/locales/en-US.json @@ -0,0 +1,5 @@ +{ + "greetings": { + "message": "You've successfully created a project with" + } +} diff --git a/template/config/vue-i18n/package.json b/template/config/vue-i18n/package.json new file mode 100644 index 00000000..c3ad3d65 --- /dev/null +++ b/template/config/vue-i18n/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "vue": "^3.4.34", + "vue-i18n": "^9.2.2" + } +} diff --git a/template/config/vue-i18n/src/i18n/en.json b/template/config/vue-i18n/src/i18n/en.json new file mode 100644 index 00000000..5d72ea76 --- /dev/null +++ b/template/config/vue-i18n/src/i18n/en.json @@ -0,0 +1,5 @@ +{ + "messages": { + "hello": "Hello, {name}!" + } +} diff --git a/template/config/vue-i18n/src/i18n/index.js b/template/config/vue-i18n/src/i18n/index.js new file mode 100644 index 00000000..a326b17e --- /dev/null +++ b/template/config/vue-i18n/src/i18n/index.js @@ -0,0 +1,10 @@ +import { createI18n } from 'vue-i18n' +import enUS from './en.json' + +const i18n = createI18n({ + locale: 'en-US', + messages: { + 'en-US': enUS + } +}) +export default i18n diff --git a/template/entry/i18n/src/main.js b/template/entry/i18n/src/main.js new file mode 100644 index 00000000..13d6ca51 --- /dev/null +++ b/template/entry/i18n/src/main.js @@ -0,0 +1,7 @@ +import { createApp } from 'vue' +import App from './App.vue' +import i18n from './i18n' + +const app = createApp(App) +app.use(i18n) +app.mount('#app') diff --git a/template/entry/pinia-and-i18n/src/main.js b/template/entry/pinia-and-i18n/src/main.js new file mode 100644 index 00000000..1d26532a --- /dev/null +++ b/template/entry/pinia-and-i18n/src/main.js @@ -0,0 +1,9 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' +import i18n from './i18n' + +const app = createApp(App) +app.use(createPinia()) +app.use(i18n) +app.mount('#app') diff --git a/template/entry/router-and-i18n/src/main.js b/template/entry/router-and-i18n/src/main.js new file mode 100644 index 00000000..a62c7d73 --- /dev/null +++ b/template/entry/router-and-i18n/src/main.js @@ -0,0 +1,9 @@ +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' +import i18n from './i18n' + +const app = createApp(App) +app.use(router) +app.use(i18n) +app.mount('#app') diff --git a/template/entry/router-pinia-and-i18n/src/main.js b/template/entry/router-pinia-and-i18n/src/main.js new file mode 100644 index 00000000..d10f08e3 --- /dev/null +++ b/template/entry/router-pinia-and-i18n/src/main.js @@ -0,0 +1,11 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' +import router from './router' +import i18n from './i18n' + +const app = createApp(App) +app.use(createPinia()) +app.use(router) +app.use(i18n) +app.mount('#app') diff --git a/utils/getLanguage.ts b/utils/getLanguage.ts index b3bc8233..5aab2c23 100644 --- a/utils/getLanguage.ts +++ b/utils/getLanguage.ts @@ -31,6 +31,7 @@ interface Language { needsEslint: LanguageItem needsPrettier: LanguageItem needsDevTools: LanguageItem + needsVueI18n: LanguageItem errors: { operationCancelled: string }