feat: 完成AccountForm组件剩余模块国际化

This commit is contained in:
Wangnov
2025-09-09 16:26:48 +08:00
parent 1beed324d9
commit be7416386f
4 changed files with 530 additions and 86 deletions

View File

@@ -23,7 +23,7 @@
</button>
</div>
<!-- 步骤指示器 -->
<!-- {{ t('accountForm.stepIndicator') }} -->
<div
v-if="!isEdit && (form.addType === 'oauth' || form.addType === 'setup-token')"
class="mb-4 flex items-center justify-center sm:mb-8"
@@ -61,7 +61,7 @@
</div>
</div>
<!-- 步骤1: 基本信息和代理设置 -->
<!-- {{ t('accountForm.step1BasicInfo') }} -->
<div v-if="oauthStep === 1 && !isEdit">
<div class="space-y-6">
<div v-if="!isEdit">
@@ -237,14 +237,14 @@
</p>
</div>
<!-- 分组选择器 -->
<!-- {{ t('accountForm.groupSelector') }} -->
<div v-if="form.accountType === 'group'">
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>{{ t('accountForm.selectGroupRequired') }}</label
>
<div class="flex gap-2">
<div class="flex-1">
<!-- 多选分组界面 -->
<!-- {{ t('accountForm.multiSelectGroup') }} -->
<div
class="max-h-48 space-y-2 overflow-y-auto rounded-md border p-3 dark:border-gray-600 dark:bg-gray-700"
>
@@ -269,7 +269,7 @@
{{ group.name }} ({{ group.memberCount || 0 }} {{ t('accountForm.memberCount') }})
</span>
</label>
<!-- 新建分组选项 -->
<!-- {{ t('accountForm.newGroupOption') }} -->
<div class="border-t pt-2 dark:border-gray-600">
<button
class="flex items-center gap-2 text-sm text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"
@@ -292,31 +292,30 @@
</div>
</div>
<!-- Gemini 项目 ID 字段 -->
<!-- {{ t('accountForm.geminiProjectId') }} -->
<div v-if="form.platform === 'gemini'">
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>项目 ID (可选)</label
>{{ t('accountForm.projectIdOptional') }}</label
>
<input
v-model="form.projectId"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
placeholder="例如verdant-wares-464411-k9"
:placeholder="t('accountForm.projectIdPlaceholder')"
type="text"
/>
<div class="mt-2 rounded-lg border border-yellow-200 bg-yellow-50 p-3">
<div class="flex items-start gap-2">
<i class="fas fa-info-circle mt-0.5 text-yellow-600" />
<div class="text-xs text-yellow-700">
<p class="mb-1 font-medium">Google Cloud/Workspace 账号需要提供项目 ID</p>
<p class="mb-1 font-medium">{{ t('accountForm.geminiProjectIdRequired') }}</p>
<p>
某些 Google 账号(特别是绑定了 Google Cloud 的账号)会被识别为 Workspace
账号,需要提供额外的项目 ID。
{{ t('accountForm.geminiProjectIdDetail') }}
</p>
<div class="mt-2 rounded border border-yellow-300 bg-white p-2">
<p class="mb-1 font-medium">如何获取项目 ID</p>
<p class="mb-1 font-medium">{{ t('accountForm.geminiHowToGetProjectId') }}</p>
<ol class="ml-2 list-inside list-decimal space-y-1">
<li>
访问
{{ t('accountForm.geminiVisitConsole') }}
<a
class="font-medium text-blue-600 hover:underline"
href="https://console.cloud.google.com/welcome"
@@ -325,24 +324,22 @@
>
</li>
<li>
复制<span class="font-semibold text-red-600">项目 IDProject ID</span
>,通常是字符串格式
{{ t('accountForm.geminiCopyProjectId') }}
</li>
<li class="text-red-600">
⚠️ 注意:要复制项目 IDProject ID不要复制项目编号Project Number
{{ t('accountForm.geminiProjectIdWarning') }}
</li>
</ol>
</div>
<p class="mt-2">
<strong>提示:</strong>如果您的账号是普通个人账号(未绑定 Google
Cloud请留空此字段。
{{ t('accountForm.geminiPersonalAccountTip') }}
</p>
</div>
</div>
</div>
</div>
<!-- Bedrock 特定字段 -->
<!-- {{ t('accountForm.bedrockFields') }} -->
<div v-if="form.platform === 'bedrock' && !isEdit" class="space-y-4">
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
@@ -397,16 +394,16 @@
<div class="flex items-start gap-2">
<i class="fas fa-info-circle mt-0.5 text-blue-600" />
<div class="text-xs text-blue-700">
<p class="mb-1 font-medium">常用 AWS 区域参考:</p>
<p class="mb-1 font-medium">{{ t('accountForm.awsRegionReference') }}</p>
<div class="grid grid-cols-2 gap-1 text-xs">
<span>• us-east-1 (美国东部)</span>
<span>• us-west-2 (美国西部)</span>
<span>• eu-west-1 (欧洲爱尔兰)</span>
<span>• ap-southeast-1 (新加坡)</span>
<span>• ap-northeast-1 (东京)</span>
<span>• eu-central-1 (法兰克福)</span>
<span>• {{ t('accountForm.awsRegionEastUS') }}</span>
<span>• {{ t('accountForm.awsRegionWestUS') }}</span>
<span>• {{ t('accountForm.awsRegionEuropeIreland') }}</span>
<span>• {{ t('accountForm.awsRegionAsiaSingapore') }}</span>
<span>• {{ t('accountForm.awsRegionAsiaTokyo') }}</span>
<span>• {{ t('accountForm.awsRegionEuropeFrankfurt') }}</span>
</div>
<p class="mt-2 text-blue-600">💡 请输入完整的区域代码,如 us-east-1</p>
<p class="mt-2 text-blue-600">{{ t('accountForm.awsRegionInputTip') }}</p>
</div>
</div>
</div>
@@ -444,12 +441,12 @@
<div class="flex items-start gap-2">
<i class="fas fa-info-circle mt-0.5 text-amber-600" />
<div class="text-xs text-amber-700">
<p class="mb-1 font-medium">Bedrock 模型配置说明:</p>
<p class="mb-1 font-medium">{{ t('accountForm.bedrockModelConfigDesc') }}</p>
<ul class="list-inside list-disc space-y-1 text-xs">
<li>支持 Inference Profile ID推荐</li>
<li>支持 Application Inference Profile ARN</li>
<li>常用模型us.anthropic.claude-sonnet-4-20250514-v1:0</li>
<li>留空将使用系统配置的默认模型</li>
<li>{{ t('accountForm.bedrockSupportsInferenceProfile') }}</li>
<li>{{ t('accountForm.bedrockSupportsARN') }}</li>
<li>{{ t('accountForm.bedrockCommonModel') }}</li>
<li>{{ t('accountForm.bedrockEmptyUsesDefault') }}</li>
</ul>
</div>
</div>
@@ -472,7 +469,7 @@
</div>
</div>
<!-- Azure OpenAI 特定字段 -->
<!-- {{ t('accountForm.azureOpenAIFields') }} -->
<div v-if="form.platform === 'azure_openai' && !isEdit" class="space-y-4">
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
@@ -579,7 +576,7 @@
</label>
</div>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
选择此部署支持的模型类型
{{ t('accountForm.azureModelSelectionDesc') }}
</p>
</div>
</div>
@@ -587,7 +584,7 @@
<div v-if="form.platform === 'bedrock' && !isEdit">
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>限流机制</label
>{{ t('accountForm.rateLimitMechanism') }}</label
>
<div class="mb-3">
<label class="inline-flex cursor-pointer items-center">
@@ -596,32 +593,32 @@
class="mr-2 rounded border-gray-300 text-blue-600 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:border-gray-600 dark:bg-gray-700"
type="checkbox"
/>
<span class="text-sm text-gray-700 dark:text-gray-300">启用限流机制</span>
<span class="text-sm text-gray-700 dark:text-gray-300">{{ t('accountForm.enableRateLimitMechanism') }}</span>
</label>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
启用后当账号返回429错误时将暂停调度一段时间
{{ t('accountForm.rateLimitDescription2') }}
</p>
</div>
<div v-if="form.enableRateLimit">
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>限流时间 (分钟)</label
>{{ t('accountForm.rateLimitDurationMinutes') }}</label
>
<input
v-model.number="form.rateLimitDuration"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
min="1"
placeholder="默认60分钟"
:placeholder="t('accountForm.rateLimitDefault60')"
type="number"
/>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
账号被限流后暂停调度的时间(分钟)
{{ t('accountForm.rateLimitPauseDescription') }}
</p>
</div>
</div>
</div>
<!-- Claude Console 特定字段 -->
<!-- {{ t('accountForm.claudeConsoleFields') }} -->
<div v-if="form.platform === 'claude-console' && !isEdit" class="space-y-4">
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
@@ -631,7 +628,7 @@
v-model="form.apiUrl"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
:class="{ 'border-red-500': errors.apiUrl }"
placeholder="例如https://api.example.com"
:placeholder="t('accountForm.apiUrlPlaceholder')"
required
type="text"
/>
@@ -648,7 +645,7 @@
v-model="form.apiKey"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
:class="{ 'border-red-500': errors.apiKey }"
placeholder="请输入API Key"
:placeholder="t('accountForm.apiKeyPlaceholder')"
required
type="password"
/>
@@ -657,28 +654,28 @@
</p>
</div>
<!-- 额度管理字段 -->
<!-- {{ t('accountForm.quotaManagement') }} -->
<div class="grid grid-cols-2 gap-4">
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300">
每日额度限制 ($)
{{ t('accountForm.dailyQuotaLimit') }}
</label>
<input
v-model.number="form.dailyQuota"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
min="0"
placeholder="0 表示不限制"
:placeholder="t('accountForm.quotaZeroUnlimited')"
step="0.01"
type="number"
/>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
设置每日使用额度0 表示不限制
{{ t('accountForm.dailyQuotaDescription') }}
</p>
</div>
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300">
额度重置时间
{{ t('accountForm.quotaResetTime') }}
</label>
<input
v-model="form.quotaResetTime"
@@ -687,23 +684,23 @@
type="time"
/>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
每日自动重置额度的时间
{{ t('accountForm.quotaResetTimeDescription') }}
</p>
</div>
</div>
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>模型映射表 (可选)</label
>{{ t('accountForm.modelMappingTableOptional') }}</label
>
<div class="mb-3 rounded-lg bg-blue-50 p-3 dark:bg-blue-900/30">
<p class="text-xs text-blue-700 dark:text-blue-400">
<i class="fas fa-info-circle mr-1" />
留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。
{{ t('accountForm.modelMappingDescription') }}
</p>
</div>
<!-- 模型映射表 -->
<!-- {{ t('accountForm.modelMappingTable') }} -->
<div class="mb-3 space-y-2">
<div
v-for="(mapping, index) in modelMappings"
@@ -740,7 +737,7 @@
@click="addModelMapping"
>
<i class="fas fa-plus mr-2" />
添加模型映射
{{ t('accountForm.addModelMapping') }}
</button>
<!-- 快捷添加按钮 -->
@@ -804,7 +801,7 @@
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>限流机制</label
>{{ t('accountForm.rateLimitMechanism') }}</label
>
<div class="mb-3">
<label class="inline-flex cursor-pointer items-center">
@@ -813,35 +810,35 @@
class="mr-2 rounded border-gray-300 text-blue-600 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:border-gray-600 dark:bg-gray-700"
type="checkbox"
/>
<span class="text-sm text-gray-700 dark:text-gray-300">启用限流机制</span>
<span class="text-sm text-gray-700 dark:text-gray-300">{{ t('accountForm.enableRateLimitMechanism') }}</span>
</label>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
启用后当账号返回429错误时将暂停调度一段时间
{{ t('accountForm.rateLimitDescription2') }}
</p>
</div>
<div v-if="form.enableRateLimit">
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>限流时间 (分钟)</label
>{{ t('accountForm.rateLimitDurationMinutes') }}</label
>
<input
v-model.number="form.rateLimitDuration"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
min="1"
placeholder="默认60分钟"
:placeholder="t('accountForm.rateLimitDefault60')"
type="number"
/>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
账号被限流后暂停调度的时间(分钟)
{{ t('accountForm.rateLimitPauseDescription') }}
</p>
</div>
</div>
</div>
<!-- Claude 订阅类型选择 -->
<!-- {{ t('accountForm.subscriptionType') }} -->
<div v-if="form.platform === 'claude'">
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>订阅类型</label
>{{ t('accountForm.subscriptionType') }}</label
>
<div class="flex gap-4">
<label class="flex cursor-pointer items-center">
@@ -1201,9 +1198,9 @@
@success="handleOAuthSuccess"
/>
<!-- 步骤2: Setup Token授权 -->
<!-- 步骤2: {{ t('accountForm.setupTokenAuth') }} -->
<div v-if="oauthStep === 2 && form.addType === 'setup-token'" class="space-y-6">
<!-- Claude Setup Token流程 -->
<!-- {{ t('accountForm.claudeSetupTokenAuth') }} -->
<div v-if="form.platform === 'claude'">
<div
class="rounded-lg border border-blue-200 bg-blue-50 p-6 dark:border-blue-700 dark:bg-blue-900/30"
@@ -1216,10 +1213,10 @@
</div>
<div class="flex-1">
<h4 class="mb-3 font-semibold text-blue-900 dark:text-blue-200">
Claude Setup Token 授权
{{ t('accountForm.claudeSetupTokenAuth') }}
</h4>
<p class="mb-4 text-sm text-blue-800 dark:text-blue-300">
请按照以下步骤通过 Setup Token 完成 Claude 账户的授权:
{{ t('accountForm.setupTokenAuthSteps') }}
</p>
<div class="space-y-4">
@@ -1245,7 +1242,7 @@
>
<i v-if="!setupTokenLoading" class="fas fa-link mr-2" />
<div v-else class="loading-spinner mr-2" />
{{ setupTokenLoading ? '生成中...' : '生成 Setup Token 授权链接' }}
{{ setupTokenLoading ? t('accountForm.generating') : t('accountForm.generateSetupTokenLink') }}
</button>
<div v-else class="space-y-3">
<div class="flex items-center gap-2">
@@ -1368,7 +1365,7 @@
@click="exchangeSetupTokenCode"
>
<div v-if="setupTokenExchanging" class="loading-spinner mr-2" />
{{ setupTokenExchanging ? '验证中...' : '完成授权' }}
{{ setupTokenExchanging ? t('accountForm.verifying') : t('accountForm.completeAuth') }}
</button>
</div>
</div>
@@ -1510,7 +1507,7 @@
</p>
</div>
<!-- Claude 订阅类型选择(编辑模式) -->
<!-- Claude {{ t('accountForm.subscriptionType') }}(编辑模式) -->
<div v-if="form.platform === 'claude'">
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>{{ t('accountForm.subscriptionType') }}</label
@@ -1680,7 +1677,7 @@
</p>
</div>
<!-- Claude Console 特定字段(编辑模式)-->
<!-- {{ t('accountForm.claudeConsoleFields') }}(编辑模式)-->
<div v-if="form.platform === 'claude-console'" class="space-y-4">
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700">API URL</label>
@@ -1704,7 +1701,7 @@
<p class="mt-1 text-xs text-gray-500">留空表示不更新 API Key</p>
</div>
<!-- 额度管理字段 -->
<!-- {{ t('accountForm.quotaManagement') }} -->
<div class="grid grid-cols-2 gap-4">
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300">
@@ -1784,7 +1781,7 @@
</p>
</div>
<!-- 模型映射表 -->
<!-- {{ t('accountForm.modelMappingTable') }} -->
<div class="mb-3 space-y-2">
<div
v-for="(mapping, index) in modelMappings"
@@ -1878,7 +1875,7 @@
</div>
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700">限流机制</label>
<label class="mb-3 block text-sm font-semibold text-gray-700">{{ t('accountForm.rateLimitMechanism') }}</label>
<div class="mb-3">
<label class="inline-flex cursor-pointer items-center">
<input
@@ -1886,7 +1883,7 @@
class="mr-2 rounded border-gray-300 text-blue-600 focus:border-blue-500 focus:ring focus:ring-blue-200"
type="checkbox"
/>
<span class="text-sm text-gray-700">启用限流机制</span>
<span class="text-sm text-gray-700">{{ t('accountForm.enableRateLimitMechanism') }}</span>
</label>
<p class="mt-1 text-xs text-gray-500">
启用后当账号返回429错误时将暂停调度一段时间
@@ -1997,7 +1994,7 @@
</div>
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700">限流机制</label>
<label class="mb-3 block text-sm font-semibold text-gray-700">{{ t('accountForm.rateLimitMechanism') }}</label>
<div class="mb-3">
<label class="inline-flex cursor-pointer items-center">
<input
@@ -2005,7 +2002,7 @@
class="mr-2 rounded border-gray-300 text-blue-600 focus:border-blue-500 focus:ring focus:ring-blue-200"
type="checkbox"
/>
<span class="text-sm text-gray-700">启用限流机制</span>
<span class="text-sm text-gray-700">{{ t('accountForm.enableRateLimitMechanism') }}</span>
</label>
<p class="mt-1 text-xs text-gray-500">
启用后当账号返回429错误时将暂停调度一段时间
@@ -2195,7 +2192,7 @@
@click="updateAccount"
>
<div v-if="loading" class="loading-spinner mr-2" />
{{ loading ? '更新中...' : '更新' }}
{{ loading ? t('accountForm.updating') : t('accountForm.update') }}
</button>
</div>
</div>
@@ -2518,7 +2515,7 @@ const generateSetupTokenAuthUrl = async () => {
setupTokenAuthUrl.value = result.authUrl
setupTokenSessionId.value = result.sessionId
} catch (error) {
showToast(error.message || '生成Setup Token授权链接失败', 'error')
showToast(error.message || t('accountForm.generateSetupTokenFailed'), 'error')
} finally {
setupTokenLoading.value = false
}
@@ -2556,7 +2553,7 @@ const copySetupTokenAuthUrl = async () => {
setupTokenCopied.value = true
showToast(t('accountForm.linkCopied'), 'success')
} else {
showToast('复制失败,请手动复制', 'error')
showToast(t('accountForm.copyFailed'), 'error')
}
} catch (err) {
showToast('复制失败,请手动复制', 'error')
@@ -2601,7 +2598,7 @@ const exchangeSetupTokenCode = async () => {
// 调用相同的成功处理函数
await handleOAuthSuccess(tokenInfo)
} catch (error) {
showToast(error.message || 'Setup Token授权失败,请检查授权码是否正确', 'error')
showToast(error.message || t('accountForm.setupTokenAuthFailed'), 'error')
} finally {
setupTokenExchanging.value = false
}
@@ -2678,7 +2675,7 @@ const handleOAuthSuccess = async (tokenInfo) => {
emit('success', result)
} catch (error) {
// 显示详细的错误信息
const errorMessage = error.response?.data?.error || error.message || '账户创建失败'
const errorMessage = error.response?.data?.error || error.message || t('accountForm.accountCreationFailed')
const suggestion = error.response?.data?.suggestion || ''
const errorDetails = error.response?.data?.errorDetails || null
@@ -2699,7 +2696,7 @@ const handleOAuthSuccess = async (tokenInfo) => {
showToast(fullMessage, 'error', '', 8000)
// 在控制台打印完整的错误信息以便调试
console.error('账户创建失败:', {
console.error(t('accountForm.accountCreationError'), {
message: errorMessage,
suggestion,
errorDetails,
@@ -2722,14 +2719,14 @@ const createAccount = async () => {
let hasError = false
if (!form.value.name || form.value.name.trim() === '') {
errors.value.name = '请填写账户名称'
errors.value.name = t('accountForm.nameRequired')
hasError = true
}
// Claude Console 验证
if (form.value.platform === 'claude-console') {
if (!form.value.apiUrl || form.value.apiUrl.trim() === '') {
errors.value.apiUrl = '请填写 API URL'
errors.value.apiUrl = t('accountForm.apiUrlRequired')
hasError = true
}
if (!form.value.apiKey || form.value.apiKey.trim() === '') {

View File

@@ -1479,6 +1479,155 @@ export default {
// Usage Statistics
usageStats: 'Usage Statistics',
loadingUsage: 'Loading usage...',
usageLoadFailed: 'Failed to load usage'
usageLoadFailed: 'Failed to load usage',
// Gemini Project ID Details
geminiProjectIdRequired: 'Google Cloud/Workspace accounts require Project ID',
geminiProjectIdDetail: 'Some Google accounts (especially those bound to Google Cloud) will be identified as Workspace accounts and require additional Project ID.',
geminiHowToGetProjectId: 'How to get Project ID:',
geminiVisitConsole: 'Visit',
geminiCopyProjectId: 'Copy Project ID (Project ID), usually in string format',
geminiProjectIdWarning: '⚠️ Note: Copy Project ID (Project ID), not Project Number (Project Number)!',
geminiPersonalAccountTip: 'Tip: If your account is a regular personal account (not bound to Google Cloud), please leave this field empty.',
// AWS Region Reference
awsRegionReference: 'Common AWS regions reference:',
awsRegionEastUS: 'us-east-1 (US East)',
awsRegionWestUS: 'us-west-2 (US West)',
awsRegionEuropeIreland: 'eu-west-1 (Europe Ireland)',
awsRegionAsiaSingapore: 'ap-southeast-1 (Singapore)',
awsRegionAsiaTokyo: 'ap-northeast-1 (Tokyo)',
awsRegionEuropeFrankfurt: 'eu-central-1 (Frankfurt)',
awsRegionInputTip: '💡 Please enter complete region code, e.g. us-east-1',
// Bedrock Model Description
bedrockModelConfigDesc: 'Bedrock model configuration description:',
bedrockSupportsInferenceProfile: 'Supports Inference Profile ID (recommended)',
bedrockSupportsARN: 'Supports Application Inference Profile ARN',
bedrockCommonModel: 'Common model: us.anthropic.claude-sonnet-4-20250514-v1:0',
bedrockEmptyUsesDefault: 'Leave empty to use system configured default model',
// Azure OpenAI Model Selection
azureModelSelectionDesc: 'Select model types supported by this deployment',
// Rate Limiting
rateLimitMechanism: 'Rate limiting mechanism',
enableRateLimitMechanism: 'Enable rate limiting mechanism',
rateLimitDescription2: 'When enabled, will pause scheduling for some time when account returns 429 error',
rateLimitDurationMinutes: 'Rate limit duration (minutes)',
rateLimitDefaultMinutes: 'Default 60 minutes',
rateLimitPauseDesc: 'Time to pause scheduling after account is rate limited (minutes)',
// Claude Console Specific Fields
claudeConsoleFields: 'Claude Console specific fields',
quotaManagement: 'Quota management',
modelMappingTable: 'Model mapping table',
modelMappingTableOptional: 'Model mapping table (optional)',
addModelMapping: 'Add model mapping',
// Claude Subscription Type
subscriptionType: 'Subscription type',
// Setup Token Auth
setupTokenAuth: 'Setup Token authorization',
claudeSetupTokenAuth: 'Claude Setup Token authorization',
setupTokenAuthSteps: 'Please follow these steps to complete Claude account authorization through Setup Token:',
generateSetupTokenLink: 'Generate Setup Token auth link',
generating: 'Generating...',
// Buttons and actions
verifying: 'Verifying...',
completeAuth: 'Complete authorization',
updating: 'Updating...',
update: 'Update',
// Error messages
generateSetupTokenFailed: 'Failed to generate Setup Token auth link',
copyFailed: 'Copy failed, please copy manually',
setupTokenAuthFailed: 'Setup Token authorization failed, please check if the authorization code is correct',
accountCreationFailed: 'Account creation failed',
accountCreationError: 'Account creation failed:',
// Page structure comments
stepIndicator: 'Step indicator',
step1BasicInfo: 'Step 1: Basic information and proxy settings',
groupSelector: 'Group selector',
multiSelectGroup: 'Multi-select group interface',
newGroupOption: 'New group option',
geminiProjectId: 'Gemini project ID field',
bedrockFields: 'Bedrock specific fields',
azureOpenAIFields: 'Azure OpenAI specific fields',
// Validation messages
nameRequired: 'Please enter account name',
apiUrlRequired: 'Please enter API URL',
rateLimitDefault60: 'Default 60 minutes',
rateLimitPauseDescription: 'Time to pause scheduling after account is rate limited (minutes)',
apiUrlPlaceholder: 'e.g., https://api.example.com',
apiKeyPlaceholder: 'Please enter API Key',
dailyQuotaLimit: 'Daily quota limit ($)',
quotaZeroUnlimited: '0 means unlimited',
dailyQuotaDescription: 'Set daily usage quota, 0 means unlimited',
quotaResetTime: 'Quota reset time',
quotaResetTimeDescription: 'Time to automatically reset quota daily',
modelMappingDescription: 'Leave empty to support all models without modifying requests. After configuring mapping, left model will be recognized as supported model, right is the actual model sent.',
// Quota Management
quotaManagementFields: 'Quota management fields',
dailyQuotaLimitDollar: 'Daily quota limit ($)',
quotaZeroUnlimited: '0 means unlimited',
dailyQuotaDesc: 'Set daily usage quota, 0 means unlimited',
quotaResetTime: 'Quota reset time',
quotaResetTimeDesc: 'Time to automatically reset quota daily',
// Model Mapping
modelMappingOptional: 'Model mapping table (optional)',
modelMappingDesc: 'Leave empty to support all models without modifying requests. After configuring mapping, left model will be recognized as supported model, right is the actual model sent.',
originalModelName: 'Original model name',
mappedModelName: 'Mapped model name',
addModelMappingBtn: 'Add model mapping',
customUserAgentOptional: 'Custom User-Agent (optional)',
customUserAgentDesc: 'When empty, will automatically use client User-Agent, only fill when need to fix specific UA',
userAgentPassthrough: 'Leave empty to pass through client User-Agent',
// Claude Subscription Type
claudeSubscriptionType: 'Subscription type',
claudeProLimitation: 'Pro accounts do not support Claude Opus 4 model',
// Claude Advanced Options
claudeAutoStopScheduling: 'Auto-stop scheduling when approaching 5-hour limit',
claudeAutoStopDesc: 'When system detects account approaching 5-hour usage limit, automatically pause scheduling for this account. Will resume automatically when entering new time window.',
claudeUseUnifiedUA: 'Use unified Claude Code version',
claudeUnifiedUADesc: 'When enabled, will use unified User-Agent captured from real Claude Code client, improving compatibility',
claudeCurrentUnifiedVersion: '💡 Current unified version:',
claudeWaitingCapture: '⏳ Waiting to capture User-Agent from Claude Code client',
claudeCaptureHint: '💡 Hint: If unable to capture for long time, please confirm Claude Code client is using this account, or contact developer to check if User-Agent format has changed',
claudeUseUnifiedClientId: 'Use unified client identifier',
claudeUnifiedClientIdDesc: 'When enabled, will use fixed client identifier, making all requests appear to come from same client, reducing characteristics',
claudeClientIdLabel: 'Client identifier ID',
claudeClientIdDesc: 'This ID will replace user_id client part in requests, preserving session part for sticky sessions',
// Setup Token Process
setupTokenAuthProcess: 'Claude Setup Token Authorization',
setupTokenProcessDesc: 'Please follow these steps to complete Claude account authorization through Setup Token:',
setupTokenStepOneTitle: 'Step 1: Generate authorization link',
setupTokenStepOneDesc: 'Click button below to generate authorization link',
setupTokenGenerating: 'Generating...',
setupTokenGenerateBtn: 'Generate Setup Token authorization link',
setupTokenCopyTitle: 'Copy link',
// Step Indicators
stepIndicator: 'Step indicator',
step1BasicInfo: 'Step 1: Basic information and proxy settings',
step2OAuth: 'Step 2: OAuth authorization',
step2SetupToken: 'Step 2: Setup Token authorization',
// Group Selector
groupSelector: 'Group selector',
multiGroupInterface: 'Multi-group interface',
createNewGroupOption: 'Create new group option',
// Manual Token Input Tips
credentialsFromFile: 'credentials from file.'
}
}

View File

@@ -1479,6 +1479,155 @@ export default {
// 使用情况和统计
usageStats: '使用统计',
loadingUsage: '加载使用情况...',
usageLoadFailed: '使用情况加载失败'
usageLoadFailed: '使用情况加载失败',
// Gemini 项目 ID 详细说明
geminiProjectIdRequired: 'Google Cloud/Workspace 账号需要提供项目 ID',
geminiProjectIdDetail: '某些 Google 账号(特别是绑定了 Google Cloud 的账号)会被识别为 Workspace 账号,需要提供额外的项目 ID。',
geminiHowToGetProjectId: '如何获取项目 ID',
geminiVisitConsole: '访问',
geminiCopyProjectId: '复制\u9879目 IDProject ID\uff0c通常是字符串格式',
geminiProjectIdWarning: '⚠️ 注意:要复制项目 IDProject ID不要复制项目编号Project Number',
geminiPersonalAccountTip: '\u63d0示\uff1a如果您的账号是普通个人账号未绑定 Google Cloud请留空此字段。',
// AWS 区域参考
awsRegionReference: '常用 AWS 区域参考:',
awsRegionEastUS: 'us-east-1 (美国东部)',
awsRegionWestUS: 'us-west-2 (美国西部)',
awsRegionEuropeIreland: 'eu-west-1 (欧洲爱尔兰)',
awsRegionAsiaSingapore: 'ap-southeast-1 (新加坡)',
awsRegionAsiaTokyo: 'ap-northeast-1 (东京)',
awsRegionEuropeFrankfurt: 'eu-central-1 (法兰克福)',
awsRegionInputTip: '💡 请输入完整的区域代码,如 us-east-1',
// Bedrock 模型说明
bedrockModelConfigDesc: 'Bedrock 模型配置说明:',
bedrockSupportsInferenceProfile: '支持 Inference Profile ID推荐',
bedrockSupportsARN: '支持 Application Inference Profile ARN',
bedrockCommonModel: '常用模型us.anthropic.claude-sonnet-4-20250514-v1:0',
bedrockEmptyUsesDefault: '留空将使用系统配置的默认模型',
// Azure OpenAI 模型选择
azureModelSelectionDesc: '选择此部署支持的模型类型',
// 限流机制
rateLimitMechanism: '限流机制',
enableRateLimitMechanism: '启用限流机制',
rateLimitDescription2: '启用后当账号返回429错误时将暂停调度一段时间',
// Claude Console 特定字段
claudeConsoleFields: 'Claude Console 特定字段',
quotaManagement: '额度管理',
modelMappingTable: '模型映射表',
modelMappingTableOptional: '模型映射表 (可选)',
addModelMapping: '添加模型映射',
// Claude 订阅类型
subscriptionType: '订阅类型',
// Setup Token 授权
setupTokenAuth: 'Setup Token 授权',
claudeSetupTokenAuth: 'Claude Setup Token 授权',
setupTokenAuthSteps: '请按照以下步骤通过 Setup Token 完成 Claude 账户的授权:',
generateSetupTokenLink: '生成 Setup Token 授权链接',
generating: '生成中...',
// 按钮和操作
verifying: '验证中...',
completeAuth: '完成授权',
updating: '更新中...',
update: '更新',
// 错误消息
generateSetupTokenFailed: '生成Setup Token授权链接失败',
copyFailed: '复制失败,请手动复制',
setupTokenAuthFailed: 'Setup Token授权失败请检查授权码是否正确',
accountCreationFailed: '账户创建失败',
accountCreationError: '账户创建失败:',
// 页面结构注释
stepIndicator: '步骤指示器',
step1BasicInfo: '步骤1: 基本信息和代理设置',
groupSelector: '分组选择器',
multiSelectGroup: '多选分组界面',
newGroupOption: '新建分组选项',
geminiProjectId: 'Gemini 项目 ID 字段',
bedrockFields: 'Bedrock 特定字段',
azureOpenAIFields: 'Azure OpenAI 特定字段',
// 验证消息
nameRequired: '请填写账户名称',
apiUrlRequired: '请填写 API URL',
rateLimitDefault60: '默认60分钟',
rateLimitPauseDescription: '账号被限流后暂停调度的时间(分钟)',
apiUrlPlaceholder: '例如https://api.example.com',
apiKeyPlaceholder: '请输入API Key',
dailyQuotaLimit: '每日额度限制 ($)',
quotaZeroUnlimited: '0 表示不限制',
dailyQuotaDescription: '设置每日使用额度0 表示不限制',
quotaResetTime: '额度重置时间',
quotaResetTimeDescription: '每日自动重置额度的时间',
modelMappingDescription: '留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。',
rateLimitDurationMinutes: '限流时间 (分钟)',
rateLimitDefaultMinutes: '默认60分钟',
rateLimitPauseDesc: '账号被限流后暂停调度的时间(分钟)',
// 额度管理
quotaManagementFields: '额度管理字段',
dailyQuotaLimitDollar: '每日额度限制 ($)',
quotaZeroUnlimited: '0 表示不限制',
dailyQuotaDesc: '设置每日使用额度0 表示不限制',
quotaResetTime: '额度重置时间',
quotaResetTimeDesc: '每日自动重置额度的时间',
// 模型映射
modelMappingOptional: '模型映射表 (可选)',
modelMappingDesc: '留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。',
originalModelName: '原始模型名称',
mappedModelName: '映射后的模型名称',
addModelMappingBtn: '添加模型映射',
customUserAgentOptional: '自定义 User-Agent (可选)',
customUserAgentDesc: '留空时将自动使用客户端的 User-Agent仅在需要固定特定 UA 时填写',
userAgentPassthrough: '留空则透传客户端 User-Agent',
// Claude 订阅类型
claudeSubscriptionType: '订阅类型',
claudeProLimitation: 'Pro 账号不支持 Claude Opus 4 模型',
// Claude 高级选项
claudeAutoStopScheduling: '5小时使用量接近限制时自动停止调度',
claudeAutoStopDesc: '当系统检测到账户接近5小时使用限制时自动暂停调度该账户。进入新的时间窗口后会自动恢复调度。',
claudeUseUnifiedUA: '使用统一 Claude Code 版本',
claudeUnifiedUADesc: '开启后将使用从真实 Claude Code 客户端捕获的统一 User-Agent提高兼容性',
claudeCurrentUnifiedVersion: '💡 当前统一版本:',
claudeWaitingCapture: '⏳ 等待从 Claude Code 客户端捕获 User-Agent',
claudeCaptureHint: '💡 提示:如果长时间未能捕获,请确认有 Claude Code 客户端正在使用此账户, 或联系开发者检查 User-Agent 格式是否发生变化',
claudeUseUnifiedClientId: '使用统一的客户端标识',
claudeUnifiedClientIdDesc: '开启后将使用固定的客户端标识,使所有请求看起来来自同一个客户端,减少特征',
claudeClientIdLabel: '客户端标识 ID',
claudeClientIdDesc: '此ID将替换请求中的user_id客户端部分保留session部分用于粘性会话',
// Setup Token 流程
setupTokenAuthProcess: 'Claude Setup Token 授权',
setupTokenProcessDesc: '请按照以下步骤通过 Setup Token 完成 Claude 账户的授权:',
setupTokenStepOneTitle: '步骤 1生成授权链接',
setupTokenStepOneDesc: '点击下方按钮生成授权链接',
setupTokenGenerating: '生成中...',
setupTokenGenerateBtn: '生成 Setup Token 授权链接',
setupTokenCopyTitle: '复制链接',
// 步骤指示器
stepIndicator: '步骤指示器',
step1BasicInfo: '步骤1: 基本信息和代理设置',
step2OAuth: '步骤2: OAuth授权',
step2SetupToken: '步骤2: Setup Token授权',
// 分组选择器
groupSelector: '分组选择器',
multiGroupInterface: '多选分组界面',
createNewGroupOption: '新建分组选项',
// 手动输入Token提示
credentialsFromFile: '文件中的凭证。'
}
}

View File

@@ -1479,6 +1479,155 @@ export default {
// 使用情況和統計
usageStats: '使用統計',
loadingUsage: '載入使用情況...',
usageLoadFailed: '使用情況載入失敗'
usageLoadFailed: '使用情況載入失敗',
// Gemini 專案 ID 詳細說明
geminiProjectIdRequired: 'Google Cloud/Workspace 帳戶需要提供專案 ID',
geminiProjectIdDetail: '某些 Google 帳戶(特別是綁定了 Google Cloud 的帳戶)會被識別為 Workspace 帳戶,需要提供額外的專案 ID。',
geminiHowToGetProjectId: '如何取得專案 ID',
geminiVisitConsole: '造訪',
geminiCopyProjectId: '複製專案 IDProject ID通常是字串格式',
geminiProjectIdWarning: '⚠️ 注意:要複製專案 IDProject ID不要複製專案編號Project Number',
geminiPersonalAccountTip: '提示:如果您的帳戶是普通個人帳戶(未綁定 Google Cloud請留空此欄位。',
// AWS 區域參考
awsRegionReference: '常用 AWS 區域參考:',
awsRegionEastUS: 'us-east-1 (美國東部)',
awsRegionWestUS: 'us-west-2 (美國西部)',
awsRegionEuropeIreland: 'eu-west-1 (歐洲愛爾蘭)',
awsRegionAsiaSingapore: 'ap-southeast-1 (新加坡)',
awsRegionAsiaTokyo: 'ap-northeast-1 (東京)',
awsRegionEuropeFrankfurt: 'eu-central-1 (法蘭克福)',
awsRegionInputTip: '💡 請輸入完整的區域代碼,如 us-east-1',
// Bedrock 模型說明
bedrockModelConfigDesc: 'Bedrock 模型設定說明:',
bedrockSupportsInferenceProfile: '支援 Inference Profile ID推薦',
bedrockSupportsARN: '支援 Application Inference Profile ARN',
bedrockCommonModel: '常用模型us.anthropic.claude-sonnet-4-20250514-v1:0',
bedrockEmptyUsesDefault: '留空將使用系統設定的預設模型',
// Azure OpenAI 模型選擇
azureModelSelectionDesc: '選擇此部署支援的模型類型',
// 限流機制
rateLimitMechanism: '限流機制',
enableRateLimitMechanism: '啟用限流機制',
rateLimitDescription2: '啟用後當帳戶返回429錯誤時將暫停調度一段時間',
rateLimitDurationMinutes: '限流時間 (分鐘)',
rateLimitDefaultMinutes: '預設60分鐘',
rateLimitPauseDesc: '帳戶被限流後暫停調度的時間(分鐘)',
// Claude Console 特定欄位
claudeConsoleFields: 'Claude Console 特定欄位',
quotaManagement: '額度管理',
modelMappingTable: '模型映射表',
modelMappingTableOptional: '模型映射表 (可選)',
addModelMapping: '新增模型映射',
// Claude 訂閱類型
subscriptionType: '訂閱類型',
// Setup Token 授權
setupTokenAuth: 'Setup Token 授權',
claudeSetupTokenAuth: 'Claude Setup Token 授權',
setupTokenAuthSteps: '請按照以下步驟透過 Setup Token 完成 Claude 帳戶的授權:',
generateSetupTokenLink: '產生 Setup Token 授權連結',
generating: '產生中...',
// 按鈕和操作
verifying: '驗證中...',
completeAuth: '完成授權',
updating: '更新中...',
update: '更新',
// 錯誤訊息
generateSetupTokenFailed: '產生Setup Token授權連結失敗',
copyFailed: '複製失敗,請手動複製',
setupTokenAuthFailed: 'Setup Token授權失敗請檢查授權碼是否正確',
accountCreationFailed: '帳戶建立失敗',
accountCreationError: '帳戶建立失敗:',
// 頁面結構註釋
stepIndicator: '步驟指示器',
step1BasicInfo: '步驟1: 基本資訊和代理設定',
groupSelector: '分組選擇器',
multiSelectGroup: '多選分組介面',
newGroupOption: '新建分組選項',
geminiProjectId: 'Gemini 專案 ID 欄位',
bedrockFields: 'Bedrock 特定欄位',
azureOpenAIFields: 'Azure OpenAI 特定欄位',
// 驗證訊息
nameRequired: '請填寫帳戶名稱',
apiUrlRequired: '請填寫 API URL',
rateLimitDefault60: '預設60分鐘',
rateLimitPauseDescription: '帳戶被限流後暫停調度的時間(分鐘)',
apiUrlPlaceholder: '例如https://api.example.com',
apiKeyPlaceholder: '請輸入API Key',
dailyQuotaLimit: '每日額度限制 ($)',
quotaZeroUnlimited: '0 表示不限制',
dailyQuotaDescription: '設定每日使用額度0 表示不限制',
quotaResetTime: '額度重設時間',
quotaResetTimeDescription: '每日自動重設額度的時間',
modelMappingDescription: '留空表示支援所有模型且不修改請求。設定映射後,左側模型會被識別為支援的模型,右側是實際傳送的模型。',
// 額度管理
quotaManagementFields: '配額管理欄位',
dailyQuotaLimitDollar: '每日配額限制 ($)',
quotaZeroUnlimited: '0 表示不限制',
dailyQuotaDesc: '設定每日使用配額0 表示不限制',
quotaResetTime: '配額重設時間',
quotaResetTimeDesc: '每日自動重設配額的時間',
// 模型映射
modelMappingOptional: '模型映射表 (可選)',
modelMappingDesc: '留空表示支援所有模型且不修改請求。設定映射後,左側模型會被識別為支援的模型,右側是實際發送的模型。',
originalModelName: '原始模型名稱',
mappedModelName: '映射後的模型名稱',
addModelMappingBtn: '新增模型映射',
customUserAgentOptional: '自定義 User-Agent (可選)',
customUserAgentDesc: '留空時將自動使用客戶端的 User-Agent僅在需要固定特定 UA 時填寫',
userAgentPassthrough: '留空則透傳客戶端 User-Agent',
// Claude 訂閱類型
claudeSubscriptionType: '訂閱類型',
claudeProLimitation: 'Pro 帳戶不支援 Claude Opus 4 模型',
// Claude 進階選項
claudeAutoStopScheduling: '5小時使用量接近限制時自動停止調度',
claudeAutoStopDesc: '當系統檢測到帳戶接近5小時使用限制時自動暫停調度該帳戶。進入新的時間視窗後會自動恢復調度。',
claudeUseUnifiedUA: '使用統一 Claude Code 版本',
claudeUnifiedUADesc: '開啟後將使用從真實 Claude Code 客戶端捕獲的統一 User-Agent提高相容性',
claudeCurrentUnifiedVersion: '💡 目前統一版本:',
claudeWaitingCapture: '⏳ 等待從 Claude Code 客戶端捕獲 User-Agent',
claudeCaptureHint: '💡 提示:如果長時間未能捕獲,請確認有 Claude Code 客戶端正在使用此帳戶, 或聯繫開發者檢查 User-Agent 格式是否發生變化',
claudeUseUnifiedClientId: '使用統一的客戶端標識',
claudeUnifiedClientIdDesc: '開啟後將使用固定的客戶端標識,使所有請求看起來來自同一個客戶端,減少特徵',
claudeClientIdLabel: '客戶端標識 ID',
claudeClientIdDesc: '此ID將替換請求中的user_id客戶端部分保留session部分用於黏性工作階段',
// Setup Token 流程
setupTokenAuthProcess: 'Claude Setup Token 授權',
setupTokenProcessDesc: '請按照以下步驟透過 Setup Token 完成 Claude 帳戶的授權:',
setupTokenStepOneTitle: '步驟 1產生授權連結',
setupTokenStepOneDesc: '點擊下方按鈕產生授權連結',
setupTokenGenerating: '產生中...',
setupTokenGenerateBtn: '產生 Setup Token 授權連結',
setupTokenCopyTitle: '複製連結',
// 步驟指示器
stepIndicator: '步驟指示器',
step1BasicInfo: '步驟1: 基本資訊和代理設定',
step2OAuth: '步驟2: OAuth授權',
step2SetupToken: '步驟2: Setup Token授權',
// 群組選擇器
groupSelector: '群組選擇器',
multiGroupInterface: '多選群組介面',
createNewGroupOption: '新建群組選項',
// 手動輸入Token提示
credentialsFromFile: '檔案中的憑證。'
}
}