"use client"; import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react"; export type Locale = "fa" | "en"; type Dict = Record; const fa: Dict = { "app.title": "حکم", "app.subtitle": "بازی کارت اصیل ایرانی", "app.tagline": "تجربه‌ای لوکس از بازی حکم، با حریف‌های هوشمند", "home.play": "شروع بازی", "home.continue": "ادامه بازی", "home.vsAI": "بازی با کامپیوتر", "home.target": "امتیاز برد", "home.targetHint": "تعداد دست برای برنده شدن", "home.yourName": "نام شما", "home.start": "بزن بریم", "home.howTo": "آموزش بازی", "home.lang": "English", "seat.you": "شما", "team.us": "ما", "team.them": "حریف", "team.0": "تیم ما", "team.1": "تیم حریف", "hakem.title": "تعیین حاکم", "hakem.desc": "ورق می‌چینیم تا اولین آس بیاید", "hakem.is": "حاکم: {name}", "trump.title": "حکم را انتخاب کنید", "trump.desc": "شما حاکم هستید — خال حکم را تعیین کنید", "trump.waiting": "{name} در حال انتخاب حکم است…", "trump.label": "حکم", "turn.you": "نوبت شماست", "turn.other": "نوبت {name}", "trick.wins": "{name} دست را برد", "round.over": "پایان دست", "round.kot": "کُت! ", "round.won": "{team} برنده شد", "round.score": "امتیاز: {us} - {them}", "round.next": "دست بعد…", "match.over": "پایان بازی", "match.youWin": "شما بردید! 🏆", "match.youLose": "این بار باختید", "match.again": "بازی دوباره", "match.menu": "منوی اصلی", "score.title": "امتیاز", "score.tricks": "دست‌ها", "hud.menu": "منو", "hud.quit": "خروج", "menu.vsComputer": "بازی با کامپیوتر", "menu.vsComputerDesc": "تمرین با حریف‌های هوشمند", "menu.online": "بازی آنلاین", "menu.onlineDesc": "با دوستان یا بازیکن‌های واقعی", "menu.profile": "پروفایل", "menu.friends": "دوستان", "menu.leaderboard": "جدول امتیازات", "menu.shop": "فروشگاه", "menu.signIn": "ورود / ثبت‌نام", "menu.guest": "مهمان", "menu.signOut": "خروج از حساب", "common.back": "بازگشت", "common.coins": "سکه", "common.level": "سطح", "common.rating": "امتیاز", "common.save": "ذخیره", "common.cancel": "انصراف", "common.confirm": "تأیید", "common.soon": "به‌زودی", "common.copy": "کپی", "common.copied": "کپی شد", "common.free": "رایگان", "chat.title": "گفتگو", "chat.placeholder": "پیام بنویسید…", "chat.send": "ارسال", "chat.empty": "گفتگو را شروع کنید", "friends.message": "پیام", "profile.title": "پروفایل", "profile.stats": "آمار", "profile.games": "بازی‌ها", "profile.wins": "بردها", "profile.winrate": "درصد برد", "profile.kots": "کُت‌ها", "profile.streak": "بهترین نوار", "profile.achievements": "دستاوردها", "profile.editName": "ویرایش نام", "profile.chooseAvatar": "انتخاب آواتار", "friends.title": "دوستان", "friends.add": "افزودن", "friends.addPlaceholder": "نام کاربری یا شماره", "friends.requests": "درخواست‌ها", "friends.online": "آنلاین", "friends.offline": "آفلاین", "friends.inGame": "در حال بازی", "friends.invite": "دعوت", "friends.accept": "قبول", "friends.decline": "رد", "friends.remove": "حذف", "friends.empty": "هنوز دوستی ندارید", "lobby.title": "بازی آنلاین", "lobby.createRoom": "ساخت اتاق خصوصی", "lobby.createDesc": "هم‌تیمی و حریف‌ها را خودتان انتخاب کنید", "lobby.random": "بازی رتبه‌ای", "lobby.randomDesc": "حریف تصادفی و کسب امتیاز و سکه", "room.title": "اتاق بازی", "room.code": "کد اتاق", "room.partner": "هم‌تیمی", "room.opponents": "حریف‌ها", "room.choosePartner": "انتخاب هم‌تیمی", "room.invite": "دعوت دوست", "room.addBot": "ربات", "room.empty": "خالی", "room.waiting": "در انتظار…", "room.start": "شروع بازی", "room.stake": "سکه ورودی", "room.leave": "ترک اتاق", "room.pickFriend": "یک دوست را انتخاب کنید", "mm.title": "جستجوی بازیکن", "mm.searching": "در حال یافتن حریف…", "mm.found": "بازیکنان پیدا شدند!", "mm.ready": "آماده شروع", "mm.cancel": "لغو", "mm.start": "ورود به بازی", "lead.title": "جدول امتیازات", "lead.rank": "رتبه", "shop.title": "فروشگاه", "shop.buy": "خرید", "shop.owned": "موجود", "shop.avatars": "آواتارها", "shop.themes": "تم‌ها", "shop.notEnough": "سکه کافی نیست", "auth.title": "ورود به حکم", "auth.subtitle": "برای بازی آنلاین وارد شوید", "auth.phone": "موبایل", "auth.email": "ایمیل", "auth.phoneLabel": "شماره موبایل", "auth.phonePlaceholder": "۰۹۱۲۳۴۵۶۷۸۹", "auth.sendCode": "ارسال کد", "auth.codeLabel": "کد تأیید", "auth.codePlaceholder": "کد ۴ رقمی", "auth.verify": "تأیید و ورود", "auth.devCode": "کد آزمایشی: {code}", "auth.emailLabel": "ایمیل", "auth.passLabel": "رمز عبور", "auth.nameLabel": "نام نمایشی", "auth.signIn": "ورود", "auth.signUp": "ثبت‌نام", "auth.google": "ورود با گوگل", "auth.toggleSignup": "حساب ندارید؟ ثبت‌نام کنید", "auth.toggleSignin": "حساب دارید؟ وارد شوید", "auth.invalidCode": "کد نادرست است", "reward.title": "پاداش بازی", "reward.rating": "امتیاز رتبه‌ای", "reward.coins": "سکه", "reward.xp": "تجربه", "reward.levelUp": "ارتقای سطح!", "reward.promoted": "ارتقای لیگ!", "reward.demoted": "سقوط لیگ", "reward.newAchievement": "دستاورد جدید", "reward.continue": "ادامه", "reward.win": "بردید! 🏆", "reward.lose": "باختید", "daily.title": "پاداش روزانه", "daily.day": "روز {n}", "daily.claim": "دریافت", "daily.claimed": "دریافت شد", "daily.come": "فردا برگردید", "rank.label": "لیگ", }; const en: Dict = { "app.title": "Hokm", "app.subtitle": "The classic Persian card game", "app.tagline": "A luxury Hokm experience with smart opponents", "home.play": "Play", "home.continue": "Continue", "home.vsAI": "Play vs Computer", "home.target": "Target score", "home.targetHint": "Rounds needed to win", "home.yourName": "Your name", "home.start": "Let's go", "home.howTo": "How to play", "home.lang": "فارسی", "seat.you": "You", "team.us": "Us", "team.them": "Them", "team.0": "Our team", "team.1": "Their team", "hakem.title": "Choosing the Hakem", "hakem.desc": "Dealing face-up until the first Ace", "hakem.is": "Hakem: {name}", "trump.title": "Choose the trump", "trump.desc": "You are the Hakem — pick the trump suit", "trump.waiting": "{name} is choosing trump…", "trump.label": "Trump", "turn.you": "Your turn", "turn.other": "{name}'s turn", "trick.wins": "{name} wins the trick", "round.over": "Round over", "round.kot": "Kot! ", "round.won": "{team} wins", "round.score": "Score: {us} - {them}", "round.next": "Next round…", "match.over": "Game over", "match.youWin": "You win! 🏆", "match.youLose": "You lost this time", "match.again": "Play again", "match.menu": "Main menu", "score.title": "Score", "score.tricks": "Tricks", "hud.menu": "Menu", "hud.quit": "Quit", "menu.vsComputer": "Play vs Computer", "menu.vsComputerDesc": "Practice against smart bots", "menu.online": "Play Online", "menu.onlineDesc": "With friends or real players", "menu.profile": "Profile", "menu.friends": "Friends", "menu.leaderboard": "Leaderboard", "menu.shop": "Shop", "menu.signIn": "Sign in / Sign up", "menu.guest": "Guest", "menu.signOut": "Sign out", "common.back": "Back", "common.coins": "Coins", "common.level": "Level", "common.rating": "Rating", "common.save": "Save", "common.cancel": "Cancel", "common.confirm": "Confirm", "common.soon": "Coming soon", "common.copy": "Copy", "common.copied": "Copied", "common.free": "Free", "chat.title": "Chat", "chat.placeholder": "Type a message…", "chat.send": "Send", "chat.empty": "Start the conversation", "friends.message": "Message", "profile.title": "Profile", "profile.stats": "Stats", "profile.games": "Games", "profile.wins": "Wins", "profile.winrate": "Win rate", "profile.kots": "Kots", "profile.streak": "Best streak", "profile.achievements": "Achievements", "profile.editName": "Edit name", "profile.chooseAvatar": "Choose avatar", "friends.title": "Friends", "friends.add": "Add", "friends.addPlaceholder": "Username or phone", "friends.requests": "Requests", "friends.online": "Online", "friends.offline": "Offline", "friends.inGame": "In game", "friends.invite": "Invite", "friends.accept": "Accept", "friends.decline": "Decline", "friends.remove": "Remove", "friends.empty": "No friends yet", "lobby.title": "Play Online", "lobby.createRoom": "Create private room", "lobby.createDesc": "Choose your partner and opponents", "lobby.random": "Ranked match", "lobby.randomDesc": "Random opponents, earn rating & coins", "room.title": "Game Room", "room.code": "Room code", "room.partner": "Partner", "room.opponents": "Opponents", "room.choosePartner": "Choose partner", "room.invite": "Invite friend", "room.addBot": "Bot", "room.empty": "Empty", "room.waiting": "Waiting…", "room.start": "Start game", "room.stake": "Entry coins", "room.leave": "Leave room", "room.pickFriend": "Pick a friend", "mm.title": "Finding players", "mm.searching": "Searching for opponents…", "mm.found": "Players found!", "mm.ready": "Ready to start", "mm.cancel": "Cancel", "mm.start": "Enter game", "lead.title": "Leaderboard", "lead.rank": "Rank", "shop.title": "Shop", "shop.buy": "Buy", "shop.owned": "Owned", "shop.avatars": "Avatars", "shop.themes": "Themes", "shop.notEnough": "Not enough coins", "auth.title": "Sign in to Hokm", "auth.subtitle": "Sign in to play online", "auth.phone": "Phone", "auth.email": "Email", "auth.phoneLabel": "Mobile number", "auth.phonePlaceholder": "0912 345 6789", "auth.sendCode": "Send code", "auth.codeLabel": "Verification code", "auth.codePlaceholder": "4-digit code", "auth.verify": "Verify & sign in", "auth.devCode": "Dev code: {code}", "auth.emailLabel": "Email", "auth.passLabel": "Password", "auth.nameLabel": "Display name", "auth.signIn": "Sign in", "auth.signUp": "Sign up", "auth.google": "Continue with Google", "auth.toggleSignup": "No account? Sign up", "auth.toggleSignin": "Have an account? Sign in", "auth.invalidCode": "Invalid code", "reward.title": "Match rewards", "reward.rating": "Rating", "reward.coins": "Coins", "reward.xp": "XP", "reward.levelUp": "Level up!", "reward.promoted": "Promoted!", "reward.demoted": "Demoted", "reward.newAchievement": "New achievement", "reward.continue": "Continue", "reward.win": "You won! 🏆", "reward.lose": "You lost", "daily.title": "Daily reward", "daily.day": "Day {n}", "daily.claim": "Claim", "daily.claimed": "Claimed", "daily.come": "Come back tomorrow", "rank.label": "League", }; const DICTS: Record = { fa, en }; interface I18nValue { locale: Locale; dir: "rtl" | "ltr"; t: (key: string, vars?: Record) => string; setLocale: (l: Locale) => void; toggle: () => void; } const I18nContext = createContext(null); export function I18nProvider({ children }: { children: React.ReactNode }) { const [locale, setLocaleState] = useState("fa"); useEffect(() => { const saved = localStorage.getItem("hokm.locale") as Locale | null; if (saved === "fa" || saved === "en") setLocaleState(saved); }, []); const setLocale = useCallback((l: Locale) => { setLocaleState(l); localStorage.setItem("hokm.locale", l); }, []); const dir: "rtl" | "ltr" = locale === "fa" ? "rtl" : "ltr"; useEffect(() => { document.documentElement.lang = locale; document.documentElement.dir = dir; }, [locale, dir]); const t = useCallback( (key: string, vars?: Record) => { let str = DICTS[locale][key] ?? DICTS.en[key] ?? key; if (vars) { for (const [k, v] of Object.entries(vars)) { str = str.replace(new RegExp(`\\{${k}\\}`, "g"), String(v)); } } return str; }, [locale] ); const value = useMemo( () => ({ locale, dir, t, setLocale, toggle: () => setLocale(locale === "fa" ? "en" : "fa"), }), [locale, dir, t, setLocale] ); return {children}; } export function useI18n(): I18nValue { const ctx = useContext(I18nContext); if (!ctx) throw new Error("useI18n must be used within I18nProvider"); return ctx; }