Skip to content

Commit 8fbe012

Browse files
authored
feat: i18n solution for prompts messages (vuejs#348)
1 parent 49fd22d commit 8fbe012

File tree

6 files changed

+245
-38
lines changed

6 files changed

+245
-38
lines changed

index.ts

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import renderTemplate from './utils/renderTemplate'
1515
import { postOrderDirectoryTraverse, preOrderDirectoryTraverse } from './utils/directoryTraverse'
1616
import generateReadme from './utils/generateReadme'
1717
import getCommand from './utils/getCommand'
18+
import getLanguage from './utils/getLanguage'
1819
import renderEslint from './utils/renderEslint'
1920
import { FILES_TO_FILTER } from './utils/filterList'
2021

@@ -115,6 +116,8 @@ async function init() {
115116

116117
const forceOverwrite = argv.force
117118

119+
const language = getLanguage()
120+
118121
let result: {
119122
projectName?: string
120123
shouldOverwrite?: boolean
@@ -148,110 +151,118 @@ async function init() {
148151
{
149152
name: 'projectName',
150153
type: targetDir ? null : 'text',
151-
message: 'Project name:',
154+
message: language.projectName.message,
152155
initial: defaultProjectName,
153156
onState: (state) => (targetDir = String(state.value).trim() || defaultProjectName)
154157
},
155158
{
156159
name: 'shouldOverwrite',
157-
type: () => (canSkipEmptying(targetDir) || forceOverwrite ? null : 'confirm'),
160+
type: () => (canSkipEmptying(targetDir) || forceOverwrite ? null : 'toggle'),
158161
message: () => {
159162
const dirForPrompt =
160-
targetDir === '.' ? 'Current directory' : `Target directory "${targetDir}"`
163+
targetDir === '.'
164+
? language.shouldOverwrite.dirForPrompts.current
165+
: `${language.shouldOverwrite.dirForPrompts.target} "${targetDir}"`
161166

162-
return `${dirForPrompt} is not empty. Remove existing files and continue?`
163-
}
167+
return `${dirForPrompt} ${language.shouldOverwrite.message}`
168+
},
169+
initial: true,
170+
active: language.defaultToggleOptions.active,
171+
inactive: language.defaultToggleOptions.inactive
164172
},
165173
{
166174
name: 'overwriteChecker',
167175
type: (prev, values) => {
168176
if (values.shouldOverwrite === false) {
169-
throw new Error(red('✖') + ' Operation cancelled')
177+
throw new Error(red('✖') + ` ${language.errors.operationCancelled}`)
170178
}
171179
return null
172180
}
173181
},
174182
{
175183
name: 'packageName',
176184
type: () => (isValidPackageName(targetDir) ? null : 'text'),
177-
message: 'Package name:',
185+
message: language.packageName.message,
178186
initial: () => toValidPackageName(targetDir),
179187
validate: (dir) => isValidPackageName(dir) || 'Invalid package.json name'
180188
},
181189
{
182190
name: 'needsTypeScript',
183191
type: () => (isFeatureFlagsUsed ? null : 'toggle'),
184-
message: 'Add TypeScript?',
192+
message: language.needsTypeScript.message,
185193
initial: false,
186-
active: 'Yes',
187-
inactive: 'No'
194+
active: language.defaultToggleOptions.active,
195+
inactive: language.defaultToggleOptions.inactive
188196
},
189197
{
190198
name: 'needsJsx',
191199
type: () => (isFeatureFlagsUsed ? null : 'toggle'),
192-
message: 'Add JSX Support?',
200+
message: language.needsJsx.message,
193201
initial: false,
194-
active: 'Yes',
195-
inactive: 'No'
202+
active: language.defaultToggleOptions.active,
203+
inactive: language.defaultToggleOptions.inactive
196204
},
197205
{
198206
name: 'needsRouter',
199207
type: () => (isFeatureFlagsUsed ? null : 'toggle'),
200-
message: 'Add Vue Router for Single Page Application development?',
208+
message: language.needsRouter.message,
201209
initial: false,
202-
active: 'Yes',
203-
inactive: 'No'
210+
active: language.defaultToggleOptions.active,
211+
inactive: language.defaultToggleOptions.inactive
204212
},
205213
{
206214
name: 'needsPinia',
207215
type: () => (isFeatureFlagsUsed ? null : 'toggle'),
208-
message: 'Add Pinia for state management?',
216+
message: language.needsPinia.message,
209217
initial: false,
210-
active: 'Yes',
211-
inactive: 'No'
218+
active: language.defaultToggleOptions.active,
219+
inactive: language.defaultToggleOptions.inactive
212220
},
213221
{
214222
name: 'needsVitest',
215223
type: () => (isFeatureFlagsUsed ? null : 'toggle'),
216-
message: 'Add Vitest for Unit Testing?',
224+
message: language.needsVitest.message,
217225
initial: false,
218-
active: 'Yes',
219-
inactive: 'No'
226+
active: language.defaultToggleOptions.active,
227+
inactive: language.defaultToggleOptions.inactive
220228
},
221229
{
222230
name: 'needsE2eTesting',
223231
type: () => (isFeatureFlagsUsed ? null : 'select'),
224-
message: 'Add an End-to-End Testing Solution?',
232+
message: language.needsE2eTesting.message,
225233
initial: 0,
226234
choices: (prev, answers) => [
227-
{ title: 'No', value: false },
228235
{
229-
title: 'Cypress',
236+
title: language.needsE2eTesting.selectOptions.negative.title,
237+
value: false
238+
},
239+
{
240+
title: language.needsE2eTesting.selectOptions.cypress.title,
230241
description: answers.needsVitest
231242
? undefined
232-
: 'also supports unit testing with Cypress Component Testing',
243+
: language.needsE2eTesting.selectOptions.cypress.desc,
233244
value: 'cypress'
234245
},
235246
{
236-
title: 'Nightwatch',
247+
title: language.needsE2eTesting.selectOptions.nightwatch.title,
237248
description: answers.needsVitest
238249
? undefined
239-
: 'also supports unit testing with Nightwatch Component Testing',
250+
: language.needsE2eTesting.selectOptions.nightwatch.desc,
240251
value: 'nightwatch'
241252
},
242253
{
243-
title: 'Playwright',
254+
title: language.needsE2eTesting.selectOptions.playwright.title,
244255
value: 'playwright'
245256
}
246257
]
247258
},
248259
{
249260
name: 'needsEslint',
250261
type: () => (isFeatureFlagsUsed ? null : 'toggle'),
251-
message: 'Add ESLint for code quality?',
262+
message: language.needsEslint.message,
252263
initial: false,
253-
active: 'Yes',
254-
inactive: 'No'
264+
active: language.defaultToggleOptions.active,
265+
inactive: language.defaultToggleOptions.inactive
255266
},
256267
{
257268
name: 'needsPrettier',
@@ -261,15 +272,15 @@ async function init() {
261272
}
262273
return 'toggle'
263274
},
264-
message: 'Add Prettier for code formatting?',
275+
message: language.needsPrettier.message,
265276
initial: false,
266-
active: 'Yes',
267-
inactive: 'No'
277+
active: language.defaultToggleOptions.active,
278+
inactive: language.defaultToggleOptions.inactive
268279
}
269280
],
270281
{
271282
onCancel: () => {
272-
throw new Error(red('✖') + ' Operation cancelled')
283+
throw new Error(red('✖') + ` ${language.errors.operationCancelled}`)
273284
}
274285
}
275286
)
@@ -308,7 +319,7 @@ async function init() {
308319
fs.mkdirSync(root)
309320
}
310321

311-
console.log(`\nScaffolding project in ${root}...`)
322+
console.log(`\n${language.infos.scaffolding} ${root}...`)
312323

313324
const pkg = { name: packageName, version: '0.0.0' }
314325
fs.writeFileSync(path.resolve(root, 'package.json'), JSON.stringify(pkg, null, 2))
@@ -496,7 +507,7 @@ async function init() {
496507
})
497508
)
498509

499-
console.log(`\nDone. Now run:\n`)
510+
console.log(`\n${language.infos.done}\n`)
500511
if (root !== cwd) {
501512
const cdProjectName = path.relative(cwd, root)
502513
console.log(

locales/en-US.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"projectName": {
3+
"message": "Project name:"
4+
},
5+
"shouldOverwrite": {
6+
"dirForPrompts": {
7+
"current": "Current directory",
8+
"target": "Target directory"
9+
},
10+
"message": "is not empty. Remove existing files and continue?"
11+
},
12+
"packageName": {
13+
"message": "Package name:"
14+
},
15+
"needsTypeScript": {
16+
"message": "Add TypeScript?"
17+
},
18+
"needsJsx": {
19+
"message": "Add JSX Support?"
20+
},
21+
"needsRouter": {
22+
"message": "Add Vue Router for Single Page Application development?"
23+
},
24+
"needsPinia": {
25+
"message": "Add Pinia for state management?"
26+
},
27+
"needsVitest": {
28+
"message": "Add Vitest for Unit Testing?"
29+
},
30+
"needsE2eTesting": {
31+
"message": "Add an End-to-End Testing Solution?",
32+
"selectOptions": {
33+
"negative": { "title": "No" },
34+
"cypress": {
35+
"title": "Cypress",
36+
"desc": "also supports unit testing with Cypress Component Testing"
37+
},
38+
"nightwatch": {
39+
"title": "Nightwatch",
40+
"desc": "also supports unit testing with Nightwatch Component Testing"
41+
},
42+
"playwright": { "title": "Playwright" }
43+
}
44+
},
45+
"needsEslint": {
46+
"message": "Add ESLint for code quality?"
47+
},
48+
"needsPrettier": {
49+
"message": "Add Prettier for code formatting?"
50+
},
51+
"errors": {
52+
"operationCancelled": "Operation cancelled"
53+
},
54+
"defaultToggleOptions": {
55+
"active": "Yes",
56+
"inactive": "No"
57+
},
58+
"infos": {
59+
"scaffolding": "Scaffolding project in",
60+
"done": "Done. Now run:"
61+
}
62+
}

locales/zh-CN.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"projectName": {
3+
"message": "请输入项目名称:"
4+
},
5+
"shouldOverwrite": {
6+
"dirForPrompts": {
7+
"current": "当前目录",
8+
"target": "目标文件夹"
9+
},
10+
"message": "非空,是否覆盖?"
11+
},
12+
"packageName": {
13+
"message": "请输入包名称:"
14+
},
15+
"needsTypeScript": {
16+
"message": "是否使用 TypeScript 语法?"
17+
},
18+
"needsJsx": {
19+
"message": "是否启用 JSX 支持?"
20+
},
21+
"needsRouter": {
22+
"message": "是否引入 Vue Router 进行单页面应用开发?"
23+
},
24+
"needsPinia": {
25+
"message": "是否引入 Pinia 用于状态管理?"
26+
},
27+
"needsVitest": {
28+
"message": "是否引入 Vitest 用于单元测试?"
29+
},
30+
"needsE2eTesting": {
31+
"message": "是否要引入一款端到端(End to End)测试工具?",
32+
"selectOptions": {
33+
"negative": { "title": "不需要" },
34+
"cypress": {
35+
"title": "Cypress",
36+
"desc": "同时支持基于 Cypress Component Testing 的单元测试"
37+
},
38+
"nightwatch": {
39+
"title": "Nightwatch",
40+
"desc": "同时支持基于 Nightwatch Component Testing 的单元测试"
41+
},
42+
"playwright": { "title": "Playwright" }
43+
}
44+
},
45+
"needsEslint": {
46+
"message": "是否引入 ESLint 用于代码质量检测?"
47+
},
48+
"needsPrettier": {
49+
"message": "是否引入 Prettier 用于代码格式化?"
50+
},
51+
"errors": {
52+
"operationCancelled": "操作取消"
53+
},
54+
"defaultToggleOptions": {
55+
"active": "",
56+
"inactive": ""
57+
},
58+
"infos": {
59+
"scaffolding": "正在构建项目",
60+
"done": "项目构建完成,可执行以下命令:"
61+
}
62+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"create-vue": "outfile.cjs"
88
},
99
"files": [
10+
"locales",
1011
"outfile.cjs",
1112
"template"
1213
],

scripts/build.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ SOFTWARE.
2727
await esbuild.build({
2828
bundle: true,
2929
entryPoints: ['index.ts'],
30+
external: ['locales/*'],
3031
outfile: 'outfile.cjs',
3132
format: 'cjs',
3233
platform: 'node',

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy