- 将注册表单从用户名改为手机号输入 - 集成短信验证码功能,添加验证码输入字段 - 实现发送短信验证码的API调用和倒计时逻辑 - 更新国际化配置以支持验证码相关文案 - 添加桌面端客服聊天弹窗功能 - 调整注册表单UI布局和样式优化 - 修改认证相关常量和类型定义以适配新流程
579 lines
20 KiB
TypeScript
579 lines
20 KiB
TypeScript
export default {
|
|
nav: {
|
|
home: 'Home',
|
|
game: 'Game',
|
|
},
|
|
shell: {
|
|
eyebrow: '36 Character Flower',
|
|
subtitle: 'Real-time draw game frontend for mobile and desktop',
|
|
},
|
|
notFound: {
|
|
eyebrow: '404',
|
|
title: 'The page you requested could not be found.',
|
|
description: 'This route does not exist. Return to the scaffold home page.',
|
|
home: 'Back home',
|
|
},
|
|
home: {
|
|
eyebrow: 'Game shell in progress',
|
|
title:
|
|
'The 36-character-flower dual-device game framework is now being built.',
|
|
description:
|
|
'The project has moved past the generic scaffold stage. It is now being structured around a shared game route, shared state, and split mobile and desktop views for the real-time betting experience.',
|
|
cards: {
|
|
routingMode: 'Routing',
|
|
dataLayer: 'State model',
|
|
transport: 'Realtime',
|
|
auth: 'Product',
|
|
metadata: 'Current focus',
|
|
},
|
|
values: {
|
|
routingMode: 'Shared URL + split device views',
|
|
dataLayer: 'Round / Bet / User / UI / Connection',
|
|
transport: 'HTTP + WebSocket',
|
|
auth: '36-grid live draw gameplay',
|
|
metadata: 'Scaffold the structure before state machine polish',
|
|
},
|
|
footnote:
|
|
'Next up: the main game route, shared business model, and dedicated mobile and desktop page shells.',
|
|
primaryAction: 'Enter game lobby',
|
|
secondaryAction: 'View project structure',
|
|
},
|
|
language: {
|
|
label: 'Language',
|
|
zhCN: '中文',
|
|
enUS: 'English',
|
|
msMY: 'Bahasa Melayu',
|
|
idID: 'Bahasa Indonesia',
|
|
},
|
|
game: {
|
|
metaTitle: 'Game Lobby',
|
|
metaDescription: '36-character-flower live game lobby.',
|
|
lobbyTitle: '36 Character Flower Lobby',
|
|
lobbySubtitle:
|
|
'Under one shared business route, mobile and desktop mount different views on top of the same game data and state.',
|
|
status: {
|
|
roundState: 'Round state',
|
|
currentRound: 'Current round {{id}}',
|
|
tablePool: 'Table pool',
|
|
onlineCount: '{{count}} online',
|
|
activeChip: 'Active chip',
|
|
announcementsRead: '{{read}}/{{total}} announcements read',
|
|
connection: 'Connection',
|
|
connectionHealthy: 'Live sync stable',
|
|
connectionRecovering: 'Waiting to recover',
|
|
synced: 'Synced',
|
|
degraded: 'Degraded',
|
|
},
|
|
board: {
|
|
historyTitle: 'Round history',
|
|
historySubtitle: 'Recent draw and payout trace',
|
|
trendTitle: 'Trend radar',
|
|
trendSubtitle: 'Momentum and miss streak snapshot',
|
|
stageTitle: 'Draw stage',
|
|
stageSubtitle:
|
|
'This stage holds the main board and control structure before the full state machine and animation pass.',
|
|
currentPhase: 'Current phase',
|
|
selectedBet: 'Bet {{amount}}',
|
|
hitCount: '{{count}} hits',
|
|
hitBadge: '{{count}}x',
|
|
badgeWin: 'Win',
|
|
badgeBet: 'Bet',
|
|
cellLabel: 'Cell {{id}}',
|
|
winningCell: 'Winning cell {{id}}',
|
|
missedRounds: 'Missed {{count}} rounds',
|
|
rising: 'Rising',
|
|
falling: 'Falling',
|
|
steady: 'Steady',
|
|
hitTotal: '{{count}} hits',
|
|
},
|
|
phases: {
|
|
betting: 'Betting',
|
|
locked: 'Locked',
|
|
settled: 'Settled',
|
|
},
|
|
roundBettingStart: {
|
|
title: 'Round {{roundId}}',
|
|
action: 'Start Betting',
|
|
},
|
|
actions: {
|
|
unifiedBetHint: 'Unified bet',
|
|
totalBet: 'Total bet',
|
|
canBet: 'Can bet',
|
|
yes: 'Yes',
|
|
no: 'No',
|
|
quickBet: 'Quick bet 08',
|
|
clearPending: 'Clear pending',
|
|
autoModeDemo: 'Auto mode demo',
|
|
stopAuto: 'Stop auto',
|
|
},
|
|
modals: {
|
|
login: {
|
|
title: 'Login',
|
|
},
|
|
register: {
|
|
title: 'Register',
|
|
},
|
|
notice: {
|
|
title: 'Event Notice',
|
|
content:
|
|
'This area will later load the real event announcement body, rich media, and a longer scrollable message. The current version focuses on shared multilingual modal wiring.',
|
|
check: 'View',
|
|
},
|
|
entryNotice: {
|
|
title: 'Site Notice',
|
|
subtitle:
|
|
'Please read the following notices and confirm before entering the game.',
|
|
loading: 'Loading notices...',
|
|
loadFailed: 'Failed to load notices. Please try again.',
|
|
retry: 'Reload',
|
|
agreement: 'I have read and agree.',
|
|
enterGame: 'Enter Game',
|
|
},
|
|
rules: {
|
|
title: 'Game Rules',
|
|
content:
|
|
'1. Basic Gameplay\n1) After each round starts, players may select one or more numbers on the board to place bets.\n2) After betting closes, the system enters the draw phase and settles rewards based on the round result.\n3) Different chip levels correspond to different bet amounts, subject to the current table limits and configuration.\n\n2. Betting Notes\n1) Bets can only be submitted during the betting phase.\n2) Before confirming, please verify your selected numbers, chip amount, and total bet.\n3) If your balance is insufficient, the round is no longer valid, or betting has closed, the request will be rejected.\n\n3. Draw and Settlement\n1) The final displayed draw result is the valid outcome.\n2) Hit rules, odds, payouts, and streak performance are settled in real time according to the current room configuration.\n3) In case of network fluctuation, please refer to the re-synced official data.\n\n4. Additional Notes\n1) Please manage your play time responsibly.\n2) Any abnormal behavior intended to interfere with the system, exploit rewards, or bypass risk control is strictly prohibited.\n3) The platform reserves the right to review orders, payouts, and account status in exceptional situations.',
|
|
confirm: 'Understood',
|
|
},
|
|
procedures: {
|
|
title: 'Top Up / Withdraw',
|
|
contentPlaceholder: 'Choose the action you want to continue with',
|
|
withdraw: 'Withdraw',
|
|
topup: 'Top Up',
|
|
},
|
|
autoSetting: {
|
|
title: 'Auto Spin',
|
|
startAutoSpin: 'Start Auto Spin',
|
|
rows: {
|
|
stopIfBalanceLowerThan: 'Stop if balance is lower than',
|
|
stopIfSingleWinExceeds: 'Stop if a single win exceeds',
|
|
stopOnAnyJackpot: 'Stop on any jackpot',
|
|
},
|
|
},
|
|
userInfo: {
|
|
title: 'User Info',
|
|
tabs: {
|
|
profile: 'Profile',
|
|
financeRecords: 'Top Up / Withdraw Records',
|
|
walletRecords: 'Wallet Records',
|
|
message: 'Messages',
|
|
},
|
|
profile: {
|
|
name: 'Name',
|
|
tel: 'Phone',
|
|
registeredAt: 'Registered at',
|
|
copyInviteLink: 'Copy invite link',
|
|
logout: 'Log out',
|
|
loggingOut: 'Logging out...',
|
|
signature:
|
|
'My signature is as unique as my personality. This area will later display the real profile summary.',
|
|
},
|
|
message: {
|
|
title: 'Messages',
|
|
back: 'Back',
|
|
loading: 'Loading messages...',
|
|
loadFailed: 'Failed to load messages. Please try again later.',
|
|
empty: 'No messages yet',
|
|
read: 'Read',
|
|
unread: 'Unread',
|
|
eventBonus:
|
|
'[Top-up Bonus Event] From October 1 to October 7, 2026, claim your rebate rewards...',
|
|
check: 'View',
|
|
deleteRecords: 'Delete records',
|
|
},
|
|
financeRecords: {
|
|
deposit: 'Top-up Records',
|
|
withdraw: 'Withdrawal Records',
|
|
orderNo: 'Order No.',
|
|
amount: 'Amount',
|
|
bonusAmount: 'Bonus Amount',
|
|
loading: 'Loading records...',
|
|
loadFailed: 'Failed to load records. Please try again later.',
|
|
empty: 'No records yet',
|
|
page: 'Page {{page}} / {{total}} total',
|
|
previous: 'Previous',
|
|
next: 'Next',
|
|
},
|
|
walletRecords: {
|
|
amount: 'Amount',
|
|
balanceAfter: 'After',
|
|
balanceBefore: 'Before',
|
|
empty: 'No wallet records yet',
|
|
loadFailed: 'Failed to load wallet records. Please try again later.',
|
|
loading: 'Loading wallet records...',
|
|
next: 'Next',
|
|
page: 'Page {{page}} / {{total}} total',
|
|
previous: 'Previous',
|
|
remark: 'Remark',
|
|
time: 'Time',
|
|
type: 'Wallet Records',
|
|
},
|
|
},
|
|
withdrawTopup: {
|
|
applyWithdraw: 'Apply for Withdrawal',
|
|
applyTopup: 'Apply for Top Up',
|
|
},
|
|
},
|
|
autoSpin: {
|
|
eyebrow: 'Auto spin',
|
|
title: 'Auto spin running',
|
|
description:
|
|
'Auto mode will cover the board while preserving target cell focus and progress.',
|
|
runningRounds: 'Auto spin running, {{count}} rounds completed',
|
|
trailingLabel: 'Manual input locked',
|
|
},
|
|
footer: {
|
|
implementationTitle: 'Current implementation',
|
|
implementationSubtitle:
|
|
'This iteration prioritizes the dual-device shell, shared model, and business wiring.',
|
|
implementationBody:
|
|
'Next steps are the real API, WebSocket, full UI store, and round lifecycle state machine.',
|
|
limitsTitle: 'Table limits',
|
|
limitsSubtitle: 'Derived from the current lobby data',
|
|
minBet: 'Min bet',
|
|
maxBet: 'Max bet',
|
|
},
|
|
},
|
|
commonUi: {
|
|
dialog: {
|
|
close: 'Close alert',
|
|
confirm: 'OK',
|
|
no: 'No',
|
|
yes: 'Yes',
|
|
},
|
|
modal: {
|
|
close: 'Close modal',
|
|
defaultAriaLabel: 'Modal',
|
|
},
|
|
toast: {
|
|
lobbyInitFailed: 'Failed to load the game lobby',
|
|
loginRequired: 'Please log in before entering the game',
|
|
loginSuccess: 'Login successful',
|
|
logoutSuccess: 'Logged out',
|
|
logoutLocalOnly: 'Logout request failed. Local session was cleared.',
|
|
registerSuccess: 'Registration successful',
|
|
inviteLinkCopied: 'Invite link copied',
|
|
inviteLinkCopyFailed:
|
|
'Failed to copy invite link. Please copy it manually.',
|
|
insufficientBalance: 'Insufficient balance. Please adjust your bet.',
|
|
betLimitExceeded: 'Single bet limit exceeded',
|
|
betUnavailable: 'Betting is not available for this round',
|
|
betPlaced: 'Bet placed successfully',
|
|
noRecentSuccessfulBet:
|
|
'No successful bet from the previous round was found',
|
|
repeatSelectionsRestored:
|
|
'Selections from the last successful round have been restored',
|
|
betRejected: 'Bet was not accepted',
|
|
betPlaceFailed: 'Failed to place the bet. Please try again.',
|
|
selectNumbersBeforeAutoHosting: 'Please select numbers first',
|
|
autoHostingStarted: 'Auto spin started',
|
|
autoHostingStopped: 'Auto spin stopped',
|
|
autoHostingStoppedBalance:
|
|
'Balance condition reached. Auto spin has stopped.',
|
|
autoHostingStoppedBetLimit:
|
|
'Single bet limit exceeded. Auto spin has stopped.',
|
|
autoHostingStoppedWin:
|
|
'Single-win condition reached. Auto spin has stopped.',
|
|
autoHostingStoppedJackpot: 'Jackpot reached. Auto spin has stopped.',
|
|
autoHostingSubmitFailed: 'Auto spin bet failed. Auto spin has stopped.',
|
|
},
|
|
},
|
|
auth: {
|
|
common: {
|
|
arrowIconAlt: 'Arrow',
|
|
actions: {
|
|
submitting: 'Submitting...',
|
|
},
|
|
passwordVisibility: {
|
|
hide: 'Hide password',
|
|
show: 'Show password',
|
|
},
|
|
},
|
|
login: {
|
|
actions: {
|
|
submit: 'Log In',
|
|
},
|
|
fields: {
|
|
username: {
|
|
label: 'Mobile:',
|
|
placeholder: 'Enter mobile number',
|
|
},
|
|
password: {
|
|
label: 'Password:',
|
|
placeholder: 'Enter password',
|
|
},
|
|
},
|
|
footer: {
|
|
registerAccount: 'Create account',
|
|
forgotPassword: 'Forgot password',
|
|
},
|
|
errors: {
|
|
submitFailed: 'Login failed. Please try again later.',
|
|
invalidCredentials: 'Incorrect account or password.',
|
|
},
|
|
},
|
|
register: {
|
|
actions: {
|
|
submit: 'Register',
|
|
},
|
|
fields: {
|
|
mobile: {
|
|
label: 'Mobile:',
|
|
placeholder: 'Enter mobile number',
|
|
},
|
|
captcha: {
|
|
label: 'Code:',
|
|
placeholder: 'Enter verification code',
|
|
},
|
|
password: {
|
|
label: 'Password:',
|
|
placeholder: 'Enter password',
|
|
},
|
|
confirmPassword: {
|
|
label: 'Confirm Password:',
|
|
placeholder: 'Re-enter password',
|
|
},
|
|
inviteCode: {
|
|
label: 'Invite Code:',
|
|
placeholder: 'Enter invite code',
|
|
},
|
|
},
|
|
footer: {
|
|
alreadyHaveAccount: 'Already have an account',
|
|
needHelp: 'Need help',
|
|
},
|
|
errors: {
|
|
submitFailed: 'Registration failed. Please try again later.',
|
|
unauthorized: 'Registration is not authorized. Please try again later.',
|
|
},
|
|
sms: {
|
|
countdown: '{{seconds}}s',
|
|
errors: {
|
|
submitFailed: 'Failed to send code. Please try again later.',
|
|
},
|
|
send: 'Get code',
|
|
sending: 'Sending...',
|
|
success: 'Verification code sent.',
|
|
},
|
|
},
|
|
validation: {
|
|
captcha: {
|
|
required: 'Please enter the verification code.',
|
|
},
|
|
username: {
|
|
required: 'Please enter your mobile number.',
|
|
invalidPhone: 'Please enter a valid mobile number.',
|
|
},
|
|
password: {
|
|
min: 'Password must be at least 6 characters.',
|
|
max: 'Password must be at most 32 characters.',
|
|
},
|
|
inviteCode: {
|
|
required: 'Please enter the invite code.',
|
|
max: 'Invite code must be at most 32 characters.',
|
|
},
|
|
confirmPassword: {
|
|
mismatch: 'The two passwords do not match.',
|
|
},
|
|
},
|
|
errors: {
|
|
requestFailed: 'Request failed. Please try again later.',
|
|
authTokenConfigMissing:
|
|
'Authentication configuration is missing. Please contact support.',
|
|
timeout: 'Request timed out. Please try again later.',
|
|
serviceUnavailable:
|
|
'Service is temporarily unavailable. Please try again later.',
|
|
},
|
|
},
|
|
gameDesktop: {
|
|
header: {
|
|
systemTime: 'System Time',
|
|
rules: 'Rules',
|
|
message: 'Message',
|
|
bgm: 'BGM',
|
|
id: 'ID',
|
|
fullscreen: 'Full Screen',
|
|
login: 'Login',
|
|
register: 'Register',
|
|
},
|
|
control: {
|
|
trend: 'Trend',
|
|
map: 'Map',
|
|
selected: 'Selected',
|
|
totalBet: 'Total Bet',
|
|
confirm: 'Confirm',
|
|
selectNumbers: 'Select Numbers',
|
|
insufficientBalance: 'Insufficient Balance',
|
|
betLimitExceeded: 'Limit Exceeded',
|
|
submitting: 'Submitting...',
|
|
actions: {
|
|
clear: 'Clear',
|
|
repeat: 'Repeat',
|
|
'auto-spin': 'Auto Spin',
|
|
},
|
|
},
|
|
status: {
|
|
odds: 'Odds',
|
|
streak: 'Streak',
|
|
limit: 'Limit',
|
|
roundId: 'Round',
|
|
phase: {
|
|
betting: {
|
|
label: 'Open',
|
|
description: '(Accepting Bets)',
|
|
},
|
|
locked: {
|
|
label: 'Locked',
|
|
description: '(Betting Closed)',
|
|
},
|
|
revealing: {
|
|
label: 'Drawing',
|
|
description: '(Revealing Result)',
|
|
},
|
|
settled: {
|
|
label: 'Drawing',
|
|
description: '(Round Complete)',
|
|
},
|
|
waiting: {
|
|
label: 'Waiting',
|
|
description: '(Waiting for Next Round)',
|
|
},
|
|
},
|
|
},
|
|
title: {
|
|
announcement: 'Announcement',
|
|
},
|
|
animal: {
|
|
insufficientBalanceRecharge: 'Insufficient balance, please top up',
|
|
betLimitExceeded: 'Single bet limit exceeded',
|
|
loading: 'Loading',
|
|
selectionLimitReached: 'Selection limit exceeded',
|
|
tapToEnter: 'Tap To Enter',
|
|
getStart: 'Get Start',
|
|
noBet: 'No Bet',
|
|
},
|
|
history: {
|
|
title: 'History',
|
|
pending: 'PENDING',
|
|
win: 'WIN',
|
|
lost: 'LOST',
|
|
orderNo: 'Order No.',
|
|
roundId: 'Round ID',
|
|
numbers: 'Bet Numbers',
|
|
createdAt: 'Time',
|
|
settledAt: 'Settled At',
|
|
totalPoolAmount: 'Bet Amount',
|
|
winningResult: 'Winning Result',
|
|
payout: 'Win Amount',
|
|
empty: 'No history yet',
|
|
end: 'No more records',
|
|
loading: 'Loading...',
|
|
settled: 'Settled',
|
|
},
|
|
periodHistory: {
|
|
title: 'Draw Result History',
|
|
close: 'Close draw result history',
|
|
empty: 'No draw results yet',
|
|
failed: 'Failed to load draw results',
|
|
loading: 'Loading...',
|
|
retry: 'Retry',
|
|
},
|
|
topup: {
|
|
title: 'Top-up Config',
|
|
platformCoinLabel: 'Platform Coin',
|
|
currencyLabel: 'Currency Type',
|
|
channelLabel: 'Payment Channel',
|
|
rateHint:
|
|
'Exchange rates are for reference only. The final amount follows the top-up-time rate.',
|
|
tier: {
|
|
bonus: 'Bonus',
|
|
coins: 'Credited Coins',
|
|
createSuccess: 'Deposit order created',
|
|
empty: 'No deposit tiers',
|
|
failed: 'Failed to load deposit tiers',
|
|
loading: 'Loading deposit tiers...',
|
|
missingPayUrl: 'Payment link is missing. Please try again later.',
|
|
openPayUrlFailed:
|
|
'Failed to open the payment page. Check your browser popup settings.',
|
|
source: 'Deposit tier endpoint',
|
|
title: 'Deposit Tiers',
|
|
},
|
|
preview: {
|
|
title: 'Top-up Preview',
|
|
depositTitle: 'Select a top-up currency and payment channel',
|
|
depositRate: 'Top-up Rate ({{currency}})',
|
|
depositRateValue: '1 {{currency}} = {{coins}} {{platformCoinLabel}}',
|
|
amount: 'Sample Credit',
|
|
},
|
|
},
|
|
mobile: {
|
|
placeholder: 'Mobile entry is under construction',
|
|
},
|
|
withdraw: {
|
|
availableBalance: 'Available balance: {{amount}}',
|
|
currencySelection: 'Currency type selection',
|
|
selectCurrency: 'Select currency type',
|
|
referenceRateNotice:
|
|
'Exchange rates are for reference only. The final payout follows the withdrawal-time rate.',
|
|
eWallet: 'E-wallet',
|
|
bank: 'Bank',
|
|
minimumAmount: 'Minimum {{currency}} {{amount}}',
|
|
processingTime: 'Processing time',
|
|
arrivalTimeValue: 'Arrives in 30s',
|
|
notice: 'Note',
|
|
feeNotice:
|
|
'Transactions between RM10 and RM99.99 will be charged a minimum withdrawal fee of RM 1.',
|
|
cancel: 'Cancel',
|
|
confirm: 'Confirm',
|
|
submitSuccess: 'Withdrawal request submitted',
|
|
withdrawal: 'Withdrawal',
|
|
fields: {
|
|
diamondAmount: 'Withdrawal Diamond Amount',
|
|
currencyType: 'Currency Type',
|
|
paymentChannel: 'Payment Channel',
|
|
bankCode: 'Bank Code',
|
|
cardHolderName: 'Card Holder Name',
|
|
bankAccountNumber: 'Bank Account Number',
|
|
receiverEmail: 'Receiver Email',
|
|
receiverPhone: 'Receiver Phone',
|
|
},
|
|
placeholders: {
|
|
bankCode: 'Select bank code',
|
|
cardHolderName: 'Enter card holder name',
|
|
bankAccountNumber: 'Enter bank account number',
|
|
receiverEmail: 'Enter receiver email',
|
|
receiverPhone: 'Enter receiver phone number',
|
|
},
|
|
errors: {
|
|
amountRequired: 'Please enter the withdrawal diamond amount.',
|
|
amountBelowMinimum:
|
|
'The withdrawal amount cannot be lower than the minimum amount ({{currency}} {{amount}} / {{diamonds}} diamonds).',
|
|
bankCodeRequired: 'Please select a bank code.',
|
|
bankCodeUnavailable: 'No bank code is currently available.',
|
|
cardHolderNameRequired: 'Please enter the card holder name.',
|
|
bankAccountRequired: 'Please enter the bank account number.',
|
|
paymentChannelRequired: 'Please select a payment channel.',
|
|
paymentChannelUnavailable: 'No payment channel is currently available.',
|
|
receiverEmailInvalid: 'Please enter a valid email address.',
|
|
receiverPhoneInvalid: 'Please enter a valid phone number.',
|
|
amountExceedsBalance:
|
|
'The withdrawal amount cannot exceed the current balance.',
|
|
},
|
|
success: {
|
|
orderNo: 'Order No: {{orderNo}}',
|
|
actualArrivalCoin: 'Actual arrival diamonds: {{amount}}',
|
|
feeCoin: 'Fee diamonds: {{amount}}',
|
|
reviewRequired: 'Risk review required: {{value}}',
|
|
},
|
|
preview: {
|
|
title: 'Exchange Preview',
|
|
diamondAmount: 'Diamond Amount',
|
|
exchangeRate: 'Exchange Rate ({{currency}})',
|
|
exchangeRateValue: '{{coins}} {{platformCoinLabel}} = 1 {{currency}}',
|
|
convertible: 'Convertible {{currency}}',
|
|
fixedExchangeDiamondAmount: 'Fixed Exchange Diamond Amount',
|
|
},
|
|
},
|
|
},
|
|
} as const
|