@inquirer/i18n 1.3.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -2
- package/dist/create.js +97 -65
- package/dist/index.js +6 -6
- package/dist/locales/es.d.ts +82 -82
- package/dist/locales/es.js +1 -1
- package/dist/locales/fr.d.ts +82 -82
- package/dist/locales/fr.js +1 -1
- package/dist/locales/pt.d.ts +82 -82
- package/dist/locales/pt.js +1 -1
- package/dist/locales/zh.d.ts +82 -82
- package/dist/locales/zh.js +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -107,7 +107,11 @@ import { createLocalizedPrompts, registerLocale } from '@inquirer/i18n';
|
|
|
107
107
|
import type { Locale } from '@inquirer/i18n';
|
|
108
108
|
|
|
109
109
|
const deLocale: Locale = {
|
|
110
|
-
confirm: {
|
|
110
|
+
confirm: {
|
|
111
|
+
yesLabel: 'Ja',
|
|
112
|
+
noLabel: 'Nein',
|
|
113
|
+
invalidAnswer: (yes, no) => `Sie müssen mit "${yes}" oder "${no}" antworten.`,
|
|
114
|
+
},
|
|
111
115
|
select: { helpNavigate: 'Navigieren', helpSelect: 'Auswählen' },
|
|
112
116
|
checkbox: {
|
|
113
117
|
helpNavigate: 'Navigieren',
|
|
@@ -121,7 +125,10 @@ const deLocale: Locale = {
|
|
|
121
125
|
loadingMessage: () => 'Überprüfung...',
|
|
122
126
|
waitingMessage: (enterKey) => `Drücken Sie ${enterKey}, um Ihren Editor zu öffnen.`,
|
|
123
127
|
},
|
|
124
|
-
password: {
|
|
128
|
+
password: {
|
|
129
|
+
maskedText: '[Eingabe verborgen]',
|
|
130
|
+
helpToggle: 'Sichtbarkeit umschalten',
|
|
131
|
+
},
|
|
125
132
|
};
|
|
126
133
|
|
|
127
134
|
// Option A — use directly
|
|
@@ -135,6 +142,33 @@ registerLocale('de', createLocalizedPrompts(deLocale));
|
|
|
135
142
|
`import { confirm } from '@inquirer/i18n'` will pick the German locale automatically
|
|
136
143
|
whenever `LANG` (or the other sources) resolve to `de`.
|
|
137
144
|
|
|
145
|
+
# Themes and locales
|
|
146
|
+
|
|
147
|
+
The strings above are the localized defaults. A `theme` passed to a prompt applies
|
|
148
|
+
in every language — it overrides the locale strings, exactly as it overrides the
|
|
149
|
+
built-in English ones in `@inquirer/prompts`. For example
|
|
150
|
+
`password({ message, theme: { style: { maskedText: '[***]' } } })` renders `[***]`
|
|
151
|
+
under every locale.
|
|
152
|
+
|
|
153
|
+
To change the words of a single language, don't put them in the theme: build a
|
|
154
|
+
locale with `createLocalizedPrompts` and register it with `registerLocale` instead:
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
import { createLocalizedPrompts, registerLocale } from '@inquirer/i18n';
|
|
158
|
+
import { locale as zh } from '@inquirer/i18n/zh';
|
|
159
|
+
|
|
160
|
+
registerLocale(
|
|
161
|
+
'zh',
|
|
162
|
+
createLocalizedPrompts({
|
|
163
|
+
...zh,
|
|
164
|
+
password: { ...zh.password, maskedText: '[已隐藏]' },
|
|
165
|
+
}),
|
|
166
|
+
);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Note: a custom `keysHelpTip` formatter receives the help-line labels already
|
|
170
|
+
translated into the active language (e.g. `导航` for `navigate` under `zh`).
|
|
171
|
+
|
|
138
172
|
# License
|
|
139
173
|
|
|
140
174
|
Copyright (c) 2025 Simon Boudrias (twitter: [@vaxilart](https://twitter.com/Vaxilart))<br/>
|
package/dist/create.js
CHANGED
|
@@ -1,6 +1,81 @@
|
|
|
1
1
|
import { checkbox as checkboxPrompt, confirm as confirmPrompt, editor as editorPrompt, expand as expandPrompt, input as inputPrompt, number as numberPrompt, password as passwordPrompt, rawlist as rawlistPrompt, search as searchPrompt, select as selectPrompt, } from '@inquirer/prompts';
|
|
2
2
|
import { makeTheme } from '@inquirer/core';
|
|
3
3
|
import { styleText } from 'node:util';
|
|
4
|
+
/**
|
|
5
|
+
* Default help-line renderer, with the same layout as every prompt's built-in
|
|
6
|
+
* theme: a bold key followed by a dim label, joined with a dim separator.
|
|
7
|
+
*/
|
|
8
|
+
function defaultKeysHelpTip(keys) {
|
|
9
|
+
return keys
|
|
10
|
+
.map(([key, label]) => `${styleText('bold', key)} ${styleText('dim', label)}`)
|
|
11
|
+
.join(styleText('dim', ' • '));
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The user's keysHelpTip formatter from `config.theme`, or the default
|
|
15
|
+
* renderer when they gave none.
|
|
16
|
+
*
|
|
17
|
+
* Merged through `makeTheme` because `config.theme` is a `PartialDeep`, which
|
|
18
|
+
* widens function members to `{}` and loses their signature — `makeTheme`
|
|
19
|
+
* returns the fully typed theme, restoring it.
|
|
20
|
+
*/
|
|
21
|
+
function resolveKeysHelpTip(userTheme) {
|
|
22
|
+
const theme = makeTheme({ style: { keysHelpTip: defaultKeysHelpTip } }, userTheme);
|
|
23
|
+
return theme.style.keysHelpTip;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Wrap a help-line renderer so it receives the labels translated into the
|
|
27
|
+
* active locale instead of the prompt's built-in English ones.
|
|
28
|
+
*/
|
|
29
|
+
function localizedKeysHelpTip(keysHelpTip, translate) {
|
|
30
|
+
return (keys) => keysHelpTip(keys.map(([key, label]) => [key, translate(label)]));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The user's theme minus its `keysHelpTip`: the wrapper installs its own
|
|
34
|
+
* composing formatter, which already delegates to the user's one with
|
|
35
|
+
* translated labels. Keeping the original in the merge would override the
|
|
36
|
+
* composer and pass English labels straight through.
|
|
37
|
+
*/
|
|
38
|
+
function themeWithoutKeysHelpTip(theme) {
|
|
39
|
+
const style = { ...theme.style };
|
|
40
|
+
delete style.keysHelpTip;
|
|
41
|
+
return { ...theme, style };
|
|
42
|
+
}
|
|
43
|
+
/** Translate the select prompt's built-in help labels. */
|
|
44
|
+
function translateSelectLabel(strings, label) {
|
|
45
|
+
if (label === 'navigate')
|
|
46
|
+
return strings.helpNavigate;
|
|
47
|
+
if (label === 'select')
|
|
48
|
+
return strings.helpSelect;
|
|
49
|
+
return label;
|
|
50
|
+
}
|
|
51
|
+
/** Translate the checkbox prompt's built-in help labels. */
|
|
52
|
+
function translateCheckboxLabel(strings, label) {
|
|
53
|
+
if (label === 'navigate')
|
|
54
|
+
return strings.helpNavigate;
|
|
55
|
+
if (label === 'select')
|
|
56
|
+
return strings.helpSelect;
|
|
57
|
+
if (label === 'submit')
|
|
58
|
+
return strings.helpSubmit;
|
|
59
|
+
if (label === 'all')
|
|
60
|
+
return strings.helpAll;
|
|
61
|
+
if (label === 'invert')
|
|
62
|
+
return strings.helpInvert;
|
|
63
|
+
return label;
|
|
64
|
+
}
|
|
65
|
+
/** Translate the search prompt's built-in help labels. */
|
|
66
|
+
function translateSearchLabel(strings, label) {
|
|
67
|
+
if (label === 'navigate')
|
|
68
|
+
return strings.helpNavigate;
|
|
69
|
+
if (label === 'select')
|
|
70
|
+
return strings.helpSelect;
|
|
71
|
+
return label;
|
|
72
|
+
}
|
|
73
|
+
/** Translate the password prompt's built-in help labels. */
|
|
74
|
+
function translatePasswordLabel(strings, label) {
|
|
75
|
+
if (label === 'toggle visibility')
|
|
76
|
+
return strings.helpToggle;
|
|
77
|
+
return label;
|
|
78
|
+
}
|
|
4
79
|
/**
|
|
5
80
|
* Factory function that creates localized prompt wrappers for a given locale.
|
|
6
81
|
*
|
|
@@ -12,77 +87,41 @@ export function createLocalizedPrompts(locale) {
|
|
|
12
87
|
confirm(config, context) {
|
|
13
88
|
// The labels are the keywords: confirm shows their first character in
|
|
14
89
|
// the hint, matches them prefix-based, and displays the label once done.
|
|
15
|
-
|
|
16
|
-
|
|
90
|
+
// Locale strings are the defaults; config.theme overrides them.
|
|
91
|
+
const theme = makeTheme({
|
|
17
92
|
keywords: {
|
|
18
93
|
yes: locale.confirm.yesLabel,
|
|
19
94
|
no: locale.confirm.noLabel,
|
|
20
95
|
error: ({ yes, no }) => locale.confirm.invalidAnswer(yes, no),
|
|
21
96
|
},
|
|
22
|
-
};
|
|
97
|
+
}, config.theme);
|
|
23
98
|
return confirmPrompt({ ...config, theme }, context);
|
|
24
99
|
},
|
|
25
100
|
select(config, context) {
|
|
26
|
-
const
|
|
101
|
+
const localeTheme = {
|
|
27
102
|
style: {
|
|
28
|
-
keysHelpTip: (
|
|
29
|
-
const localizedKeys = keys.map(([key, label]) => {
|
|
30
|
-
if (label === 'navigate')
|
|
31
|
-
return [key, locale.select.helpNavigate];
|
|
32
|
-
if (label === 'select')
|
|
33
|
-
return [key, locale.select.helpSelect];
|
|
34
|
-
return [key, label];
|
|
35
|
-
});
|
|
36
|
-
return localizedKeys
|
|
37
|
-
.map(([k, l]) => `${styleText('bold', k)} ${styleText('dim', l)}`)
|
|
38
|
-
.join(styleText('dim', ' • '));
|
|
39
|
-
},
|
|
103
|
+
keysHelpTip: localizedKeysHelpTip(resolveKeysHelpTip(config.theme), (label) => translateSelectLabel(locale.select, label)),
|
|
40
104
|
},
|
|
41
|
-
}
|
|
105
|
+
};
|
|
106
|
+
const theme = makeTheme(localeTheme, themeWithoutKeysHelpTip(config.theme ?? {}));
|
|
42
107
|
return selectPrompt({ ...config, theme }, context);
|
|
43
108
|
},
|
|
44
109
|
checkbox(config, context) {
|
|
45
|
-
const
|
|
110
|
+
const localeTheme = {
|
|
46
111
|
style: {
|
|
47
|
-
keysHelpTip: (
|
|
48
|
-
const localizedKeys = keys.map(([key, label]) => {
|
|
49
|
-
if (label === 'navigate')
|
|
50
|
-
return [key, locale.checkbox.helpNavigate];
|
|
51
|
-
if (label === 'select')
|
|
52
|
-
return [key, locale.checkbox.helpSelect];
|
|
53
|
-
if (label === 'submit')
|
|
54
|
-
return [key, locale.checkbox.helpSubmit];
|
|
55
|
-
if (label === 'all')
|
|
56
|
-
return [key, locale.checkbox.helpAll];
|
|
57
|
-
if (label === 'invert')
|
|
58
|
-
return [key, locale.checkbox.helpInvert];
|
|
59
|
-
return [key, label];
|
|
60
|
-
});
|
|
61
|
-
return localizedKeys
|
|
62
|
-
.map(([k, l]) => `${styleText('bold', k)} ${styleText('dim', l)}`)
|
|
63
|
-
.join(styleText('dim', ' • '));
|
|
64
|
-
},
|
|
112
|
+
keysHelpTip: localizedKeysHelpTip(resolveKeysHelpTip(config.theme), (label) => translateCheckboxLabel(locale.checkbox, label)),
|
|
65
113
|
},
|
|
66
|
-
}
|
|
114
|
+
};
|
|
115
|
+
const theme = makeTheme(localeTheme, themeWithoutKeysHelpTip(config.theme ?? {}));
|
|
67
116
|
return checkboxPrompt({ ...config, theme }, context);
|
|
68
117
|
},
|
|
69
118
|
search(config, context) {
|
|
70
|
-
const
|
|
119
|
+
const localeTheme = {
|
|
71
120
|
style: {
|
|
72
|
-
keysHelpTip: (
|
|
73
|
-
const localizedKeys = keys.map(([key, label]) => {
|
|
74
|
-
if (label === 'navigate')
|
|
75
|
-
return [key, locale.search.helpNavigate];
|
|
76
|
-
if (label === 'select')
|
|
77
|
-
return [key, locale.search.helpSelect];
|
|
78
|
-
return [key, label];
|
|
79
|
-
});
|
|
80
|
-
return localizedKeys
|
|
81
|
-
.map(([k, l]) => `${styleText('bold', k)} ${styleText('dim', l)}`)
|
|
82
|
-
.join(styleText('dim', ' • '));
|
|
83
|
-
},
|
|
121
|
+
keysHelpTip: localizedKeysHelpTip(resolveKeysHelpTip(config.theme), (label) => translateSearchLabel(locale.search, label)),
|
|
84
122
|
},
|
|
85
|
-
}
|
|
123
|
+
};
|
|
124
|
+
const theme = makeTheme(localeTheme, themeWithoutKeysHelpTip(config.theme ?? {}));
|
|
86
125
|
return searchPrompt({ ...config, theme }, context);
|
|
87
126
|
},
|
|
88
127
|
expand(config, context) {
|
|
@@ -92,12 +131,13 @@ export function createLocalizedPrompts(locale) {
|
|
|
92
131
|
return rawlistPrompt(config, context);
|
|
93
132
|
},
|
|
94
133
|
editor(config, context) {
|
|
95
|
-
const
|
|
134
|
+
const localeTheme = {
|
|
96
135
|
style: {
|
|
97
136
|
loadingMessage: locale.editor.loadingMessage,
|
|
98
137
|
waitingMessage: locale.editor.waitingMessage,
|
|
99
138
|
},
|
|
100
|
-
}
|
|
139
|
+
};
|
|
140
|
+
const theme = makeTheme(localeTheme, config.theme);
|
|
101
141
|
return editorPrompt({ ...config, theme }, context);
|
|
102
142
|
},
|
|
103
143
|
input(config, context) {
|
|
@@ -107,21 +147,13 @@ export function createLocalizedPrompts(locale) {
|
|
|
107
147
|
return numberPrompt(config, context);
|
|
108
148
|
},
|
|
109
149
|
password(config, context) {
|
|
110
|
-
const
|
|
150
|
+
const localeTheme = {
|
|
111
151
|
style: {
|
|
112
152
|
maskedText: locale.password.maskedText,
|
|
113
|
-
keysHelpTip: (
|
|
114
|
-
const localizedKeys = keys.map(([key, label]) => {
|
|
115
|
-
if (label === 'toggle visibility')
|
|
116
|
-
return [key, locale.password.helpToggle];
|
|
117
|
-
return [key, label];
|
|
118
|
-
});
|
|
119
|
-
return localizedKeys
|
|
120
|
-
.map(([k, l]) => `${styleText('bold', k)} ${styleText('dim', l)}`)
|
|
121
|
-
.join(styleText('dim', ' • '));
|
|
122
|
-
},
|
|
153
|
+
keysHelpTip: localizedKeysHelpTip(resolveKeysHelpTip(config.theme), (label) => translatePasswordLabel(locale.password, label)),
|
|
123
154
|
},
|
|
124
|
-
}
|
|
155
|
+
};
|
|
156
|
+
const theme = makeTheme(localeTheme, themeWithoutKeysHelpTip(config.theme ?? {}));
|
|
125
157
|
return passwordPrompt({ ...config, theme }, context);
|
|
126
158
|
},
|
|
127
159
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as en from
|
|
2
|
-
import * as es from
|
|
3
|
-
import * as fr from
|
|
4
|
-
import * as pt from
|
|
5
|
-
import * as zh from
|
|
6
|
-
export * from
|
|
1
|
+
import * as en from './locales/en.js';
|
|
2
|
+
import * as es from './locales/es.js';
|
|
3
|
+
import * as fr from './locales/fr.js';
|
|
4
|
+
import * as pt from './locales/pt.js';
|
|
5
|
+
import * as zh from './locales/zh.js';
|
|
6
|
+
export * from './create.js';
|
|
7
7
|
const localeMap = { en, es, fr, pt, zh };
|
|
8
8
|
/**
|
|
9
9
|
* Register a custom locale so it is automatically picked up by the
|