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 @@
+
+
+
+
+
{{ msg }}
+
+ {{ t('greetings.message') }}
+ Vite +
+ Vue 3.
+
+
+
+
+
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
}