Commit 5d943281 by RedwindA Committed by GitHub

feat(system-settings): add user token limit configuration section (#5678)

parent 0b2cf43e
/*
Copyright (C) 2023-2026 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import { zodResolver } from '@hookform/resolvers/zod'
import { useEffect } from 'react'
import { useForm } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
import * as z from 'zod'
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { SettingsForm } from '../components/settings-form-layout'
import { SettingsPageFormActions } from '../components/settings-page-context'
import { SettingsSection } from '../components/settings-section'
import { useUpdateOption } from '../hooks/use-update-option'
const tokenLimitSchema = z.object({
token_setting: z.object({
max_user_tokens: z.number().min(1),
}),
})
type TokenLimitFormValues = z.output<typeof tokenLimitSchema>
type TokenLimitFormInput = z.input<typeof tokenLimitSchema>
type NormalizedTokenLimitValues = {
'token_setting.max_user_tokens': number
}
type TokenLimitSectionProps = {
defaultValues: NormalizedTokenLimitValues
}
const buildFormDefaults = (
defaults: TokenLimitSectionProps['defaultValues']
): TokenLimitFormInput => ({
token_setting: {
max_user_tokens: defaults['token_setting.max_user_tokens'],
},
})
const normalizeFormValues = (
values: TokenLimitFormValues
): NormalizedTokenLimitValues => ({
'token_setting.max_user_tokens': values.token_setting.max_user_tokens,
})
export function TokenLimitSection({ defaultValues }: TokenLimitSectionProps) {
const { t } = useTranslation()
const updateOption = useUpdateOption()
const form = useForm<TokenLimitFormInput, unknown, TokenLimitFormValues>({
resolver: zodResolver(tokenLimitSchema),
mode: 'onChange',
defaultValues: buildFormDefaults(defaultValues),
})
useEffect(() => {
form.reset(buildFormDefaults(defaultValues))
}, [defaultValues, form])
const onSubmit = async (values: TokenLimitFormValues) => {
const key = 'token_setting.max_user_tokens' as const
const normalized = normalizeFormValues(values)
const value = normalized[key]
if (value !== defaultValues[key]) {
await updateOption.mutateAsync({ key, value })
}
}
return (
<SettingsSection title={t('Token Limits')}>
<Form {...form}>
<SettingsForm onSubmit={form.handleSubmit(onSubmit)}>
<SettingsPageFormActions
onSave={form.handleSubmit(onSubmit)}
isSaving={updateOption.isPending}
saveLabel='Save token limits'
/>
<FormField
control={form.control}
name='token_setting.max_user_tokens'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Maximum tokens per user')}</FormLabel>
<FormControl>
<Input
type='number'
min={1}
step={1}
{...field}
onChange={(e) =>
field.onChange(Number.parseInt(e.target.value) || 1)
}
/>
</FormControl>
<FormDescription>
{t(
'Maximum number of tokens each user can create. Default 1000. Setting too large may affect performance.'
)}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</SettingsForm>
</Form>
</SettingsSection>
)
}
...@@ -41,6 +41,7 @@ const defaultSecuritySettings: SecuritySettings = { ...@@ -41,6 +41,7 @@ const defaultSecuritySettings: SecuritySettings = {
'fetch_setting.ip_list': [], 'fetch_setting.ip_list': [],
'fetch_setting.allowed_ports': [], 'fetch_setting.allowed_ports': [],
'fetch_setting.apply_ip_filter_for_domain': false, 'fetch_setting.apply_ip_filter_for_domain': false,
'token_setting.max_user_tokens': 1000,
} }
export function SecuritySettings() { export function SecuritySettings() {
......
...@@ -19,6 +19,7 @@ For commercial licensing, please contact support@quantumnous.com ...@@ -19,6 +19,7 @@ For commercial licensing, please contact support@quantumnous.com
import { RateLimitSection } from '../request-limits/rate-limit-section' import { RateLimitSection } from '../request-limits/rate-limit-section'
import { SensitiveWordsSection } from '../request-limits/sensitive-words-section' import { SensitiveWordsSection } from '../request-limits/sensitive-words-section'
import { SSRFSection } from '../request-limits/ssrf-section' import { SSRFSection } from '../request-limits/ssrf-section'
import { TokenLimitSection } from '../request-limits/token-limit-section'
import type { SecuritySettings } from '../types' import type { SecuritySettings } from '../types'
import { createSectionRegistry } from '../utils/section-registry' import { createSectionRegistry } from '../utils/section-registry'
...@@ -77,6 +78,18 @@ const SECURITY_SECTIONS = [ ...@@ -77,6 +78,18 @@ const SECURITY_SECTIONS = [
/> />
), ),
}, },
{
id: 'token-limits',
titleKey: 'Token Limits',
build: (settings: SecuritySettings) => (
<TokenLimitSection
defaultValues={{
'token_setting.max_user_tokens':
settings['token_setting.max_user_tokens'],
}}
/>
),
},
] as const ] as const
export type SecuritySectionId = (typeof SECURITY_SECTIONS)[number]['id'] export type SecuritySectionId = (typeof SECURITY_SECTIONS)[number]['id']
......
...@@ -378,6 +378,7 @@ export type SecuritySettings = { ...@@ -378,6 +378,7 @@ export type SecuritySettings = {
'fetch_setting.ip_list': string[] 'fetch_setting.ip_list': string[]
'fetch_setting.allowed_ports': number[] 'fetch_setting.allowed_ports': number[]
'fetch_setting.apply_ip_filter_for_domain': boolean 'fetch_setting.apply_ip_filter_for_domain': boolean
'token_setting.max_user_tokens': number
} }
export type UpstreamChannel = { export type UpstreamChannel = {
......
...@@ -370,6 +370,7 @@ ...@@ -370,6 +370,7 @@
"API Key disabled successfully": "API Key disabled successfully", "API Key disabled successfully": "API Key disabled successfully",
"API Key enabled successfully": "API Key enabled successfully", "API Key enabled successfully": "API Key enabled successfully",
"API key from the provider": "API key from the provider", "API key from the provider": "API key from the provider",
"API key is loading, please try again in a moment": "API key is loading, please try again in a moment",
"API key is required": "API key is required", "API key is required": "API key is required",
"API Key mode (does not support batch creation)": "API Key mode (does not support batch creation)", "API Key mode (does not support batch creation)": "API Key mode (does not support batch creation)",
"API Key mode: use APIKey|Region": "API Key mode: use APIKey|Region", "API Key mode: use APIKey|Region": "API Key mode: use APIKey|Region",
...@@ -1701,6 +1702,7 @@ ...@@ -1701,6 +1702,7 @@
"Failed to copy keys": "Failed to copy keys", "Failed to copy keys": "Failed to copy keys",
"Failed to copy model names": "Failed to copy model names", "Failed to copy model names": "Failed to copy model names",
"Failed to copy to clipboard": "Failed to copy to clipboard", "Failed to copy to clipboard": "Failed to copy to clipboard",
"Failed to create account": "Failed to create account",
"Failed to create API key": "Failed to create API key", "Failed to create API key": "Failed to create API key",
"Failed to create channel": "Failed to create channel", "Failed to create channel": "Failed to create channel",
"Failed to create deployment": "Failed to create deployment", "Failed to create deployment": "Failed to create deployment",
...@@ -1753,6 +1755,8 @@ ...@@ -1753,6 +1755,8 @@
"Failed to load key status": "Failed to load key status", "Failed to load key status": "Failed to load key status",
"Failed to load logs": "Failed to load logs", "Failed to load logs": "Failed to load logs",
"Failed to load Passkey status": "Failed to load Passkey status", "Failed to load Passkey status": "Failed to load Passkey status",
"Failed to load playground groups": "Failed to load playground groups",
"Failed to load playground models": "Failed to load playground models",
"Failed to load profile": "Failed to load profile", "Failed to load profile": "Failed to load profile",
"Failed to load redemption codes": "Failed to load redemption codes", "Failed to load redemption codes": "Failed to load redemption codes",
"Failed to load setup data": "Failed to load setup data", "Failed to load setup data": "Failed to load setup data",
...@@ -1779,7 +1783,9 @@ ...@@ -1779,7 +1783,9 @@
"Failed to search API keys": "Failed to search API keys", "Failed to search API keys": "Failed to search API keys",
"Failed to search redemption codes": "Failed to search redemption codes", "Failed to search redemption codes": "Failed to search redemption codes",
"Failed to search users": "Failed to search users", "Failed to search users": "Failed to search users",
"Failed to send reset email": "Failed to send reset email",
"Failed to send verification code": "Failed to send verification code", "Failed to send verification code": "Failed to send verification code",
"Failed to send verification email": "Failed to send verification email",
"Failed to set tag": "Failed to set tag", "Failed to set tag": "Failed to set tag",
"Failed to setup 2FA": "Failed to setup 2FA", "Failed to setup 2FA": "Failed to setup 2FA",
"Failed to start {{provider}} login": "Failed to start {{provider}} login", "Failed to start {{provider}} login": "Failed to start {{provider}} login",
...@@ -1822,6 +1828,7 @@ ...@@ -1822,6 +1828,7 @@
"Fee": "Fee", "Fee": "Fee",
"Fee Amount": "Fee Amount", "Fee Amount": "Fee Amount",
"Fetch available models for:": "Fetch available models for:", "Fetch available models for:": "Fetch available models for:",
"Fetch available models from upstream": "Fetch available models from upstream",
"Fetch from Upstream": "Fetch from Upstream", "Fetch from Upstream": "Fetch from Upstream",
"Fetch Models": "Fetch Models", "Fetch Models": "Fetch Models",
"Fetched {{count}} model(s) from upstream": "Fetched {{count}} model(s) from upstream", "Fetched {{count}} model(s) from upstream": "Fetched {{count}} model(s) from upstream",
...@@ -2445,10 +2452,12 @@ ...@@ -2445,10 +2452,12 @@
"Maximum 500 characters. Supports Markdown and HTML.": "Maximum 500 characters. Supports Markdown and HTML.", "Maximum 500 characters. Supports Markdown and HTML.": "Maximum 500 characters. Supports Markdown and HTML.",
"Maximum check-in quota": "Maximum check-in quota", "Maximum check-in quota": "Maximum check-in quota",
"Maximum input window": "Maximum input window", "Maximum input window": "Maximum input window",
"Maximum number of tokens each user can create. Default 1000. Setting too large may affect performance.": "Maximum number of tokens each user can create. Default 1000. Setting too large may affect performance.",
"Maximum number of tokens in the response": "Maximum number of tokens in the response", "Maximum number of tokens in the response": "Maximum number of tokens in the response",
"Maximum quota amount awarded for check-in": "Maximum quota amount awarded for check-in", "Maximum quota amount awarded for check-in": "Maximum quota amount awarded for check-in",
"Maximum tokens including hidden reasoning tokens": "Maximum tokens including hidden reasoning tokens", "Maximum tokens including hidden reasoning tokens": "Maximum tokens including hidden reasoning tokens",
"Maximum tokens per response": "Maximum tokens per response", "Maximum tokens per response": "Maximum tokens per response",
"Maximum tokens per user": "Maximum tokens per user",
"maxRequests ≥ 0, maxSuccess ≥ 1, both ≤ 2,147,483,647": "maxRequests ≥ 0, maxSuccess ≥ 1, both ≤ 2,147,483,647", "maxRequests ≥ 0, maxSuccess ≥ 1, both ≤ 2,147,483,647": "maxRequests ≥ 0, maxSuccess ≥ 1, both ≤ 2,147,483,647",
"May be used for training by upstream provider": "May be used for training by upstream provider", "May be used for training by upstream provider": "May be used for training by upstream provider",
"Media pricing": "Media pricing", "Media pricing": "Media pricing",
...@@ -2517,7 +2526,9 @@ ...@@ -2517,7 +2526,9 @@
"Model Mapping (JSON)": "Model Mapping (JSON)", "Model Mapping (JSON)": "Model Mapping (JSON)",
"Model Mapping must be a JSON object like": "Model Mapping must be a JSON object like", "Model Mapping must be a JSON object like": "Model Mapping must be a JSON object like",
"Model mapping must be a JSON object with string values": "Model mapping must be a JSON object with string values", "Model mapping must be a JSON object with string values": "Model mapping must be a JSON object with string values",
"Model mapping must be a valid JSON object": "Model mapping must be a valid JSON object",
"Model mapping must be valid JSON": "Model mapping must be valid JSON", "Model mapping must be valid JSON": "Model mapping must be valid JSON",
"Model mapping must be valid JSON format": "Model mapping must be valid JSON format",
"Model mapping values must be strings": "Model mapping values must be strings", "Model mapping values must be strings": "Model mapping values must be strings",
"Model name": "Model name", "Model name": "Model name",
"Model Name": "Model Name", "Model Name": "Model Name",
...@@ -2748,6 +2759,7 @@ ...@@ -2748,6 +2759,7 @@
"No missing models found.": "No missing models found.", "No missing models found.": "No missing models found.",
"No model found.": "No model found.", "No model found.": "No model found.",
"No model mappings configured. Click \"Add Mapping\" to get started.": "No model mappings configured. Click \"Add Mapping\" to get started.", "No model mappings configured. Click \"Add Mapping\" to get started.": "No model mappings configured. Click \"Add Mapping\" to get started.",
"No model price changes to save": "No model price changes to save",
"No models available": "No models available", "No models available": "No models available",
"No models available in this category": "No models available in this category", "No models available in this category": "No models available in this category",
"No models available. Create your first model to get started.": "No models available. Create your first model to get started.", "No models available. Create your first model to get started.": "No models available. Create your first model to get started.",
...@@ -2760,6 +2772,7 @@ ...@@ -2760,6 +2772,7 @@
"No models match the selected filters": "No models match the selected filters", "No models match the selected filters": "No models match the selected filters",
"No models match your current filters.": "No models match your current filters.", "No models match your current filters.": "No models match your current filters.",
"No models match your search": "No models match your search", "No models match your search": "No models match your search",
"No models matched your search.": "No models matched your search.",
"No models selected": "No models selected", "No models selected": "No models selected",
"No models to add": "No models to add", "No models to add": "No models to add",
"No models to copy": "No models to copy", "No models to copy": "No models to copy",
...@@ -3072,6 +3085,7 @@ ...@@ -3072,6 +3085,7 @@
"Password Login": "Password Login", "Password Login": "Password Login",
"Password must be at least 8 characters": "Password must be at least 8 characters", "Password must be at least 8 characters": "Password must be at least 8 characters",
"Password must be at least 8 characters long": "Password must be at least 8 characters long", "Password must be at least 8 characters long": "Password must be at least 8 characters long",
"Password must be between 8 and 20 characters": "Password must be between 8 and 20 characters",
"Password Registration": "Password Registration", "Password Registration": "Password Registration",
"Password reset and copied to clipboard: {{password}}": "Password reset and copied to clipboard: {{password}}", "Password reset and copied to clipboard: {{password}}": "Password reset and copied to clipboard: {{password}}",
"Password reset: {{password}}": "Password reset: {{password}}", "Password reset: {{password}}": "Password reset: {{password}}",
...@@ -3323,6 +3337,7 @@ ...@@ -3323,6 +3337,7 @@
"Prompt Details": "Prompt Details", "Prompt Details": "Prompt Details",
"Prompt price ($/1M tokens)": "Prompt price ($/1M tokens)", "Prompt price ($/1M tokens)": "Prompt price ($/1M tokens)",
"Proprietary": "Proprietary", "Proprietary": "Proprietary",
"Protect login and registration with Cloudflare Turnstile": "Protect login and registration with Cloudflare Turnstile",
"Provide a JSON object where each key maps to an endpoint definition.": "Provide a JSON object where each key maps to an endpoint definition.", "Provide a JSON object where each key maps to an endpoint definition.": "Provide a JSON object where each key maps to an endpoint definition.",
"Provide a valid URL starting with http:// or https://": "Provide a valid URL starting with http:// or https://", "Provide a valid URL starting with http:// or https://": "Provide a valid URL starting with http:// or https://",
"Provide Markdown, HTML, or an external URL for the privacy policy": "Provide Markdown, HTML, or an external URL for the privacy policy", "Provide Markdown, HTML, or an external URL for the privacy policy": "Provide Markdown, HTML, or an external URL for the privacy policy",
...@@ -3860,6 +3875,7 @@ ...@@ -3860,6 +3875,7 @@
"Send a request": "Send a request", "Send a request": "Send a request",
"Send code": "Send code", "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 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...", "Sending...": "Sending...",
"Sensitive Words": "Sensitive Words", "Sensitive Words": "Sensitive Words",
"Sent the API key to FluentRead.": "Sent the API key to FluentRead.", "Sent the API key to FluentRead.": "Sent the API key to FluentRead.",
...@@ -4240,6 +4256,7 @@ ...@@ -4240,6 +4256,7 @@
"This action cannot be undone.": "This action cannot be undone.", "This action cannot be undone.": "This action cannot be undone.",
"This action cannot be undone. This will permanently delete your account and remove all your data from our servers.": "This action cannot be undone. This will permanently delete your account and remove all your data from our servers.", "This action cannot be undone. This will permanently delete your account and remove all your data from our servers.": "This action cannot be undone. This will permanently delete your account and remove all your data from our servers.",
"This action will permanently remove 2FA protection from your account.": "This action will permanently remove 2FA protection from your account.", "This action will permanently remove 2FA protection from your account.": "This action will permanently remove 2FA protection from your account.",
"This channel has no configured models.": "This channel has no configured models.",
"This channel is not an Ollama channel.": "This channel is not an Ollama channel.", "This channel is not an Ollama channel.": "This channel is not an Ollama channel.",
"This channel type does not support fetching models": "This channel type does not support fetching models", "This channel type does not support fetching models": "This channel type does not support fetching models",
"This channel type requires additional configuration": "This channel type requires additional configuration", "This channel type requires additional configuration": "This channel type requires additional configuration",
...@@ -4326,6 +4343,7 @@ ...@@ -4326,6 +4343,7 @@
"Token Endpoint (Optional)": "Token Endpoint (Optional)", "Token Endpoint (Optional)": "Token Endpoint (Optional)",
"Token estimator": "Token estimator", "Token estimator": "Token estimator",
"Token group": "Token group", "Token group": "Token group",
"Token Limits": "Token Limits",
"Token management": "Token management", "Token management": "Token management",
"Token Management": "Token Management", "Token Management": "Token Management",
"Token Mgmt": "Token Mgmt", "Token Mgmt": "Token Mgmt",
...@@ -4524,6 +4542,7 @@ ...@@ -4524,6 +4542,7 @@
"Updated system setting {{key}}": "Updated system setting {{key}}", "Updated system setting {{key}}": "Updated system setting {{key}}",
"Updated user {{username}} (ID: {{id}})": "Updated user {{username}} (ID: {{id}})", "Updated user {{username}} (ID: {{id}})": "Updated user {{username}} (ID: {{id}})",
"Updating all channel balances. This may take a while. Please refresh to see results.": "Updating all channel balances. This may take a while. Please refresh to see results.", "Updating all channel balances. This may take a while. Please refresh to see results.": "Updating all channel balances. This may take a while. Please refresh to see results.",
"Updating...": "Updating...",
"Upgrade Group": "Upgrade Group", "Upgrade Group": "Upgrade Group",
"Upgrade plaintext SMTP connection with STARTTLS before authentication": "Upgrade plaintext SMTP connection with STARTTLS before authentication", "Upgrade plaintext SMTP connection with STARTTLS before authentication": "Upgrade plaintext SMTP connection with STARTTLS before authentication",
"Upload": "Upload", "Upload": "Upload",
...@@ -4728,6 +4747,7 @@ ...@@ -4728,6 +4747,7 @@
"Visual Parameter Override": "Visual Parameter Override", "Visual Parameter Override": "Visual Parameter Override",
"VolcEngine": "VolcEngine", "VolcEngine": "VolcEngine",
"vs. previous": "vs. previous", "vs. previous": "vs. previous",
"Waffo": "Waffo",
"Waffo Aggregator Gateway": "Waffo Aggregator Gateway", "Waffo Aggregator Gateway": "Waffo Aggregator Gateway",
"Waffo Pancake Dashboard": "Waffo Pancake Dashboard", "Waffo Pancake Dashboard": "Waffo Pancake Dashboard",
"Waffo Pancake MoR": "Waffo Pancake MoR", "Waffo Pancake MoR": "Waffo Pancake MoR",
......
...@@ -370,6 +370,7 @@ ...@@ -370,6 +370,7 @@
"API Key disabled successfully": "API 密钥禁用成功", "API Key disabled successfully": "API 密钥禁用成功",
"API Key enabled successfully": "API 密钥启用成功", "API Key enabled successfully": "API 密钥启用成功",
"API key from the provider": "来自提供商的 API 密钥", "API key from the provider": "来自提供商的 API 密钥",
"API key is loading, please try again in a moment": "API 密钥正在加载,请稍后再试",
"API key is required": "需要 API 密钥", "API key is required": "需要 API 密钥",
"API Key mode (does not support batch creation)": "API Key 模式(不支持批量创建)", "API Key mode (does not support batch creation)": "API Key 模式(不支持批量创建)",
"API Key mode: use APIKey|Region": "API Key 模式:使用 APIKey|Region", "API Key mode: use APIKey|Region": "API Key 模式:使用 APIKey|Region",
...@@ -1701,6 +1702,7 @@ ...@@ -1701,6 +1702,7 @@
"Failed to copy keys": "复制密钥失败", "Failed to copy keys": "复制密钥失败",
"Failed to copy model names": "复制模型名称失败", "Failed to copy model names": "复制模型名称失败",
"Failed to copy to clipboard": "复制到剪贴板失败", "Failed to copy to clipboard": "复制到剪贴板失败",
"Failed to create account": "创建账户失败",
"Failed to create API key": "创建API密钥失败", "Failed to create API key": "创建API密钥失败",
"Failed to create channel": "创建渠道失败", "Failed to create channel": "创建渠道失败",
"Failed to create deployment": "创建部署失败", "Failed to create deployment": "创建部署失败",
...@@ -1753,6 +1755,8 @@ ...@@ -1753,6 +1755,8 @@
"Failed to load key status": "加载密钥状态失败", "Failed to load key status": "加载密钥状态失败",
"Failed to load logs": "加载日志失败", "Failed to load logs": "加载日志失败",
"Failed to load Passkey status": "加载 Passkey 状态失败", "Failed to load Passkey status": "加载 Passkey 状态失败",
"Failed to load playground groups": "加载 playground 分组失败",
"Failed to load playground models": "加载 playground 模型失败",
"Failed to load profile": "加载个人资料失败", "Failed to load profile": "加载个人资料失败",
"Failed to load redemption codes": "加载兑换码失败", "Failed to load redemption codes": "加载兑换码失败",
"Failed to load setup data": "无法加载设置数据", "Failed to load setup data": "无法加载设置数据",
...@@ -1779,7 +1783,9 @@ ...@@ -1779,7 +1783,9 @@
"Failed to search API keys": "搜索 API 密钥失败", "Failed to search API keys": "搜索 API 密钥失败",
"Failed to search redemption codes": "搜索兑换码失败", "Failed to search redemption codes": "搜索兑换码失败",
"Failed to search users": "搜索用户失败", "Failed to search users": "搜索用户失败",
"Failed to send reset email": "发送重置邮件失败",
"Failed to send verification code": "发送验证码失败", "Failed to send verification code": "发送验证码失败",
"Failed to send verification email": "发送验证邮件失败",
"Failed to set tag": "设置标签失败", "Failed to set tag": "设置标签失败",
"Failed to setup 2FA": "设置 2FA 失败", "Failed to setup 2FA": "设置 2FA 失败",
"Failed to start {{provider}} login": "启动 {{provider}} 登录失败", "Failed to start {{provider}} login": "启动 {{provider}} 登录失败",
...@@ -1822,6 +1828,7 @@ ...@@ -1822,6 +1828,7 @@
"Fee": "扣费", "Fee": "扣费",
"Fee Amount": "扣费金额", "Fee Amount": "扣费金额",
"Fetch available models for:": "获取可用模型:", "Fetch available models for:": "获取可用模型:",
"Fetch available models from upstream": "从上游获取可用模型",
"Fetch from Upstream": "从上游获取", "Fetch from Upstream": "从上游获取",
"Fetch Models": "获取模型", "Fetch Models": "获取模型",
"Fetched {{count}} model(s) from upstream": "从上游获取了 {{count}} 个模型", "Fetched {{count}} model(s) from upstream": "从上游获取了 {{count}} 个模型",
...@@ -2445,10 +2452,12 @@ ...@@ -2445,10 +2452,12 @@
"Maximum 500 characters. Supports Markdown and HTML.": "最多 500 个字符。支持 Markdown 和 HTML。", "Maximum 500 characters. Supports Markdown and HTML.": "最多 500 个字符。支持 Markdown 和 HTML。",
"Maximum check-in quota": "签到最大额度", "Maximum check-in quota": "签到最大额度",
"Maximum input window": "最大输入窗口", "Maximum input window": "最大输入窗口",
"Maximum number of tokens each user can create. Default 1000. Setting too large may affect performance.": "每个用户可创建的最大令牌数量。默认 1000。设置过大可能会影响性能。",
"Maximum number of tokens in the response": "响应中最大 token 数", "Maximum number of tokens in the response": "响应中最大 token 数",
"Maximum quota amount awarded for check-in": "签到奖励的最大额度", "Maximum quota amount awarded for check-in": "签到奖励的最大额度",
"Maximum tokens including hidden reasoning tokens": "最大 token 数(含隐藏的推理 token)", "Maximum tokens including hidden reasoning tokens": "最大 token 数(含隐藏的推理 token)",
"Maximum tokens per response": "单次响应最大 token 数", "Maximum tokens per response": "单次响应最大 token 数",
"Maximum tokens per user": "每个用户的最大令牌数",
"maxRequests ≥ 0, maxSuccess ≥ 1, both ≤ 2,147,483,647": "maxRequests ≥ 0, maxSuccess ≥ 1,两者均 ≤ 2,147,483,647", "maxRequests ≥ 0, maxSuccess ≥ 1, both ≤ 2,147,483,647": "maxRequests ≥ 0, maxSuccess ≥ 1,两者均 ≤ 2,147,483,647",
"May be used for training by upstream provider": "可能被上游提供商用于训练", "May be used for training by upstream provider": "可能被上游提供商用于训练",
"Media pricing": "媒体定价", "Media pricing": "媒体定价",
...@@ -2517,7 +2526,9 @@ ...@@ -2517,7 +2526,9 @@
"Model Mapping (JSON)": "模型映射 (JSON)", "Model Mapping (JSON)": "模型映射 (JSON)",
"Model Mapping must be a JSON object like": "模型映射必须是如下所示的 JSON 对象", "Model Mapping must be a JSON object like": "模型映射必须是如下所示的 JSON 对象",
"Model mapping must be a JSON object with string values": "模型映射必须是值为字符串的 JSON 对象", "Model mapping must be a JSON object with string values": "模型映射必须是值为字符串的 JSON 对象",
"Model mapping must be a valid JSON object": "模型映射必须是有效的 JSON 对象",
"Model mapping must be valid JSON": "模型映射必须是有效的 JSON", "Model mapping must be valid JSON": "模型映射必须是有效的 JSON",
"Model mapping must be valid JSON format": "模型映射必须是有效的 JSON 格式",
"Model mapping values must be strings": "模型映射的值必须是字符串", "Model mapping values must be strings": "模型映射的值必须是字符串",
"Model name": "模型名称", "Model name": "模型名称",
"Model Name": "模型名称", "Model Name": "模型名称",
...@@ -2748,6 +2759,7 @@ ...@@ -2748,6 +2759,7 @@
"No missing models found.": "未找到缺失的模型。", "No missing models found.": "未找到缺失的模型。",
"No model found.": "未找到模型。", "No model found.": "未找到模型。",
"No model mappings configured. Click \"Add Mapping\" to get started.": "未配置模型映射。点击“添加映射”即可开始使用。", "No model mappings configured. Click \"Add Mapping\" to get started.": "未配置模型映射。点击“添加映射”即可开始使用。",
"No model price changes to save": "没有模型价格变更需要保存",
"No models available": "没有可用的模型", "No models available": "没有可用的模型",
"No models available in this category": "该分类下没有可用模型", "No models available in this category": "该分类下没有可用模型",
"No models available. Create your first model to get started.": "没有可用的模型。创建您的第一个模型即可开始使用。", "No models available. Create your first model to get started.": "没有可用的模型。创建您的第一个模型即可开始使用。",
...@@ -2760,6 +2772,7 @@ ...@@ -2760,6 +2772,7 @@
"No models match the selected filters": "没有匹配筛选条件的模型", "No models match the selected filters": "没有匹配筛选条件的模型",
"No models match your current filters.": "没有模型匹配您当前的筛选条件。", "No models match your current filters.": "没有模型匹配您当前的筛选条件。",
"No models match your search": "没有匹配的模型", "No models match your search": "没有匹配的模型",
"No models matched your search.": "没有匹配搜索的模型",
"No models selected": "未选择模型", "No models selected": "未选择模型",
"No models to add": "无待新增模型", "No models to add": "无待新增模型",
"No models to copy": "没有模型可复制", "No models to copy": "没有模型可复制",
...@@ -3072,6 +3085,7 @@ ...@@ -3072,6 +3085,7 @@
"Password Login": "密码登录", "Password Login": "密码登录",
"Password must be at least 8 characters": "密码必须至少 8 个字符", "Password must be at least 8 characters": "密码必须至少 8 个字符",
"Password must be at least 8 characters long": "密码必须至少 8 个字符长", "Password must be at least 8 characters long": "密码必须至少 8 个字符长",
"Password must be between 8 and 20 characters": "密码长度必须在 8 到 20 个字符之间",
"Password Registration": "密码注册", "Password Registration": "密码注册",
"Password reset and copied to clipboard: {{password}}": "密码已重置并复制到剪贴板:{{password}}", "Password reset and copied to clipboard: {{password}}": "密码已重置并复制到剪贴板:{{password}}",
"Password reset: {{password}}": "密码已重置:{{password}}", "Password reset: {{password}}": "密码已重置:{{password}}",
...@@ -3323,6 +3337,7 @@ ...@@ -3323,6 +3337,7 @@
"Prompt Details": "提示词详情", "Prompt Details": "提示词详情",
"Prompt price ($/1M tokens)": "提示词价格(美元/100 万 token)", "Prompt price ($/1M tokens)": "提示词价格(美元/100 万 token)",
"Proprietary": "商业闭源", "Proprietary": "商业闭源",
"Protect login and registration with Cloudflare Turnstile": "使用 Cloudflare Turnstile 保护登录和注册",
"Provide a JSON object where each key maps to an endpoint definition.": "提供一个 JSON 对象,其中每个键映射到一个端点定义。", "Provide a JSON object where each key maps to an endpoint definition.": "提供一个 JSON 对象,其中每个键映射到一个端点定义。",
"Provide a valid URL starting with http:// or https://": "请提供以 http:// 或 https:// 开头的有效 URL", "Provide a valid URL starting with http:// or https://": "请提供以 http:// 或 https:// 开头的有效 URL",
"Provide Markdown, HTML, or an external URL for the privacy policy": "提供 Markdown、HTML 或外部 URL 作为隐私政策", "Provide Markdown, HTML, or an external URL for the privacy policy": "提供 Markdown、HTML 或外部 URL 作为隐私政策",
...@@ -3860,6 +3875,7 @@ ...@@ -3860,6 +3875,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": "发送重置邮件",
"Sending...": "发送中...", "Sending...": "发送中...",
"Sensitive Words": "敏感词", "Sensitive Words": "敏感词",
"Sent the API key to FluentRead.": "API 密钥已发送至 FluentRead。", "Sent the API key to FluentRead.": "API 密钥已发送至 FluentRead。",
...@@ -4240,6 +4256,7 @@ ...@@ -4240,6 +4256,7 @@
"This action cannot be undone.": "此操作无法撤消。", "This action cannot be undone.": "此操作无法撤消。",
"This action cannot be undone. This will permanently delete your account and remove all your data from our servers.": "此操作无法撤消。这将永久删除您的账户并从我们的服务器中移除您的所有数据。", "This action cannot be undone. This will permanently delete your account and remove all your data from our servers.": "此操作无法撤消。这将永久删除您的账户并从我们的服务器中移除您的所有数据。",
"This action will permanently remove 2FA protection from your account.": "此操作将永久移除您账户的 2FA 保护。", "This action will permanently remove 2FA protection from your account.": "此操作将永久移除您账户的 2FA 保护。",
"This channel has no configured models.": "该渠道没有配置模型。",
"This channel is not an Ollama channel.": "该渠道不是 Ollama 渠道。", "This channel is not an Ollama channel.": "该渠道不是 Ollama 渠道。",
"This channel type does not support fetching models": "此渠道类型不支持获取模型", "This channel type does not support fetching models": "此渠道类型不支持获取模型",
"This channel type requires additional configuration": "此渠道类型需要填写额外配置", "This channel type requires additional configuration": "此渠道类型需要填写额外配置",
...@@ -4326,6 +4343,7 @@ ...@@ -4326,6 +4343,7 @@
"Token Endpoint (Optional)": "Token 端点(可选)", "Token Endpoint (Optional)": "Token 端点(可选)",
"Token estimator": "Token 估算器", "Token estimator": "Token 估算器",
"Token group": "令牌分组", "Token group": "令牌分组",
"Token Limits": "令牌限制",
"Token management": "令牌管理", "Token management": "令牌管理",
"Token Management": "令牌管理", "Token Management": "令牌管理",
"Token Mgmt": "令牌管理", "Token Mgmt": "令牌管理",
...@@ -4524,6 +4542,7 @@ ...@@ -4524,6 +4542,7 @@
"Updated system setting {{key}}": "修改系统设置 {{key}}", "Updated system setting {{key}}": "修改系统设置 {{key}}",
"Updated user {{username}} (ID: {{id}})": "更新用户 {{username}}(ID: {{id}})", "Updated user {{username}} (ID: {{id}})": "更新用户 {{username}}(ID: {{id}})",
"Updating all channel balances. This may take a while. Please refresh to see results.": "正在更新所有渠道余额。这可能需要一段时间。请刷新以查看结果。", "Updating all channel balances. This may take a while. Please refresh to see results.": "正在更新所有渠道余额。这可能需要一段时间。请刷新以查看结果。",
"Updating...": "更新中...",
"Upgrade Group": "升级分组", "Upgrade Group": "升级分组",
"Upgrade plaintext SMTP connection with STARTTLS before authentication": "在身份验证前使用 STARTTLS 升级明文 SMTP 连接", "Upgrade plaintext SMTP connection with STARTTLS before authentication": "在身份验证前使用 STARTTLS 升级明文 SMTP 连接",
"Upload": "上传", "Upload": "上传",
...@@ -4728,6 +4747,7 @@ ...@@ -4728,6 +4747,7 @@
"Visual Parameter Override": "可视化参数覆盖", "Visual Parameter Override": "可视化参数覆盖",
"VolcEngine": "火山方舟", "VolcEngine": "火山方舟",
"vs. previous": "相较上期", "vs. previous": "相较上期",
"Waffo": "Waffo",
"Waffo Aggregator Gateway": "Waffo 聚合网关", "Waffo Aggregator Gateway": "Waffo 聚合网关",
"Waffo Pancake Dashboard": "Waffo Pancake 控制台", "Waffo Pancake Dashboard": "Waffo Pancake 控制台",
"Waffo Pancake MoR": "Waffo Pancake MoR", "Waffo Pancake MoR": "Waffo Pancake MoR",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment