Files
nofx/web/src/i18n/translations.ts
2025-11-01 19:39:27 +08:00

652 lines
26 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export type Language = 'en' | 'zh';
export const translations = {
en: {
// Header
appTitle: 'NOFX',
subtitle: 'Multi-AI Model Trading Platform',
aiTraders: 'AI Traders',
details: 'Details',
tradingPanel: 'Trading Panel',
competition: 'Competition',
running: 'RUNNING',
stopped: 'STOPPED',
adminMode: 'Admin Mode',
logout: 'Logout',
switchTrader: 'Switch Trader:',
view: 'View',
// Footer
footerTitle: 'NOFX - AI Trading System',
footerWarning: '⚠️ Trading involves risk. Use at your own discretion.',
// Stats Cards
totalEquity: 'Total Equity',
availableBalance: 'Available Balance',
totalPnL: 'Total P&L',
positions: 'Positions',
margin: 'Margin',
free: 'Free',
// Positions Table
currentPositions: 'Current Positions',
active: 'Active',
symbol: 'Symbol',
side: 'Side',
entryPrice: 'Entry Price',
markPrice: 'Mark Price',
quantity: 'Quantity',
positionValue: 'Position Value',
leverage: 'Leverage',
unrealizedPnL: 'Unrealized P&L',
liqPrice: 'Liq. Price',
long: 'LONG',
short: 'SHORT',
noPositions: 'No Positions',
noActivePositions: 'No active trading positions',
// Recent Decisions
recentDecisions: 'Recent Decisions',
lastCycles: 'Last {count} trading cycles',
noDecisionsYet: 'No Decisions Yet',
aiDecisionsWillAppear: 'AI trading decisions will appear here',
cycle: 'Cycle',
success: 'Success',
failed: 'Failed',
inputPrompt: 'Input Prompt',
aiThinking: 'AI Chain of Thought',
collapse: 'Collapse',
expand: 'Expand',
// Equity Chart
accountEquityCurve: 'Account Equity Curve',
noHistoricalData: 'No Historical Data',
dataWillAppear: 'Equity curve will appear after running a few cycles',
initialBalance: 'Initial Balance',
currentEquity: 'Current Equity',
historicalCycles: 'Historical Cycles',
displayRange: 'Display Range',
recent: 'Recent',
allData: 'All Data',
cycles: 'Cycles',
// Comparison Chart
comparisonMode: 'Comparison Mode',
dataPoints: 'Data Points',
currentGap: 'Current Gap',
count: '{count} pts',
// Competition Page
aiCompetition: 'AI Competition',
traders: 'traders',
liveBattle: 'Live Battle',
realTimeBattle: 'Real-time Battle',
leader: 'Leader',
leaderboard: 'Leaderboard',
live: 'LIVE',
realTime: 'LIVE',
performanceComparison: 'Performance Comparison',
realTimePnL: 'Real-time PnL %',
realTimePnLPercent: 'Real-time PnL %',
headToHead: 'Head-to-Head Battle',
leadingBy: 'Leading by {gap}%',
behindBy: 'Behind by {gap}%',
equity: 'Equity',
pnl: 'P&L',
pos: 'Pos',
// AI Learning
aiLearning: 'AI Learning & Reflection',
tradesAnalyzed: '{count} trades analyzed · Real-time evolution',
latestReflection: 'Latest Reflection',
fullCoT: 'Full Chain of Thought',
totalTrades: 'Total Trades',
winRate: 'Win Rate',
avgWin: 'Avg Win',
avgLoss: 'Avg Loss',
profitFactor: 'Profit Factor',
avgWinDivLoss: 'Avg Win ÷ Avg Loss',
excellent: '🔥 Excellent - Strong profitability',
good: '✓ Good - Stable profits',
fair: '⚠️ Fair - Needs optimization',
poor: '❌ Poor - Losses exceed gains',
bestPerformer: 'Best Performer',
worstPerformer: 'Worst Performer',
symbolPerformance: 'Symbol Performance',
tradeHistory: 'Trade History',
completedTrades: 'Recent {count} completed trades',
noCompletedTrades: 'No completed trades yet',
completedTradesWillAppear: 'Completed trades will appear here',
entry: 'Entry',
exit: 'Exit',
stopLoss: 'Stop Loss',
latest: 'Latest',
// AI Learning Description
howAILearns: 'How AI Learns & Evolves',
aiLearningPoint1: 'Analyzes last 20 trading cycles before each decision',
aiLearningPoint2: 'Identifies best & worst performing symbols',
aiLearningPoint3: 'Optimizes position sizing based on win rate',
aiLearningPoint4: 'Avoids repeating past mistakes',
// AI Traders Management
manageAITraders: 'Manage your AI trading bots',
aiModels: 'AI Models',
exchanges: 'Exchanges',
createTrader: 'Create Trader',
modelConfiguration: 'Model Configuration',
configured: 'Configured',
notConfigured: 'Not Configured',
currentTraders: 'Current Traders',
noTraders: 'No AI Traders',
createFirstTrader: 'Create your first AI trader to get started',
configureModelsFirst: 'Please configure AI models first',
configureExchangesFirst: 'Please configure exchanges first',
configureModelsAndExchangesFirst: 'Please configure AI models and exchanges first',
modelNotConfigured: 'Selected model is not configured',
exchangeNotConfigured: 'Selected exchange is not configured',
confirmDeleteTrader: 'Are you sure you want to delete this trader?',
status: 'Status',
start: 'Start',
stop: 'Stop',
createNewTrader: 'Create New AI Trader',
selectAIModel: 'Select AI Model',
selectExchange: 'Select Exchange',
traderName: 'Trader Name',
enterTraderName: 'Enter trader name',
cancel: 'Cancel',
create: 'Create',
configureAIModels: 'Configure AI Models',
configureExchanges: 'Configure Exchanges',
useTestnet: 'Use Testnet',
enabled: 'Enabled',
save: 'Save',
// AI Model Configuration
officialAPI: 'Official API',
customAPI: 'Custom API',
apiKey: 'API Key',
customAPIURL: 'Custom API URL',
enterAPIKey: 'Enter API Key',
enterCustomAPIURL: 'Enter custom API endpoint URL',
useOfficialAPI: 'Use official API service',
useCustomAPI: 'Use custom API endpoint',
// Exchange Configuration
secretKey: 'Secret Key',
privateKey: 'Private Key',
walletAddress: 'Wallet Address',
user: 'User',
signer: 'Signer',
passphrase: 'Passphrase',
enterPrivateKey: 'Enter Private Key',
enterWalletAddress: 'Enter Wallet Address',
enterUser: 'Enter User',
enterSigner: 'Enter Signer Address',
enterSecretKey: 'Enter Secret Key',
enterPassphrase: 'Enter Passphrase (Required for OKX)',
hyperliquidPrivateKeyDesc: 'Hyperliquid uses private key for trading authentication',
hyperliquidWalletAddressDesc: 'Wallet address corresponding to the private key',
testnetDescription: 'Enable to connect to exchange test environment for simulated trading',
securityWarning: 'Security Warning',
saveConfiguration: 'Save Configuration',
// Trader Configuration
positionMode: 'Position Mode',
crossMarginMode: 'Cross Margin',
isolatedMarginMode: 'Isolated Margin',
crossMarginDescription: 'Cross margin: All positions share account balance as collateral',
isolatedMarginDescription: 'Isolated margin: Each position manages collateral independently, risk isolation',
leverageConfiguration: 'Leverage Configuration',
btcEthLeverage: 'BTC/ETH Leverage',
altcoinLeverage: 'Altcoin Leverage',
leverageRecommendation: 'Recommended: BTC/ETH 5-10x, Altcoins 3-5x for risk control',
tradingSymbols: 'Trading Symbols',
tradingSymbolsPlaceholder: 'Enter symbols, comma separated (e.g., BTCUSDT,ETHUSDT,SOLUSDT)',
selectSymbols: 'Select Symbols',
selectTradingSymbols: 'Select Trading Symbols',
selectedSymbolsCount: 'Selected {count} symbols',
clearSelection: 'Clear All',
confirmSelection: 'Confirm',
tradingSymbolsDescription: 'Empty = use default symbols. Must end with USDT (e.g., BTCUSDT, ETHUSDT)',
btcEthLeverageValidation: 'BTC/ETH leverage must be between 1-50x',
altcoinLeverageValidation: 'Altcoin leverage must be between 1-20x',
invalidSymbolFormat: 'Invalid symbol format: {symbol}, must end with USDT',
// Loading & Error
loading: 'Loading...',
loadingError: '⚠️ Failed to load AI learning data',
noCompleteData: 'No complete trading data (needs to complete open → close cycle)',
// AI Traders Page - Additional
inUse: 'In Use',
noModelsConfigured: 'No configured AI models',
noExchangesConfigured: 'No configured exchanges',
signalSource: 'Signal Source',
signalSourceConfig: 'Signal Source Configuration',
coinPoolDescription: 'API endpoint for coin pool data, leave blank to disable this signal source',
oiTopDescription: 'API endpoint for open interest rankings, leave blank to disable this signal source',
information: 'Information',
signalSourceInfo1: '• Signal source configuration is per-user, each user can set their own URLs',
signalSourceInfo2: '• When creating traders, you can choose whether to use these signal sources',
signalSourceInfo3: '• Configured URLs will be used to fetch market data and trading signals',
editAIModel: 'Edit AI Model',
addAIModel: 'Add AI Model',
confirmDeleteModel: 'Are you sure you want to delete this AI model configuration?',
selectModel: 'Select AI Model',
pleaseSelectModel: 'Please select a model',
customBaseURL: 'Base URL (Optional)',
customBaseURLPlaceholder: 'Custom API base URL, e.g.: https://api.openai.com/v1',
leaveBlankForDefault: 'Leave blank to use default API address',
modelConfigInfo1: '• API Key will be encrypted and stored, please ensure it is valid',
modelConfigInfo2: '• Base URL is used for custom API server address',
modelConfigInfo3: '• After deleting configuration, traders using this model will not work properly',
saveConfig: 'Save Configuration',
editExchange: 'Edit Exchange',
addExchange: 'Add Exchange',
confirmDeleteExchange: 'Are you sure you want to delete this exchange configuration?',
pleaseSelectExchange: 'Please select an exchange',
exchangeConfigWarning1: '• API keys will be encrypted, recommend using read-only or futures trading permissions',
exchangeConfigWarning2: '• Do not grant withdrawal permissions to ensure fund security',
exchangeConfigWarning3: '• After deleting configuration, related traders will not be able to trade',
edit: 'Edit',
// Error Messages
createTraderFailed: 'Failed to create trader',
getTraderConfigFailed: 'Failed to get trader configuration',
modelConfigNotExist: 'Model configuration does not exist or is not enabled',
exchangeConfigNotExist: 'Exchange configuration does not exist or is not enabled',
updateTraderFailed: 'Failed to update trader',
deleteTraderFailed: 'Failed to delete trader',
operationFailed: 'Operation failed',
deleteConfigFailed: 'Failed to delete configuration',
modelNotExist: 'Model does not exist',
saveConfigFailed: 'Failed to save configuration',
exchangeNotExist: 'Exchange does not exist',
deleteExchangeConfigFailed: 'Failed to delete exchange configuration',
saveSignalSourceFailed: 'Failed to save signal source configuration',
// Login & Register
login: 'Sign In',
register: 'Sign Up',
email: 'Email',
password: 'Password',
confirmPassword: 'Confirm Password',
emailPlaceholder: 'your@email.com',
passwordPlaceholder: 'Enter your password',
confirmPasswordPlaceholder: 'Re-enter your password',
otpPlaceholder: '000000',
loginTitle: 'Sign in to your account',
registerTitle: 'Create a new account',
loginButton: 'Sign In',
registerButton: 'Sign Up',
back: 'Back',
noAccount: "Don't have an account?",
hasAccount: 'Already have an account?',
registerNow: 'Sign up now',
loginNow: 'Sign in now',
forgotPassword: 'Forgot password?',
rememberMe: 'Remember me',
otpCode: 'OTP Code',
scanQRCode: 'Scan QR Code',
enterOTPCode: 'Enter 6-digit OTP code',
verifyOTP: 'Verify OTP',
setupTwoFactor: 'Set up two-factor authentication',
setupTwoFactorDesc: 'Follow the steps below to secure your account with Google Authenticator',
scanQRCodeInstructions: 'Scan this QR code with Google Authenticator or Authy',
otpSecret: 'Or enter this secret manually:',
qrCodeHint: 'QR code (if scanning fails, use the secret below):',
step1Title: 'Step 1: Install Google Authenticator',
step1Desc: 'Download and install Google Authenticator from your app store',
step2Title: 'Step 2: Add account',
step2Desc: 'Tap "+", then choose "Scan QR code" or "Enter a setup key"',
step3Title: 'Step 3: Verify setup',
step3Desc: 'After setup, continue to enter the 6-digit code',
setupCompleteContinue: 'I have completed setup, continue',
copy: 'Copy',
completeRegistration: 'Complete Registration',
completeRegistrationSubtitle: 'to complete registration',
loginSuccess: 'Login successful',
registrationSuccess: 'Registration successful',
loginFailed: 'Login failed',
registrationFailed: 'Registration failed',
verificationFailed: 'OTP verification failed',
invalidCredentials: 'Invalid email or password',
passwordMismatch: 'Passwords do not match',
emailRequired: 'Email is required',
passwordRequired: 'Password is required',
invalidEmail: 'Invalid email format',
passwordTooShort: 'Password must be at least 6 characters',
},
zh: {
// Header
appTitle: 'NOFX',
subtitle: '多AI模型交易平台',
aiTraders: 'AI交易员',
details: '详情',
tradingPanel: '交易面板',
competition: '竞赛',
running: '运行中',
stopped: '已停止',
adminMode: '管理员模式',
logout: '退出',
switchTrader: '切换交易员:',
view: '查看',
// Footer
footerTitle: 'NOFX - AI交易系统',
footerWarning: '⚠️ 交易有风险,请谨慎使用。',
// Stats Cards
totalEquity: '总净值',
availableBalance: '可用余额',
totalPnL: '总盈亏',
positions: '持仓',
margin: '保证金',
free: '空闲',
// Positions Table
currentPositions: '当前持仓',
active: '活跃',
symbol: '币种',
side: '方向',
entryPrice: '入场价',
markPrice: '标记价',
quantity: '数量',
positionValue: '仓位价值',
leverage: '杠杆',
unrealizedPnL: '未实现盈亏',
liqPrice: '强平价',
long: '多头',
short: '空头',
noPositions: '无持仓',
noActivePositions: '当前没有活跃的交易持仓',
// Recent Decisions
recentDecisions: '最近决策',
lastCycles: '最近 {count} 个交易周期',
noDecisionsYet: '暂无决策',
aiDecisionsWillAppear: 'AI交易决策将显示在这里',
cycle: '周期',
success: '成功',
failed: '失败',
inputPrompt: '输入提示',
aiThinking: '💭 AI思维链分析',
collapse: '▼ 收起',
expand: '▶ 展开',
// Equity Chart
accountEquityCurve: '账户净值曲线',
noHistoricalData: '暂无历史数据',
dataWillAppear: '运行几个周期后将显示收益率曲线',
initialBalance: '初始余额',
currentEquity: '当前净值',
historicalCycles: '历史周期',
displayRange: '显示范围',
recent: '最近',
allData: '全部数据',
cycles: '个',
// Comparison Chart
comparisonMode: '对比模式',
dataPoints: '数据点数',
currentGap: '当前差距',
count: '{count} 个',
// Competition Page
aiCompetition: 'AI竞赛',
traders: '交易员',
liveBattle: '实时对战',
realTimeBattle: '实时对战',
leader: '领先者',
leaderboard: '排行榜',
live: '实时',
realTime: '实时',
performanceComparison: '表现对比',
realTimePnL: '实时收益率',
realTimePnLPercent: '实时收益率',
headToHead: '正面对决',
leadingBy: '领先 {gap}%',
behindBy: '落后 {gap}%',
equity: '权益',
pnl: '收益',
pos: '持仓',
// AI Learning
aiLearning: 'AI学习与反思',
tradesAnalyzed: '已分析 {count} 笔交易 · 实时演化',
latestReflection: '最新反思',
fullCoT: '📋 完整思维链',
totalTrades: '总交易数',
winRate: '胜率',
avgWin: '平均盈利',
avgLoss: '平均亏损',
profitFactor: '盈亏比',
avgWinDivLoss: '平均盈利 ÷ 平均亏损',
excellent: '🔥 优秀 - 盈利能力强',
good: '✓ 良好 - 稳定盈利',
fair: '⚠️ 一般 - 需要优化',
poor: '❌ 较差 - 亏损超过盈利',
bestPerformer: '最佳表现',
worstPerformer: '最差表现',
symbolPerformance: '📊 币种表现',
tradeHistory: '历史成交',
completedTrades: '最近 {count} 笔已完成交易',
noCompletedTrades: '暂无完成的交易',
completedTradesWillAppear: '已完成的交易将显示在这里',
entry: '入场',
exit: '出场',
stopLoss: '止损',
latest: '最新',
// AI Learning Description
howAILearns: '💡 AI如何学习和进化',
aiLearningPoint1: '每次决策前分析最近20个交易周期',
aiLearningPoint2: '识别表现最好和最差的币种',
aiLearningPoint3: '根据胜率优化仓位大小',
aiLearningPoint4: '避免重复过去的错误',
// AI Traders Management
manageAITraders: '管理您的AI交易机器人',
aiModels: 'AI模型',
exchanges: '交易所',
createTrader: '创建交易员',
modelConfiguration: '模型配置',
configured: '已配置',
notConfigured: '未配置',
currentTraders: '当前交易员',
noTraders: '暂无AI交易员',
createFirstTrader: '创建您的第一个AI交易员开始使用',
configureModelsFirst: '请先配置AI模型',
configureExchangesFirst: '请先配置交易所',
configureModelsAndExchangesFirst: '请先配置AI模型和交易所',
modelNotConfigured: '所选模型未配置',
exchangeNotConfigured: '所选交易所未配置',
confirmDeleteTrader: '确定要删除这个交易员吗?',
status: '状态',
start: '启动',
stop: '停止',
createNewTrader: '创建新的AI交易员',
selectAIModel: '选择AI模型',
selectExchange: '选择交易所',
traderName: '交易员名称',
enterTraderName: '输入交易员名称',
cancel: '取消',
create: '创建',
configureAIModels: '配置AI模型',
configureExchanges: '配置交易所',
useTestnet: '使用测试网',
enabled: '启用',
save: '保存',
// AI Model Configuration
officialAPI: '官方API',
customAPI: '自定义API',
apiKey: 'API密钥',
customAPIURL: '自定义API地址',
enterAPIKey: '请输入API密钥',
enterCustomAPIURL: '请输入自定义API端点地址',
useOfficialAPI: '使用官方API服务',
useCustomAPI: '使用自定义API端点',
// Exchange Configuration
secretKey: '密钥',
privateKey: '私钥',
walletAddress: '钱包地址',
user: '用户名',
signer: '签名者',
passphrase: '口令',
enterSecretKey: '输入密钥',
enterPrivateKey: '输入私钥',
enterWalletAddress: '输入钱包地址',
enterUser: '输入用户名',
enterSigner: '输入签名者地址',
enterPassphrase: '输入Passphrase (OKX必填)',
hyperliquidPrivateKeyDesc: 'Hyperliquid 使用私钥进行交易认证',
hyperliquidWalletAddressDesc: '与私钥对应的钱包地址',
testnetDescription: '启用后将连接到交易所测试环境,用于模拟交易',
securityWarning: '安全提示',
saveConfiguration: '保存配置',
// Trader Configuration
positionMode: '仓位模式',
crossMarginMode: '全仓模式',
isolatedMarginMode: '逐仓模式',
crossMarginDescription: '全仓模式:所有仓位共享账户余额作为保证金',
isolatedMarginDescription: '逐仓模式:每个仓位独立管理保证金,风险隔离',
leverageConfiguration: '杠杆配置',
btcEthLeverage: 'BTC/ETH杠杆',
altcoinLeverage: '山寨币杠杆',
leverageRecommendation: '推荐BTC/ETH 5-10倍山寨币 3-5倍控制风险',
tradingSymbols: '交易币种',
tradingSymbolsPlaceholder: '输入币种逗号分隔BTCUSDT,ETHUSDT,SOLUSDT',
selectSymbols: '选择币种',
selectTradingSymbols: '选择交易币种',
selectedSymbolsCount: '已选择 {count} 个币种',
clearSelection: '清空选择',
confirmSelection: '确认选择',
tradingSymbolsDescription: '留空 = 使用默认币种。必须以USDT结尾BTCUSDT, ETHUSDT',
btcEthLeverageValidation: 'BTC/ETH杠杆必须在1-50倍之间',
altcoinLeverageValidation: '山寨币杠杆必须在1-20倍之间',
invalidSymbolFormat: '无效的币种格式:{symbol}必须以USDT结尾',
// Loading & Error
loading: '加载中...',
loadingError: '⚠️ 加载AI学习数据失败',
noCompleteData: '暂无完整交易数据(需要完成开仓→平仓的完整周期)',
// AI Traders Page - Additional
inUse: '正在使用',
noModelsConfigured: '暂无已配置的AI模型',
noExchangesConfigured: '暂无已配置的交易所',
signalSource: '信号源',
signalSourceConfig: '信号源配置',
coinPoolDescription: '用于获取币种池数据的API地址留空则不使用此信号源',
oiTopDescription: '用于获取持仓量排行数据的API地址留空则不使用此信号源',
information: '说明',
signalSourceInfo1: '• 信号源配置为用户级别每个用户可以设置自己的信号源URL',
signalSourceInfo2: '• 在创建交易员时可以选择是否使用这些信号源',
signalSourceInfo3: '• 配置的URL将用于获取市场数据和交易信号',
editAIModel: '编辑AI模型',
addAIModel: '添加AI模型',
confirmDeleteModel: '确定要删除此AI模型配置吗',
selectModel: '选择AI模型',
pleaseSelectModel: '请选择模型',
customBaseURL: 'Base URL (可选)',
customBaseURLPlaceholder: '自定义API基础URL如: https://api.openai.com/v1',
leaveBlankForDefault: '留空则使用默认API地址',
modelConfigInfo1: '• API Key将被加密存储请确保密钥有效',
modelConfigInfo2: '• Base URL用于自定义API服务器地址',
modelConfigInfo3: '• 删除配置后,使用此模型的交易员将无法正常工作',
saveConfig: '保存配置',
editExchange: '编辑交易所',
addExchange: '添加交易所',
confirmDeleteExchange: '确定要删除此交易所配置吗?',
pleaseSelectExchange: '请选择交易所',
exchangeConfigWarning1: '• API密钥将被加密存储建议使用只读或期货交易权限',
exchangeConfigWarning2: '• 不要授予提现权限,确保资金安全',
exchangeConfigWarning3: '• 删除配置后,相关交易员将无法正常交易',
edit: '编辑',
// Error Messages
createTraderFailed: '创建交易员失败',
getTraderConfigFailed: '获取交易员配置失败',
modelConfigNotExist: 'AI模型配置不存在或未启用',
exchangeConfigNotExist: '交易所配置不存在或未启用',
updateTraderFailed: '更新交易员失败',
deleteTraderFailed: '删除交易员失败',
operationFailed: '操作失败',
deleteConfigFailed: '删除配置失败',
modelNotExist: '模型不存在',
saveConfigFailed: '保存配置失败',
exchangeNotExist: '交易所不存在',
deleteExchangeConfigFailed: '删除交易所配置失败',
saveSignalSourceFailed: '保存信号源配置失败',
// Login & Register
login: '登录',
register: '注册',
email: '邮箱',
password: '密码',
confirmPassword: '确认密码',
emailPlaceholder: '请输入邮箱地址',
passwordPlaceholder: '请输入密码至少6位',
confirmPasswordPlaceholder: '请再次输入密码',
otpPlaceholder: '000000',
loginTitle: '登录到您的账户',
registerTitle: '创建新账户',
loginButton: '登录',
registerButton: '注册',
back: '返回',
noAccount: '还没有账户?',
hasAccount: '已有账户?',
registerNow: '立即注册',
loginNow: '立即登录',
forgotPassword: '忘记密码?',
rememberMe: '记住我',
otpCode: 'OTP验证码',
scanQRCode: '扫描二维码',
enterOTPCode: '输入6位OTP验证码',
verifyOTP: '验证OTP',
setupTwoFactor: '设置双因素认证',
setupTwoFactorDesc: '请按以下步骤设置Google验证器以保护您的账户安全',
scanQRCodeInstructions: '使用Google Authenticator或Authy扫描此二维码',
otpSecret: '或手动输入此密钥:',
qrCodeHint: '二维码(如果无法扫描,请使用下方密钥):',
step1Title: '步骤1下载Google Authenticator',
step1Desc: '在手机应用商店下载并安装Google Authenticator应用',
step2Title: '步骤2添加账户',
step2Desc: '在应用中点击“+”,选择“扫描二维码”或“手动输入密钥”',
step3Title: '步骤3验证设置',
step3Desc: '设置完成后点击下方按钮输入6位验证码',
setupCompleteContinue: '我已完成设置,继续',
copy: '复制',
completeRegistration: '完成注册',
completeRegistrationSubtitle: '以完成注册',
loginSuccess: '登录成功',
registrationSuccess: '注册成功',
loginFailed: '登录失败',
registrationFailed: '注册失败',
verificationFailed: 'OTP验证失败',
invalidCredentials: '邮箱或密码错误',
passwordMismatch: '两次输入的密码不一致',
emailRequired: '请输入邮箱',
passwordRequired: '请输入密码',
invalidEmail: '邮箱格式不正确',
passwordTooShort: '密码至少需要6个字符',
}
};
export function t(key: string, lang: Language, params?: Record<string, string | number>): string {
let text = translations[lang][key as keyof typeof translations['en']] || key;
// Replace parameters like {count}, {gap}, etc.
if (params) {
Object.entries(params).forEach(([param, value]) => {
text = text.replace(`{${param}}`, String(value));
});
}
return text;
}