@kikkimo/claude-launcher 2.4.0 → 3.0.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/CHANGELOG.md +71 -0
- package/README.md +32 -17
- package/claude-launcher +638 -393
- package/docs/README-zh.md +32 -17
- package/lib/api-manager.js +136 -11
- package/lib/auth/password-input.js +8 -4
- package/lib/auth/password-validator.js +83 -48
- package/lib/i18n/index.js +4 -3
- package/lib/i18n/language-manager.js +4 -3
- package/lib/i18n/locales/de.js +93 -9
- package/lib/i18n/locales/en.js +93 -9
- package/lib/i18n/locales/es.js +93 -9
- package/lib/i18n/locales/fr.js +93 -9
- package/lib/i18n/locales/it.js +93 -9
- package/lib/i18n/locales/ja.js +93 -9
- package/lib/i18n/locales/ko.js +93 -9
- package/lib/i18n/locales/pt.js +93 -9
- package/lib/i18n/locales/ru.js +93 -9
- package/lib/i18n/locales/zh-TW.js +93 -9
- package/lib/i18n/locales/zh.js +93 -9
- package/lib/launcher.js +131 -93
- package/lib/presets/providers.js +39 -18
- package/lib/ui/api-editor.js +210 -0
- package/lib/ui/interactive-table.js +216 -99
- package/lib/ui/menu.js +78 -55
- package/lib/ui/prompts.js +168 -139
- package/lib/ui/screen.js +125 -0
- package/lib/utils/stdin-manager.js +11 -9
- package/lib/utils/version-checker.js +63 -3
- package/package.json +2 -2
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
const { getPasswordInput } = require('./password-input');
|
|
7
7
|
const colors = require('../ui/colors');
|
|
8
8
|
const { validatePasswordStrength, getPasswordRequirements, generatePasswordExample } = require('./password-strength');
|
|
9
|
+
const { waitForKey } = require('../ui/prompts');
|
|
9
10
|
const i18n = require('../i18n');
|
|
11
|
+
const screen = require('../ui/screen');
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Force cleanup stdin state to prevent navigation issues
|
|
@@ -43,36 +45,70 @@ function getTranslatedStrength(strength) {
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* @
|
|
48
|
+
* Unified password guard for protected operations
|
|
49
|
+
* Mode A (delete/edit): clears screen, shows header, prompts password
|
|
50
|
+
* Mode B (export/import): no clear, no header, just prompts password
|
|
51
|
+
* @param {Object} apiManager - ApiManager instance
|
|
52
|
+
* @param {string} operation - 'delete' | 'edit' | 'export' | 'import'
|
|
53
|
+
* @returns {Promise<boolean>} true if authorized, false if denied/cancelled
|
|
50
54
|
*/
|
|
51
|
-
async function
|
|
55
|
+
async function passwordGuard(apiManager, operation) {
|
|
56
|
+
const hasPassword = apiManager.hasExportPassword();
|
|
57
|
+
|
|
58
|
+
// Mode A: delete/edit — no password means allow freely
|
|
59
|
+
if ((operation === 'delete' || operation === 'edit') && !hasPassword) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Mode B: export/import — no password means block (defense-in-depth)
|
|
64
|
+
if ((operation === 'export' || operation === 'import') && !hasPassword) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Mode A: clear screen and show header
|
|
69
|
+
if (operation === 'delete' || operation === 'edit') {
|
|
70
|
+
const headerKey = `password.guard.${operation}.header`;
|
|
71
|
+
screen.render([
|
|
72
|
+
'',
|
|
73
|
+
colors.bright + colors.orange + i18n.tSync(headerKey) + colors.reset,
|
|
74
|
+
'',
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
|
|
52
78
|
try {
|
|
53
79
|
const password = await getPasswordInput(i18n.tSync('messages.prompts.enter_password'));
|
|
54
80
|
|
|
81
|
+
// Empty password check
|
|
55
82
|
if (!password) {
|
|
56
83
|
forceStdinCleanup();
|
|
57
|
-
|
|
84
|
+
screen.write(colors.red + i18n.tSync('errors.password.empty') + colors.reset + '\n');
|
|
85
|
+
await waitForKey(i18n.tSync('ui.general.press_any_key_continue'));
|
|
58
86
|
return false;
|
|
59
87
|
}
|
|
60
88
|
|
|
89
|
+
// Verify password
|
|
61
90
|
if (!apiManager.verifyExportPassword(password)) {
|
|
62
91
|
forceStdinCleanup();
|
|
63
|
-
|
|
64
|
-
|
|
92
|
+
screen.write(colors.red + '❌ ' + i18n.tSync('errors.password.verification_failed') + colors.reset + '\n');
|
|
93
|
+
await waitForKey(i18n.tSync('ui.general.press_any_key_continue'));
|
|
65
94
|
return false;
|
|
66
95
|
}
|
|
67
96
|
|
|
68
97
|
return true;
|
|
69
98
|
} catch (error) {
|
|
70
99
|
forceStdinCleanup();
|
|
71
|
-
if (error.message
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
100
|
+
if (error.message === 'Password input cancelled') {
|
|
101
|
+
// Esc — silent return
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (error.message.includes('Ctrl+C')) {
|
|
105
|
+
// Delegate to stdinManager double-tap exit
|
|
106
|
+
const stdinManager = require('../utils/stdin-manager');
|
|
107
|
+
stdinManager.handleCtrlC();
|
|
108
|
+
return false;
|
|
75
109
|
}
|
|
110
|
+
// Unexpected error — treat as failure
|
|
111
|
+
screen.write(colors.red + `❌ ${error.message}` + colors.reset + '\n');
|
|
76
112
|
return false;
|
|
77
113
|
}
|
|
78
114
|
}
|
|
@@ -88,13 +124,13 @@ async function verifyCurrentPassword(apiManager) {
|
|
|
88
124
|
|
|
89
125
|
if (!currentPassword) {
|
|
90
126
|
forceStdinCleanup();
|
|
91
|
-
|
|
127
|
+
screen.write(colors.red + i18n.tSync('errors.password.empty') + colors.reset + '\n');
|
|
92
128
|
return false;
|
|
93
129
|
}
|
|
94
130
|
|
|
95
131
|
if (!apiManager.verifyExportPassword(currentPassword)) {
|
|
96
132
|
forceStdinCleanup();
|
|
97
|
-
|
|
133
|
+
screen.write(colors.red + '❌ ' + i18n.tSync('errors.password.current_incorrect') + colors.reset + '\n');
|
|
98
134
|
return false;
|
|
99
135
|
}
|
|
100
136
|
|
|
@@ -102,9 +138,9 @@ async function verifyCurrentPassword(apiManager) {
|
|
|
102
138
|
} catch (error) {
|
|
103
139
|
forceStdinCleanup();
|
|
104
140
|
if (error.message.includes('cancelled')) {
|
|
105
|
-
|
|
141
|
+
screen.write(colors.yellow + '\n' + i18n.tSync('errors.password.verification_cancelled') + colors.reset + '\n');
|
|
106
142
|
} else {
|
|
107
|
-
|
|
143
|
+
screen.write(colors.red + `❌ Password verification error: ${error.message}` + colors.reset + '\n');
|
|
108
144
|
}
|
|
109
145
|
return false;
|
|
110
146
|
}
|
|
@@ -118,24 +154,23 @@ async function verifyCurrentPassword(apiManager) {
|
|
|
118
154
|
*/
|
|
119
155
|
async function setupNewPassword(apiManager, isFirstTime = false) {
|
|
120
156
|
try {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
console.log('');
|
|
157
|
+
const titleLine = colors.cyan + (isFirstTime ? i18n.tSync('password.setup.title') : i18n.tSync('password.setup.change_title')) + colors.reset;
|
|
158
|
+
const requirements = getPasswordRequirements();
|
|
124
159
|
|
|
160
|
+
const headerLines = ['', titleLine, ''];
|
|
125
161
|
if (!isFirstTime) {
|
|
126
|
-
|
|
127
|
-
|
|
162
|
+
headerLines.push(colors.yellow + '⚠️ ' + i18n.tSync('password.setup.warning') + colors.reset);
|
|
163
|
+
headerLines.push('');
|
|
128
164
|
}
|
|
129
|
-
|
|
130
|
-
// Display password requirements
|
|
131
|
-
console.log(colors.cyan + i18n.tSync('ui.general.password_requirements_title') + colors.reset);
|
|
132
|
-
const requirements = getPasswordRequirements();
|
|
165
|
+
headerLines.push(colors.cyan + i18n.tSync('ui.general.password_requirements_title') + colors.reset);
|
|
133
166
|
requirements.forEach(req => {
|
|
134
|
-
|
|
167
|
+
headerLines.push(colors.gray + ' ' + req + colors.reset);
|
|
135
168
|
});
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
169
|
+
headerLines.push('');
|
|
170
|
+
headerLines.push(colors.gray + i18n.tSync('ui.general.example_strong_password', generatePasswordExample()) + colors.reset);
|
|
171
|
+
headerLines.push('');
|
|
172
|
+
|
|
173
|
+
screen.render(headerLines);
|
|
139
174
|
|
|
140
175
|
let attempts = 0;
|
|
141
176
|
const maxAttempts = 3;
|
|
@@ -149,9 +184,9 @@ async function setupNewPassword(apiManager, isFirstTime = false) {
|
|
|
149
184
|
|
|
150
185
|
if (!newPassword) {
|
|
151
186
|
forceStdinCleanup();
|
|
152
|
-
|
|
187
|
+
screen.write(colors.red + i18n.tSync('errors.password.empty') + colors.reset + '\n');
|
|
153
188
|
if (attempts < maxAttempts) {
|
|
154
|
-
|
|
189
|
+
screen.write('\n');
|
|
155
190
|
continue;
|
|
156
191
|
} else {
|
|
157
192
|
return false;
|
|
@@ -162,27 +197,27 @@ async function setupNewPassword(apiManager, isFirstTime = false) {
|
|
|
162
197
|
const validation = validatePasswordStrength(newPassword);
|
|
163
198
|
|
|
164
199
|
if (!validation.valid) {
|
|
165
|
-
|
|
200
|
+
screen.write(colors.red + '❌ ' + i18n.tSync('errors.password.requirements_not_met') + colors.reset + '\n');
|
|
166
201
|
validation.errors.forEach(error => {
|
|
167
|
-
|
|
202
|
+
screen.write(colors.red + ' • ' + error + colors.reset + '\n');
|
|
168
203
|
});
|
|
169
204
|
|
|
170
205
|
if (validation.suggestions.length > 0) {
|
|
171
|
-
|
|
206
|
+
screen.write(colors.yellow + '💡 ' + i18n.tSync('ui.general.suggestions') + colors.reset + '\n');
|
|
172
207
|
validation.suggestions.forEach(suggestion => {
|
|
173
|
-
|
|
208
|
+
screen.write(colors.yellow + ' • ' + suggestion + colors.reset + '\n');
|
|
174
209
|
});
|
|
175
210
|
}
|
|
176
211
|
// If password is invalid, force display strength as "Weak" regardless of technical score
|
|
177
212
|
const strengthKey = validation.valid ? validation.strength : 'Weak';
|
|
178
213
|
const translatedStrength = getTranslatedStrength(strengthKey);
|
|
179
|
-
|
|
214
|
+
screen.write(colors.gray + i18n.tSync('ui.general.current_password_strength', translatedStrength) + colors.reset + '\n');
|
|
180
215
|
|
|
181
216
|
if (attempts < maxAttempts) {
|
|
182
|
-
|
|
217
|
+
screen.write('\n');
|
|
183
218
|
continue;
|
|
184
219
|
} else {
|
|
185
|
-
|
|
220
|
+
screen.write(colors.red + i18n.tSync('ui.general.max_attempts_password_failed') + colors.reset + '\n');
|
|
186
221
|
return false;
|
|
187
222
|
}
|
|
188
223
|
}
|
|
@@ -192,9 +227,9 @@ async function setupNewPassword(apiManager, isFirstTime = false) {
|
|
|
192
227
|
|
|
193
228
|
if (newPassword !== confirmPassword) {
|
|
194
229
|
forceStdinCleanup();
|
|
195
|
-
|
|
230
|
+
screen.write(colors.red + i18n.tSync('ui.general.passwords_mismatch') + colors.reset + '\n');
|
|
196
231
|
if (attempts < maxAttempts) {
|
|
197
|
-
|
|
232
|
+
screen.write('\n');
|
|
198
233
|
continue;
|
|
199
234
|
} else {
|
|
200
235
|
return false;
|
|
@@ -203,8 +238,8 @@ async function setupNewPassword(apiManager, isFirstTime = false) {
|
|
|
203
238
|
|
|
204
239
|
// Success - set the password
|
|
205
240
|
apiManager.setExportPassword(newPassword);
|
|
206
|
-
|
|
207
|
-
|
|
241
|
+
screen.write('\n');
|
|
242
|
+
screen.write(colors.green + '✓ ' + i18n.tSync('password.setup.password_success', getTranslatedStrength(validation.strength)) + colors.reset + '\n');
|
|
208
243
|
return true;
|
|
209
244
|
}
|
|
210
245
|
|
|
@@ -213,9 +248,9 @@ async function setupNewPassword(apiManager, isFirstTime = false) {
|
|
|
213
248
|
} catch (error) {
|
|
214
249
|
forceStdinCleanup();
|
|
215
250
|
if (error.message.includes('cancelled')) {
|
|
216
|
-
|
|
251
|
+
screen.write(colors.yellow + '\n' + i18n.tSync('errors.password.setup_cancelled') + colors.reset + '\n');
|
|
217
252
|
} else {
|
|
218
|
-
|
|
253
|
+
screen.write(colors.red + `❌ Failed to set password: ${error.message}` + colors.reset + '\n');
|
|
219
254
|
}
|
|
220
255
|
return false;
|
|
221
256
|
}
|
|
@@ -234,21 +269,21 @@ async function changePassword(apiManager) {
|
|
|
234
269
|
return false;
|
|
235
270
|
}
|
|
236
271
|
|
|
237
|
-
|
|
238
|
-
|
|
272
|
+
screen.write(colors.green + i18n.tSync('errors.password.current_password_verified') + colors.reset + '\n');
|
|
273
|
+
screen.write('\n');
|
|
239
274
|
|
|
240
275
|
// Set new password
|
|
241
276
|
return await setupNewPassword(apiManager, false);
|
|
242
277
|
|
|
243
278
|
} catch (error) {
|
|
244
279
|
forceStdinCleanup();
|
|
245
|
-
|
|
280
|
+
screen.write(colors.red + `❌ Password change failed: ${error.message}` + colors.reset + '\n');
|
|
246
281
|
return false;
|
|
247
282
|
}
|
|
248
283
|
}
|
|
249
284
|
|
|
250
285
|
module.exports = {
|
|
251
|
-
|
|
286
|
+
passwordGuard,
|
|
252
287
|
verifyCurrentPassword,
|
|
253
288
|
setupNewPassword,
|
|
254
289
|
changePassword
|
package/lib/i18n/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
const LanguageManager = require('./language-manager');
|
|
7
7
|
const MessageFormatter = require('./formatter');
|
|
8
|
+
const screen = require('../ui/screen');
|
|
8
9
|
|
|
9
10
|
class I18n {
|
|
10
11
|
constructor() {
|
|
@@ -34,14 +35,14 @@ class I18n {
|
|
|
34
35
|
for (const k of keys) {
|
|
35
36
|
value = value?.[k];
|
|
36
37
|
if (value === undefined) {
|
|
37
|
-
|
|
38
|
+
screen.debug(`Translation key not found: ${key}`);
|
|
38
39
|
return key; // Return key as fallback
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
// If value is not a string, return the key as fallback
|
|
43
44
|
if (typeof value !== 'string') {
|
|
44
|
-
|
|
45
|
+
screen.debug(`Translation value is not a string for key: ${key}`);
|
|
45
46
|
return key;
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -56,7 +57,7 @@ class I18n {
|
|
|
56
57
|
|
|
57
58
|
return result;
|
|
58
59
|
} catch (error) {
|
|
59
|
-
|
|
60
|
+
screen.debug(`Translation error for key ${key}: ` + error.message);
|
|
60
61
|
return key; // Return key as fallback
|
|
61
62
|
}
|
|
62
63
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const os = require('os');
|
|
9
|
+
const screen = require('../ui/screen');
|
|
9
10
|
|
|
10
11
|
class LanguageManager {
|
|
11
12
|
constructor() {
|
|
@@ -83,7 +84,7 @@ class LanguageManager {
|
|
|
83
84
|
this.languageCache.set(this.currentLanguage, languagePack);
|
|
84
85
|
return languagePack;
|
|
85
86
|
} catch (error) {
|
|
86
|
-
|
|
87
|
+
screen.debug(`Failed to load language pack for ${this.currentLanguage}, falling back to English. Error: ${error.message}`);
|
|
87
88
|
|
|
88
89
|
// Fallback to English
|
|
89
90
|
if (this.currentLanguage !== 'en') {
|
|
@@ -118,7 +119,7 @@ class LanguageManager {
|
|
|
118
119
|
|
|
119
120
|
fs.writeFileSync(this.configFile, JSON.stringify(config, null, 2));
|
|
120
121
|
} catch (error) {
|
|
121
|
-
|
|
122
|
+
screen.debug('Failed to save language preference: ' + error.message);
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
125
|
|
|
@@ -134,7 +135,7 @@ class LanguageManager {
|
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
} catch (error) {
|
|
137
|
-
|
|
138
|
+
screen.debug('Failed to load language preference, using default (English)');
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
|
package/lib/i18n/locales/de.js
CHANGED
|
@@ -10,10 +10,11 @@ module.exports = {
|
|
|
10
10
|
title: "Hauptmenü",
|
|
11
11
|
launch_default: "Claude Code starten",
|
|
12
12
|
launch_skip: "Claude Code starten (Berechtigungsprüfung überspringen)",
|
|
13
|
+
launch_auto_mode: "Claude Code starten (Auto-Modus aktivieren)",
|
|
13
14
|
launch_api: "Claude Code mit Drittanbieter-API starten",
|
|
14
15
|
launch_api_skip: "Claude Code mit Drittanbieter-API starten (Berechtigungsprüfung überspringen)",
|
|
15
16
|
api_management: "Drittanbieter-API-Verwaltung",
|
|
16
|
-
|
|
17
|
+
config_management: "Konfigurationsverwaltung",
|
|
17
18
|
version_check: "Versionsaktualisierung prüfen",
|
|
18
19
|
exit: "Beenden"
|
|
19
20
|
},
|
|
@@ -21,11 +22,26 @@ module.exports = {
|
|
|
21
22
|
title: "Drittanbieter-API-Verwaltung",
|
|
22
23
|
add_new: "Neue Drittanbieter-API hinzufügen",
|
|
23
24
|
remove: "API entfernen",
|
|
25
|
+
edit: "Edit API",
|
|
24
26
|
switch: "Aktive API wechseln",
|
|
25
27
|
statistics: "API-Statistiken anzeigen",
|
|
26
28
|
export: "Konfiguration exportieren",
|
|
27
29
|
import: "Konfiguration importieren",
|
|
28
30
|
change_password: "Passwort ändern",
|
|
31
|
+
manual_upgrade: "Manuelles Modell-Upgrade",
|
|
32
|
+
back: "Zurück zum Hauptmenü"
|
|
33
|
+
},
|
|
34
|
+
config: {
|
|
35
|
+
title: "Konfigurationsverwaltung",
|
|
36
|
+
language: "Spracheinstellungen",
|
|
37
|
+
auto_model_upgrade: "Automatisches Modell-Upgrade",
|
|
38
|
+
model_upgrade_notification: "Modell-Upgrade-Benachrichtigung",
|
|
39
|
+
telemetry: "Anthropic Telemetrie",
|
|
40
|
+
api_launch_mode: "Drittanbieter-API-Startmodus",
|
|
41
|
+
back: "Zurück zum Hauptmenü"
|
|
42
|
+
},
|
|
43
|
+
api_select: {
|
|
44
|
+
title: "Wählen Sie eine API zum Starten:",
|
|
29
45
|
back: "Zurück zum Hauptmenü"
|
|
30
46
|
},
|
|
31
47
|
remove_api: {
|
|
@@ -203,6 +219,23 @@ module.exports = {
|
|
|
203
219
|
remove_confirm: "Zu entfernende API: {0}",
|
|
204
220
|
cannot_undo: "Diese Aktion kann nicht rückgängig gemacht werden!",
|
|
205
221
|
removed_info: "Entfernt: {0}"
|
|
222
|
+
},
|
|
223
|
+
edit: {
|
|
224
|
+
select_api: 'Select API to edit',
|
|
225
|
+
current_value: 'Current value: {0}',
|
|
226
|
+
new_value: 'New value: ',
|
|
227
|
+
success: '✅ {0} updated successfully',
|
|
228
|
+
cancelled: 'Edit cancelled',
|
|
229
|
+
back: 'Back',
|
|
230
|
+
field_name: 'Name',
|
|
231
|
+
field_provider: 'Provider',
|
|
232
|
+
field_base_url: 'Base URL',
|
|
233
|
+
field_model: 'Model',
|
|
234
|
+
name_required: 'Name cannot be empty when editing',
|
|
235
|
+
duplicate: 'This change would create a duplicate configuration',
|
|
236
|
+
provider_url_mismatch: 'Provider and URL may be inconsistent',
|
|
237
|
+
provider_url_mismatch_detail: 'Provider: {0} / URL suggests: {1}',
|
|
238
|
+
url_provider_hint: "URL matches provider '{0}' but current provider is '{1}'. Consider updating Provider field."
|
|
206
239
|
}
|
|
207
240
|
},
|
|
208
241
|
|
|
@@ -276,6 +309,10 @@ module.exports = {
|
|
|
276
309
|
good: "Gut",
|
|
277
310
|
strong: "Stark",
|
|
278
311
|
very_strong: "Sehr stark"
|
|
312
|
+
},
|
|
313
|
+
guard: {
|
|
314
|
+
delete: { header: '🗑️ Remove API — Password required to verify identity' },
|
|
315
|
+
edit: { header: '✏️ Edit API — Password required to verify identity' }
|
|
279
316
|
}
|
|
280
317
|
},
|
|
281
318
|
|
|
@@ -323,15 +360,22 @@ module.exports = {
|
|
|
323
360
|
|
|
324
361
|
// Navigation und UI
|
|
325
362
|
navigation: {
|
|
326
|
-
use_arrows: "Verwenden Sie ↑↓ Pfeiltasten zum Navigieren, Enter zum Auswählen, doppelt Ctrl+C zum Beenden",
|
|
327
|
-
use_arrows_esc: "Verwenden Sie ↑↓ zum Navigieren, Enter zum {0}, ESC zum
|
|
363
|
+
use_arrows: "Verwenden Sie ↑↓ Pfeiltasten zum Navigieren, Enter/Leertaste zum Auswählen, doppelt Ctrl+C zum Beenden",
|
|
364
|
+
use_arrows_esc: "Verwenden Sie ↑↓ zum Navigieren, Enter zum {0}, ESC zum Abbrechen",
|
|
365
|
+
use_arrows_page_esc: "←→ Page {0}/{1}, ↑↓ to navigate, Enter to {2}, ESC to cancel",
|
|
328
366
|
use_number_keys: "Verwenden Sie Zahlentasten zum Auswählen:",
|
|
329
367
|
currently_active: "Derzeit aktive API",
|
|
330
368
|
select_action: "Aktion auswählen:",
|
|
331
369
|
no_options: "Keine Optionen verfügbar",
|
|
332
370
|
enter_choice: "Geben Sie Ihre Wahl ein ({0}, oder beliebige andere Taste zum Hauptmenü zurückkehren):",
|
|
333
371
|
arrow_keys_not_available: "Pfeiltasten nicht verfügbar. Geben Sie Auswahlnummer ein (1-{0}):",
|
|
334
|
-
enter_choice_prompt: "[>] Geben Sie Ihre Wahl ein (1-2, oder beliebige andere Taste zum Hauptmenü zurückkehren): "
|
|
372
|
+
enter_choice_prompt: "[>] Geben Sie Ihre Wahl ein (1-2, oder beliebige andere Taste zum Hauptmenü zurückkehren): ",
|
|
373
|
+
action: {
|
|
374
|
+
edit: 'edit',
|
|
375
|
+
remove: 'remove',
|
|
376
|
+
switch: 'switch',
|
|
377
|
+
select: 'select'
|
|
378
|
+
}
|
|
335
379
|
},
|
|
336
380
|
|
|
337
381
|
// Start-Prozess
|
|
@@ -572,19 +616,15 @@ module.exports = {
|
|
|
572
616
|
model_upgrade: {
|
|
573
617
|
notification: "Modell-Upgrade verfügbar: {0} → {1}",
|
|
574
618
|
notification_api: "API: {0}",
|
|
575
|
-
notification_hint: "
|
|
619
|
+
notification_hint: "Auto-Upgrade: \"Konfigurationsverwaltung\" / Manuell: \"Drittanbieter-API-Verwaltung > Manuelles Modell-Upgrade\"",
|
|
576
620
|
auto_upgraded: "Modell automatisch upgegradet: {0} → {1}",
|
|
577
621
|
|
|
578
|
-
settings_title: "Modell-Upgrade-Einstellungen",
|
|
579
622
|
current_config: "Aktuelle Konfiguration",
|
|
580
623
|
auto_upgrade_label: "Neuestes Modell automatisch verwenden",
|
|
581
624
|
auto_upgrade_on: "AN",
|
|
582
625
|
auto_upgrade_off: "AUS",
|
|
583
626
|
|
|
584
|
-
menu_toggle_auto_on: "Auto-Upgrade [● AN]",
|
|
585
|
-
menu_toggle_auto_off: "Auto-Upgrade [○ AUS]",
|
|
586
627
|
menu_manual_upgrade: "Alle Modelle manuell upgraden",
|
|
587
|
-
menu_back: "Zurück",
|
|
588
628
|
|
|
589
629
|
manual_title: "Modell-Upgrade-Prüfung",
|
|
590
630
|
manual_checking: "{0} API-Konfigurationen werden geprüft...",
|
|
@@ -599,5 +639,49 @@ module.exports = {
|
|
|
599
639
|
manual_complete: "Upgrade abgeschlossen!",
|
|
600
640
|
manual_stats_upgraded: "Upgegradet: {0}",
|
|
601
641
|
manual_stats_skipped: "Übersprungen: {0} ({1} bereits aktuell, {2} keine Upgrade-Info)"
|
|
642
|
+
},
|
|
643
|
+
hints: {
|
|
644
|
+
auto_mode_info: 'Nach dem Start Shift+Tab drücken, um in den automatischen Ausführungsmodus zu wechseln',
|
|
645
|
+
active_api_info: 'Aktiv: {0} / {1}',
|
|
646
|
+
no_active_api: 'Keine aktive API konfiguriert. Gehen Sie zur "API-Verwaltung", um eine hinzuzufügen.',
|
|
647
|
+
direct_mode_desc: 'Direktstartmodus, startet sofort mit der aktiven API',
|
|
648
|
+
direct_mode_api_info: 'API: {0} | Anbieter: {1}',
|
|
649
|
+
direct_mode_api_detail: 'Modell: {0} | Zuletzt verwendet: {1}',
|
|
650
|
+
direct_mode_change: 'Startmodus kann in "Konfigurationsverwaltung" geändert werden',
|
|
651
|
+
direct_mode_no_active: 'Direktstartmodus, aber keine aktive API ausgewählt',
|
|
652
|
+
direct_mode_no_active_detail: '{0} APIs konfiguriert, bitte wählen Sie eine in "Drittanbieter-API-Verwaltung"',
|
|
653
|
+
select_mode_desc: 'Auswahlmodus, wählen Sie eine API aus der Liste vor dem Start',
|
|
654
|
+
select_mode_change: 'Startmodus kann in "Konfigurationsverwaltung" geändert werden',
|
|
655
|
+
select_mode_api_count: '{0} APIs konfiguriert, aktiv: {1}',
|
|
656
|
+
select_mode_active_none: 'keine',
|
|
657
|
+
no_api_configured: 'Keine Drittanbieter-APIs konfiguriert. Fügen Sie zuerst eine in "Drittanbieter-API-Verwaltung" hinzu',
|
|
658
|
+
api_management_info: '{0} APIs konfiguriert, aktiv: {1}',
|
|
659
|
+
config_summary: 'Sprache: {0} | Startmodus: {1} | Telemetrie: {2}',
|
|
660
|
+
edit_password_required: '🔒 Password verification required to edit API configuration',
|
|
661
|
+
remove_password_required: '🔒 Password verification required to remove API',
|
|
662
|
+
export_password_required: '🔒 Password verification required to export configuration',
|
|
663
|
+
import_password_required: '🔒 Password verification required to import configuration',
|
|
664
|
+
config: {
|
|
665
|
+
language: 'Anzeigesprache wechseln, aktuell: {0}',
|
|
666
|
+
auto_upgrade: 'Modellversionen für Drittanbieter-APIs automatisch erkennen und upgraden',
|
|
667
|
+
upgrade_notification: 'Modell-Upgrade-Benachrichtigung oben im Hauptmenü anzeigen',
|
|
668
|
+
telemetry: 'Injiziert DISABLE_TELEMETRY=1 wenn deaktiviert. Empfohlen: AUS',
|
|
669
|
+
launch_mode: 'Direkt: mit aktiver API starten / Auswahl: zuerst aus Liste wählen'
|
|
670
|
+
},
|
|
671
|
+
api_select: {
|
|
672
|
+
info: 'API: {0}',
|
|
673
|
+
detail: 'Anbieter: {0} | Modell: {1}',
|
|
674
|
+
usage: 'Nutzung: {0} mal | Zuletzt verwendet: {1}'
|
|
675
|
+
}
|
|
676
|
+
},
|
|
677
|
+
|
|
678
|
+
config: {
|
|
679
|
+
values: {
|
|
680
|
+
on: 'AN',
|
|
681
|
+
off: 'AUS',
|
|
682
|
+
direct_mode: 'Direktmodus',
|
|
683
|
+
select_mode: 'Auswahlmodus',
|
|
684
|
+
recommended_off: 'AUS (Empfohlen)'
|
|
685
|
+
}
|
|
602
686
|
}
|
|
603
687
|
};
|