class_name I18n extends RefCounted const LOCALE_EN := "en" const SETTINGS_PATH := "user://farm_settings.cfg" const SETTINGS_SECTION := "i18n" const SETTINGS_LOCALE_KEY := "locale" const LANGUAGE_OPTIONS := [ {"code": LOCALE_EN, "label": "English"}, ] const EN := { "离开": "Leave", "关闭": "Close", "确定": "Confirm", "开启": "On", "系统设置": "Settings", "音乐:": "Music:", "音效:": "SFX:", "帐号:": "Account:", "装扮:": "Skin:", "语言:": "Language:", "切换帐号": "Switch Account", "装扮设置": "Skin Settings", "装扮切换失败": "Skin switch failed", "语言已切换": "Language updated", "操作失败": "Operation failed", "操作成功": "Done", "登录信息失效": "Login expired", "播种失败": "Planting failed", "播种成功": "Planted", "收获失败": "Harvest failed", "铲除失败": "Clear failed", "施肥失败": "Fertilize failed", "浇水失败": "Watering failed", "除虫失败": "Bug removal failed", "除草失败": "Weed removal failed", "农田上已经有农作物": "This land already has a crop", "当前等级不足": "Current level too low", "你没有这个物品": "You do not have this item", "物品数量不够": "Not enough items", "物品类型错误": "Wrong item type", "农田上没有种植种子": "This land has no crop", "尚未成熟": "Not mature yet", "你已经收割过该农作物": "This crop has already been harvested", "农田不需要清理": "This land does not need clearing", "农作物已经成熟": "Crop is already mature", "操作错误": "Invalid operation", "施肥已经到达上限": "Fertilizing is already maxed", "施肥时间错误": "Cannot fertilize now", "土地等级不够,无法种植该植物": "Land level too low for this crop", "物品": "Item", "作物": "Crop", "神秘种子": "Mystery Seed", "剩余果实:%s": "Fruit left: %s", "已经收获": "Harvested", "%s秒": "%ss", "0秒": "0s", "%s后%s": "%s until %s", "种子期": "Seed", "发芽期": "Sprout", "生长期": "Growing", "成熟期": "Mature", "枯萎": "Withered", "浇水成功": "Watered", "成就": "Achievements", "竞技": "Arena", "游乐园": "Playground", "升级": "Upgrade", "制作": "Craft", "获得 %s": "Received %s", "房屋升级": "House Upgrade", "房屋升级失败:%s": "House upgrade failed: %s", "房屋已满级": "House is max level", "房屋配置缺失": "House config missing", "升级房屋需要农场主等级达到:": "Required farmer level:", "收获土地的果实将增加产量百分比:": "Fruit yield bonus:", "升级房屋等级将增加农场主经验百分比:": "Farmer EXP bonus:", "满级": "Max", "房屋升级失败": "House upgrade failed", "房屋升级成功": "House upgraded", "农场主等级不足": "Farmer level too low", "角色等级不足": "Character level too low", "等级不足": "Level too low", "金币不足,无法扩建": "Not enough gold to expand", "金豆不足,无法扩建": "Not enough gold beans to expand", "升级材料不足": "Not enough upgrade materials", "材料不足": "Not enough materials", "配置缺失": "Config missing", "土地升级失败": "Land upgrade failed", "土地升级配置缺失": "Land upgrade config missing", "扩建配置缺失": "Expansion config missing", "扩建土地失败:%s": "Land expansion failed: %s", "扩建土地成功": "Land expanded", "扩建这块土地需要:": "This expansion requires:", "角色等级:": "Character Level:", "扩建": "Expand", "升级成功": "Upgrade complete", "普通土地": "Basic Land", "棕土地": "Brown Land", "银土地": "Silver Land", "紫土地": "Purple Land", "没有足够的%s": "Not enough %s", "升级%s需要农场主等级达到:": "Upgrade %s requires farmer level:", "收获%s的果实将增加农场主经验点:": "Harvesting %s adds farmer EXP:", "收获%s的果实将增加产量个数:": "Harvesting %s adds yield:", "%s点": "%s pts", "%s个": "%s pcs", "战宠": "Battle Pet", "战宠列表": "Pet List", "战宠商店": "Pet Shop", "请在神秘商城中购买战宠蛋并在仓库道具栏中使用,在战宠界面孵化并参战。": "Buy a pet egg in the mystery shop, use it from warehouse items, hatch it here, then send it to battle.", "喂养": "Feed", "宠物名:": "Pet Name:", "战斗力:": "Power:", "饱食度:": "Fullness:", "注1:饱食度为0,战宠将无法出战.": "Note 1: A pet with 0 fullness cannot battle.", "注2:宠物战力越高,战斗胜利的越高.": "Note 2: Higher pet power improves battle odds.", "注3:宠物战斗后需要消耗一部分口粮恢复饱食度.": "Note 3: Pets consume food to recover fullness after battle.", "暂无战宠,请到战宠商店购买。": "No battle pets. Buy one from the pet shop.", "暂无战宠商品": "No pet items", "剩余的狗粮时间:": "Food time left:", "单价": "Price", "放出": "Deploy", "已拥有": "Owned", "没有可用狗粮": "No usable pet food", "喂养失败:%s": "Feed failed: %s", "喂养失败": "Feed failed", "喂养成功": "Fed", "放出失败:%s": "Deploy failed: %s", "已放出战宠": "Battle pet deployed", "购买失败:等级不足": "Purchase failed: level too low", "购买失败:金币不足": "Purchase failed: not enough gold", "购买失败:金豆不足": "Purchase failed: not enough gold beans", "购买失败:钻石不足,请充值!": "Purchase failed: not enough gems. Top up first.", "购买失败:资源不足,请充值!": "Purchase failed: not enough resources. Top up first.", "购买失败:商店接口未初始化": "Purchase failed: shop API not ready", "购买失败:%s": "Purchase failed: %s", "购买成功": "Purchased", "狗狗没有上场": "No pet deployed", "没有狗粮了": "No pet food left", "初级狗粮": "Basic Pet Food", "中级狗粮": "Medium Pet Food", "高级狗粮": "Advanced Pet Food", "宠物蛋": "Pet Egg", "基本属性": "Stats", "战力升级": "Power Up", "宠物进化": "Evolution", "您没有宠物": "You have no pets", "功能开发中": "Coming soon", "饿了...": "Hungry...", "汪~": "Woof~", "宠物战力:": "Pet Power:", "攻击方式:": "Attack Type:", "宠物等级:": "Pet Level:", "战斗消耗:": "Battle Cost:", "经验值:": "EXP:", "血量:": "HP:", "攻击:": "ATK:", "暴击:": "Crit:", "闪避:": "Dodge:", "防御:": "DEF:", "无类型": "None", "近身攻击": "Melee", "远程攻击": "Ranged", "参战失败": "Deploy failed", "参战成功": "Deployed", "没有狗粮": "No pet food", "全国排名": "Global Rank", "好友排名": "Friend Rank", "排名": "Rank", "游戏昵称": "Name", "等级": "Level", "家园": "Home", "财富": "Wealth", "排行榜加载失败:%s": "Rank load failed: %s", "战力排行暂未开放": "Power ranking is not open yet", "好友搜索面板后续补齐": "Friend search is coming later", "好友申请面板后续补齐": "Friend requests are coming later", "查看家园:%s": "View home: %s", "互动:%s": "Interact: %s", "兑换金币": "Gold Exchange", "兑换金豆": "Gold Bean Exchange", "金币:%s": "Gold: %s", "金豆:%s": "Gold Beans: %s", "钻石:%s": "Gems: %s", "钻石兑金币": "Gems to Gold", "钻石兑金豆": "Gems to Gold Beans", "金币兑钻石": "Gold to Gems", "金豆兑钻石": "Gold Beans to Gems", "兑换": "Exchange", "兑换记录": "Exchange History", "正在读取兑换记录...": "Loading exchange history...", "兑换记录读取失败": "Failed to load exchange history", "兑换记录已加载": "Exchange history loaded", "暂无兑换记录": "No exchange history", "钻石兑换金币": "Gems to Gold", "钻石兑换金豆": "Gems to Gold Beans", "金币兑换钻石": "Gold to Gems", "金豆兑换钻石": "Gold Beans to Gems", "兑换比例 1 钻石 = %s 金币": "Rate: 1 gem = %s gold", "兑换比例 1 钻石 = %s 金豆": "Rate: 1 gem = %s gold beans", "兑换比例 %s 金币 = 1 钻石": "Rate: %s gold = 1 gem", "兑换比例 %s 金豆 = 1 钻石": "Rate: %s gold beans = 1 gem", "预计获得 %s 金币": "You will get %s gold", "预计获得 %s 金豆": "You will get %s gold beans", "预计获得 %s 钻石": "You will get %s gems", "钻石不足": "Not enough gems", "金币不足": "Not enough gold", "金豆不足": "Not enough gold beans", "兑换失败": "Exchange failed", "兑换成功": "Exchanged", "兑换获得金币": "Exchanged for gold", "兑换获得金豆": "Exchanged for gold beans", "兑换获得钻石": "Exchanged for gems", "本周已累计签到": "Signed in this week", "天": "days", "%s天": "%s days", "签到": "Sign In", "补签": "Make Up", "剩余补签卡%s张": "Make-up cards left: %s", "今日已签到": "Already signed in today", "签到读取失败": "Failed to load sign-in data", "签到失败": "Sign-in failed", "签到成功": "Signed in", "当前不能补签": "Cannot make up now", "补签卡不足": "Not enough make-up cards", "补签失败": "Make-up failed", "补签成功": "Make-up complete", "没有可领取的连续签到奖励": "No streak reward available", "领取连续签到奖励失败": "Failed to claim streak reward", "领取成功": "Claimed", "玩家信息缺失": "Player info missing", "读取等级礼包...": "Loading level gifts...", "LV.%s 等级礼包": "LV.%s Level Gift", "领取": "Claim", "已领取": "Claimed", "未达成": "Locked", "等级礼包读取失败": "Failed to load level gifts", "领取等级礼包失败": "Failed to claim level gift", "在线礼包 %s": "Online Gift %s", "礼包倒计时未结束": "Gift countdown is not over", "领取在线礼包失败": "Failed to claim online gift", "普通道具": "Items", "神秘商店": "Mystery Shop", "背景": "Background", "购买": "Buy", "果实": "Fruit", "种子": "Seeds", "道具": "Items", "该物品不能出售": "This item cannot be sold", "总计收入": "Total", "卖出": "Sell", "出售失败:%s": "Sell failed: %s", "出售成功,获得%s金币": "Sold for %s gold", "出售成功,获得%s金豆": "Sold for %s gold beans", "钻石充值": "Gem Top-up", "金币充值": "Gold Top-up", "金豆充值": "Gold Bean Top-up", "暂无充值配置": "No top-up config", "充值下单失败": "Top-up order failed", "充值下单成功": "Top-up order created", "正在打开支付": "Opening payment", "日志读取失败": "Failed to load logs", "读取日志中...": "Loading logs...", "玩家日志": "Player Log", "系统日志": "System Log", "暂无日志": "No logs", "清空": "Clear", "清空失败": "Clear failed", "我": "Me", "玩家": "Player", "种植": "Plant", "收获": "Harvest", "偷取了": "stole", "对植物进行了施肥": "fertilized a plant", "进行了锄地": "cleared land", "进行了土地升级": "upgraded land", "切换了农场风格": "changed farm skin", "喂了狗狗": "fed the pet", "使坏放虫": "released bugs", "使坏种草": "planted weeds", "对土地浇水": "watered land", "对植物除虫": "removed bugs", "对植物除草": "removed weeds", "扩建了1块土地": "expanded one land plot", "进行了房屋升级": "upgraded house", "被偷了": "was stolen from", "狗狗抓住": "pet caught", "被狗狗抓住": "was caught by a pet", "给你放虫": "released bugs on your land", "给你种草": "planted weeds on your land", "帮你浇水": "watered for you", "帮你放虫": "released bugs for you", "操作": "Action", "(本次免费)": "(Free this time)", "抽奖失败": "Draw failed", "抽中 %s": "Won %s", "公告读取失败": "Failed to load notices", "读取公告中...": "Loading notices...", "暂无公告": "No notices", "读取中...": "Loading...", "系统成就 %s 项": "%s achievements", "进度 %s/%s": "Progress %s/%s", "可领取": "Claimable", "进行中": "In Progress", "我的竞技": "My Arena", "排名 %s 战力 %s 积分 %s": "Rank %s Power %s Score %s", "胜 %s / 负 %s": "Win %s / Loss %s", "可挑战": "Challenge", "次数不足": "No attempts", "请先设置出战宠物": "Set a battle pet first", "战宠出战后才能进行竞技场挑战。": "You need a battle pet to challenge the arena.", "未开启": "Closed", "竞技场数据已加载": "Arena data loaded", "竞技场未开启": "Arena is closed", "排行榜": "Leaderboard", "暂无排名数据": "No rank data", "今日次数": "Today's Attempts", "今日已进入 %s 次 VIP免费次数 %s": "Entered %s times today VIP free times %s", "超过免费次数后,后端会按旧规则扣除金币。": "After free attempts, gold is charged by the old server rule.", "超过免费次数后,后端会按旧规则扣除金豆。": "After free attempts, gold beans are charged by the old server rule.", "游乐园已就绪": "Playground ready", "可进入": "Enter", "需金币": "Needs Gold", "需金豆": "Needs Gold Beans", "奖励档位 %s": "Reward Tier %s", "需要积分 %s": "Needs Score %s", "奖励池:%s": "Reward Pool: %s", "种植达人": "Planting Expert", "福利达人": "Benefits Expert", "游戏达人": "Game Expert", "挑战达人": "Challenge Expert", "掠夺达人": "Raid Expert", "资源达人": "Resource Expert", "驯兽师": "Pet Trainer", "驯兽王": "Pet Master", "驯兽皇": "Pet Emperor", "消费达人": "Spending Expert", "竞技冠军": "Arena Champion", "水果商": "Fruit Merchant", "水果大亨": "Fruit Tycoon", "建筑大师": "Building Master", "成就大师": "Achievement Master", "签到达人": "Sign-in Expert", "碎片收集者": "Shard Collector", "小偷克星": "Thief Catcher", "世界神偷": "World Thief", "天下第一": "World No.1", "充值达人": "Top-up Expert", "玩家完成日常种植任务次数": "Times completing daily planting tasks", "玩家领取在线礼包次数": "Times claiming online gifts", "玩家积累开启大转盘次数": "Total wheel spins", "玩家积累进入游乐场": "Playground entries", "玩家积累挑战玩家": "Player challenges", "玩家积累掠夺玩家资源次数": "Resource raids", "玩家积累水晶": "Crystals accumulated", "成功积累石材数量": "Stone accumulated", "成功孵化5只宠物": "Hatch 5 pets", "农场主宠物等级达到": "Farmer pet level reaches", "玩家建设农场消耗次数": "Farm construction spending count", "击败并战胜对手个数": "Opponents defeated", "种植收获多少水果个数": "Fruit harvested", "积累消耗水果个数": "Fruit consumed", "成功升级场景主建筑": "Main building upgrades", "收集成就徽章个数": "Achievement badges collected", "成功签到天数": "Sign-in days", "成功收集碎片个数": "Shards collected", "成功抓捕小偷次数": "Thieves caught", "成功偷取玩家果实次数": "Player fruit stolen", "成为全世界第一名": "Reach world rank 1", "在商城钻石消费积累": "Gems spent in shop", "充值钻石次数": "Gem top-up count", "金桔种子999": "Kumquat Seed 999", "柚子种子": "Pomelo Seed", "圣女果种子": "Cherry Tomato Seed", "龙眼种子": "Longan Seed", "番石榴种子": "Guava Seed", "芒果种子": "Mango Seed", "木瓜种子": "Papaya Seed", "香瓜种子": "Melon Seed", "椰子种子": "Coconut Seed", "仙人掌果种子": "Cactus Fruit Seed", "牛奶果种子": "Milk Fruit Seed", "人参果种子": "Ginseng Fruit Seed", "葡萄种子": "Grape Seed", "菠萝种子": "Pineapple Seed", "金桔": "Kumquat", "柚子": "Pomelo", "圣女果": "Cherry Tomato", "龙眼": "Longan", "番石榴": "Guava", "芒果": "Mango", "木瓜": "Papaya", "香瓜": "Melon", "椰子": "Coconut", "仙人掌果": "Cactus Fruit", "牛奶果": "Milk Fruit", "人参果": "Ginseng Fruit", "葡萄": "Grape", "菠萝": "Pineapple", "普通化肥": "Basic Fertilizer", "高效化肥": "Advanced Fertilizer", "特效化肥": "Special Fertilizer", "极效化肥": "Extreme Fertilizer", "低档宠物粮": "Low-grade Pet Food", "中档宠物粮": "Mid-grade Pet Food", "高档宠物粮": "High-grade Pet Food", "补签卡": "Make-up Card", "田园风光": "Pastoral Scenery", "海滩风光": "Beach Scenery", "城市风光": "City Scenery", "农场风光": "Farm Scenery", "钻石": "Gems", "金币": "Gold", "大狗": "Large Pet", "超级杀虫剂": "Super Pesticide", "超级除草剂": "Super Herbicide", "猪崽": "Piglet", "鸡崽": "Chick", "牛崽": "Calf", "猪肉": "Pork", "牛肉": "Beef", "鸡肉": "Chicken", "牛奶": "Milk", "便便": "Manure", "鸡蛋": "Egg", "普通饲料": "Basic Feed", "中级饲料": "Medium Feed", "高级饲料": "Advanced Feed", "石材": "Stone", "钢材": "Steel", "红宝石": "Ruby", "绿宝石": "Emerald", "蓝宝石": "Sapphire", "黄宝石": "Topaz", "金色宝石": "Golden Gem", "红水晶": "Red Crystal", "绿水晶": "Green Crystal", "蓝水晶": "Blue Crystal", "黄水晶": "Yellow Crystal", "金水晶": "Gold Crystal", "绿色宠物蛋": "Green Pet Egg", "蓝色宠物蛋": "Blue Pet Egg", "紫色宠物蛋": "Purple Pet Egg", "橙色宠物蛋": "Orange Pet Egg", "白色宠物蛋": "White Pet Egg", "母鸡": "Hen", "奶牛": "Cow", "母猪": "Sow", "松狮": "Chow Chow", "棕色松狮": "Brown Chow Chow", "烈火松狮": "Flame Chow Chow", "爆炎松狮": "Blazing Chow Chow", "狼崽": "Wolf Pup", "灰狼": "Gray Wolf", "魔狼": "Demon Wolf", "魔狼王": "Demon Wolf King", "小蛇": "Snakelet", "独眼蛇": "One-eyed Snake", "红炎巨蟒": "Red Flame Python", "双头蛇王": "Two-headed Snake King", "熊头": "Bear Cub", "红眼熊": "Red-eyed Bear", "利爪熊": "Clawed Bear", "熊王": "Bear King", "小火兽": "Little Fire Beast", "火龙兽": "Fire Dragon Beast", "喷火龙": "Fire Dragon", "火龙王": "Fire Dragon King", "周卡": "Weekly Card", "月卡": "Monthly Card" } const TERM_REPLACEMENTS := { "等级礼包": "Level Gift", "在线礼包": "Online Gift", "兑换记录": "Exchange History", "农场主": "Farmer", "战斗力": "Power", "饱食度": "Fullness", "经验值": "EXP", "角色等级": "Character Level", "玩家": "Player", "金币": "Gold", "金豆": "Gold Bean", "钻石": "Gems", "礼包": "Gift", "等级": "Level", "经验": "EXP", "果实": "Fruit", "种子": "Seed", "道具": "Item", "物品": "Item", "宠物": "Pet", "战宠": "Battle Pet", "房屋": "House", "土地": "Land", "扩建": "Expand", "升级": "Upgrade", "领取": "Claim", "已领取": "Claimed", "未达成": "Locked", "购买": "Buy", "卖出": "Sell", "出售": "Sell", "兑换": "Exchange", "失败": "failed", "成功": "complete", "不足": "not enough", "暂无": "No", "读取": "Load", "加载": "Load", "已": "", "中": "", "需要": "needs", "获得": "received", "预计": "estimated", "剩余": "left", "今日": "today", "本周": "this week", "累计": "total", "签到": "sign-in", "补签": "make-up", "记录": "history", "可": "can", "进入": "enter", "挑战": "challenge", "竞技场": "arena", "排行榜": "leaderboard", "游乐园": "playground", "成就": "achievement", "普通": "basic", "神秘": "mystery", "商店": "shop", "背景": "background", "仓库": "warehouse", "好友": "friend", "家园": "home", "排名": "rank", "财富": "wealth", "语言": "language", "音乐": "music", "音效": "SFX", "帐号": "account", "装扮": "skin", "关闭": "close", "开启": "on", "离开": "leave", "单价": "price", "总计收入": "total", "比例": "rate", "次数": "times", "天": "days", "小时": "h", "分": "m", "秒": "s", "点": "pts", "个": "pcs", "张": "", ":": ": ", ",": ", ", "。": ".", "、": ", ", "(": "(", ")": ")", } static var _locale := LOCALE_EN static var _loaded := false static func available_languages() -> Array: return LANGUAGE_OPTIONS.duplicate(true) static func current_locale() -> String: _ensure_loaded() return _locale static func set_locale(locale: String) -> void: _ensure_loaded() _locale = _normalize_locale(locale) var config := ConfigFile.new() config.set_value(SETTINGS_SECTION, SETTINGS_LOCALE_KEY, _locale) config.save(SETTINGS_PATH) static func language_label(locale: String) -> String: var normalized := _normalize_locale(locale) for option in LANGUAGE_OPTIONS: if str(option.get("code", "")) == normalized: return str(option.get("label", normalized)) return normalized static func t(value: Variant) -> String: _ensure_loaded() var text := str(value) if text.is_empty(): return text if _locale != LOCALE_EN: return text return _translate_english(text) static func format_duration(seconds: int) -> String: var left := maxi(seconds, 0) var days := int(left / 86400) left %= 86400 var hours := int(left / 3600) left %= 3600 var minutes := int(left / 60) var secs := left % 60 if days > 0: return "%sd %sh %sm %ss" % [days, hours, minutes, secs] if hours > 0: return "%sh %sm %ss" % [hours, minutes, secs] if minutes > 0: return "%sm %ss" % [minutes, secs] return "%ss" % secs static func list_separator() -> String: return ", " if current_locale() == LOCALE_EN else "、" static func has_han(text: String) -> bool: for index in range(text.length()): var code := text.unicode_at(index) if code >= 0x4E00 and code <= 0x9FFF: return true return false static func _translate_english(text: String) -> String: if EN.has(text): return str(EN.get(text)) var result := text if result.ends_with("秒") and result.trim_suffix("秒").is_valid_int(): return format_duration(int(result.trim_suffix("秒"))) result = _replace_terms(result) if has_han(result): result = _strip_han(result) result = result.strip_edges() return result if not result.is_empty() else "Text" static func _replace_terms(text: String) -> String: var result := text var keys := TERM_REPLACEMENTS.keys() keys.sort_custom(func(left, right) -> bool: return str(left).length() > str(right).length() ) for key in keys: result = result.replace(str(key), str(TERM_REPLACEMENTS.get(key))) return result static func _strip_han(text: String) -> String: var result := "" for index in range(text.length()): var code := text.unicode_at(index) if code >= 0x4E00 and code <= 0x9FFF: continue result += text.substr(index, 1) return result static func _ensure_loaded() -> void: if _loaded: return _loaded = true var config := ConfigFile.new() if config.load(SETTINGS_PATH) == OK: _locale = _normalize_locale(str(config.get_value(SETTINGS_SECTION, SETTINGS_LOCALE_KEY, LOCALE_EN))) else: _locale = LOCALE_EN static func _normalize_locale(locale: String) -> String: for option in LANGUAGE_OPTIONS: if str(option.get("code", "")) == locale: return locale return LOCALE_EN