Skip to content

Commit 703c91b

Browse files
committed
feat: i18n solution for prompts messages (#348)
1 parent db84fe9 commit 703c91b

File tree

6 files changed

+245
-38
lines changed

6 files changed

+245
-38
lines changed

index.ts

+49-38
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

+62
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

+62
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

+1
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

+1
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)