diff --git a/controller/channel.go b/controller/channel.go index eb95ccc364e6..5eeb39fbaaa3 100644 --- a/controller/channel.go +++ b/controller/channel.go @@ -1193,15 +1193,14 @@ func CopyChannel(c *gin.Context) { clone.UsedQuota = 0 } - // insert - if err := model.BatchInsertChannels([]model.Channel{clone}); err != nil { + // insert and keep the generated ID on the cloned record + if err := clone.Insert(); err != nil { common.SysError("failed to clone channel: " + err.Error()) c.JSON(http.StatusOK, gin.H{"success": false, "message": "复制渠道失败,请稍后重试"}) return } model.InitChannelCache() - // success - c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": gin.H{"id": clone.Id}}) + common.ApiSuccess(c, gin.H{"id": clone.Id}) } // MultiKeyManageRequest represents the request for multi-key management operations diff --git a/web/default/src/components/layout/components/chat-presets-item.tsx b/web/default/src/components/layout/components/chat-presets-item.tsx index 0c55cc09fe4b..d3523881ff8a 100644 --- a/web/default/src/components/layout/components/chat-presets-item.tsx +++ b/web/default/src/components/layout/components/chat-presets-item.tsx @@ -61,7 +61,9 @@ function ChatMenuItem({ /> } > - {preset.name} + + {preset.name} + ) @@ -77,11 +79,13 @@ function ChatMenuItem({ isActive={false} className='justify-between' > - {preset.name} + + {preset.name} + {loading ? ( - + ) : ( - + )} @@ -103,9 +107,12 @@ function DropdownPresetItem({ if (preset.type === 'web') { return ( } > - {preset.name} + + {preset.name} + ) } @@ -116,12 +123,15 @@ function DropdownPresetItem({ onClick={() => { if (!loading) void onOpen(preset) }} + className='min-w-0' > - {preset.name} + + {preset.name} + {loading ? ( - + ) : ( - + )} ) diff --git a/web/default/src/features/auth/forgot-password/components/forgot-password-form.tsx b/web/default/src/features/auth/forgot-password/components/forgot-password-form.tsx index f2845677c64b..842890539f9c 100644 --- a/web/default/src/features/auth/forgot-password/components/forgot-password-form.tsx +++ b/web/default/src/features/auth/forgot-password/components/forgot-password-form.tsx @@ -80,7 +80,7 @@ export function ForgotPasswordForm({ name='email' render={({ field }) => ( - Email + {t('Email')} @@ -89,8 +89,10 @@ export function ForgotPasswordForm({ )} /> - diff --git a/web/default/src/features/channels/components/data-table-row-actions.tsx b/web/default/src/features/channels/components/data-table-row-actions.tsx index 73ccd1bb282a..8e99f7fdba7a 100644 --- a/web/default/src/features/channels/components/data-table-row-actions.tsx +++ b/web/default/src/features/channels/components/data-table-row-actions.tsx @@ -58,6 +58,7 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) { const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false) const [isTesting, setIsTesting] = useState(false) const [isTogglingStatus, setIsTogglingStatus] = useState(false) + const [isDeleting, setIsDeleting] = useState(false) const isEnabled = isChannelEnabled(channel) const isMultiKey = isMultiKeyChannel(channel) @@ -280,8 +281,7 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) { {/* Delete */} { - e.preventDefault() + onClick={() => { setDeleteConfirmOpen(true) }} className='text-destructive focus:text-destructive' @@ -299,11 +299,18 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) { onOpenChange={setDeleteConfirmOpen} title={t('Delete Channel')} desc={`Are you sure you want to delete "${channel.name}"? This action cannot be undone.`} - confirmText='Delete' + confirmText={t('Delete')} destructive - handleConfirm={() => { - handleDeleteChannel(channel.id, queryClient) - setDeleteConfirmOpen(false) + isLoading={isDeleting} + handleConfirm={async () => { + setIsDeleting(true) + try { + await handleDeleteChannel(channel.id, queryClient, () => { + setDeleteConfirmOpen(false) + }) + } finally { + setIsDeleting(false) + } }} /> diff --git a/web/default/src/features/channels/components/dialogs/copy-channel-dialog.tsx b/web/default/src/features/channels/components/dialogs/copy-channel-dialog.tsx index 3a0353eeb0de..deaff3b035c0 100644 --- a/web/default/src/features/channels/components/dialogs/copy-channel-dialog.tsx +++ b/web/default/src/features/channels/components/dialogs/copy-channel-dialog.tsx @@ -104,7 +104,7 @@ export function CopyChannelDialog({ diff --git a/web/default/src/features/channels/lib/channel-actions.ts b/web/default/src/features/channels/lib/channel-actions.ts index 8c49740e1063..bb0162bc6522 100644 --- a/web/default/src/features/channels/lib/channel-actions.ts +++ b/web/default/src/features/channels/lib/channel-actions.ts @@ -235,10 +235,12 @@ export async function handleCopyChannel( ): Promise { try { const response = await copyChannel(id, params) - if (response.success && response.data?.id) { + if (response.success) { toast.success(i18next.t(SUCCESS_MESSAGES.COPIED)) queryClient?.invalidateQueries({ queryKey: channelsQueryKeys.lists() }) - onSuccess?.(response.data.id) + onSuccess?.(response.data?.id ?? 0) + } else { + toast.error(response.message || i18next.t('Failed to copy channel')) } } catch (_error) { toast.error(i18next.t('Failed to copy channel')) diff --git a/web/default/src/features/keys/components/api-keys-mutate-drawer.tsx b/web/default/src/features/keys/components/api-keys-mutate-drawer.tsx index 9ce6331596b6..a4d9d4b10592 100644 --- a/web/default/src/features/keys/components/api-keys-mutate-drawer.tsx +++ b/web/default/src/features/keys/components/api-keys-mutate-drawer.tsx @@ -1,5 +1,5 @@ import { useEffect, useState, type ReactNode } from 'react' -import { useForm } from 'react-hook-form' +import { useForm, type FieldErrors } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { useQuery } from '@tanstack/react-query' import { @@ -151,17 +151,31 @@ export function ApiKeysMutateDrawer({ // Load existing data when updating useEffect(() => { if (open && isUpdate && currentRow) { - // For update, fetch fresh data - getApiKey(currentRow.id).then((result) => { - if (result.success && result.data) { - form.reset(transformApiKeyToFormDefaults(result.data)) - } - }) + form.reset(transformApiKeyToFormDefaults(currentRow)) + + let cancelled = false + getApiKey(currentRow.id) + .then((result) => { + if (cancelled) return + if (result.success && result.data) { + form.reset(transformApiKeyToFormDefaults(result.data)) + } else { + toast.error(result.message || t(ERROR_MESSAGES.LOAD_FAILED)) + } + }) + .catch(() => { + if (!cancelled) { + toast.error(t(ERROR_MESSAGES.LOAD_FAILED)) + } + }) + return () => { + cancelled = true + } } else if (open && !isUpdate) { // For create, reset to defaults form.reset(getApiKeyFormDefaultValues(defaultUseAutoGroup)) } - }, [open, isUpdate, currentRow, form, defaultUseAutoGroup]) + }, [open, isUpdate, currentRow, form, defaultUseAutoGroup, t]) const onSubmit = async (data: ApiKeyFormValues) => { setIsSubmitting(true) @@ -218,6 +232,29 @@ export function ApiKeysMutateDrawer({ } } + const onInvalidSubmit = (errors: FieldErrors) => { + if (errors.model_limits || errors.allow_ips) { + setAdvancedOpen(true) + } + + if (errors.name) { + toast.error(t('Please enter a name')) + return + } + + const firstMessage = Object.values(errors).find( + (error) => typeof error?.message === 'string' + )?.message + + toast.error( + typeof firstMessage === 'string' + ? firstMessage + : t(ERROR_MESSAGES.UNEXPECTED) + ) + } + + const submitForm = form.handleSubmit(onSubmit, onInvalidSubmit) + const handleSetExpiry = (months: number, days: number, hours: number) => { if (months === 0 && days === 0 && hours === 0) { form.setValue('expired_time', undefined) @@ -270,7 +307,7 @@ export function ApiKeysMutateDrawer({
)} @@ -323,7 +323,7 @@ export function BillingHistoryDialog({ onClick={handleConfirmComplete} disabled={completing} > - {completing ? 'Processing...' : 'Confirm'} + {completing ? t('Processing...') : t('Confirm')} diff --git a/web/default/src/i18n/locales/en.json b/web/default/src/i18n/locales/en.json index 05e8c5bd4296..402a82ae5e18 100644 --- a/web/default/src/i18n/locales/en.json +++ b/web/default/src/i18n/locales/en.json @@ -925,6 +925,7 @@ "Copied: {{model}}": "Copied: {{model}}", "Copied!": "Copied!", "Copy": "Copy", + "Copying...": "Copying...", "Copy {{name}} pricing": "Copy {{name}} pricing", "Copy a request header": "Copy a request header", "Copy All": "Copy All", @@ -1002,6 +1003,7 @@ "Create, revoke, and audit API tokens.": "Create, revoke, and audit API tokens.", "Created": "Created", "Created At": "Created At", + "Credited Amount": "Credited Amount", "Credential generated": "Credential generated", "Credential refreshed": "Credential refreshed", "Credentials": "Credentials", @@ -2817,6 +2819,7 @@ "Path:": "Path:", "Pay": "Pay", "Pay-as-you-go with real-time usage monitoring": "Pay-as-you-go with real-time usage monitoring", + "Payment": "Payment", "Payment Channel": "Payment Channel", "Payment Gateway": "Payment Gateway", "Payment initiated": "Payment initiated", @@ -3522,6 +3525,7 @@ "Send a request": "Send a request", "Send code": "Send code", "Send email alerts when a user falls below this quota": "Send email alerts when a user falls below this quota", + "Send reset email": "Send reset email", "Sending...": "Sending...", "Sensitive Words": "Sensitive Words", "Sent the API key to FluentRead.": "Sent the API key to FluentRead.", @@ -4023,6 +4027,7 @@ "Trim Suffix": "Trim Suffix", "Truncate embeddings to this many dimensions": "Truncate embeddings to this many dimensions", "Trusted": "Trusted", + "Try adjusting your search": "Try adjusting your search", "Try adjusting your search to locate a missing model.": "Try adjusting your search to locate a missing model.", "TTFT P50": "TTFT P50", "TTFT P95": "TTFT P95", @@ -4398,6 +4403,7 @@ "Your setup guide is collapsed so usage stays in focus.": "Your setup guide is collapsed so usage stays in focus.", "Your system access token for API authentication. Keep it secure and don't share it with others.": "Your system access token for API authentication. Keep it secure and don't share it with others.", "Your Telegram Bot Token": "Your Telegram Bot Token", + "Your transaction history will appear here": "Your transaction history will appear here", "Your Turnstile secret key": "Your Turnstile secret key", "Your Turnstile site key": "Your Turnstile site key", "Zero retention": "Zero retention", diff --git a/web/default/src/i18n/locales/fr.json b/web/default/src/i18n/locales/fr.json index f13d1b8bf368..eca3df054d40 100644 --- a/web/default/src/i18n/locales/fr.json +++ b/web/default/src/i18n/locales/fr.json @@ -925,6 +925,7 @@ "Copied: {{model}}": "Copié : {{model}}", "Copied!": "Copié !", "Copy": "Copier", + "Copying...": "Copie en cours...", "Copy {{name}} pricing": "Copier la tarification de {{name}}", "Copy a request header": "Copier un en-tête de requête", "Copy All": "Tout copier", @@ -1002,6 +1003,7 @@ "Create, revoke, and audit API tokens.": "Créer, révoquer et auditer les jetons API.", "Created": "Créé", "Created At": "Créé le", + "Credited Amount": "Montant crédité", "Credential generated": "Identifiant généré", "Credential refreshed": "Identifiant actualisé", "Credentials": "Identifiants", @@ -2817,6 +2819,7 @@ "Path:": "Chemin :", "Pay": "Pay", "Pay-as-you-go with real-time usage monitoring": "Paiement à l'usage avec suivi de la consommation en temps réel", + "Payment": "Paiement", "Payment Channel": "Canal de paiement", "Payment Gateway": "Passerelle de paiement", "Payment initiated": "Paiement initié", @@ -3522,6 +3525,7 @@ "Send a request": "Envoyer une requête", "Send code": "Envoyer le code", "Send email alerts when a user falls below this quota": "Envoyer des alertes par e-mail lorsqu'un utilisateur descend en dessous de ce quota", + "Send reset email": "Envoyer l'e-mail de réinitialisation", "Sending...": "Envoi en cours...", "Sensitive Words": "Mots sensibles", "Sent the API key to FluentRead.": "Clé API envoyée à FluentRead.", @@ -4023,6 +4027,7 @@ "Trim Suffix": "Supprimer le suffixe", "Truncate embeddings to this many dimensions": "Tronquer les vecteurs à autant de dimensions", "Trusted": "Fiable", + "Try adjusting your search": "Essayez d'ajuster votre recherche", "Try adjusting your search to locate a missing model.": "Essayez d'ajuster votre recherche pour localiser un modèle manquant.", "TTFT P50": "TTFT P50", "TTFT P95": "TTFT P95", @@ -4398,6 +4403,7 @@ "Your setup guide is collapsed so usage stays in focus.": "Le guide de configuration est réduit afin de garder l'utilisation au premier plan.", "Your system access token for API authentication. Keep it secure and don't share it with others.": "Votre jeton d'accès système pour l'authentification API. Gardez-le en sécurité et ne le partagez pas avec d'autres.", "Your Telegram Bot Token": "Votre Jeton de Bot Telegram", + "Your transaction history will appear here": "Votre historique des transactions apparaîtra ici", "Your Turnstile secret key": "Votre clé secrète Turnstile", "Your Turnstile site key": "Votre clé de site Turnstile", "Zero retention": "Aucune rétention", diff --git a/web/default/src/i18n/locales/ja.json b/web/default/src/i18n/locales/ja.json index 7a17e1cd5f91..2629f5a1bf38 100644 --- a/web/default/src/i18n/locales/ja.json +++ b/web/default/src/i18n/locales/ja.json @@ -925,6 +925,7 @@ "Copied: {{model}}": "コピーしました: {{model}}", "Copied!": "コピーしました!", "Copy": "コピー", + "Copying...": "コピー中...", "Copy {{name}} pricing": "{{name}} の料金をコピー", "Copy a request header": "リクエストヘッダーをコピー", "Copy All": "すべてコピー", @@ -1002,6 +1003,7 @@ "Create, revoke, and audit API tokens.": "APIトークンを作成、取り消し、監査。", "Created": "作成済み", "Created At": "作成日時", + "Credited Amount": "付与額", "Credential generated": "認証情報を生成しました", "Credential refreshed": "認証情報を更新しました", "Credentials": "認証情報", @@ -2817,6 +2819,7 @@ "Path:": "パス:", "Pay": "Pay", "Pay-as-you-go with real-time usage monitoring": "リアルタイム使用量監視付き従量課金制", + "Payment": "支払い", "Payment Channel": "決済チャネル", "Payment Gateway": "決済ゲートウェイ", "Payment initiated": "支払いが開始されました", @@ -3522,6 +3525,7 @@ "Send a request": "リクエストを送信", "Send code": "コードを送信", "Send email alerts when a user falls below this quota": "ユーザーがこのクォータを下回ったときにメールアラートを送信", + "Send reset email": "リセットメールを送信", "Sending...": "送信中...", "Sensitive Words": "機密語", "Sent the API key to FluentRead.": "API キーを FluentRead に送信しました。", @@ -4023,6 +4027,7 @@ "Trim Suffix": "サフィックス削除", "Truncate embeddings to this many dimensions": "指定した次元数にベクトルを切り詰めます", "Trusted": "信頼済み", + "Try adjusting your search": "検索条件を調整してみてください", "Try adjusting your search to locate a missing model.": "見つからないモデルを見つけるには、検索を調整してみてください。", "TTFT P50": "TTFT P50", "TTFT P95": "TTFT P95", @@ -4398,6 +4403,7 @@ "Your setup guide is collapsed so usage stays in focus.": "利用状況に集中できるよう、セットアップガイドを折りたたみました。", "Your system access token for API authentication. Keep it secure and don't share it with others.": "API認証用のシステムアクセストークンです。安全に保管し、他者と共有しないでください。", "Your Telegram Bot Token": "あなたのTelegramボットトークン", + "Your transaction history will appear here": "取引履歴がここに表示されます", "Your Turnstile secret key": "あなたのTurnstileシークレットキー", "Your Turnstile site key": "あなたのTurnstileサイトキー", "Zero retention": "データ保持なし", diff --git a/web/default/src/i18n/locales/ru.json b/web/default/src/i18n/locales/ru.json index 91f8030ee433..4cae3720ea7c 100644 --- a/web/default/src/i18n/locales/ru.json +++ b/web/default/src/i18n/locales/ru.json @@ -925,6 +925,7 @@ "Copied: {{model}}": "Скопировано: {{model}}", "Copied!": "Скопировано!", "Copy": "Копировать", + "Copying...": "Копирование...", "Copy {{name}} pricing": "Копировать тариф {{name}}", "Copy a request header": "Копировать заголовок запроса", "Copy All": "Скопировать все", @@ -1002,6 +1003,7 @@ "Create, revoke, and audit API tokens.": "Создать, отозвать и аудитировать токены API.", "Created": "Создано", "Created At": "Дата создания", + "Credited Amount": "Зачисляемая сумма", "Credential generated": "Учётные данные созданы", "Credential refreshed": "Учётные данные обновлены", "Credentials": "Учетные данные", @@ -2817,6 +2819,7 @@ "Path:": "Путь:", "Pay": "Pay", "Pay-as-you-go with real-time usage monitoring": "Оплата по мере использования с мониторингом в реальном времени", + "Payment": "Платёж", "Payment Channel": "Платёжный канал", "Payment Gateway": "Платежный шлюз", "Payment initiated": "Платёж инициирован", @@ -3522,6 +3525,7 @@ "Send a request": "Отправить запрос", "Send code": "Отправить код", "Send email alerts when a user falls below this quota": "Отправлять оповещения по электронной почте, когда пользователь опускается ниже этой квоты", + "Send reset email": "Отправить письмо для сброса пароля", "Sending...": "Отправка...", "Sensitive Words": "Чувствительные слова", "Sent the API key to FluentRead.": "API-ключ отправлен в FluentRead.", @@ -4023,6 +4027,7 @@ "Trim Suffix": "Обрезать суффикс", "Truncate embeddings to this many dimensions": "Усечь эмбеддинги до указанного числа измерений", "Trusted": "Доверенный", + "Try adjusting your search": "Попробуйте изменить поисковый запрос", "Try adjusting your search to locate a missing model.": "Попробуйте изменить параметры поиска, чтобы найти отсутствующую модель.", "TTFT P50": "TTFT P50", "TTFT P95": "TTFT P95", @@ -4398,6 +4403,7 @@ "Your setup guide is collapsed so usage stays in focus.": "Руководство свернуто, чтобы основные показатели оставались в фокусе.", "Your system access token for API authentication. Keep it secure and don't share it with others.": "Ваш системный токен доступа для аутентификации API. Храните его в безопасности и не делитесь им с другими.", "Your Telegram Bot Token": "Ваш токен Telegram-бота", + "Your transaction history will appear here": "История ваших транзакций появится здесь", "Your Turnstile secret key": "Секретный ключ Turnstile", "Your Turnstile site key": "Ключ сайта Turnstile", "Zero retention": "Без хранения данных", diff --git a/web/default/src/i18n/locales/vi.json b/web/default/src/i18n/locales/vi.json index 1e5fede3bf27..50d047c0d811 100644 --- a/web/default/src/i18n/locales/vi.json +++ b/web/default/src/i18n/locales/vi.json @@ -925,6 +925,7 @@ "Copied: {{model}}": "Đã sao chép: {{model}}", "Copied!": "Đã sao chép!", "Copy": "Sao chép", + "Copying...": "Đang sao chép...", "Copy {{name}} pricing": "Sao chép giá của {{name}}", "Copy a request header": "Sao chép header yêu cầu", "Copy All": "Sao chép tất cả", @@ -1002,6 +1003,7 @@ "Create, revoke, and audit API tokens.": "Tạo, thu hồi và kiểm toán token API.", "Created": "Đã tạo", "Created At": "Ngày tạo", + "Credited Amount": "Số tiền được ghi có", "Credential generated": "Đã tạo thông tin xác thực", "Credential refreshed": "Đã làm mới thông tin xác thực", "Credentials": "Thông tin xác thực", @@ -2817,6 +2819,7 @@ "Path:": "Đường dẫn:", "Pay": "Pay", "Pay-as-you-go with real-time usage monitoring": "Thanh toán theo mức sử dụng với theo dõi mức sử dụng theo thời gian thực", + "Payment": "Thanh toán", "Payment Channel": "Kênh thanh toán", "Payment Gateway": "Cổng thanh toán", "Payment initiated": "Đã khởi tạo thanh toán", @@ -3522,6 +3525,7 @@ "Send a request": "Gửi yêu cầu", "Send code": "Gửi mã", "Send email alerts when a user falls below this quota": "Gửi cảnh báo email khi người dùng xuống dưới hạn mức này", + "Send reset email": "Gửi email đặt lại mật khẩu", "Sending...": "Đang gửi...", "Sensitive Words": "Từ ngữ nhạy cảm", "Sent the API key to FluentRead.": "Đã gửi khóa API đến FluentRead.", @@ -4023,6 +4027,7 @@ "Trim Suffix": "Cắt hậu tố", "Truncate embeddings to this many dimensions": "Cắt embedding xuống số chiều này", "Trusted": "Đáng tin cậy", + "Try adjusting your search": "Hãy thử điều chỉnh tìm kiếm", "Try adjusting your search to locate a missing model.": "Hãy thử điều chỉnh tìm kiếm của bạn để định vị một mô hình bị thiếu.", "TTFT P50": "TTFT P50", "TTFT P95": "TTFT P95", @@ -4398,6 +4403,7 @@ "Your setup guide is collapsed so usage stays in focus.": "Hướng dẫn thiết lập đã thu gọn để giữ phần sử dụng ở vị trí nổi bật.", "Your system access token for API authentication. Keep it secure and don't share it with others.": "Mã truy cập hệ thống của bạn để xác thực API. Hãy giữ nó an toàn và đừng chia sẻ nó với người khác.", "Your Telegram Bot Token": "Mã thông báo bot Telegram của bạn", + "Your transaction history will appear here": "Lịch sử giao dịch của bạn sẽ xuất hiện tại đây", "Your Turnstile secret key": "Khóa bí mật Turnstile của bạn", "Your Turnstile site key": "Khóa site Turnstile của bạn", "Zero retention": "Không lưu dữ liệu", diff --git a/web/default/src/i18n/locales/zh.json b/web/default/src/i18n/locales/zh.json index 5d3014ce7408..a6fb5b3853ce 100644 --- a/web/default/src/i18n/locales/zh.json +++ b/web/default/src/i18n/locales/zh.json @@ -925,6 +925,7 @@ "Copied: {{model}}": "已复制: {{model}}", "Copied!": "已复制!", "Copy": "复制", + "Copying...": "复制中...", "Copy {{name}} pricing": "复制 {{name}} 定价", "Copy a request header": "复制请求头", "Copy All": "全部复制", @@ -1002,6 +1003,7 @@ "Create, revoke, and audit API tokens.": "创建、撤销和审计 API 令牌。", "Created": "创建时间", "Created At": "创建时间", + "Credited Amount": "到账金额", "Credential generated": "凭据已生成", "Credential refreshed": "凭据已刷新", "Credentials": "凭证", @@ -2817,6 +2819,7 @@ "Path:": "路径:", "Pay": "支付", "Pay-as-you-go with real-time usage monitoring": "按量付费,实时监控使用情况", + "Payment": "支付金额", "Payment Channel": "支付渠道", "Payment Gateway": "支付网关", "Payment initiated": "已发起支付", @@ -3522,6 +3525,7 @@ "Send a request": "发送请求", "Send code": "发送验证码", "Send email alerts when a user falls below this quota": "当用户低于此配额时发送电子邮件警报", + "Send reset email": "发送重置邮件", "Sending...": "发送中...", "Sensitive Words": "敏感词", "Sent the API key to FluentRead.": "API 密钥已发送至 FluentRead。", @@ -4023,6 +4027,7 @@ "Trim Suffix": "裁剪后缀", "Truncate embeddings to this many dimensions": "将向量截断到指定维度", "Trusted": "受信任", + "Try adjusting your search": "请尝试调整搜索条件", "Try adjusting your search to locate a missing model.": "尝试调整您的搜索以找到缺失的模型。", "TTFT P50": "TTFT P50", "TTFT P95": "TTFT P95", @@ -4398,6 +4403,7 @@ "Your setup guide is collapsed so usage stays in focus.": "设置引导已收起,让用量信息保持在焦点位置。", "Your system access token for API authentication. Keep it secure and don't share it with others.": "您的系统访问令牌,用于 API 认证。请妥善保管,不要与他人分享。", "Your Telegram Bot Token": "您的 Telegram 机器人令牌", + "Your transaction history will appear here": "您的交易历史将在此显示", "Your Turnstile secret key": "您的 Turnstile 密钥", "Your Turnstile site key": "您的 Turnstile 站点密钥", "Zero retention": "零数据保留",