import { createApp } from 'vue'; import { createPinia } from 'pinia'; import { createI18n } from 'vue-i18n'; import App from './App.vue'; import router from './router/index.ts'; import './styles.css'; const i18n = createI18n({ legacy: false, locale: localStorage.getItem('locale') || 'zh-CN', fallbackLocale: ['en-US', 'zh-CN'], messages: { 'zh-CN': { common: { pull_refresh: '下拉刷新', release_refresh: '释放刷新', refreshing: '刷新中…', loading_more: '加载更多…', no_more: '没有更多了', load_failed: '加载失败', retry: '重试', }, nav: { home: '主页', bet: '投注', bet_history: '历史投注', wallet: '账单', profile: '我的' }, home: { hot_matches: '热门赛事', no_matches: '暂无赛事', announcement_badge: '公告', announcement_default: '欢迎光临 TheBet365 · 足球赛事火热进行中 · 理性投注,量力而行', banner_prev: '上一张', banner_next: '下一张', banner_slide: '第 {n} 张', banner_fallback: 'Banner', }, history: { league_default: '足球', stake: '投注', return: '回报', est_return: '预计回报', odds: '赔率', ft: '全场', ht: '半场', parlay_title: '串关 · {n} 场', parlay_league: '串关 Parlay', empty: '暂无投注记录', no_more: '没有更多记录了', status_won: '赢', status_pending: '待定', status_lost: '输', status_push: '走盘', back: '返回', not_found: '注单不存在', my_pick: '我的选择', my_bets: '我的投注', legs: '串关明细', summary: '投注摘要', bet_no: '注单号', awaiting_result: '等待比赛结果…', filter_all: '全部', filter_won: '已赢', filter_lost: '已输', filter_pending: '待定', filter_push: '走盘', stats_total: '总投注', stats_won: '赢', stats_lost: '输', stats_pending: '待定', stats_push: '走盘', stats_stake: '总投注额', stats_return: '总回报', cashbacked: '已回水', }, auth: { login: '登录', register: '注册账号', logout: '退出登录', username: '账号', password: '密码', invite_code: '邀请码', optional: '选填', captcha_placeholder: '验证码', captcha_refresh: '点击换一张', captcha_wrong: '验证码错误', slide_to_verify: '向右滑动完成验证', click_to_verify: '点击验证', verified: '验证成功', login_required: '请先登录', login_hint: '登录后可下注及访问更多功能', go_login: '去登录', go_register: '没有账号?立即注册', have_account: '已有账号?去登录', register_btn: '注册', register_failed: '注册失败,请重试', continue_browsing: '暂不登录', username_placeholder: '请输入账号', login_account: '手机号 / 账号', login_account_placeholder: '本地号码或账号', login_username_placeholder: '手机号(含区号)或账号', confirm_password: '确认密码', password_mismatch: '两次密码不一致', password_placeholder: '请输入密码', login_btn: '登录', login_failed: '登录失败,请重试', phone: '手机号', phone_placeholder: '请输入手机号', phone_local_placeholder: '请输入手机号', phone_required: '请填写手机号', phone_invalid: '手机号格式无效,请检查位数与号码', phone_country_unsupported: '暂不支持该国家/地区', sms_code: '短信验证码', sms_code_placeholder: '6 位验证码', sms_code_required: '请填写短信验证码', sms_required: '请先获取短信验证码', send_sms: '获取验证码', resend_sms: '{sec}s 后重试', country_search: '搜索国家或区号', country_not_found: '未找到匹配国家', }, support: { short: '客服', title: '在线客服', open: '打开在线客服', close: '关闭', url_pending: '客服链接暂未配置,请联系管理员。', }, wallet: { balance: '余额', cash_balance: '现金余额', card_holder: '持卡人', unsettled: '未结算', available: '可用', no_records: '暂无账单记录', tx_deposit: '充值', tx_admin_deposit: '管理员上分', tx_agent_deposit: '代理上分', tx_player_deposit: '自助充值', tx_withdraw: '人工提款', tx_admin_withdraw: '管理员下分', tx_agent_withdraw: '代理下分', tx_adjust: '人工调整', tx_bet_freeze: '投注冻结', tx_bet_deduct: '投注扣款', tx_bet_win: '投注派彩', tx_bet_lose: '投注结算', tx_bet_push: '投注退水', tx_bet_refund: '投注退款', tx_bet_void: '投注撤销', tx_cashback: '返水入账', tx_resettle: '重新结算', summary_bet: '注单 {betNo}', summary_opening_bonus: '开户赠金', stats_income: '收入', stats_expense: '支出', stats_net: '净额', stats_cashback: '反水', filter_all: '全部', filter_deposit: '充值', filter_withdraw: '提款', filter_bet: '投注', filter_cashback: '反水', view_all: '查看全部账单', detail_summary: '账务明细', detail_amount: '变动金额', detail_balance_before: '变动前余额', detail_balance_after: '变动后余额', detail_frozen_before: '变动前冻结', detail_frozen_after: '变动后冻结', detail_reference: '关联信息', detail_reference_type: '业务类型', detail_reference_id: '关联编号', detail_remark: '备注', detail_bet_link: '查看注单', detail_tx_id: '流水号', detail_not_found: '账单不存在', ref_bet: '投注', ref_deposit: '充值', ref_withdraw: '提款', view_cashbacks: '返水明细', view_cashbacks_detail: '查看返水周期明细', cashback_filter_hint: '此处为入账流水;周期、比例等详见返水明细。', detail_cashback_link: '查看返水明细', ref_cashback: '返水批次', }, recharge: { title: '充值', history: '记录', history_title: '充值记录', bank_transfer: '银行转账', bank_name: '银行名称', account_holder: '账户名', account_number: '账号', usdt_address: 'USDT 地址', amount_label: '充值金额', amount_placeholder: '请输入充值金额', screenshot_label: '上传转账截图', upload_hint: '点击上传截图(最大 5MB)', compressing: '压缩中', submit: '提交充值', submitting: '提交中', submitted: '充值已提交', pending_review: '管理员正在审核,请耐心等待', new_recharge: '继续充值', no_methods: '暂无可用充值方式', select_method: '请选择充值方式', enter_amount: '请输入充值金额', upload_screenshot: '请上传转账截图', submit_failed: '提交失败,请重试', file_must_be_image: '请上传图片文件', file_too_large: '文件不能超过 10MB', status_pending: '充值中', status_approved: '已通过', status_rejected: '已拒绝', no_orders: '暂无充值记录', credited: '实际到账', reject_reason: '拒绝原因', apply_time: '申请时间', review_time: '审核时间', remark: '审核备注', }, cashback: { title: '返水明细', list_title: '发放明细', total_received: '累计返水', record_count: '共 {n} 笔', period: '统计周期', effective_stake: '有效投注', bet_count: '{n} 笔注单', empty: '暂无返水记录', empty_hint: '返水由后台按周期统计并发放,到账后可在此查看。', ledger_hint: '每笔返水确认后,账单中会有对应的「返水入账」流水,金额一致。', }, bet: { bet_slip: '投注单', stake: '投注金额', place_bet: '确认下注', place_bet_short: '下注', parlay: '串关', tab_matches: '球赛', tab_outright: '优胜冠军', tab_parlay: '串关投注', tab_today: '今日', tab_early: '早盘', show_open_only: '仅显示待开赛', show_all_matches: '显示全部', today: '今日', loading: '加载中…', no_matches: '暂无赛事', outright_coming: '优胜冠军玩法即将上线', outright_enter_stake: '请输入投注金额', outright_balance: '结余', outright_stake_amount: '投注额度', outright_success: '下注成功', outright_done: '完毕', outright_bet_failed: '下注失败', outright_insufficient: '余额不足', stake_label: '投注金额', stake_placeholder: '输入金额', stake_max: '全部', placing: '提交中…', no_outright: '暂无冠军盘口', no_outright_hint: '请使用玩家账号登录;若仍无数据,请联系管理员在后台发布优胜冠军赛事', outright_events_summary: '共 {events} 个冠军赛事 · {teams} 支队伍', outright_teams_count: '{n} 支队伍', outright_load_failed: '冠军盘加载失败,请检查网络或稍后重试', outright_player_only: '请使用玩家账号登录后查看', outright_shown_count: '已显示 {shown} / {total} 队', outright_load_more: '加载更多', cancel: '取消', parlay_title: '串关投注', parlay_guide_title: '串关怎么投?', parlay_guide_help: '查看串关说明', parlay_desc: '选择 2–5 场赛前赛事组合串关(2 串 1 至 5 串 1)。赔率相乘,不含滚球、冠军盘与四分盘让球/大小。', parlay_guide_1: '在列表中点击各场赔率,选中项显示金边;再点同一项可取消', parlay_guide_2: '须选 2–5 项,且须为不同赛事;冠军盘与四分盘让球/大小不可选', parlay_guide_3: '选好后点底部「确认下单」打开投注单,填写金额并提交', parlay_max_legs: '串关最多 5 项', parlay_block_outright: '冠军盘不可串关', parlay_block_quarter: '四分盘让球/大小不可串关', parlay_block_not_allowed: '该玩法不可串关', parlay_filter_all: '全部', parlay_empty: '暂无可用串关赛事', parlay_same_match: '同一场比赛不能串关', parlay_same_match_singles: '已选 {n} 项,将分 {n} 笔单关下单', parlay_confirm_singles: '确认下单({n}笔单关)', parlay_confirm_parlay: '确认串关下单', parlay_need_more: '请至少选择 2 项进行串关', back: '返回', refresh: '刷新', download: '下载', reward_active: '奖励生效中!', market_closed: '暂未开盘', match_phase_closed_pending: '封盘待结算', match_phase_settled: '已结算', view_match: '查看赛况', expand_market: '展开玩法', collapse_market: '收起玩法', market_cs: '波胆', market_ht_cs: '上半场波胆', market_sh_cs: '下半场波胆', market_ft_handicap: '全场 让球', market_ft_ou: '全场 大小', market_ft_1x2: '全场 独赢盘', market_ft_oe: '全场 单/双', market_ht_handicap: '半场 让球', market_ht_ou: '半场 大小', market_ht_1x2: '半场 独赢盘', parlay_lbl_handicap: '让球', parlay_lbl_ou: '大小', parlay_lbl_1x2: '独赢盘', parlay_lbl_oe: '单/双', parlay_sel_home: '主', parlay_sel_away: '客', parlay_sel_draw: '和', parlay_sel_over: '大', parlay_sel_under: '小', parlay_sel_odd: '单', parlay_sel_even: '双', cs_other_home: '主胜其它比分', cs_other_draw: '和局其它比分', cs_other_away: '客胜其它比分', col_home: '主场', col_draw: '平', col_away: '客场', cs_stake_required: '请至少在一个比分输入投注金额', cs_confirm_title: '确认波胆下注', cs_confirm_count: '共 {n} 注', cs_confirm_total_stake: '总投注额', cs_place_success: '下注成功', cs_place_failed: '下注失败', kickoff_time: '开赛时间:', guide_title: '怎么下注?', guide_help_aria: '查看下注说明', guide_got_it: '知道了', guide_flow_normal: '让球 / 大小 / 独赢等', guide_normal_1: '点「展开玩法」打开赔率', guide_normal_2: '点一项赔率选中(金边),再点同一项可取消', guide_normal_3: '选中后在当前玩法底部点「确认下单」填金额并提交', guide_flow_cs: '波胆(猜比分)', guide_cs_1: '点「展开玩法」在表格里填各比分金额', guide_cs_2: '填好金额后点该玩法底部「确认下单」,核对后提交', guide_cs_3: '可一次填多个比分,会拆成多笔注单', guide_flow_parlay: '串关(2–5 场)', guide_parlay_1: '本页为单关/波胆。串关:底部导航点「投注」,在页面顶部切换到「串关投注」,选 2–5 场不同赛事后在投注单提交。', guide_rules_link: '完整规则见「我的」→ 投注规则。', mode_cs_tag: '本页直接下注', mode_slip_tag: '加入投注单', cs_confirm_btn: '确认下注', cs_confirm_cell: '确认下单', cs_panel_hint: '在下方表格填写金额,填好后点上方「确认下注」', slip_panel_hint: '点赔率加入投注单,选好后用页面底部入口打开投注单', slip_pick_hint: '点选项加入投注单;金边表示已选,再点一次可取消', picked_tag: '已选', pick_added: '已加入投注单', pick_removed: '已从投注单移除', slip_bar_ready: '已选一项', slip_bar_go: '投注单', cs_top_hint: '① 在比分格填金额 ② 点上方「确认下注」', slip_empty_hint: '点击赔率加入投注单', slip_remove: '移除', slip_singles_hint: '共 {n} 笔单关(串关请到「投注」页顶部「串关投注」)', slip_stake_per_bet: '每笔投注金额', slip_est_return: '预计总返还', slip_parlay_odds: '组合赔率 {odds}', place_success: '下注成功', place_failed: '下注失败', }, profile: { edit: '修改资料', language: '语言', avatar: '选择头像', avatar_change: '修改头像', avatar_confirm: '确定', section_contact: '联系方式', section_account: '账号信息', change_password: '修改密码', show_password: '查看', hide_password: '隐藏', password_unavailable: '••••••••', password_unavailable_hint: '密码不可查看,如需重置请联系客服', section_password: '修改密码(可选)', avatar_hint: '从内置球员中选择头像', avatar_search: '搜索球员、位置或国家', avatar_empty: '未找到匹配球员', phone: '手机号', email: '邮箱', phone_placeholder: '请输入手机号', email_placeholder: '请输入邮箱', save: '保存', password_optional_hint: '不修改密码可留空', old_password_placeholder: '留空则不修改', new_password_placeholder: '留空则不修改', confirm_password_placeholder: '留空则不修改', old_password: '当前密码', new_password: '新密码', confirm_password: '确认新密码', back: '返回', saved: '联系方式已保存', save_failed: '保存失败', password_changed: '密码已更新', password_failed: '密码修改失败', password_mismatch: '两次新密码不一致', password_incomplete: '修改密码需填写当前密码、新密码及确认密码', username_placeholder: '登录账号名', username_readonly_hint: '账号名称由后台管理,如需修改请联系客服', username_updated: '账号名称已更新', password_disabled: '当前账号不允许自行修改密码,请联系客服', rules_title: '投注规则', rules_p1: '本平台第一版仅支持足球赛前盘,不含滚球、Cash Out、改单及系统串关。', rules_p2: '串关为 2 串 1 至 5 串 1,每场最多选 1 项;冠军盘、四分盘让球/大小不可进入串关。', rules_p3: '赛果由平台根据官方录入的半场/全场比分结算,结算预览经确认后入账。', rules_p4: '若本说明与后台公告冲突,以最新公告及实际盘口规则为准。', rules_p5: '操作步骤:进入任意赛事详情,点右上角「?」查看玩法说明。', }, }, 'en-US': { common: { pull_refresh: 'Pull to refresh', release_refresh: 'Release to refresh', refreshing: 'Refreshing…', loading_more: 'Loading more…', no_more: 'No more', load_failed: 'Failed to load', retry: 'Retry', }, nav: { home: 'Home', bet: 'Bet', bet_history: 'History', wallet: 'Wallet', profile: 'Profile' }, home: { hot_matches: 'Hot matches', no_matches: 'No matches', announcement_badge: 'Notice', announcement_default: 'Welcome to TheBet365 · Football events are live · Bet responsibly', banner_prev: 'Previous slide', banner_next: 'Next slide', banner_slide: 'Slide {n}', banner_fallback: 'Banner', }, history: { league_default: 'Football', stake: 'Stake', return: 'Return', est_return: 'Est. Return', odds: 'Odds', ft: 'FT', ht: 'HT', parlay_title: 'Parlay · {n} legs', parlay_league: 'Parlay', empty: 'No bets yet', no_more: 'No more bets', status_won: 'WON', status_pending: 'PENDING', status_lost: 'LOST', status_push: 'PUSH', back: 'Back', not_found: 'Bet not found', my_pick: 'My pick', my_bets: 'My bets', legs: 'Parlay legs', summary: 'Summary', bet_no: 'Bet ID', awaiting_result: 'Awaiting result…', filter_all: 'All', filter_won: 'Won', filter_lost: 'Lost', filter_pending: 'Pending', filter_push: 'Push', stats_total: 'Total', stats_won: 'Won', stats_lost: 'Lost', stats_pending: 'Pending', stats_push: 'Push', stats_stake: 'Total Stake', stats_return: 'Total Return', cashbacked: 'Cashbacked', }, auth: { login: 'Login', register: 'Create Account', logout: 'Log out', username: 'Username', password: 'Password', invite_code: 'Invitation Code', optional: 'Optional', captcha_placeholder: 'Code', captcha_refresh: 'Click to refresh', captcha_wrong: 'Incorrect captcha code', slide_to_verify: 'Slide to verify', click_to_verify: 'Click to verify', verified: 'Verified', login_required: 'Login Required', login_hint: 'Log in to place bets and access more features', go_login: 'Go to login', go_register: 'No account? Register now', have_account: 'Already have an account? Log in', register_btn: 'Register', register_failed: 'Registration failed, please try again', continue_browsing: 'Skip login', username_placeholder: 'Enter username', login_account: 'Phone / Username', login_account_placeholder: 'Local number or username', login_username_placeholder: 'Registered phone (with country code) or username', confirm_password: 'Confirm password', password_mismatch: 'Passwords do not match', password_placeholder: 'Enter password', login_btn: 'Log In', login_failed: 'Login failed, please try again', phone: 'Phone', phone_placeholder: 'Enter phone number', phone_local_placeholder: 'Enter phone number', phone_required: 'Phone number is required', phone_invalid: 'Invalid phone number format', phone_country_unsupported: 'This country or region is not supported', sms_code: 'SMS Code', sms_code_placeholder: '6-digit code', sms_code_required: 'Please enter the SMS code', sms_required: 'Please request an SMS code first', send_sms: 'Get Code', resend_sms: 'Retry in {sec}s', country_search: 'Search country or code', country_not_found: 'No matching country', }, support: { short: 'Support', title: 'Customer Support', open: 'Open customer support', close: 'Close', url_pending: 'Support URL is not configured yet.', }, wallet: { balance: 'Balance', cash_balance: 'Cash Balance', card_holder: 'Cardholder', unsettled: 'Unsettled', available: 'Available', no_records: 'No records', tx_deposit: 'Deposit', tx_admin_deposit: 'Admin top-up', tx_agent_deposit: 'Agent top-up', tx_player_deposit: 'Self deposit', tx_withdraw: 'Withdrawal', tx_admin_withdraw: 'Admin withdraw', tx_agent_withdraw: 'Agent withdraw', tx_adjust: 'Manual Adjust', tx_bet_freeze: 'Bet Frozen', tx_bet_deduct: 'Bet Deducted', tx_bet_win: 'Bet Payout', tx_bet_lose: 'Bet Settled', tx_bet_push: 'Bet Push', tx_bet_refund: 'Bet Refund', tx_bet_void: 'Bet Voided', tx_cashback: 'Cashback credit', tx_resettle: 'Resettlement', summary_bet: 'Bet {betNo}', summary_opening_bonus: 'Opening bonus', stats_income: 'Income', stats_expense: 'Expense', stats_net: 'Net', stats_cashback: 'Cashback', filter_all: 'All', filter_deposit: 'Deposit', filter_withdraw: 'Withdraw', filter_bet: 'Bet', filter_cashback: 'Cashback', view_all: 'View all transactions', detail_summary: 'Details', detail_amount: 'Amount', detail_balance_before: 'Balance Before', detail_balance_after: 'Balance After', detail_frozen_before: 'Frozen Before', detail_frozen_after: 'Frozen After', detail_reference: 'Reference', detail_reference_type: 'Type', detail_reference_id: 'Reference ID', detail_remark: 'Remark', detail_bet_link: 'View Bet', detail_tx_id: 'Transaction ID', detail_not_found: 'Transaction not found', ref_bet: 'Bet', ref_deposit: 'Deposit', ref_withdraw: 'Withdraw', view_cashbacks: 'Cashback details', view_cashbacks_detail: 'View cashback details (period/rate)', cashback_filter_hint: 'This list shows wallet credits; see cashback details for period and rate.', ref_cashback: 'Cashback batch', detail_cashback_link: 'View cashback details', }, recharge: { title: 'Recharge', history: 'History', history_title: 'Recharge History', bank_transfer: 'Bank Transfer', bank_name: 'Bank Name', account_holder: 'Account Holder', account_number: 'Account Number', usdt_address: 'USDT Address', amount_label: 'Amount', amount_placeholder: 'Enter recharge amount', screenshot_label: 'Upload Screenshot', upload_hint: 'Click to upload screenshot (max 5MB)', compressing: 'Compressing', submit: 'Submit', submitting: 'Submitting', submitted: 'Recharge Submitted', pending_review: 'Admin is reviewing, please wait', new_recharge: 'New Recharge', no_methods: 'No payment methods available', select_method: 'Please select a payment method', enter_amount: 'Please enter the amount', upload_screenshot: 'Please upload a screenshot', submit_failed: 'Submit failed, please retry', file_must_be_image: 'Please upload an image file', file_too_large: 'File exceeds 10MB', status_pending: 'Processing', status_approved: 'Approved', status_rejected: 'Rejected', no_orders: 'No recharge records', credited: 'Credited', reject_reason: 'Rejection reason', apply_time: 'Apply time', review_time: 'Review time', remark: 'Remark', }, cashback: { title: 'Cashback Details', list_title: 'Payout details', total_received: 'Total cashback', record_count: '{n} record(s)', period: 'Period', effective_stake: 'Effective stake', bet_count: '{n} bet(s)', empty: 'No cashback records yet', empty_hint: 'Cashback is issued by the platform after each settlement period.', ledger_hint: 'Matches wallet entries under the Cashback filter; amounts are the same.', }, bet: { bet_slip: 'Bet Slip', stake: 'Stake', place_bet: 'Place Bet', place_bet_short: 'Bet', parlay: 'Parlay', tab_matches: 'Matches', tab_outright: 'Outright', tab_parlay: 'Parlay', tab_today: 'Today', tab_early: 'Early', show_open_only: 'Open only', show_all_matches: 'Show all', today: 'Today', loading: 'Loading…', no_matches: 'No matches', outright_coming: 'Outright markets coming soon', outright_enter_stake: 'Enter stake', outright_balance: 'Balance', outright_stake_amount: 'Stake', outright_success: 'Bet placed', outright_done: 'Done', outright_bet_failed: 'Bet failed', outright_insufficient: 'Insufficient balance', stake_label: 'Stake', stake_placeholder: 'Enter amount', stake_max: 'Max', placing: 'Placing…', no_outright: 'No outright markets', no_outright_hint: 'Sign in as a player. If empty, ask admin to publish outright events.', outright_events_summary: '{events} outright events · {teams} teams', outright_teams_count: '{n} teams', outright_load_failed: 'Failed to load outright markets', outright_player_only: 'Player login required', outright_shown_count: '{shown} / {total} teams shown', outright_load_more: 'Load more', cancel: 'Cancel', parlay_title: 'Parlay', parlay_guide_title: 'How to parlay', parlay_guide_help: 'Parlay help', parlay_desc: 'Combine 2–5 pre-match legs (2-fold to 5-fold). No live, outright, or quarter-ball HDP/O-U in parlay.', parlay_guide_1: 'Tap odds in the list; selected cells show a gold border. Tap again to remove', parlay_guide_2: 'Pick 2–5 legs from different matches. No outright or quarter-ball HDP/O-U', parlay_guide_3: 'Tap Confirm order at the bottom, enter stake in the bet slip, and submit', parlay_max_legs: 'Parlay allows up to 5 legs', parlay_block_outright: 'Outright cannot be parlayed', parlay_block_quarter: 'Quarter-ball HDP/O-U cannot be parlayed', parlay_block_not_allowed: 'This market cannot be parlayed', parlay_filter_all: 'All', parlay_empty: 'No matches available for parlay betting', parlay_same_match: 'Cannot parlay selections from the same match', parlay_same_match_singles: '{n} selection(s) → {n} separate single bet(s)', parlay_confirm_singles: 'Place {n} single bet(s)', parlay_confirm_parlay: 'Place parlay', parlay_need_more: 'Select at least 2 legs for parlay', back: 'Back', refresh: 'Refresh', download: 'Download', reward_active: 'Reward active!', market_closed: 'Not open', match_phase_closed_pending: 'Closed pending', match_phase_settled: 'Settled', view_match: 'View match', expand_market: 'Expand', collapse_market: 'Collapse', market_cs: 'Correct Score', market_ht_cs: '1H Correct Score', market_sh_cs: '2H Correct Score', market_ft_handicap: 'FT Handicap', market_ft_ou: 'FT O/U', market_ft_1x2: 'FT 1X2', market_ft_oe: 'FT Odd/Even', market_ht_handicap: 'HT Handicap', market_ht_ou: 'HT O/U', market_ht_1x2: 'HT 1X2', parlay_lbl_handicap: 'Handicap', parlay_lbl_ou: 'O/U', parlay_lbl_1x2: '1X2', parlay_lbl_oe: 'Odd/Even', parlay_sel_home: 'H', parlay_sel_away: 'A', parlay_sel_draw: 'D', parlay_sel_over: 'O', parlay_sel_under: 'U', parlay_sel_odd: 'Odd', parlay_sel_even: 'Even', cs_other_home: 'Home win (other score)', cs_other_draw: 'Draw (other score)', cs_other_away: 'Away win (other score)', col_home: 'Home', col_draw: 'Draw', col_away: 'Away', cs_stake_required: 'Enter stake on at least one score', cs_confirm_title: 'Confirm correct score bets', cs_confirm_count: '{n} bet(s)', cs_confirm_total_stake: 'Total stake', cs_place_success: 'Bet placed', cs_place_failed: 'Bet failed', kickoff_time: 'Kickoff: ', guide_title: 'How to bet', guide_help_aria: 'Betting help', guide_got_it: 'Got it', guide_flow_normal: 'Handicap / O-U / 1X2 etc.', guide_normal_1: 'Tap Expand to show odds', guide_normal_2: 'Tap one odds to select (gold border); tap again to cancel', guide_normal_3: 'Tap Place order under that market, enter stake and confirm', guide_flow_cs: 'Correct score', guide_cs_1: 'Expand and enter stake on each score', guide_cs_2: 'Enter stakes, then tap Place order at the bottom of that market', guide_cs_3: 'Multiple scores = multiple bets', guide_flow_parlay: 'Parlay (2–5 legs)', guide_parlay_1: 'This page is for singles and correct score. Parlay: tap Bet in the bottom nav, then the Parlay tab at the top of that page, pick 2–5 different matches, and submit from the bet slip.', guide_rules_link: 'Full rules: Profile → Betting Rules.', mode_cs_tag: 'Bet here', mode_slip_tag: 'Add to slip', cs_confirm_btn: 'Confirm bet', cs_confirm_cell: 'Place order', cs_panel_hint: 'Enter stakes below, then tap Confirm bet above', slip_panel_hint: 'Tap odds to add; use the bottom bar when done', slip_pick_hint: 'Tap to add/remove from slip; gold border = selected', picked_tag: 'Selected', pick_added: 'Added to bet slip', pick_removed: 'Removed from bet slip', slip_bar_ready: '1 selection', slip_bar_go: 'Bet slip', cs_top_hint: '① Enter stake ② Tap Confirm bet above', slip_empty_hint: 'Tap odds to add to bet slip', slip_remove: 'Remove', slip_singles_hint: '{n} single bet(s). Parlay: Bet page → top Parlay tab.', slip_stake_per_bet: 'Stake per bet', slip_est_return: 'Est. total return', slip_parlay_odds: 'Combined odds {odds}', place_success: 'Bet placed', place_failed: 'Bet failed', }, profile: { edit: 'Edit Profile', language: 'Language', avatar: 'Avatar', avatar_change: 'Change avatar', avatar_confirm: 'Confirm', section_contact: 'Contact', section_account: 'Account', change_password: 'Change password', show_password: 'Show', hide_password: 'Hide', password_unavailable: '••••••••', password_unavailable_hint: 'Password not available; contact support to reset', section_password: 'Change password (optional)', avatar_hint: 'Choose from built-in player portraits', avatar_search: 'Search player, position or country', avatar_empty: 'No players found', phone: 'Phone', email: 'Email', phone_placeholder: 'Phone number', email_placeholder: 'Email address', save: 'Save', password_optional_hint: 'Leave password fields blank to keep current password', old_password_placeholder: 'Leave blank to skip', new_password_placeholder: 'Leave blank to skip', confirm_password_placeholder: 'Leave blank to skip', old_password: 'Current password', new_password: 'New password', confirm_password: 'Confirm password', back: 'Back', saved: 'Contact saved', save_failed: 'Save failed', password_changed: 'Password updated', password_failed: 'Password change failed', password_mismatch: 'Passwords do not match', password_incomplete: 'Fill current, new and confirm password to change password', username_placeholder: 'Login username', username_readonly_hint: 'Username is managed by admin; contact support to change', username_updated: 'Username updated', password_disabled: 'Password change is disabled for this account; contact support', rules_title: 'Betting Rules', rules_p1: 'Football pre-match only in v1. No live betting, Cash Out, bet edits, or system parlays.', rules_p2: 'Parlays: 2–5 legs from different matches (one per match). Outright and quarter-ball HDP/O-U are excluded.', rules_p3: 'Results use admin-entered half-time and full-time scores; payouts apply after settlement preview is confirmed.', rules_p4: 'If this text conflicts with site notices, the latest notice and market rules prevail.', rules_p5: 'How to bet: open any match, tap the ? icon on the top right.', }, }, 'ms-MY': { common: { pull_refresh: 'Tarik untuk segar', release_refresh: 'Lepas untuk segar', refreshing: 'Menyegarkan…', loading_more: 'Memuat lagi…', no_more: 'Tiada lagi', load_failed: 'Gagal dimuat', retry: 'Cuba lagi', }, nav: { home: 'Laman Utama', bet: 'Pertaruhan', bet_history: 'Sejarah', wallet: 'Bil', profile: 'Profil', }, home: { hot_matches: 'Perlawanan popular', no_matches: 'Tiada perlawanan', announcement_badge: 'Notis', announcement_default: 'Selamat datang ke TheBet365 · Perlawanan bola sepak sedang berlangsung · Bertaruh secara bertanggungjawab', banner_prev: 'Slaid sebelumnya', banner_next: 'Slaid seterusnya', banner_slide: 'Slaid {n}', banner_fallback: 'Banner', }, history: { league_default: 'Bola Sepak', stake: 'Jumlah', return: 'Pulangan', est_return: 'Anggaran pulangan', odds: 'Odds', ft: 'PT', ht: 'SP', parlay_title: 'Berganda · {n} perlawanan', parlay_league: 'Berganda', empty: 'Tiada rekod pertaruhan', no_more: 'Tiada lagi rekod', status_won: 'MENANG', status_pending: 'MENUNGGU', status_lost: 'KALAH', status_push: 'SERI', back: 'Kembali', not_found: 'Pertaruhan tidak dijumpai', my_pick: 'Pilihan saya', my_bets: 'Pertaruhan saya', legs: 'Butiran berganda', summary: 'Ringkasan', bet_no: 'ID Pertaruhan', awaiting_result: 'Menunggu keputusan…', filter_all: 'Semua', filter_won: 'Menang', filter_lost: 'Kalah', filter_pending: 'Menunggu', filter_push: 'Seri', stats_total: 'Jumlah', stats_won: 'Menang', stats_lost: 'Kalah', stats_pending: 'Menunggu', stats_push: 'Seri', stats_stake: 'Jumlah Taruhan', stats_return: 'Jumlah Pulangan', cashbacked: 'Rebat dibayar', }, auth: { login: 'Log Masuk', register: 'Daftar Akaun', logout: 'Log Keluar', username: 'Nama Pengguna', password: 'Kata Laluan', invite_code: 'Kod Jemputan', optional: 'Pilihan', captcha_placeholder: 'Kod', captcha_refresh: 'Klik untuk muat semula', captcha_wrong: 'Kod captcha salah', slide_to_verify: 'Gelongsor untuk mengesahkan', click_to_verify: 'Klik untuk mengesahkan', verified: 'Disahkan', login_required: 'Sila Log Masuk', login_hint: 'Log masuk untuk bertaruh dan akses lebih banyak ciri', go_login: 'Pergi log masuk', go_register: 'Tiada akaun? Daftar sekarang', have_account: 'Sudah ada akaun? Log masuk', register_btn: 'Daftar', register_failed: 'Pendaftaran gagal, sila cuba lagi', continue_browsing: 'Langkau log masuk', username_placeholder: 'Masukkan nama pengguna', login_account: 'Telefon / Akaun', login_account_placeholder: 'Nombor tempatan atau akaun', login_username_placeholder: 'Telefon berdaftar (dengan kod negara) atau akaun', confirm_password: 'Sahkan kata laluan', password_mismatch: 'Kata laluan tidak sepadan', password_placeholder: 'Masukkan kata laluan', login_btn: 'Log Masuk', login_failed: 'Log masuk gagal, sila cuba lagi', phone: 'Telefon', phone_placeholder: 'Masukkan nombor telefon', phone_local_placeholder: 'Masukkan nombor telefon', phone_required: 'Nombor telefon diperlukan', phone_invalid: 'Format nombor telefon tidak sah', phone_country_unsupported: 'Negara atau wilayah ini tidak disokong', sms_code: 'Kod SMS', sms_code_placeholder: 'Kod 6 digit', sms_code_required: 'Sila masukkan kod SMS', sms_required: 'Sila minta kod SMS dahulu', send_sms: 'Dapatkan Kod', resend_sms: 'Cuba lagi dalam {sec}s', country_search: 'Cari negara atau kod', country_not_found: 'Tiada negara sepadan', }, support: { short: 'Sokongan', title: 'Khidmat Pelanggan', open: 'Buka khidmat pelanggan', close: 'Tutup', url_pending: 'Pautan khidmat pelanggan belum dikonfigurasi.', }, wallet: { balance: 'Baki', cash_balance: 'Baki Tunai', card_holder: 'Pemegang', unsettled: 'Belum Selesai', available: 'Tersedia', no_records: 'Tiada rekod', tx_deposit: 'Deposit', tx_admin_deposit: 'Tambah baki admin', tx_agent_deposit: 'Tambah baki ejen', tx_player_deposit: 'Deposit sendiri', tx_withdraw: 'Pengeluaran', tx_admin_withdraw: 'Pengeluaran admin', tx_agent_withdraw: 'Pengeluaran ejen', tx_adjust: 'Pelarasan Manual', tx_bet_freeze: 'Pertaruhan Ditahan', tx_bet_deduct: 'Pertaruhan Ditolak', tx_bet_win: 'Bayaran Pertaruhan', tx_bet_lose: 'Pertaruhan Selesai', tx_bet_push: 'Pertaruhan Seri', tx_bet_refund: 'Bayaran Balik', tx_bet_void: 'Pertaruhan Dibatalkan', tx_cashback: 'Kredit rebat', tx_resettle: 'Penyelesaian Semula', summary_bet: 'Pertaruhan {betNo}', summary_opening_bonus: 'Bonus pembukaan', stats_income: 'Pendapatan', stats_expense: 'Perbelanjaan', stats_net: 'Bersih', stats_cashback: 'Rebat', filter_all: 'Semua', filter_deposit: 'Deposit', filter_withdraw: 'Pengeluaran', filter_bet: 'Pertaruhan', filter_cashback: 'Rebat', view_all: 'Lihat semua transaksi', detail_summary: 'Butiran', detail_amount: 'Jumlah', detail_balance_before: 'Baki Sebelum', detail_balance_after: 'Baki Selepas', detail_frozen_before: 'Beku Sebelum', detail_frozen_after: 'Beku Selepas', detail_reference: 'Rujukan', detail_reference_type: 'Jenis', detail_reference_id: 'ID Rujukan', detail_remark: 'Catatan', detail_bet_link: 'Lihat Pertaruhan', detail_tx_id: 'ID Transaksi', detail_not_found: 'Rekod tidak dijumpai', ref_bet: 'Pertaruhan', ref_deposit: 'Deposit', ref_withdraw: 'Pengeluaran', view_cashbacks: 'Butiran rebat', view_cashbacks_detail: 'Lihat butiran rebat (tempoh/kadar)', cashback_filter_hint: 'Senarai ini ialah kredit dompet; tempoh dan kadar ada di butiran rebat.', ref_cashback: 'Batch rebat', detail_cashback_link: 'Lihat butiran rebat', }, recharge: { title: 'Topup', history: 'Sejarah', history_title: 'Sejarah Topup', bank_transfer: 'Pindahan Bank', bank_name: 'Nama Bank', account_holder: 'Pemegang Akaun', account_number: 'Nombor Akaun', usdt_address: 'Alamat USDT', amount_label: 'Jumlah', amount_placeholder: 'Masukkan jumlah topup', screenshot_label: 'Muat Naik Screenshot', upload_hint: 'Klik untuk muat naik (maks 5MB)', compressing: 'Memampat', submit: 'Hantar', submitting: 'Menghantar', submitted: 'Topup Dihantar', pending_review: 'Admin sedang menyemak, sila tunggu', new_recharge: 'Topup Baru', no_methods: 'Tiada kaedah pembayaran tersedia', select_method: 'Sila pilih kaedah pembayaran', enter_amount: 'Sila masukkan jumlah', upload_screenshot: 'Sila muat naik screenshot', submit_failed: 'Gagal, sila cuba lagi', file_must_be_image: 'Sila muat naik fail imej', file_too_large: 'Fail melebihi 10MB', status_pending: 'Memproses', status_approved: 'Diluluskan', status_rejected: 'Ditolak', no_orders: 'Tiada rekod topup', credited: 'Dikreditkan', reject_reason: 'Sebab penolakan', apply_time: 'Masa permohonan', review_time: 'Masa semakan', remark: 'Catatan', }, cashback: { title: 'Butiran Rebat', list_title: 'Butiran pembayaran', total_received: 'Jumlah rebat', record_count: '{n} rekod', period: 'Tempoh', effective_stake: 'Pertaruhan sah', bet_count: '{n} pertaruhan', empty: 'Tiada rekod rebat', empty_hint: 'Rebat dikeluarkan oleh platform mengikut kitaran penyelesaian.', ledger_hint: 'Sepadan dengan entri dompet di penapis Rebat; jumlah adalah sama.', }, bet: { bet_slip: 'Slip Pertaruhan', stake: 'Jumlah', place_bet: 'Letak Pertaruhan', place_bet_short: 'Pertaruhan', parlay: 'Berganda', tab_matches: 'Perlawanan', tab_outright: 'Juara', tab_parlay: 'Berganda', tab_today: 'Hari Ini', tab_early: 'Awal', show_open_only: 'Buka sahaja', show_all_matches: 'Tunjuk semua', today: 'Hari Ini', loading: 'Memuatkan…', no_matches: 'Tiada perlawanan', outright_coming: 'Pasaran juara akan datang', outright_enter_stake: 'Masukkan jumlah', outright_balance: 'Baki', outright_stake_amount: 'Jumlah pertaruhan', outright_success: 'Pertaruhan berjaya', outright_done: 'Selesai', outright_bet_failed: 'Pertaruhan gagal', outright_insufficient: 'Baki tidak mencukupi', stake_label: 'Jumlah', stake_placeholder: 'Masukkan jumlah', stake_max: 'Maks', placing: 'Memproses…', no_outright: 'Tiada pasaran juara', no_outright_hint: 'Log masuk sebagai pemain. Jika kosong, minta admin terbitkan acara juara.', outright_events_summary: '{events} acara juara · {teams} pasukan', outright_teams_count: '{n} pasukan', outright_load_failed: 'Gagal memuatkan pasaran juara', outright_player_only: 'Log masuk pemain diperlukan', outright_shown_count: '{shown} / {total} pasukan dipaparkan', outright_load_more: 'Muat lagi', cancel: 'Batal', parlay_title: 'Pertaruhan Berganda', parlay_guide_title: 'Cara parlay', parlay_guide_help: 'Bantuan parlay', parlay_desc: 'Gabung 2–5 perlawanan pra-perlawanan (2 hingga 5 liputan). Tiada live, outright atau suku bola HDP/O-U.', parlay_guide_1: 'Ketik odds dalam senarai; pilihan dipilih ada sempadan emas. Ketik lagi untuk batal', parlay_guide_2: 'Pilih 2–5 pilihan dari perlawanan berbeza. Tiada outright atau suku bola HDP/O-U', parlay_guide_3: 'Ketik Sahkan pesanan di bawah, isi pegangan dalam slip, dan hantar', parlay_max_legs: 'Maksimum 5 pilihan parlay', parlay_block_outright: 'Outright tidak boleh parlay', parlay_block_quarter: 'HDP/O-U suku bola tidak boleh parlay', parlay_block_not_allowed: 'Pasaran ini tidak boleh parlay', parlay_filter_all: 'Semua', parlay_empty: 'Tiada perlawanan untuk pertaruhan berganda', parlay_same_match: 'Perlawanan sama tidak boleh berganda', parlay_same_match_singles: '{n} pilihan → {n} pertaruhan tunggal berasingan', parlay_confirm_singles: 'Sahkan {n} pertaruhan tunggal', parlay_confirm_parlay: 'Sahkan parlay', parlay_need_more: 'Pilih sekurang-kurangnya 2 pilihan', back: 'Kembali', refresh: 'Muat semula', download: 'Muat turun', reward_active: 'Ganjaran aktif!', market_closed: 'Belum dibuka', match_phase_closed_pending: 'Ditutup menunggu', match_phase_settled: 'Selesai', view_match: 'Lihat perlawanan', expand_market: 'Kembang', collapse_market: 'Tutup', market_cs: 'Skor Tepat', market_ht_cs: 'Skor Tepat PB1', market_sh_cs: 'Skor Tepat PB2', market_ft_handicap: 'Handicap Penuh', market_ft_ou: 'Atas/Bawah Penuh', market_ft_1x2: '1X2 Penuh', market_ft_oe: 'Ganjil/Genap Penuh', market_ht_handicap: 'Handicap Separuh', market_ht_ou: 'Atas/Bawah Separuh', market_ht_1x2: '1X2 Separuh', parlay_lbl_handicap: 'Handicap', parlay_lbl_ou: 'Atas/Bawah', parlay_lbl_1x2: '1X2', parlay_lbl_oe: 'Ganjil/Genap', parlay_sel_home: 'R', parlay_sel_away: 'P', parlay_sel_draw: 'S', parlay_sel_over: 'Atas', parlay_sel_under: 'Bwh', parlay_sel_odd: 'G', parlay_sel_even: 'Gn', cs_other_home: 'Menang rumah (skor lain)', cs_other_draw: 'Seri (skor lain)', cs_other_away: 'Menang pelawat (skor lain)', col_home: 'Home', col_draw: 'Seri', col_away: 'Away', cs_stake_required: 'Masukkan jumlah pada sekurang-kurangnya satu skor', cs_confirm_title: 'Sahkan pertaruhan skor tepat', cs_confirm_count: '{n} pertaruhan', cs_confirm_total_stake: 'Jumlah pertaruhan', cs_place_success: 'Pertaruhan berjaya', cs_place_failed: 'Pertaruhan gagal', kickoff_time: 'Masa mula: ', guide_title: 'Cara pertaruhan', guide_help_aria: 'Bantuan pertaruhan', guide_got_it: 'Faham', guide_flow_normal: 'Handicap / O-U / 1X2', guide_normal_1: 'Ketik Kembang untuk lihat odds', guide_normal_2: 'Pilih satu odds (sisi emas); ketik lagi untuk batal', guide_normal_3: 'Ketik Sahkan pesanan di bawah pasaran, isi jumlah dan sahkan', guide_flow_cs: 'Skor tepat', guide_cs_1: 'Kembang dan isi jumlah setiap skor', guide_cs_2: 'Isi jumlah, kemudian Sahkan pesanan di bawah pasaran itu', guide_cs_3: 'Beberapa skor = beberapa pertaruhan', guide_flow_parlay: 'Parlay (2–5 perlawanan)', guide_parlay_1: 'Halaman ini untuk tunggal dan skor tepat. Parlay: ketik Pertaruhan di nav bawah, kemudian tab Parlay di bahagian atas halaman, pilih 2–5 perlawanan berbeza, hantar dari slip.', guide_rules_link: 'Peraturan penuh: Profil → Peraturan Pertaruhan.', mode_cs_tag: 'Pertaruhan di sini', mode_slip_tag: 'Tambah ke slip', cs_confirm_btn: 'Sahkan pertaruhan', cs_confirm_cell: 'Sahkan pesanan', cs_panel_hint: 'Isi jumlah di bawah, kemudian Sahkan di atas', slip_panel_hint: 'Ketik odds; guna bar bawah apabila siap', slip_pick_hint: 'Ketik untuk tambah/buang; sisi emas = dipilih', picked_tag: 'Dipilih', pick_added: 'Ditambah ke slip', pick_removed: 'Dikeluarkan dari slip', slip_bar_ready: '1 pilihan', slip_bar_go: 'Buka slip', cs_top_hint: '① Isi jumlah ② Ketik Sahkan di atas', slip_empty_hint: 'Ketik odds untuk tambah ke slip', slip_remove: 'Buang', slip_singles_hint: '{n} pertaruhan tunggal. Parlay: halaman Pertaruhan → tab Berganda di atas.', slip_stake_per_bet: 'Jumlah setiap pertaruhan', slip_est_return: 'Anggaran pulangan', slip_parlay_odds: 'Odds gabungan {odds}', place_success: 'Pertaruhan berjaya', place_failed: 'Pertaruhan gagal', }, profile: { edit: 'Edit Profil', language: 'Bahasa', avatar: 'Avatar', avatar_change: 'Tukar avatar', avatar_confirm: 'Sahkan', section_contact: 'Maklumat hubungan', section_account: 'Akaun', change_password: 'Tukar kata laluan', show_password: 'Lihat', hide_password: 'Sembunyi', password_unavailable: '••••••••', password_unavailable_hint: 'Kata laluan tidak tersedia; hubungi sokongan', section_password: 'Tukar kata laluan (pilihan)', avatar_hint: 'Pilih dari potret pemain terbina', avatar_search: 'Cari pemain, posisi atau negara', avatar_empty: 'Tiada pemain dijumpai', phone: 'Telefon', email: 'E-mel', phone_placeholder: 'Nombor telefon', email_placeholder: 'Alamat e-mel', save: 'Simpan', password_optional_hint: 'Biarkan kosong jika tidak mahu tukar kata laluan', old_password_placeholder: 'Biarkan kosong untuk langkau', new_password_placeholder: 'Biarkan kosong untuk langkau', confirm_password_placeholder: 'Biarkan kosong untuk langkau', old_password: 'Kata laluan semasa', new_password: 'Kata laluan baharu', confirm_password: 'Sahkan kata laluan', back: 'Kembali', saved: 'Hubungan disimpan', save_failed: 'Gagal simpan', password_changed: 'Kata laluan dikemas kini', password_failed: 'Gagal tukar kata laluan', password_mismatch: 'Kata laluan tidak sepadan', password_incomplete: 'Isi kata laluan semasa, baharu dan pengesahan untuk menukar', username_placeholder: 'Nama log masuk', username_readonly_hint: 'Nama akaun diurus admin; hubungi sokongan untuk ubah', username_updated: 'Nama akaun dikemas kini', password_disabled: 'Akaun ini tidak dibenarkan tukar kata laluan; hubungi sokongan', rules_title: 'Peraturan Pertaruhan', rules_p1: 'Versi pertama: hanya bola sepak pra-perlawanan. Tiada live, Cash Out, edit pertaruhan atau parlay sistem.', rules_p2: 'Parlay 2–5 pilihan, satu pilihan setiap perlawanan. Outright dan suku bola HDP/O-U tidak boleh parlay.', rules_p3: 'Keputusan berdasarkan skor separuh masa/penuh yang dimasukkan admin; bayaran selepas pratonton disahkan.', rules_p4: 'Jika bercanggah dengan notis laman, ikut notis terkini dan peraturan pasaran.', rules_p5: 'Langkah operasi: buka butiran perlawanan, ketik ikon ? di atas kanan.', }, }, }, }); createApp(App).use(createPinia()).use(router).use(i18n).mount('#app'); const loader = document.getElementById('app-loading'); if (loader) { loader.style.opacity = '0'; loader.style.transition = 'opacity 0.3s ease'; setTimeout(() => loader.remove(), 350); }