Validate desktop i18n catalogs (#9776)

Signed-off-by: Angie Jones <jones.angie@gmail.com>
This commit is contained in:
Angie Jones
2026-06-13 12:38:18 +05:30
committed by GitHub
parent 0629f9951f
commit 6b9360c74f
6 changed files with 622 additions and 320 deletions
+4 -2
View File
@@ -42,9 +42,10 @@
"test:integration:watch": "vitest --config vitest.integration.config.ts",
"test:integration:debug": "DEBUG=1 vitest run --config vitest.integration.config.ts",
"i18n:extract": "formatjs extract 'src/**/*.{ts,tsx}' --ignore '**/*.d.ts' --out-file src/i18n/messages/en.json --flatten && pnpm run i18n:compile",
"i18n:check": "node scripts/i18n-check.js",
"i18n:check": "node scripts/i18n-check.js && node scripts/i18n-validate-locale.js",
"i18n:compile": "node scripts/i18n-compile.js",
"i18n:validate-ja": "node scripts/i18n-validate-locale.js ja"
"i18n:validate-ja": "node scripts/i18n-validate-locale.js ja",
"i18n:validate-locale": "node scripts/i18n-validate-locale.js"
},
"dependencies": {
"@aaif/goose-sdk": "workspace:*",
@@ -118,6 +119,7 @@
"@electron/fuses": "^1.8.0",
"@eslint/js": "^9.39.2",
"@formatjs/cli": "^6.14.0",
"@formatjs/icu-messageformat-parser": "3.5.3",
"@hey-api/openapi-ts": "^0.93.0",
"@modelcontextprotocol/sdk": "^1.27.0",
"@playwright/test": "^1.58.2",
+122 -32
View File
@@ -1,56 +1,146 @@
#!/usr/bin/env node
/**
* Validate that a translated locale catalog mirrors en.json and preserves ICU placeholders.
* Validate that translated locale catalogs mirror en.json and preserve ICU placeholders.
* Pass one or more locale codes to validate specific catalogs, or no arguments to validate all locales.
*/
const fs = require('fs');
const path = require('path');
const { TYPE, parse } = require('@formatjs/icu-messageformat-parser');
const requestedLocales = process.argv.slice(2);
if (requestedLocales.includes('en')) {
console.error('en is the source catalog and cannot be validated as a translated locale.');
process.exit(1);
}
const locale = process.argv[2] || 'ja';
const projectDir = path.join(__dirname, '..');
const messagesDir = path.join(projectDir, 'src', 'i18n', 'messages');
const enPath = path.join(messagesDir, 'en.json');
const localePath = path.join(messagesDir, locale + '.json');
function readJson(file) {
return JSON.parse(fs.readFileSync(file, 'utf8'));
}
function extractPlaceholders(message) {
const placeholders = new Set();
const re = /\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*(?=[},])/g;
let match;
while ((match = re.exec(message)) !== null) {
placeholders.add(match[1]);
function collectArguments(elements, args) {
for (const element of elements) {
switch (element.type) {
case TYPE.argument:
case TYPE.number:
case TYPE.date:
case TYPE.time:
args.add(element.value);
break;
case TYPE.select:
case TYPE.plural:
args.add(element.value);
for (const option of Object.values(element.options)) {
collectArguments(option.value, args);
}
break;
case TYPE.tag:
args.add(element.value);
collectArguments(element.children, args);
break;
}
}
}
function extractPlaceholders(message) {
const args = new Set();
collectArguments(parse(message), args);
return [...args].sort();
}
function listLocales() {
return fs
.readdirSync(messagesDir)
.filter((file) => file.endsWith('.json') && file !== 'en.json')
.map((file) => path.basename(file, '.json'))
.sort();
}
function validateLocale(locale, en, enKeys) {
const localePath = path.join(messagesDir, locale + '.json');
if (!fs.existsSync(localePath)) {
return {
locale,
missingFile: true,
missing: [],
extra: [],
placeholderIssues: [],
};
}
const translated = readJson(localePath);
const localeKeys = Object.keys(translated).sort();
const missing = enKeys.filter((key) => !Object.prototype.hasOwnProperty.call(translated, key));
const extra = localeKeys.filter((key) => !Object.prototype.hasOwnProperty.call(en, key));
const placeholderIssues = [];
for (const key of enKeys) {
if (!translated[key]) continue;
const source = en[key].defaultMessage || '';
const target = translated[key].defaultMessage || '';
const sourcePlaceholders = extractPlaceholders(source);
const targetPlaceholders = extractPlaceholders(target);
if (JSON.stringify(sourcePlaceholders) !== JSON.stringify(targetPlaceholders)) {
placeholderIssues.push({ key, sourcePlaceholders, targetPlaceholders });
}
}
return { locale, missingFile: false, missing, extra, placeholderIssues };
}
function printIssues(result) {
const { locale, missingFile, missing, extra, placeholderIssues } = result;
if (missingFile) {
console.error('Missing locale file for ' + locale + '.');
}
if (missing.length) {
console.error(
'Missing ' + locale + ' keys (' + missing.length + ', showing first 50):',
missing.slice(0, 50)
);
}
if (extra.length) {
console.error(
'Extra ' + locale + ' keys (' + extra.length + ', showing first 50):',
extra.slice(0, 50)
);
}
if (placeholderIssues.length) {
console.error(
'Placeholder issues in ' + locale + ' (' + placeholderIssues.length + ', showing first 20):',
placeholderIssues.slice(0, 20)
);
}
return [...placeholders].sort();
}
const en = readJson(enPath);
const translated = readJson(localePath);
const enKeys = Object.keys(en).sort();
const localeKeys = Object.keys(translated).sort();
const locales = requestedLocales.length ? requestedLocales : listLocales();
const missing = enKeys.filter((key) => !Object.prototype.hasOwnProperty.call(translated, key));
const extra = localeKeys.filter((key) => !Object.prototype.hasOwnProperty.call(en, key));
const placeholderIssues = [];
for (const key of enKeys) {
if (!translated[key]) continue;
const source = en[key].defaultMessage || '';
const target = translated[key].defaultMessage || '';
const sourcePlaceholders = extractPlaceholders(source);
const targetPlaceholders = extractPlaceholders(target);
if (JSON.stringify(sourcePlaceholders) !== JSON.stringify(targetPlaceholders)) {
placeholderIssues.push({ key, sourcePlaceholders, targetPlaceholders });
}
}
if (missing.length || extra.length || placeholderIssues.length) {
if (missing.length) console.error('Missing ' + locale + ' keys:', missing.slice(0, 50));
if (extra.length) console.error('Extra ' + locale + ' keys:', extra.slice(0, 50));
if (placeholderIssues.length) console.error('Placeholder issues:', placeholderIssues.slice(0, 20));
if (!locales.length) {
console.error('No translated locale catalogs found.');
process.exit(1);
}
console.log('i18n locale "' + locale + '" is valid (' + enKeys.length + ' messages).');
const results = locales.map((locale) => validateLocale(locale, en, enKeys));
const failures = results.filter(
({ missingFile, missing, extra, placeholderIssues }) =>
missingFile || missing.length || extra.length || placeholderIssues.length
);
for (const result of failures) {
printIssues(result);
}
if (failures.length) {
process.exit(1);
}
console.log(
'i18n locale validation passed for ' + locales.join(', ') + ' (' + enKeys.length + ' messages).'
);
+120 -33
View File
@@ -44,6 +44,66 @@
"appsView.title": {
"defaultMessage": "Приложения"
},
"authSettings.activeProviderWarning": {
"defaultMessage": "Это активный провайдер. Новые запросы могут завершаться ошибкой, пока вы не настроите другие учетные данные."
},
"authSettings.cancel": {
"defaultMessage": "Отмена"
},
"authSettings.delete": {
"defaultMessage": "Удалить"
},
"authSettings.deleteCredential": {
"defaultMessage": "Удалить учетные данные"
},
"authSettings.deleteMessage": {
"defaultMessage": "Удалить учетные данные {name} для {provider}?"
},
"authSettings.deleteTitle": {
"defaultMessage": "Удалить учетные данные"
},
"authSettings.deleted": {
"defaultMessage": "Учетные данные удалены"
},
"authSettings.description": {
"defaultMessage": "Управляйте учетными данными провайдеров, сохраненными локально в goose."
},
"authSettings.empty": {
"defaultMessage": "Локально сохраненные учетные данные провайдеров не найдены."
},
"authSettings.expiresAt": {
"defaultMessage": "Истекает {date}"
},
"authSettings.failedToConfigure": {
"defaultMessage": "Не удалось настроить учетные данные: {error}"
},
"authSettings.failedToDelete": {
"defaultMessage": "Не удалось удалить учетные данные: {error}"
},
"authSettings.failedToLoad": {
"defaultMessage": "Не удалось загрузить учетные данные провайдера"
},
"authSettings.loading": {
"defaultMessage": "Загрузка учетных данных..."
},
"authSettings.reauthorize": {
"defaultMessage": "Авторизоваться снова"
},
"authSettings.signIn": {
"defaultMessage": "Войти"
},
"authSettings.signedIn": {
"defaultMessage": "Учетные данные настроены"
},
"authSettings.storageProviderCache": {
"defaultMessage": "Кэш провайдера"
},
"authSettings.storageSecretStore": {
"defaultMessage": "Хранилище секретов"
},
"authSettings.title": {
"defaultMessage": "Учетные данные провайдера"
},
"backButton.back": {
"defaultMessage": "Назад"
},
@@ -1457,6 +1517,21 @@
"huggingFaceModelSearch.tooLarge": {
"defaultMessage": "Может не поместиться в память (модель {size}, доступно {available})"
},
"huggingFaceSignInPrompt.failedToConfigure": {
"defaultMessage": "Не удалось войти в Hugging Face: {error}"
},
"huggingFaceSignInPrompt.signIn": {
"defaultMessage": "Войти"
},
"huggingFaceSignInPrompt.signedIn": {
"defaultMessage": "Вход в Hugging Face выполнен"
},
"huggingFaceSignInPrompt.signingIn": {
"defaultMessage": "Выполняется вход..."
},
"huggingFaceSignInPrompt.title": {
"defaultMessage": "Hugging Face"
},
"imagePreview.altText": {
"defaultMessage": "изображение goose"
},
@@ -1796,6 +1871,9 @@
"localInferenceSettings.featuredModels": {
"defaultMessage": "Рекомендуемые модели"
},
"localInferenceSettings.huggingFaceSignInNote": {
"defaultMessage": "Войдите, чтобы увеличить лимиты запросов при поиске и загрузке моделей, а также получить доступ к приватным или ограниченным репозиториям Hugging Face."
},
"localInferenceSettings.modelSettings": {
"defaultMessage": "Настройки модели"
},
@@ -2174,24 +2252,6 @@
"modelSettingsPanel.batchSizeDescription": {
"defaultMessage": "Пакет обработки промпта"
},
"modelSettingsPanel.contextAndGeneration": {
"defaultMessage": "Контекст и генерация"
},
"modelSettingsPanel.contextSize": {
"defaultMessage": "Размер контекста"
},
"modelSettingsPanel.contextSizeDescription": {
"defaultMessage": "Максимальное контекстное окно (0 = по умолчанию модели)"
},
"modelSettingsPanel.etaLearningRate": {
"defaultMessage": "Eta (скорость обучения)"
},
"modelSettingsPanel.flashAttention": {
"defaultMessage": "Flash attention"
},
"modelSettingsPanel.flashAttentionDescription": {
"defaultMessage": "Включить оптимизацию flash attention"
},
"modelSettingsPanel.builtinChatTemplate": {
"defaultMessage": "Встроенный шаблон"
},
@@ -2213,26 +2273,29 @@
"modelSettingsPanel.chatTemplateEmbedded": {
"defaultMessage": "Встроенный"
},
"modelSettingsPanel.contextAndGeneration": {
"defaultMessage": "Контекст и генерация"
},
"modelSettingsPanel.contextSize": {
"defaultMessage": "Размер контекста"
},
"modelSettingsPanel.contextSizeDescription": {
"defaultMessage": "Максимальное контекстное окно (0 = по умолчанию модели)"
},
"modelSettingsPanel.customChatTemplate": {
"defaultMessage": "Пользовательский шаблон чата"
},
"modelSettingsPanel.customChatTemplateDescription": {
"defaultMessage": "Вставьте полный исходный код шаблона Jinja"
},
"modelSettingsPanel.toolCalling": {
"defaultMessage": "Вызов инструментов"
"modelSettingsPanel.etaLearningRate": {
"defaultMessage": "Eta (скорость обучения)"
},
"modelSettingsPanel.toolCallingAuto": {
"defaultMessage": "Авто"
"modelSettingsPanel.flashAttention": {
"defaultMessage": "Flash attention"
},
"modelSettingsPanel.toolCallingDescription": {
"defaultMessage": "Выберите, как локальные модели используют нативный или эмулируемый вызов инструментов"
},
"modelSettingsPanel.toolCallingForceEmulated": {
"defaultMessage": "Принудительно эмулируемый"
},
"modelSettingsPanel.toolCallingForceNative": {
"defaultMessage": "Принудительно нативный"
"modelSettingsPanel.flashAttentionDescription": {
"defaultMessage": "Включить оптимизацию flash attention"
},
"modelSettingsPanel.frequencyPenalty": {
"defaultMessage": "Штраф частоты"
@@ -2315,6 +2378,21 @@
"modelSettingsPanel.threadsDescription": {
"defaultMessage": "Потоки CPU для генерации"
},
"modelSettingsPanel.toolCalling": {
"defaultMessage": "Вызов инструментов"
},
"modelSettingsPanel.toolCallingAuto": {
"defaultMessage": "Авто"
},
"modelSettingsPanel.toolCallingDescription": {
"defaultMessage": "Выберите, как локальные модели используют нативный или эмулируемый вызов инструментов"
},
"modelSettingsPanel.toolCallingForceEmulated": {
"defaultMessage": "Принудительно эмулируемый"
},
"modelSettingsPanel.toolCallingForceNative": {
"defaultMessage": "Принудительно нативный"
},
"modelSettingsPanel.topK": {
"defaultMessage": "Top K"
},
@@ -2792,6 +2870,9 @@
"providerConfigurationModal.goBack": {
"defaultMessage": "Назад"
},
"providerConfigurationModal.huggingFaceOAuthDescription": {
"defaultMessage": "Войдите, чтобы использовать Hugging Face Inference Providers без ручного ввода API-токена."
},
"providerConfigurationModal.oauthLoginFailed": {
"defaultMessage": "Вход OAuth не удался: {error}"
},
@@ -3650,6 +3731,9 @@
"securityToggle.mlTokenDescription": {
"defaultMessage": "Токен аутентификации для ML-сервиса (например, токен HuggingFace)"
},
"securityToggle.overrideNotice": {
"defaultMessage": "Этот параметр управляется вашей организацией и не может быть изменен."
},
"securityToggle.promptInjectionDescription": {
"defaultMessage": "Обнаруживать и предотвращать потенциальные атаки prompt injection"
},
@@ -3659,6 +3743,9 @@
"securityToggle.thresholdDescription": {
"defaultMessage": "Чем выше значение, тем строже проверка (0.01 = очень мягко, 1.0 = максимально строго)"
},
"securityToggle.warpNotice": {
"defaultMessage": "Обнаружение внедрения команд работает лучше всего при подключении к WARP (требуется для доступа к сервису классификации)."
},
"sessionHistory.cancel": {
"defaultMessage": "Отмена"
},
@@ -3842,9 +3929,6 @@
"sessions.error.tryAgain": {
"defaultMessage": "Повторить попытку"
},
"sessions.extensions": {
"defaultMessage": "Расширения:"
},
"sessions.import": {
"defaultMessage": "Импортировать сеанс"
},
@@ -4043,6 +4127,9 @@
"settingsView.tabApp": {
"defaultMessage": "Приложение"
},
"settingsView.tabAuth": {
"defaultMessage": "Авторизация"
},
"settingsView.tabChat": {
"defaultMessage": "Чат"
},
+148 -220
View File
@@ -11,9 +11,6 @@
"announcementModal.gotIt": {
"defaultMessage": "Anladım!"
},
"appLayout.closeNavigation": {
"defaultMessage": "Gezinmeyi kapat"
},
"appLayout.openNavigation": {
"defaultMessage": "Gezinmeyi aç"
},
@@ -47,6 +44,66 @@
"appsView.title": {
"defaultMessage": "Uygulamalar"
},
"authSettings.activeProviderWarning": {
"defaultMessage": "Bu etkin sağlayıcıdır. Başka bir kimlik bilgisi yapılandırana kadar yeni istekler başarısız olabilir."
},
"authSettings.cancel": {
"defaultMessage": "İptal"
},
"authSettings.delete": {
"defaultMessage": "Sil"
},
"authSettings.deleteCredential": {
"defaultMessage": "Kimlik bilgisini sil"
},
"authSettings.deleteMessage": {
"defaultMessage": "{provider} için {name} kimlik bilgisi silinsin mi?"
},
"authSettings.deleteTitle": {
"defaultMessage": "Kimlik bilgisini sil"
},
"authSettings.deleted": {
"defaultMessage": "Kimlik bilgisi silindi"
},
"authSettings.description": {
"defaultMessage": "goose tarafından yerel olarak saklanan sağlayıcı kimlik bilgilerini yönetin."
},
"authSettings.empty": {
"defaultMessage": "Yerel olarak saklanan sağlayıcı kimlik bilgisi bulunamadı."
},
"authSettings.expiresAt": {
"defaultMessage": "{date} tarihinde sona erer"
},
"authSettings.failedToConfigure": {
"defaultMessage": "Kimlik bilgisi yapılandırılamadı: {error}"
},
"authSettings.failedToDelete": {
"defaultMessage": "Kimlik bilgisi silinemedi: {error}"
},
"authSettings.failedToLoad": {
"defaultMessage": "Sağlayıcı kimlik bilgileri yüklenemedi"
},
"authSettings.loading": {
"defaultMessage": "Kimlik bilgileri yükleniyor..."
},
"authSettings.reauthorize": {
"defaultMessage": "Yeniden yetkilendir"
},
"authSettings.signIn": {
"defaultMessage": "Oturum aç"
},
"authSettings.signedIn": {
"defaultMessage": "Kimlik bilgisi yapılandırıldı"
},
"authSettings.storageProviderCache": {
"defaultMessage": "Sağlayıcı önbelleği"
},
"authSettings.storageSecretStore": {
"defaultMessage": "Gizli anahtar deposu"
},
"authSettings.title": {
"defaultMessage": "Sağlayıcı Kimlik Bilgileri"
},
"backButton.back": {
"defaultMessage": "Geri"
},
@@ -110,24 +167,6 @@
"chat.notification.taskComplete.title": {
"defaultMessage": "Goose görevi tamamladı."
},
"chatHistorySearch.keyboardHintMac": {
"defaultMessage": "⌘K"
},
"chatHistorySearch.keyboardHintOther": {
"defaultMessage": "Ctrl+K"
},
"chatHistorySearch.messageCount": {
"defaultMessage": "{count,plural,one{# mesaj} other{# mesaj}}"
},
"chatHistorySearch.noResults": {
"defaultMessage": "Sohbet bulunamadı"
},
"chatHistorySearch.searchError": {
"defaultMessage": "Arama başarısız oldu"
},
"chatHistorySearch.searchPlaceholder": {
"defaultMessage": "Sohbetlerde ara…"
},
"chatInput.contextWindow": {
"defaultMessage": "Bağlam penceresi"
},
@@ -182,12 +221,6 @@
"chatInput.waitingForImages": {
"defaultMessage": "Resimlerin kaydedilmesi bekleniyor..."
},
"chatSessionsDropdown.newChat": {
"defaultMessage": "Yeni Sohbet"
},
"chatSessionsDropdown.showAll": {
"defaultMessage": "Tümünü Göster"
},
"chatSettings.modeDescription": {
"defaultMessage": "Goose'nin araçlar ve uzantılarla nasıl etkileşimde bulunacağını yapılandırın"
},
@@ -200,9 +233,6 @@
"chatSettings.responseStylesTitle": {
"defaultMessage": "Yanıt Stilleri"
},
"condensedRenderer.newChat": {
"defaultMessage": "Yeni Sohbet"
},
"configSettings.configReset": {
"defaultMessage": "Yapılandırma Sıfırlama"
},
@@ -1382,63 +1412,6 @@
"goosehintsSection.title": {
"defaultMessage": "Proje İpuçları (.goosehints)"
},
"greeting.readyToBuild": {
"defaultMessage": "Harika bir şey inşa etmeye hazır mısınız?"
},
"greeting.readyToCreateGreat": {
"defaultMessage": "Harika bir şey yaratmaya hazır mısınız?"
},
"greeting.readyToGetStarted": {
"defaultMessage": "Başlamaya hazır mısınız?"
},
"greeting.whatCanBeAchieved": {
"defaultMessage": "Ne başarılabilir?"
},
"greeting.whatCanBeBuilt": {
"defaultMessage": "Bugün ne inşa edilebilir?"
},
"greeting.whatNeedsToBeDone": {
"defaultMessage": "Ne yapılması gerekiyor?"
},
"greeting.whatProgress": {
"defaultMessage": "Hangi ilerleme kaydedilebilir?"
},
"greeting.whatProjectNeedsAttention": {
"defaultMessage": "Hangi projenin ilgiye ihtiyacı var?"
},
"greeting.whatProjectReadyToBegin": {
"defaultMessage": "Hangi proje başlamaya hazır?"
},
"greeting.whatShallWeCreate": {
"defaultMessage": "Bugün ne yaratacağız?"
},
"greeting.whatTaskAwaits": {
"defaultMessage": "Hangi görev bekliyor?"
},
"greeting.whatToAccomplish": {
"defaultMessage": "Neyi başarmak istersiniz?"
},
"greeting.whatToExplore": {
"defaultMessage": "Neyi keşfetmek istersiniz?"
},
"greeting.whatToTackle": {
"defaultMessage": "Neyle uğraşmak istersin?"
},
"greeting.whatToWorkOn": {
"defaultMessage": "Ne üzerinde çalışmak istersin?"
},
"greeting.whatsNextChallenge": {
"defaultMessage": "Bir sonraki zorluk nedir?"
},
"greeting.whatsOnYourMind": {
"defaultMessage": "Aklında ne var?"
},
"greeting.whatsTheMission": {
"defaultMessage": "Bugünkü görev nedir?"
},
"greeting.whatsThePlan": {
"defaultMessage": "Bugünkü planın ne?"
},
"groupedExtensionLoadingToast.askGoose": {
"defaultMessage": "goose'a sorun"
},
@@ -1499,6 +1472,15 @@
"headersSection.value": {
"defaultMessage": "Değer"
},
"hub.goodAfternoon": {
"defaultMessage": "İyi günler"
},
"hub.goodEvening": {
"defaultMessage": "İyi akşamlar"
},
"hub.goodMorning": {
"defaultMessage": "Günaydın"
},
"huggingFaceModelSearch.download": {
"defaultMessage": "İndir"
},
@@ -1535,6 +1517,21 @@
"huggingFaceModelSearch.tooLarge": {
"defaultMessage": "Belleğe sığmayabilir ({size} modeli, {available} mevcuttur)"
},
"huggingFaceSignInPrompt.failedToConfigure": {
"defaultMessage": "Hugging Face oturumu açılamadı: {error}"
},
"huggingFaceSignInPrompt.signIn": {
"defaultMessage": "Oturum aç"
},
"huggingFaceSignInPrompt.signedIn": {
"defaultMessage": "Hugging Face oturumu açıldı"
},
"huggingFaceSignInPrompt.signingIn": {
"defaultMessage": "Oturum açılıyor..."
},
"huggingFaceSignInPrompt.title": {
"defaultMessage": "Hugging Face"
},
"imagePreview.altText": {
"defaultMessage": "goose resmi"
},
@@ -1874,6 +1871,9 @@
"localInferenceSettings.featuredModels": {
"defaultMessage": "Öne Çıkan Modeller"
},
"localInferenceSettings.huggingFaceSignInNote": {
"defaultMessage": "Model ararken ve indirirken hız sınırlarını artırmak ve özel ya da erişimi kısıtlı Hugging Face depolarına erişmek için oturum açın."
},
"localInferenceSettings.modelSettings": {
"defaultMessage": "Modeli Ayarları"
},
@@ -2252,24 +2252,6 @@
"modelSettingsPanel.batchSizeDescription": {
"defaultMessage": "Hızlı işlem toplu"
},
"modelSettingsPanel.contextAndGeneration": {
"defaultMessage": "Bağlam ve Üretim"
},
"modelSettingsPanel.contextSize": {
"defaultMessage": "Bağlam boyutu"
},
"modelSettingsPanel.contextSizeDescription": {
"defaultMessage": "Maksimum bağlam penceresi (0 = model varsayılanı)"
},
"modelSettingsPanel.etaLearningRate": {
"defaultMessage": "Eta (öğrenme oranı)"
},
"modelSettingsPanel.flashAttention": {
"defaultMessage": "Flaş dikkat"
},
"modelSettingsPanel.flashAttentionDescription": {
"defaultMessage": "Flaş dikkati optimizasyonunu etkinleştir"
},
"modelSettingsPanel.builtinChatTemplate": {
"defaultMessage": "Yerleşik şablon"
},
@@ -2291,26 +2273,29 @@
"modelSettingsPanel.chatTemplateEmbedded": {
"defaultMessage": "Gömülü"
},
"modelSettingsPanel.contextAndGeneration": {
"defaultMessage": "Bağlam ve Üretim"
},
"modelSettingsPanel.contextSize": {
"defaultMessage": "Bağlam boyutu"
},
"modelSettingsPanel.contextSizeDescription": {
"defaultMessage": "Maksimum bağlam penceresi (0 = model varsayılanı)"
},
"modelSettingsPanel.customChatTemplate": {
"defaultMessage": "Özel sohbet şablonu"
},
"modelSettingsPanel.customChatTemplateDescription": {
"defaultMessage": "Tam Jinja sohbet şablonu kaynağını yapıştır"
},
"modelSettingsPanel.toolCalling": {
"defaultMessage": "Araç çağırma"
"modelSettingsPanel.etaLearningRate": {
"defaultMessage": "Eta (öğrenme oranı)"
},
"modelSettingsPanel.toolCallingAuto": {
"defaultMessage": "Otomatik"
"modelSettingsPanel.flashAttention": {
"defaultMessage": "Flaş dikkat"
},
"modelSettingsPanel.toolCallingDescription": {
"defaultMessage": "Yerel modellerin yerel veya emüle araç çağırmayı nasıl seçeceğini belirleyin"
},
"modelSettingsPanel.toolCallingForceEmulated": {
"defaultMessage": "Emüle etmeye zorla"
},
"modelSettingsPanel.toolCallingForceNative": {
"defaultMessage": "Yereli zorla"
"modelSettingsPanel.flashAttentionDescription": {
"defaultMessage": "Flaş dikkati optimizasyonunu etkinleştir"
},
"modelSettingsPanel.frequencyPenalty": {
"defaultMessage": "Frekans cezası"
@@ -2393,6 +2378,21 @@
"modelSettingsPanel.threadsDescription": {
"defaultMessage": "Nesil için CPU iş parçacıkları"
},
"modelSettingsPanel.toolCalling": {
"defaultMessage": "Araç çağırma"
},
"modelSettingsPanel.toolCallingAuto": {
"defaultMessage": "Otomatik"
},
"modelSettingsPanel.toolCallingDescription": {
"defaultMessage": "Yerel modellerin yerel veya emüle araç çağırmayı nasıl seçeceğini belirleyin"
},
"modelSettingsPanel.toolCallingForceEmulated": {
"defaultMessage": "Emüle etmeye zorla"
},
"modelSettingsPanel.toolCallingForceNative": {
"defaultMessage": "Yereli zorla"
},
"modelSettingsPanel.topK": {
"defaultMessage": "En İyi K"
},
@@ -2426,77 +2426,41 @@
"modelsSection.resetTitle": {
"defaultMessage": "Sağlayıcıyı ve Modeli Sıfırla"
},
"navigationCustomization.dragInstructions": {
"defaultMessage": "Yeniden sıralamak için sürükleyin, öğeleri göstermek/gizlemek için göz simgesini tıklayın"
},
"navigationCustomization.hideItem": {
"defaultMessage": "Öğeyi gizle"
},
"navigationCustomization.itemApps": {
"navigation.itemApps": {
"defaultMessage": "Uygulamalar"
},
"navigationCustomization.itemChat": {
"defaultMessage": "Sohbet"
},
"navigationCustomization.itemExtensions": {
"navigation.itemExtensions": {
"defaultMessage": "Uzantılar"
},
"navigationCustomization.itemHome": {
"defaultMessage": "Ana sayfa"
"navigation.itemHome": {
"defaultMessage": "Yeni Sohbet"
},
"navigationCustomization.itemRecipes": {
"navigation.itemRecipes": {
"defaultMessage": "Tarifler"
},
"navigationCustomization.itemScheduler": {
"navigation.itemScheduler": {
"defaultMessage": "Zamanlayıcı"
},
"navigationCustomization.itemSettings": {
"navigation.itemSessions": {
"defaultMessage": "Oturum Geçmişi"
},
"navigation.itemSettings": {
"defaultMessage": "Ayarlar"
},
"navigationCustomization.itemSkills": {
"navigation.itemSkills": {
"defaultMessage": "Beceriler"
},
"navigationCustomization.resetToDefaults": {
"defaultMessage": "Varsayılanlara sıfırla"
"navigationPanel.chats": {
"defaultMessage": "Sohbetler"
},
"navigationCustomization.showItem": {
"defaultMessage": "Öğeyi göster"
"navigationPanel.collapseSidebar": {
"defaultMessage": "Kenar çubuğunu daralt"
},
"navigationModeSelector.overlayDescription": {
"defaultMessage": "Tam ekran yer paylaşımı"
"navigationPanel.noChats": {
"defaultMessage": "Son sohbet yok"
},
"navigationModeSelector.overlayLabel": {
"defaultMessage": "Kaplama"
},
"navigationModeSelector.pushDescription": {
"defaultMessage": "Gezinme içeriği zorlar"
},
"navigationModeSelector.pushLabel": {
"defaultMessage": "İt"
},
"navigationPositionSelector.bottomLabel": {
"defaultMessage": "Alt"
},
"navigationPositionSelector.leftLabel": {
"defaultMessage": "Sol"
},
"navigationPositionSelector.rightLabel": {
"defaultMessage": "Sağ"
},
"navigationPositionSelector.topLabel": {
"defaultMessage": "Üst"
},
"navigationStyleSelector.listDescription": {
"defaultMessage": "Klasik yoğunlaştırılmış görünüm"
},
"navigationStyleSelector.listLabel": {
"defaultMessage": "Liste"
},
"navigationStyleSelector.tileDescription": {
"defaultMessage": "Büyütülmüş döşeme görünümü"
},
"navigationStyleSelector.tileLabel": {
"defaultMessage": "Fayans"
"navigationPanel.untitledSession": {
"defaultMessage": "Başlıksız oturum"
},
"onboardingGuard.checkProviderErrorDescription": {
"defaultMessage": "Sunucu başlatılıyor veya geçici olarak kullanılamıyor olabilir."
@@ -2906,6 +2870,9 @@
"providerConfigurationModal.goBack": {
"defaultMessage": "Geri Dön"
},
"providerConfigurationModal.huggingFaceOAuthDescription": {
"defaultMessage": "API belirtecini elle girmeden Hugging Face Inference Providers kullanmak için oturum açın."
},
"providerConfigurationModal.oauthLoginFailed": {
"defaultMessage": "OAuth oturum açma işlemi başarısız oldu: {error}"
},
@@ -3764,6 +3731,9 @@
"securityToggle.mlTokenDescription": {
"defaultMessage": "ML hizmeti için kimlik doğrulama belirteci (ör. HuggingFace belirteci)"
},
"securityToggle.overrideNotice": {
"defaultMessage": "Bu ayar kuruluşunuz tarafından yönetiliyor ve değiştirilemez."
},
"securityToggle.promptInjectionDescription": {
"defaultMessage": "Potansiyel anlık enjeksiyon saldırılarını tespit edin ve önleyin"
},
@@ -3773,6 +3743,9 @@
"securityToggle.thresholdDescription": {
"defaultMessage": "Daha yüksek değerler daha katıdır (0,01 = çok yumuşak, 1,0 = maksimum katı)"
},
"securityToggle.warpNotice": {
"defaultMessage": "Komut enjeksiyonu algılama, WARP bağlantısı olduğunda en iyi şekilde çalışır (sınıflandırma hizmetine erişmek için gereklidir)."
},
"sessionHistory.cancel": {
"defaultMessage": "İptal"
},
@@ -3956,9 +3929,6 @@
"sessions.error.tryAgain": {
"defaultMessage": "Tekrar Deneyin"
},
"sessions.extensions": {
"defaultMessage": "Uzantılar:"
},
"sessions.import": {
"defaultMessage": "Oturumu İçe Aktar"
},
@@ -4037,33 +4007,6 @@
"sessions.toast.updated": {
"defaultMessage": "Oturum açıklaması başarıyla güncellendi"
},
"sessionsInsights.failedToLoad": {
"defaultMessage": "Analizler yüklenemedi"
},
"sessionsInsights.noRecentChats": {
"defaultMessage": "Yeni sohbet oturumu bulunamadı."
},
"sessionsInsights.recentChats": {
"defaultMessage": "Son sohbetler"
},
"sessionsInsights.seeAll": {
"defaultMessage": "Tümünü gör"
},
"sessionsInsights.totalSessions": {
"defaultMessage": "Toplam oturumlar"
},
"sessionsInsights.totalTokens": {
"defaultMessage": "Toplam jeton"
},
"sessionsList.showAll": {
"defaultMessage": "Tümünü Göster"
},
"sessionsList.startNewChat": {
"defaultMessage": "Yeni Sohbet Başlat"
},
"sessionsList.untitledSession": {
"defaultMessage": "Başlıksız oturum"
},
"sessionsView.error.failedToLoad": {
"defaultMessage": "Oturum ayrıntıları yüklenemedi. Lütfen daha sonra tekrar deneyin."
},
@@ -4109,24 +4052,6 @@
"settings.menuBarIcon.title": {
"defaultMessage": "Menü çubuğu simgesi"
},
"settings.navigation.customize": {
"defaultMessage": "Öğeleri Özelleştir"
},
"settings.navigation.description": {
"defaultMessage": "Gezinme düzenini ve davranışını özelleştirin"
},
"settings.navigation.mode": {
"defaultMessage": "Mod"
},
"settings.navigation.position": {
"defaultMessage": "Pozisyon"
},
"settings.navigation.style": {
"defaultMessage": "Stil"
},
"settings.navigation.title": {
"defaultMessage": "Navigasyon"
},
"settings.notifications.configGuide": {
"defaultMessage": "Yapılandırma kılavuzu"
},
@@ -4202,6 +4127,9 @@
"settingsView.tabApp": {
"defaultMessage": "Uygulama"
},
"settingsView.tabAuth": {
"defaultMessage": "Kimlik Doğrulama"
},
"settingsView.tabChat": {
"defaultMessage": "Sohbet"
},
+225 -33
View File
@@ -44,6 +44,66 @@
"appsView.title": {
"defaultMessage": "应用"
},
"authSettings.activeProviderWarning": {
"defaultMessage": "这是当前正在使用的提供商。在配置其他凭据之前,新的请求可能会失败。"
},
"authSettings.cancel": {
"defaultMessage": "取消"
},
"authSettings.delete": {
"defaultMessage": "删除"
},
"authSettings.deleteCredential": {
"defaultMessage": "删除凭据"
},
"authSettings.deleteMessage": {
"defaultMessage": "要删除 {provider} 的 {name} 凭据吗?"
},
"authSettings.deleteTitle": {
"defaultMessage": "删除凭据"
},
"authSettings.deleted": {
"defaultMessage": "凭据已删除"
},
"authSettings.description": {
"defaultMessage": "管理 goose 在本地存储的提供商凭据。"
},
"authSettings.empty": {
"defaultMessage": "未找到本地存储的提供商凭据。"
},
"authSettings.expiresAt": {
"defaultMessage": "到期时间:{date}"
},
"authSettings.failedToConfigure": {
"defaultMessage": "配置凭据失败:{error}"
},
"authSettings.failedToDelete": {
"defaultMessage": "删除凭据失败:{error}"
},
"authSettings.failedToLoad": {
"defaultMessage": "加载提供商凭据失败"
},
"authSettings.loading": {
"defaultMessage": "正在加载凭据..."
},
"authSettings.reauthorize": {
"defaultMessage": "重新授权"
},
"authSettings.signIn": {
"defaultMessage": "登录"
},
"authSettings.signedIn": {
"defaultMessage": "凭据已配置"
},
"authSettings.storageProviderCache": {
"defaultMessage": "提供商缓存"
},
"authSettings.storageSecretStore": {
"defaultMessage": "密钥存储"
},
"authSettings.title": {
"defaultMessage": "提供商凭据"
},
"backButton.back": {
"defaultMessage": "返回"
},
@@ -497,12 +557,21 @@
"cronPicker.august": {
"defaultMessage": "八月"
},
"cronPicker.cronExpression": {
"defaultMessage": "Cron 表达式"
},
"cronPicker.custom": {
"defaultMessage": "自定义 cron"
},
"cronPicker.day": {
"defaultMessage": "日"
},
"cronPicker.december": {
"defaultMessage": "十二月"
},
"cronPicker.emptyCronError": {
"defaultMessage": "Cron 表达式不能为空"
},
"cronPicker.every": {
"defaultMessage": "每"
},
@@ -518,6 +587,9 @@
"cronPicker.inMonth": {
"defaultMessage": "于"
},
"cronPicker.invalidDayOfMonth": {
"defaultMessage": "日期必须在 1 到 {max} 之间"
},
"cronPicker.january": {
"defaultMessage": "一月"
},
@@ -536,6 +608,9 @@
"cronPicker.minute": {
"defaultMessage": "分"
},
"cronPicker.mode": {
"defaultMessage": "模式"
},
"cronPicker.monday": {
"defaultMessage": "周一"
},
@@ -554,12 +629,18 @@
"cronPicker.onDay": {
"defaultMessage": "于第几日"
},
"cronPicker.quarter": {
"defaultMessage": "季度"
},
"cronPicker.saturday": {
"defaultMessage": "周六"
},
"cronPicker.september": {
"defaultMessage": "九月"
},
"cronPicker.startingMonth": {
"defaultMessage": "起始月份"
},
"cronPicker.sunday": {
"defaultMessage": "周日"
},
@@ -875,9 +956,30 @@
"dictationSettings.voiceDictationProvider": {
"defaultMessage": "语音输入提供商"
},
"dirSwitcher.chooseDirectory": {
"defaultMessage": "选择目录…"
},
"dirSwitcher.currentDirectory": {
"defaultMessage": "当前目录"
},
"dirSwitcher.failedToUpdateWorkingDir": {
"defaultMessage": "更新工作目录失败"
},
"dirSwitcher.gitWorktrees": {
"defaultMessage": "Git 工作树"
},
"dirSwitcher.noWorktreesFound": {
"defaultMessage": "未找到工作树"
},
"dirSwitcher.openInFinder": {
"defaultMessage": "在文件管理器中打开"
},
"dirSwitcher.recentDirectories": {
"defaultMessage": "最近的目录"
},
"elicitationRequest.accept": {
"defaultMessage": "接受"
},
"elicitationRequest.cancelled": {
"defaultMessage": "信息请求已取消。"
},
@@ -1370,6 +1472,15 @@
"headersSection.value": {
"defaultMessage": "值"
},
"hub.goodAfternoon": {
"defaultMessage": "下午好"
},
"hub.goodEvening": {
"defaultMessage": "晚上好"
},
"hub.goodMorning": {
"defaultMessage": "早上好"
},
"huggingFaceModelSearch.download": {
"defaultMessage": "下载"
},
@@ -1406,6 +1517,21 @@
"huggingFaceModelSearch.tooLarge": {
"defaultMessage": "可能超出内存(模型 {size},可用 {available}"
},
"huggingFaceSignInPrompt.failedToConfigure": {
"defaultMessage": "登录 Hugging Face 失败:{error}"
},
"huggingFaceSignInPrompt.signIn": {
"defaultMessage": "登录"
},
"huggingFaceSignInPrompt.signedIn": {
"defaultMessage": "已登录 Hugging Face"
},
"huggingFaceSignInPrompt.signingIn": {
"defaultMessage": "正在登录..."
},
"huggingFaceSignInPrompt.title": {
"defaultMessage": "Hugging Face"
},
"imagePreview.altText": {
"defaultMessage": "goose 图片"
},
@@ -1745,6 +1871,9 @@
"localInferenceSettings.featuredModels": {
"defaultMessage": "推荐模型"
},
"localInferenceSettings.huggingFaceSignInNote": {
"defaultMessage": "登录后可在搜索和下载模型时提高速率限制,并访问私有或受限的 Hugging Face 仓库。"
},
"localInferenceSettings.modelSettings": {
"defaultMessage": "模型设置"
},
@@ -2123,24 +2252,6 @@
"modelSettingsPanel.batchSizeDescription": {
"defaultMessage": "提示词处理批大小"
},
"modelSettingsPanel.contextAndGeneration": {
"defaultMessage": "上下文与生成"
},
"modelSettingsPanel.contextSize": {
"defaultMessage": "上下文大小"
},
"modelSettingsPanel.contextSizeDescription": {
"defaultMessage": "最大上下文窗口(0 = 模型默认)"
},
"modelSettingsPanel.etaLearningRate": {
"defaultMessage": "Eta(学习率)"
},
"modelSettingsPanel.flashAttention": {
"defaultMessage": "Flash Attention"
},
"modelSettingsPanel.flashAttentionDescription": {
"defaultMessage": "启用 Flash Attention 优化"
},
"modelSettingsPanel.builtinChatTemplate": {
"defaultMessage": "内置模板"
},
@@ -2162,26 +2273,29 @@
"modelSettingsPanel.chatTemplateEmbedded": {
"defaultMessage": "嵌入式"
},
"modelSettingsPanel.contextAndGeneration": {
"defaultMessage": "上下文与生成"
},
"modelSettingsPanel.contextSize": {
"defaultMessage": "上下文大小"
},
"modelSettingsPanel.contextSizeDescription": {
"defaultMessage": "最大上下文窗口(0 = 模型默认)"
},
"modelSettingsPanel.customChatTemplate": {
"defaultMessage": "自定义聊天模板"
},
"modelSettingsPanel.customChatTemplateDescription": {
"defaultMessage": "粘贴完整的 Jinja 聊天模板源码"
},
"modelSettingsPanel.toolCalling": {
"defaultMessage": "工具调用"
"modelSettingsPanel.etaLearningRate": {
"defaultMessage": "Eta(学习率)"
},
"modelSettingsPanel.toolCallingAuto": {
"defaultMessage": "自动"
"modelSettingsPanel.flashAttention": {
"defaultMessage": "Flash Attention"
},
"modelSettingsPanel.toolCallingDescription": {
"defaultMessage": "选择本地模型如何使用原生或模拟工具调用"
},
"modelSettingsPanel.toolCallingForceEmulated": {
"defaultMessage": "强制模拟"
},
"modelSettingsPanel.toolCallingForceNative": {
"defaultMessage": "强制原生"
"modelSettingsPanel.flashAttentionDescription": {
"defaultMessage": "启用 Flash Attention 优化"
},
"modelSettingsPanel.frequencyPenalty": {
"defaultMessage": "频率惩罚"
@@ -2264,6 +2378,21 @@
"modelSettingsPanel.threadsDescription": {
"defaultMessage": "用于生成的 CPU 线程数"
},
"modelSettingsPanel.toolCalling": {
"defaultMessage": "工具调用"
},
"modelSettingsPanel.toolCallingAuto": {
"defaultMessage": "自动"
},
"modelSettingsPanel.toolCallingDescription": {
"defaultMessage": "选择本地模型如何使用原生或模拟工具调用"
},
"modelSettingsPanel.toolCallingForceEmulated": {
"defaultMessage": "强制模拟"
},
"modelSettingsPanel.toolCallingForceNative": {
"defaultMessage": "强制原生"
},
"modelSettingsPanel.topK": {
"defaultMessage": "Top K"
},
@@ -2312,12 +2441,27 @@
"navigation.itemScheduler": {
"defaultMessage": "调度"
},
"navigation.itemSessions": {
"defaultMessage": "会话历史"
},
"navigation.itemSettings": {
"defaultMessage": "设置"
},
"navigation.itemSkills": {
"defaultMessage": "技能"
},
"navigationPanel.chats": {
"defaultMessage": "聊天"
},
"navigationPanel.collapseSidebar": {
"defaultMessage": "折叠侧边栏"
},
"navigationPanel.noChats": {
"defaultMessage": "没有最近的聊天"
},
"navigationPanel.untitledSession": {
"defaultMessage": "未命名会话"
},
"onboardingGuard.checkProviderErrorDescription": {
"defaultMessage": "服务器可能正在启动或暂时不可用。"
},
@@ -2726,6 +2870,9 @@
"providerConfigurationModal.goBack": {
"defaultMessage": "返回"
},
"providerConfigurationModal.huggingFaceOAuthDescription": {
"defaultMessage": "登录后即可使用 Hugging Face Inference Providers,而无需手动输入 API 令牌。"
},
"providerConfigurationModal.oauthLoginFailed": {
"defaultMessage": "OAuth 登录失败:{error}"
},
@@ -3584,6 +3731,9 @@
"securityToggle.mlTokenDescription": {
"defaultMessage": "机器学习服务的认证令牌(例如 HuggingFace token"
},
"securityToggle.overrideNotice": {
"defaultMessage": "此设置由你的组织管理,无法更改。"
},
"securityToggle.promptInjectionDescription": {
"defaultMessage": "检测并防范潜在的提示注入攻击"
},
@@ -3593,6 +3743,9 @@
"securityToggle.thresholdDescription": {
"defaultMessage": "值越高越严格(0.01 = 非常宽松,1.0 = 最严格)"
},
"securityToggle.warpNotice": {
"defaultMessage": "连接到 WARP 时,命令注入检测效果最佳(访问分类服务需要 WARP)。"
},
"sessionHistory.cancel": {
"defaultMessage": "取消"
},
@@ -3737,6 +3890,9 @@
"sessions.action.openNewWindow": {
"defaultMessage": "在新窗口中打开"
},
"sessions.action.shareNostr": {
"defaultMessage": "分享加密的 Nostr 链接"
},
"sessions.cancel": {
"defaultMessage": "取消"
},
@@ -3746,6 +3902,9 @@
"sessions.chatHistoryDesc": {
"defaultMessage": "查看并搜索你与 Goose 的过往对话。按 {shortcut} 搜索。"
},
"sessions.close": {
"defaultMessage": "关闭"
},
"sessions.delete.message": {
"defaultMessage": "确定要删除会话“{name}”吗?此操作无法撤销。"
},
@@ -3770,12 +3929,24 @@
"sessions.error.tryAgain": {
"defaultMessage": "重试"
},
"sessions.extensions": {
"defaultMessage": "扩展:"
},
"sessions.import": {
"defaultMessage": "导入会话"
},
"sessions.importNostr": {
"defaultMessage": "导入链接"
},
"sessions.importNostr.description": {
"defaultMessage": "粘贴 Goose Nostr 分享链接以获取、解密并导入会话。"
},
"sessions.importNostr.placeholder": {
"defaultMessage": "goose://sessions/nostr?nevent=...&key=..."
},
"sessions.importNostr.title": {
"defaultMessage": "导入 Nostr 会话"
},
"sessions.importing": {
"defaultMessage": "正在导入..."
},
"sessions.loadingMore": {
"defaultMessage": "正在加载更多会话…"
},
@@ -3794,6 +3965,15 @@
"sessions.searchPlaceholder": {
"defaultMessage": "搜索历史…"
},
"sessions.shareNostr.description": {
"defaultMessage": "任何拥有此链接的人都可以获取并解密该会话。请像对待密钥一样保护它。"
},
"sessions.shareNostr.title": {
"defaultMessage": "加密的 Nostr 分享链接"
},
"sessions.toast.copied": {
"defaultMessage": "已复制到剪贴板"
},
"sessions.toast.deleteFailed": {
"defaultMessage": "删除会话“{name}”失败:{error}"
},
@@ -3815,6 +3995,12 @@
"sessions.toast.imported": {
"defaultMessage": "会话导入成功"
},
"sessions.toast.shareNostr": {
"defaultMessage": "已创建加密的 Nostr 分享链接"
},
"sessions.toast.shareNostrFailed": {
"defaultMessage": "创建 Nostr 分享链接失败:{error}"
},
"sessions.toast.updateFailed": {
"defaultMessage": "更新会话描述失败:{error}"
},
@@ -3941,6 +4127,9 @@
"settingsView.tabApp": {
"defaultMessage": "应用"
},
"settingsView.tabAuth": {
"defaultMessage": "身份验证"
},
"settingsView.tabChat": {
"defaultMessage": "聊天"
},
@@ -4241,6 +4430,9 @@
"switchModelModal.thinkingEffort": {
"defaultMessage": "思考努力"
},
"switchModelModal.thinkingEffortOff": {
"defaultMessage": "关闭 - 不使用扩展思考"
},
"switchModelModal.thinkingLevel": {
"defaultMessage": "思考级别"
},
+3
View File
@@ -226,6 +226,9 @@ importers:
'@formatjs/cli':
specifier: ^6.14.0
version: 6.14.0
'@formatjs/icu-messageformat-parser':
specifier: 3.5.3
version: 3.5.3
'@hey-api/openapi-ts':
specifier: ^0.93.0
version: 0.93.1(magicast@0.5.2)(typescript@5.9.3)