refactor(auth): replace dashboard sessions with stateless tokens and session control (#6329)
* refactor(auth): replace dashboard sessions with stateless tokens * feat(auth): harden session issuance and distributed enforcement * fix(proxy): preserve trusted proxy compatibility defaults * refactor: address dashboard auth review feedback * refactor: remove classic frontend and flatten web app
This commit is contained in:
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 i18n from 'i18next'
|
||||
import LanguageDetector from 'i18next-browser-languagedetector'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
|
||||
import { convertDetectedLanguage } from './languages'
|
||||
import en from './locales/en.json'
|
||||
import fr from './locales/fr.json'
|
||||
import ja from './locales/ja.json'
|
||||
import ru from './locales/ru.json'
|
||||
import vi from './locales/vi.json'
|
||||
import zhTW from './locales/zh-TW.json'
|
||||
import zhCN from './locales/zh.json'
|
||||
|
||||
export const resources = {
|
||||
en,
|
||||
zhCN,
|
||||
fr,
|
||||
ru,
|
||||
ja,
|
||||
vi,
|
||||
zhTW,
|
||||
} as const
|
||||
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources,
|
||||
fallbackLng: 'en',
|
||||
supportedLngs: ['en', 'zhCN', 'fr', 'ru', 'ja', 'vi', 'zhTW'],
|
||||
load: 'currentOnly',
|
||||
nsSeparator: false, // Allow literal colons in keys (e.g., URLs, labels)
|
||||
debug: import.meta.env.DEV,
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
detection: {
|
||||
order: ['localStorage', 'navigator'],
|
||||
caches: ['localStorage'],
|
||||
// Browsers report `zh-CN`/`zh-TW`/`zh`; map them onto our `zhCN`/`zhTW`
|
||||
// codes (non-Chinese codes pass through for normal supportedLngs matching).
|
||||
convertDetectedLanguage,
|
||||
},
|
||||
})
|
||||
|
||||
export default i18n
|
||||
Vendored
+101
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
export const INTERFACE_LANGUAGE_OPTIONS = [
|
||||
{ code: 'zhCN', label: '简体中文' },
|
||||
{ code: 'en', label: 'English' },
|
||||
{ code: 'fr', label: 'Français' },
|
||||
{ code: 'ru', label: 'Русский' },
|
||||
{ code: 'ja', label: '日本語' },
|
||||
{ code: 'vi', label: 'Tiếng Việt' },
|
||||
{ code: 'zhTW', label: '繁體中文' },
|
||||
] as const
|
||||
|
||||
export type InterfaceLanguageCode =
|
||||
(typeof INTERFACE_LANGUAGE_OPTIONS)[number]['code']
|
||||
|
||||
export function normalizeInterfaceLanguage(value?: string | null): string {
|
||||
if (!value) return 'en'
|
||||
|
||||
let normalized = value.trim().replaceAll('_', '-').toLowerCase()
|
||||
if (
|
||||
value === 'zh-TW' ||
|
||||
value === 'zh-HK' ||
|
||||
value === 'zh-MO' ||
|
||||
value === 'zhTW'
|
||||
) {
|
||||
normalized = 'zhTW'
|
||||
}
|
||||
if (value === 'zh-CN' || value === 'zh-Hans' || value === 'zhCN') {
|
||||
normalized = 'zhCN'
|
||||
}
|
||||
|
||||
return INTERFACE_LANGUAGE_OPTIONS.some((lang) => lang.code === normalized)
|
||||
? normalized
|
||||
: 'en'
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a browser-detected locale onto the interface language codes this project
|
||||
* uses with i18next (`zhCN` / `zhTW`).
|
||||
*
|
||||
* Browsers report standard BCP-47 tags (`zh-CN`, `zh-TW`, `zh-Hant`, `zh`, ...),
|
||||
* but `supportedLngs`/resources use the non-standard camelCase codes, so without
|
||||
* this mapping a Chinese browser would never match and fall back to English.
|
||||
* Non-Chinese codes are returned unchanged so i18next's own `supportedLngs`
|
||||
* matching still applies (e.g. `fr-FR` -> `fr`, `ja` -> `ja`).
|
||||
*/
|
||||
export function convertDetectedLanguage(value: string): string {
|
||||
const lower = value.trim().replaceAll('_', '-').toLowerCase()
|
||||
if (!lower.startsWith('zh')) return value
|
||||
if (
|
||||
lower === 'zh-tw' ||
|
||||
lower === 'zh-hk' ||
|
||||
lower === 'zh-mo' ||
|
||||
lower.startsWith('zh-hant')
|
||||
) {
|
||||
return 'zhTW'
|
||||
}
|
||||
return 'zhCN'
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an interface language code (the values i18next uses, such as `zhCN` /
|
||||
* `zhTW`) into a valid BCP-47 locale tag that the `Intl.*` APIs accept.
|
||||
*
|
||||
* `new Intl.NumberFormat('zhCN')` throws `RangeError: Invalid language tag`, so
|
||||
* any locale derived from `i18n.language` / `i18n.resolvedLanguage` MUST be run
|
||||
* through this before it reaches an `Intl` constructor. Unknown values fall back
|
||||
* to `undefined`, which makes `Intl` use the runtime default locale.
|
||||
*/
|
||||
export function toIntlLocale(value?: string | null): string | undefined {
|
||||
if (!value) return undefined
|
||||
switch (value) {
|
||||
case 'zhCN':
|
||||
return 'zh-CN'
|
||||
case 'zhTW':
|
||||
return 'zh-TW'
|
||||
default:
|
||||
break
|
||||
}
|
||||
try {
|
||||
return Intl.getCanonicalLocales(value)[0]
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"base": "en.json",
|
||||
"locales": {
|
||||
"en": {
|
||||
"file": "en.json",
|
||||
"missingCount": 0,
|
||||
"extrasCount": 0,
|
||||
"untranslatedCount": 0
|
||||
},
|
||||
"fr": {
|
||||
"file": "fr.json",
|
||||
"missingCount": 0,
|
||||
"extrasCount": 0,
|
||||
"untranslatedCount": 0
|
||||
},
|
||||
"ja": {
|
||||
"file": "ja.json",
|
||||
"missingCount": 0,
|
||||
"extrasCount": 0,
|
||||
"untranslatedCount": 0
|
||||
},
|
||||
"ru": {
|
||||
"file": "ru.json",
|
||||
"missingCount": 0,
|
||||
"extrasCount": 0,
|
||||
"untranslatedCount": 0
|
||||
},
|
||||
"vi": {
|
||||
"file": "vi.json",
|
||||
"missingCount": 0,
|
||||
"extrasCount": 0,
|
||||
"untranslatedCount": 0
|
||||
},
|
||||
"zh-TW": {
|
||||
"file": "zh-TW.json",
|
||||
"missingCount": 0,
|
||||
"extrasCount": 0,
|
||||
"untranslatedCount": 0
|
||||
},
|
||||
"zh": {
|
||||
"file": "zh.json",
|
||||
"missingCount": 0,
|
||||
"extrasCount": 0,
|
||||
"untranslatedCount": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+5218
File diff suppressed because it is too large
Load Diff
Vendored
+5218
File diff suppressed because it is too large
Load Diff
Vendored
+5218
File diff suppressed because it is too large
Load Diff
Vendored
+5218
File diff suppressed because it is too large
Load Diff
Vendored
+5218
File diff suppressed because it is too large
Load Diff
Vendored
+5218
File diff suppressed because it is too large
Load Diff
Vendored
+5218
File diff suppressed because it is too large
Load Diff
Vendored
+575
@@ -0,0 +1,575 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
// Static translation keys that don't get picked up by the t('...') regex.
|
||||
// These cover dynamic labels (e.g. constants, configs) that are passed into t at runtime.
|
||||
export const STATIC_I18N_KEYS = [
|
||||
// Header navigation
|
||||
'Home',
|
||||
'Console',
|
||||
'Model Square',
|
||||
'Rankings',
|
||||
'Docs',
|
||||
'About',
|
||||
|
||||
// Sidebar views (drill-in workspaces)
|
||||
'System Settings',
|
||||
'Back to Dashboard',
|
||||
'Auto-disable rules',
|
||||
'Channel health checks',
|
||||
'Request retry',
|
||||
|
||||
// System settings sidebar
|
||||
'System Administration',
|
||||
'General',
|
||||
'Authentication',
|
||||
'Request Limits',
|
||||
'Content',
|
||||
'Integrations',
|
||||
'Models',
|
||||
'Routing Reliability',
|
||||
'Maintenance',
|
||||
|
||||
// System info
|
||||
'online',
|
||||
'stale',
|
||||
'Master instances run scheduled background tasks.',
|
||||
'Worker instances do not run master-only background tasks.',
|
||||
'Drawing task polling',
|
||||
|
||||
// Pricing constants
|
||||
'Name',
|
||||
'Price: Low to High',
|
||||
'Price: High to Low',
|
||||
'All Models',
|
||||
'Token-based',
|
||||
'Per Request',
|
||||
'All Types',
|
||||
'Chat',
|
||||
'Response',
|
||||
'Anthropic',
|
||||
'Gemini',
|
||||
'Rerank',
|
||||
'Image',
|
||||
'Embeddings',
|
||||
'Video',
|
||||
'Sort',
|
||||
'All',
|
||||
'All Vendors',
|
||||
'All Groups',
|
||||
'All Tags',
|
||||
'More...',
|
||||
'Less',
|
||||
|
||||
// Roles
|
||||
'Super Admin',
|
||||
'Admin',
|
||||
'User',
|
||||
'Guest',
|
||||
|
||||
// API Keys
|
||||
'Enabled',
|
||||
'Disabled',
|
||||
'Expired',
|
||||
'Exhausted',
|
||||
'API Key created successfully',
|
||||
'API Key updated successfully',
|
||||
'API Key deleted successfully',
|
||||
'API Key enabled successfully',
|
||||
'API Key disabled successfully',
|
||||
'Failed to load API keys',
|
||||
'Failed to search API keys',
|
||||
'Failed to create API key',
|
||||
'Failed to update API key',
|
||||
'Failed to delete API key',
|
||||
'Failed to delete API keys',
|
||||
'Failed to update API key status',
|
||||
'Expected a JSON array of group identifiers',
|
||||
'Successfully created {{count}} API Key(s)',
|
||||
'Successfully deleted {{count}} API key(s)',
|
||||
'Enter API key for this channel',
|
||||
|
||||
// Users
|
||||
'Root',
|
||||
'Deleted',
|
||||
'User created successfully',
|
||||
'User updated successfully',
|
||||
'User updated successfully',
|
||||
'Failed to load users',
|
||||
'Failed to search users',
|
||||
'Failed to create user',
|
||||
'Failed to update user',
|
||||
'Failed to delete user',
|
||||
'No user selected',
|
||||
|
||||
// Redemption codes
|
||||
'Unused',
|
||||
'Disabled',
|
||||
'Used',
|
||||
'Expired',
|
||||
'Redemption code(s) created successfully',
|
||||
'Redemption code updated successfully',
|
||||
'Redemption code deleted successfully',
|
||||
'Redemption code enabled successfully',
|
||||
'Redemption code disabled successfully',
|
||||
'Copied to clipboard',
|
||||
'An unexpected error occurred',
|
||||
'Failed to load redemption codes',
|
||||
'Failed to search redemption codes',
|
||||
'Failed to create redemption code',
|
||||
'Failed to update redemption code',
|
||||
'Failed to delete redemption code',
|
||||
'Failed to delete invalid redemption codes',
|
||||
'Failed to update redemption code status',
|
||||
'Name must be between {{min}} and {{max}} characters',
|
||||
'Count must be between {{min}} and {{max}}',
|
||||
'Expired time cannot be earlier than current time',
|
||||
'Quota must be a positive number',
|
||||
'Successfully created {{count}} redemption codes',
|
||||
|
||||
// Home page (constants-driven labels)
|
||||
'Cost Tracking',
|
||||
'Model Access',
|
||||
'Guardrails',
|
||||
'Observability',
|
||||
'Budgets',
|
||||
'Load Balancing',
|
||||
'Rate Limiting',
|
||||
'Token Mgmt',
|
||||
'Prompt Caching',
|
||||
'Pass-Through',
|
||||
'requests served',
|
||||
'AI models supported',
|
||||
'uptime',
|
||||
'active users',
|
||||
'Lightning Fast',
|
||||
'Optimized network architecture ensures millisecond response times',
|
||||
'Secure & Reliable',
|
||||
'Enterprise-grade security with comprehensive permission management',
|
||||
'Global Coverage',
|
||||
'Multi-region deployment for stable global access',
|
||||
'Developer Friendly',
|
||||
'Complete API documentation with multi-language SDK support',
|
||||
'High Performance',
|
||||
'Support for high concurrency with automatic load balancing',
|
||||
'Transparent Billing',
|
||||
'Pay-as-you-go with real-time usage monitoring',
|
||||
'Team Collaboration',
|
||||
'Multi-user management with flexible permission allocation',
|
||||
'Technical Support',
|
||||
'Professional team providing 24/7 technical support',
|
||||
|
||||
// User management (interpolated keys)
|
||||
'Remaining Quota ({{currency}})',
|
||||
'Enter quota in tokens',
|
||||
'Enter quota in {{currency}}',
|
||||
|
||||
// Setup wizard — steps
|
||||
'Database check',
|
||||
'Verify your database connection',
|
||||
'Create credentials for the root user',
|
||||
'Choose how the platform will operate',
|
||||
'Review & initialize',
|
||||
'Confirm settings and finish setup',
|
||||
|
||||
// Setup wizard — database step
|
||||
'SQLite stores all data in a single file. Make sure that file is persisted when running in containers.',
|
||||
'MySQL is a production-ready relational database. Keep your credentials secure.',
|
||||
'PostgreSQL offers advanced reliability and data integrity for production workloads.',
|
||||
'Custom database driver detected.',
|
||||
'The setup wizard will use this database during initialization.',
|
||||
|
||||
// Setup wizard — usage mode step
|
||||
'External operations',
|
||||
'Serve multiple users or teams with billing and quota control.',
|
||||
'Personal use',
|
||||
'Best for single-tenant deployments. Pricing and billing options stay hidden.',
|
||||
'Demo site',
|
||||
'Showcase core capabilities with demo credentials and limited access.',
|
||||
|
||||
// Setup wizard — complete step
|
||||
'External operations mode',
|
||||
'Personal use mode',
|
||||
'Demo site mode',
|
||||
'Existing account will be reused',
|
||||
'Not set yet',
|
||||
|
||||
// Models section-registry nav (dynamic titleKey)
|
||||
'Grok',
|
||||
|
||||
// Channel Affinity section
|
||||
'Channel Affinity',
|
||||
|
||||
// Models constants
|
||||
'Exact Match',
|
||||
'Prefix Match',
|
||||
'Contains Match',
|
||||
'Suffix Match',
|
||||
'Exact',
|
||||
'Prefix',
|
||||
'Contains',
|
||||
'Suffix',
|
||||
'Match model name exactly',
|
||||
'Match models starting with this name',
|
||||
'Match models containing this name',
|
||||
'Match models ending with this name',
|
||||
|
||||
// Playground parameter controls
|
||||
'Temperature',
|
||||
'Top P',
|
||||
'Frequency Penalty',
|
||||
'Presence Penalty',
|
||||
'Max Tokens',
|
||||
'Seed',
|
||||
'Controls randomness and creativity',
|
||||
'Limits token selection to a probability mass',
|
||||
'Reduces repeated wording',
|
||||
'Encourages new topics',
|
||||
'Caps the response length',
|
||||
'Keeps compatible responses more repeatable',
|
||||
'All Status',
|
||||
'All Sync Status',
|
||||
'Official Sync',
|
||||
'No Sync',
|
||||
'Usage-based',
|
||||
'Per-call',
|
||||
'Chinese',
|
||||
'English',
|
||||
'Japanese',
|
||||
'Official Repository',
|
||||
'Configuration File',
|
||||
'Sync from the public upstream metadata repository.',
|
||||
'Upload or reference a local configuration file.',
|
||||
|
||||
// Subscription constants (dynamic labelKey)
|
||||
'years',
|
||||
'months',
|
||||
'days',
|
||||
'hours',
|
||||
'seconds',
|
||||
'minutes',
|
||||
'Custom (seconds)',
|
||||
'No Reset',
|
||||
'Daily',
|
||||
'Weekly',
|
||||
'Monthly',
|
||||
|
||||
// CC Switch dialog
|
||||
'Import to CC Switch',
|
||||
'Open CC Switch',
|
||||
'Primary Model',
|
||||
'Haiku Model',
|
||||
'Sonnet Model',
|
||||
'Opus Model',
|
||||
'Enter model name',
|
||||
|
||||
// User binding dialog
|
||||
'Account Binding Management',
|
||||
'Built-in',
|
||||
'Confirm Unbind',
|
||||
'Unbind',
|
||||
'Unbind failed',
|
||||
'This user has no bindings',
|
||||
|
||||
// Subscription plans
|
||||
'Subscription Plans',
|
||||
'Subscribe Now',
|
||||
'Purchase Subscription',
|
||||
'My Subscriptions',
|
||||
'Plan Name',
|
||||
'Validity Period',
|
||||
'Reset Period',
|
||||
'Quota Reset',
|
||||
'Raw Quota',
|
||||
'Amount Due',
|
||||
'Purchase Limit',
|
||||
'Purchase limit reached',
|
||||
'Limit Reached',
|
||||
'No plans available',
|
||||
'Select payment method',
|
||||
'Wallet First',
|
||||
'Wallet Only',
|
||||
'Subscription First',
|
||||
'Subscription Only',
|
||||
'No Active',
|
||||
'No Reset',
|
||||
'Remaining',
|
||||
'Received',
|
||||
'Payment initiated',
|
||||
'Payment page opened',
|
||||
|
||||
// Upstream model updates
|
||||
'Upstream Model Updates',
|
||||
'Sync Fields',
|
||||
'Add Models',
|
||||
'Remove Models',
|
||||
'Select All Visible',
|
||||
'Partial Submission',
|
||||
'No models to add',
|
||||
'No models to remove',
|
||||
|
||||
// Header manipulation
|
||||
'Pass Headers',
|
||||
'Set Header',
|
||||
'Copy Header',
|
||||
'Delete Header',
|
||||
'Move Header',
|
||||
'Prepend',
|
||||
'Append',
|
||||
'Ensure Prefix',
|
||||
'Ensure Suffix',
|
||||
'Trim Prefix',
|
||||
'Trim Suffix',
|
||||
'Trim Space',
|
||||
'To Upper',
|
||||
'To Lower',
|
||||
'Regex Replace',
|
||||
'Return Error',
|
||||
'Param Override',
|
||||
'Override request parameters',
|
||||
|
||||
// Profile / 2FA
|
||||
'Backed up',
|
||||
'Not backed up',
|
||||
'No backup',
|
||||
'Generate New Codes',
|
||||
'Audio Preview',
|
||||
|
||||
// Status-code risk dialog
|
||||
'High-risk status code retry risk check 1',
|
||||
'High-risk status code retry risk check 2',
|
||||
'High-risk status code retry risk check 3',
|
||||
'High-risk status code retry risk check 4',
|
||||
'High-risk operation confirmation',
|
||||
'High-risk status code retry risk disclaimer',
|
||||
'Detected high-risk status code redirect rules',
|
||||
'Action confirmation',
|
||||
'High-risk status code retry confirmation text',
|
||||
'High-risk status code retry input placeholder',
|
||||
'High-risk status code retry input mismatch',
|
||||
'I confirm enabling high-risk retry',
|
||||
|
||||
// Subscription management
|
||||
'Subscription Management',
|
||||
'Subscriptions',
|
||||
'Stripe/Creem requires creating products on the third-party platform and entering the ID',
|
||||
'Create Plan',
|
||||
'Active',
|
||||
'Invalidated',
|
||||
'Plan',
|
||||
'Price',
|
||||
'Priority',
|
||||
'Payment Channel',
|
||||
'No Upgrade',
|
||||
'Downgrade to pre-purchase group',
|
||||
'Downgrade Group',
|
||||
'Downgrade to this group after the subscription expires',
|
||||
'Allow wallet balance after quota used up',
|
||||
'Unlimited',
|
||||
'Update plan info',
|
||||
'Create new subscription plan',
|
||||
'Modify existing subscription plan configuration',
|
||||
'Fill in the following info to create a new subscription plan',
|
||||
'Basic Info',
|
||||
'Plan Title',
|
||||
'e.g. Basic Plan',
|
||||
'Plan Subtitle',
|
||||
'e.g. Suitable for light usage',
|
||||
'Actual Amount',
|
||||
'Plan Price',
|
||||
'Amount the user pays to purchase this plan; the actual currency depends on the payment gateway.',
|
||||
'Plan Quota',
|
||||
'Total quota included in the plan, usable per billing period. 0 means unlimited.',
|
||||
'Total Quota',
|
||||
'0 means unlimited',
|
||||
'Sort Order',
|
||||
'Enabled Status',
|
||||
'Duration Settings',
|
||||
'Duration Unit',
|
||||
'Custom Seconds',
|
||||
'Duration Value',
|
||||
'Third-party Payment Config',
|
||||
'Submitting...',
|
||||
'Submit',
|
||||
'Update succeeded',
|
||||
'Create succeeded',
|
||||
'Request failed',
|
||||
'Please enter plan title',
|
||||
'Please enter amount',
|
||||
'No subscription plans yet',
|
||||
'Click "Create Plan" to create your first subscription plan',
|
||||
'Confirm disable',
|
||||
'Confirm enable',
|
||||
'After disabling, it will no longer be shown to users, but historical orders are not affected. Continue?',
|
||||
'After enabling, the plan will be shown to users. Continue?',
|
||||
'Has been disabled',
|
||||
'Has been enabled',
|
||||
'Operation failed',
|
||||
'Edit',
|
||||
'Disable',
|
||||
'Enable',
|
||||
|
||||
// User subscription management
|
||||
'User Subscription Management',
|
||||
'Select subscription plan',
|
||||
'Add subscription',
|
||||
'Loading...',
|
||||
'No subscription records',
|
||||
'Source',
|
||||
'Start',
|
||||
'End',
|
||||
'Invalidate',
|
||||
'Delete',
|
||||
'Confirm invalidate',
|
||||
'Confirm delete',
|
||||
'After invalidating, this subscription will be immediately deactivated. Historical records are not affected. Continue?',
|
||||
'Deleting will permanently remove this subscription record (including benefit details). Continue?',
|
||||
'Loading failed',
|
||||
'Please select a subscription plan',
|
||||
'Added successfully',
|
||||
'Has been invalidated',
|
||||
'Deleted',
|
||||
'Validity',
|
||||
'Actions',
|
||||
|
||||
// Sidebar modules
|
||||
'Chat Area',
|
||||
'Playground and chat functions',
|
||||
'Playground',
|
||||
'AI model testing environment',
|
||||
'Chat session management',
|
||||
'No content to copy',
|
||||
'Please wait for the current generation to complete',
|
||||
'An unknown error occurred',
|
||||
'Request error occurred',
|
||||
'Network connection failed or server not responding',
|
||||
'Error parsing response data',
|
||||
'Error establishing connection',
|
||||
'Connection closed',
|
||||
'Generation was interrupted',
|
||||
'Note',
|
||||
'Tip',
|
||||
'Important',
|
||||
'Image not available',
|
||||
'Back to footnote {{id}} reference',
|
||||
'Console Area',
|
||||
'Data management and log viewing',
|
||||
'Dashboard',
|
||||
'System data statistics',
|
||||
'Flow',
|
||||
'Flow Filters',
|
||||
'Filter the traffic flow view by time range and user.',
|
||||
'Requests',
|
||||
'Token Management',
|
||||
'API token management',
|
||||
'Usage Logs',
|
||||
'API usage records',
|
||||
'Drawing Logs',
|
||||
'Drawing task records',
|
||||
'Task Logs',
|
||||
'System task records',
|
||||
'Personal Center Area',
|
||||
'User personal functions',
|
||||
'Wallet Management',
|
||||
'Balance and top-up management',
|
||||
'Personal Settings',
|
||||
'Personal info settings',
|
||||
'Saved successfully',
|
||||
'Save failed',
|
||||
'Save failed, please retry',
|
||||
'Reset to default configuration',
|
||||
'Sidebar Personal Settings',
|
||||
'Customize sidebar display content',
|
||||
'Reset to Default',
|
||||
|
||||
// Available models
|
||||
'Available Models',
|
||||
'View all currently available models',
|
||||
'No available models',
|
||||
'models',
|
||||
'More',
|
||||
'Collapse',
|
||||
'No models available in this category',
|
||||
'Copied: {{model}}',
|
||||
|
||||
// Grok settings
|
||||
'Grok Settings',
|
||||
'Enable violation deduction',
|
||||
'When enabled, violation requests will incur additional charges.',
|
||||
'Official documentation',
|
||||
'Violation deduction amount',
|
||||
'Base amount. Actual deduction = base amount × system group rate.',
|
||||
|
||||
// Chat2Link
|
||||
'No available Web chat links',
|
||||
'No enabled tokens available',
|
||||
'Redirecting to chat page...',
|
||||
|
||||
// Channel upstream updates
|
||||
'No processable upstream model updates for this channel',
|
||||
'Upstream model updates applied: {{added}} added, {{removed}} removed, {{ignored}} ignored this time, {{totalIgnored}} total ignored models',
|
||||
'Batch processing failed',
|
||||
'Batch upstream model updates applied: {{channels}} channels, {{added}} added, {{removed}} removed, {{fails}} failed',
|
||||
'Detection failed',
|
||||
'Detection complete: {{add}} to add, {{remove}} to remove',
|
||||
'Batch detection failed',
|
||||
'Batch detection complete: {{channels}} channels, {{add}} to add, {{remove}} to remove, {{fails}} failed',
|
||||
|
||||
// Advanced Custom model discovery
|
||||
'Only one OpenAI Models route is allowed',
|
||||
'OpenAI Models route does not support client model rules',
|
||||
'OpenAI Models route must use native forwarding',
|
||||
'OpenAI Models upstream path must not contain {model}',
|
||||
'OpenAI Models route is required to enable upstream model checks',
|
||||
|
||||
// Dashboard flow stages (labels/descriptions passed to t at runtime)
|
||||
'User',
|
||||
'Node',
|
||||
'Token',
|
||||
'Group',
|
||||
'Model',
|
||||
'Channel',
|
||||
'The user who made the requests',
|
||||
'The deployment node that handled the requests',
|
||||
'The API key used for the requests',
|
||||
'The user group applied to the requests',
|
||||
'The model that was requested',
|
||||
'The upstream channel that served the requests',
|
||||
|
||||
// Misc
|
||||
'Cancel',
|
||||
'Status',
|
||||
'Upgrade Group',
|
||||
'Regenerate',
|
||||
'Untitled',
|
||||
'Open in new tab',
|
||||
'Failed to load',
|
||||
'Expired at',
|
||||
'Cancelled at',
|
||||
'Too many active login sessions. On a device where you are already signed in, open Login sessions and use “Sign out other sessions” to revoke them. If you cannot access a signed-in device, reset your password to sign out all sessions.',
|
||||
'Too many login sessions were created recently. Please wait for the rolling window to pass, then try again.',
|
||||
'Telegram binding is disabled.',
|
||||
'The Telegram authorization request is invalid or expired.',
|
||||
'This Telegram binding request has expired or has already been used.',
|
||||
'The login session that started this Telegram binding is no longer valid.',
|
||||
'This Telegram account is already bound.',
|
||||
'This user account no longer exists.',
|
||||
'This user account is disabled.',
|
||||
'Telegram binding failed. Please try again.',
|
||||
'Verification scope is missing',
|
||||
] as const
|
||||
Reference in New Issue
Block a user