Files
epic-go/internal/logic/i18n/i18n.go
hu xiaotong 9ef6ac9cdb refactor(internal): 优化 OSS 预签名 URL 缓存刷新任务和英雄数据缓存逻辑
- 注释掉 OSS预签名 URL 缓存刷新任务的定时执行代码
- 在 hero/hero.go 中增加对 Redis缓存和英雄数据集的非空校验
- 修改 OSS预签名 URL 生成逻辑,自动替换为 CDN 域名
2025-07-17 17:37:13 +08:00

977 lines
40 KiB
Go
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.

package i18n
import (
"context"
"epic/internal/dao"
"epic/internal/model/entity"
"epic/internal/util"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"sync"
"time"
)
// I18nEnToZh 英文->中文映射表(仅做备份,不再作为主数据源)
var I18nEnToZh = map[string]string{
"A Little Queen's Huge Crown": "小小女王的巨大王冠",
"A Song for Everybody": "献给你和这个世界的歌曲",
"A Symbol of Unity": "团结的象征",
"Abyssal Crown": "深渊王冠",
"Achates": "雅卡泰丝",
"Adamant Shield": "金刚石盾牌",
"Adin": "艾庭",
"Adlay": "亚迪赖",
"Adventurer Ras": "冒险家拉斯",
"Ainos": "艾诺斯",
"Ains": "艾因兹",
"Air-to-Surface Missile: MISHA": "空地导弹:美莎 ",
"Aither": "埃德勒",
"Alabastron": "雪花石膏瓶",
"Alencia": "艾莲西雅",
"Alencinox's Wrath": "艾莲西诺克斯的逆鳞",
"Alexa": "雅莉莎",
"Alexa's Basket": "雅莉莎的提篮",
"All-Rounder Wanda": "疑难杂症专家汪达",
"Alsacian Spear": "艾尔赛斯之矛",
"Ambitious Tywin": "野心分子泰温",
"Ambrote": "安布罗泰",
"Ancient Dragon's Legacy": "古龙遗产",
"Ancient Sheath": "古代剑鞘",
"Andre's Crossbow": "安德烈斯之弩",
"Angel of Light Angelica": "光之天使安洁莉卡",
"Angelic Montmorancy": "守护天使蒙茉朗西",
"Angelica": "安洁莉卡",
"Anti-Magic Mask": "抗魔面具",
"Apocalypse Ravi": "末日萝菲",
"Aqua Rose": "水玫瑰",
"Aramintha": "雅拉敏塔",
"Arbiter Vildred": "执行官维德瑞",
"Archdemon's Shadow": "魔神的暗影",
"Armin": "亚敏",
"Arowell": "雅洛薇",
"Ascending Axe": "参天斧",
"Assassin Cartuja": "杀手卡尔图哈",
"Assassin Cidd": "杀手席德",
"Assassin Coli": "杀手可丽",
"Atma's Portal": "亚特玛的传送门",
"Aurius": "亚乌利斯",
"Auxiliary Lots": "辅助型拉兹",
"Azalea": "亚洁理亚",
"Azure Comet": "青光彗星",
"Abyssal Yufine": "深渊优芬妮",
"Amiki": "雅蜜琪",
"Baal & Sezan": "巴尔&塞尚",
"Baiken": "梅喧",
"Barthez's Orbuculum": "巴泰斯的水晶球",
"Basar": "巴萨尔",
"Bask": "巴思克",
"Bastion of Hope": "希望的堡垒",
"Bastion of Perlutia": "波鲁迪亚的堡垒",
"Batisse": "巴托斯",
"Belian": "伯里安",
"Bellona": "维尔萝娜",
"Benevolent Romann": "仁慈的洛曼",
"Biting Wind Star": "寒风飞镖",
"Black Hand of the Goddess": "女神的黑手",
"Blaze Dingo": "烈火汀果",
"Blessings of Camaraderie": "友情祝福",
"Blood Blade Karin": "血剑卡琳",
"Blood Moon Haste": "赤月贵族海斯特",
"Blood-Seared Moon": "血染之月",
"Bloodbead Dagger": "血诛短剑",
"Bloodstone": "血玉髓",
"Bloody Rose": "血玫瑰",
"Bloody Warhammer": "血腥战锤",
"Bomb Model Kanna": "爆击型卡农",
"Border Coin": "孤注一掷",
"Briar Witch Iseria": "灰光森林的伊赛丽亚",
"Broken Will of the Priest": "残破的祭司长意志",
"Butcher Corps Inquisitor": "屠杀部队员",
"Butterfly Mandolin": "蝴蝶的曼陀林",
"Blooming Lidica": "花园丽迪卡",
"Byblis": "维波里丝",
"Beguiling Wings": "迷惑羽翼",
"Camilla": "卡蜜拉",
"Captain Rikoris": "先锋队长里科黎司",
"Card of Small Miracles": "小小奇迹贺年卡",
"Carmainerose": "卡麦萝兹",
"Carrot": "卡萝",
"Cartuja": "卡尔图哈",
"Cecilia": "赛西莉亚",
"Celeste": "赛雷斯特",
"Celestial Mercedes": "外太空的玫勒赛德丝",
"Celestial Spear": "天空之矛",
"Celestine": "天青石",
"Celine": "瑟琳",
"Cerise": "赛瑞丝",
"Cermia": "洁若米亚",
"Challenger Dominiel": "挑战者多米妮尔",
"Champion Zerato": "终结者杰拉图",
"Champion's Trophy": "优胜者奖杯",
"Chaos Inquisitor": "混沌教屠杀追击者",
"Chaos Sect Axe": "混沌教巨斧大将军",
"Charles": "查尔斯",
"Charlotte": "夏绿蒂",
"Chatty": "柴迪",
"Chloe": "克萝爱",
"Choux": "小泡芙",
"Christy": "克莉丝媞",
"Church of Ilryos Axe": "伊利欧斯教斧兵",
"Cidd": "席德",
"Circus Fantasia": "奇幻马戏团",
"Clarissa": "克莱莉莎",
"Closer Charles": "末日指挥官查尔斯",
"Coli": "可丽",
"Command Model Laika": "指挥型莱伊卡",
"Commander Lorina": "指挥官萝里娜",
"Conqueror Lilias": "支配者莉莉亚斯",
"Corvus": "科尔布思",
"Cradle of Life": "生命摇篮",
"Creation & Destruction": "创造之福&破坏之颂",
"Crescent Moon Rin": "新月舞姬铃儿",
"Crimson Armin": "红焰亚敏",
"Crimson Moon of Nightmares": "红色噩梦之月",
"Crimson Seed": "红焰种子",
"Crown of Glory": "荣耀之冠",
"Crozet": "克罗泽",
"Cruel Mischief": "残酷的玩笑",
"Cursed Compass": "诅咒的罗盘",
"Claudia": "克劳蒂亚",
"Dark Corvus": "黑暗的科尔布思",
"Daydream Joker": "白日梦小丑",
"Days of Destiny": "命中注定的相遇",
"Deadly Sword": "必杀大剑",
"Demon's Pistol": "恶魔手枪",
"Desert Jewel Basar": "沙漠宝石巴萨尔",
"Designer Lilibet": "设计师莉莉贝",
"Destina": "戴丝蒂娜",
"Devil's Brand": "恶魔烙印",
"Diene": "迪埃妮",
"Dignus Orb": "尊严宝珠",
"Dingo": "汀果",
"Dizzy": "蒂姬",
"Doctor's Bag": "急救包",
"Doll Maker Pearlhorizon": "制偶师波萝莱珍",
"Dominiel": "多米妮尔",
"Doris": "朵莉思",
"Double-Edged Decrescent": "双刃下弦月",
"Draco Plate": "龙族板甲",
"Dream Scroll": "梦之卷轴",
"Durandal": "杜兰月",
"Dust Devil": "尘埃恶魔",
"Dux Noctis": "暗夜指挥者",
"Dragon King Sharun": "龙王莎伦",
"Eaton": "伊顿",
"Eda": "艾妲",
"Egg of Delusion": "迷惑之蛋",
"El's Fist": "艾尔之拳",
"Elbris Ritual Sword": "埃布利斯的宝剑",
"Elena": "艾蕾娜",
"Elf's Bow": "妖精之弓",
"Elphelt": "爱尔菲特",
"Elson": "艾尔森",
"Elyha's Knife": "埃里哈刀",
"Emilia": "爱蜜莉雅",
"Enhanced Gauntlet": "强化拳套",
"Enott": "艾诺特",
"Envoy's Pipe": "死神烟斗",
"Ervalen": "艾尔巴伦",
"Eternus": "埃特诺斯",
"Etica's Scepter": "艾帝嘉权杖",
"Exorcist's Tonfa": "斗鬼的拐棍",
"Elvira": "艾碧拉",
"Eternal Wanderer Ludwig": "永劫漂流者鲁特比",
"Ezra": "艾自拉",
"Fairy Tale for a Nightmare": "噩梦童话",
"Fairy's Grimoire": "妖精的魔法书",
"Fairytale Tenebria": "童话泰妮布里雅",
"Faithless Lidica": "无神论者丽迪卡",
"Falconer Kluri": "鹰猎人可露莉",
"Fallen Cecilia": "堕落的赛西莉亚",
"Fighter Maya": "战斗型玛雅",
"Firm Shield": "坚定之盾",
"Flan": "芙兰",
"Flawless Garments": "天衣无缝",
"Flower Shower": "洒花",
"Forest Totem": "绿林图腾",
"Free Spirit Tieria": "永恒不变的黛莉亚",
"Furious": "尤贝乌斯",
"Fumyr": "芙米尔",
"General Purrgis": "大将法济斯",
"Glenn": "格伦",
"Gloomyrain": "格鲁美兰",
"Goblin's Lamp": "鬼怪明灯",
"Godmother": "教母",
"Golden Cocoa Cookie": "黄金可可豆饼干",
"Grail of Blood": "鲜血圣杯",
"Great Chief Khawana": "大族长卡瓦娜",
"Guardian Ice Crystals": "守护的冰封碎片",
"Guide to a Decision": "选择的指标",
"Guider Aither": "求道者埃德勒",
"Guiding Light": "引导之光",
"Gunther": "坤特",
"Haste": "海斯特",
"Hataan": "哈坦",
"Hazel": "海兹",
"Helen": "海伦",
"Helga": "赫尔嘉",
"Hell Cutter": "地狱切割机",
"Hilag Lance": "锡拉革骑士长矛",
"Holiday Yufine": "度假风优芬妮",
"Holy Sacrifice": "神圣牺牲",
"Hurado": "修拉杜",
"Ian": "伊安",
"Idol's Cheer": "歌姬助阵",
"Iela Violin": "依埃萝小提琴",
"Ilynav": "伊莉娜芙",
"Inferno Khawazu": "烈焰的卡瓦朱",
"Infinity Basket": "无限提篮",
"Iron Fan": "铁扇",
"Iseria": "伊赛丽亚",
"Jecht": "杰克托",
"Jena": "捷娜",
"Judge Kise": "审判者绮世",
"Judith": "茱迪丝",
"Junkyard Dog": "Junkyard Dog",
"Justice for All": "为众人的正义",
"Kal'adra": "嘉拉特拉",
"Karin": "卡琳",
"Kawerik": "卡威利",
"Kayron": "凯隆",
"Ken": "肯恩",
"Khawana": "卡瓦娜",
"Khawazu": "卡瓦朱",
"Kikirat v2": "奇奇拉特V.2",
"Kiris": "奇丽丝",
"Kise": "绮世",
"Kitty Clarissa": "猫咪克莱莉莎",
"Kizuna AI": "绊爱",
"Kluri": "可露莉",
"Knowledge Seed": "知识种子",
"Krau": "克劳乌",
"Kane": "该隐",
"Labyrinth Cube": "迷宫的方块",
"Landy": "兰蒂",
"Last Rider Krau": "最后的骑士克劳乌",
"Last Teatime": "最后的下午茶",
"Lena": "雷娜",
"Leo": "雷欧",
"Lidica": "丽迪卡",
"Lilias": "莉莉亚斯",
"Lilibet": "莉莉贝",
"Little Queen Charlotte": "年轻的女王夏绿蒂",
"Lorina": "萝里娜",
"Lots": "拉兹",
"Love Potion": "爱情灵丹",
"Lucy": "露西",
"Ludwig": "鲁特比",
"Luluca": "璐璐卡",
"Luna": "露娜",
"Leah": "蕾娅",
"Magaraha's Tome": "玛姬拉哈的魔法古书",
"Magic Scholar Doris": "魔法学者朵莉思",
"Maid Chloe": "仆人克萝爱",
"Manica of Control": "控制的护臂",
"Manifu": "玛尼普",
"Martial Artist Ken": "武斗家肯恩",
"Mascot Hazel": "吉祥物海兹",
"Maya": "玛雅",
"Mediator Kawerik": "协调者卡威利",
"Melany": "玫拉妮",
"Melissa": "梅丽莎",
"Mercedes": "玫勒赛德丝",
"Mercenary Helga": "自由自在的佣兵赫尔嘉",
"Merciless Glutton": "无情的大食客",
"Midnight Bloom": "月夜之花",
"Mighty Scout": "侦查兵玛伊堤",
"Mighty Yaksha": "金刚夜叉",
"Milim": "蜜莉姆",
"Mirsa": "米勒莎",
"Mistychain": "美丝缇彩",
"Montmorancy": "蒙茉朗西",
"Moonlight Dreamblade": "皎月梦夜",
"Moonlight's Vestige": "月光之痕",
"Mort": "魔勒",
"Ms. Confille": "Miss Confile",
"Mucacha": "穆卡察",
"Mui": "缪伊",
"Muse Rima": "缪斯黎玛",
"Necro & Undine": "恶魔&天使",
"Nemunas": "尼姆拉斯",
"New Year Cookies": "蕴含幸福的岁末饼干",
"Noble Oath": "高洁的誓言",
"Oath Key": "誓约钥匙",
"Official Levulin Beach Volleyball": "里柏林沙滩排球指定用球",
"One Year of Gratitude": "心存感谢的一年",
"Operator Sigret": "操作员赛珂兰特",
"Otherworldly Machinery": "异界的机械",
"Otillie": "奥缇莉尔",
"Old Gardening Shears": "老旧园艺剪刀",
"Pavel": "帕贝尔",
"Pearlhorizon": "波萝莱珍",
"Penelope": "潘尼罗佩",
"Politis": "佛里蒂丝",
"Portrait of the Saviors": "救援者们的画像",
"Proof of Valor": "勇猛证据",
"Prophetic Candlestick": "预视的烛台",
"Pure White Trust": "纯白的信赖",
"Purrgis": "法济斯",
"Pyllis": "费莉丝",
"Radiant Forever": "灿烂的永恒",
"Rainbow Scale": "人鱼公主的鳞片",
"Ram": "拉姆",
"Ran": "岚",
"Ranon's Memorandum": "拉农的备忘录",
"Ras": "拉斯",
"Ravi": "萝菲",
"Ray": "雷伊",
"Reingar's Special Drink": "雷茵格尔特调饮料",
"Rem": "雷姆",
"Remnant Violet": "残影的菲奥雷托",
"Requiemroar": "雷奎姆洛",
"Researcher Carrot": "研究者卡萝",
"Resolute Soldier Series": "坚毅的战士",
"Rhianna & Luciella": "里安娜&路西艾拉",
"Righteous Thief Roozid": "义贼鲁兹德",
"Rikoris": "里科黎司",
"Rima": "黎玛",
"Rimuru": "利姆路",
"Rin": "铃儿",
"Rise of a Monarch": "王的诞生",
"Roaming Warrior Leo": "流浪勇士雷欧",
"Roana": "罗安纳",
"Rod of Amaryllis": "孤挺花之杖",
"Romann": "洛曼",
"Roozid": "鲁兹德",
"Rosa Hargana": "罗沙哈勒戈纳",
"Rose": "萝季",
"Ruby Essence": "红玉精髓",
"Ruele of Light": "光之瑞儿",
"Sage Baal & Sezan": "贤者巴尔&塞尚",
"Samsara Prayer Beads": "循环念珠",
"Santa Muerte": "死亡圣神",
"Sashe Ithanes": "香袋伊妲涅斯",
"Schuri": "修里",
"Seaside Bellona": "海边的维尔萝娜",
"Secret Art - Storm Sword": "秘笈:雷天一剑",
"Senya": "赛娜",
"Sepulcrum": "塞弗克鲁姆",
"Serila": "塞丽拉",
"Severed Horn Wand": "被截断的犄角手杖",
"Sez": "赛兹",
"Shadow Knight Pyllis": "黑骑士费莉丝",
"Shadow Rose": "暗影萝季",
"Shepherd of the Hollow": "无为的引导者",
"Shepherds of Chaos": "混沌的引导者们",
"Shimadra Staff": "席玛德拉的手杖",
"Shooting Star Achates": "流星雅卡泰丝",
"Shuna": "朱菜",
"Sigret": "赛珂兰特",
"Sigurd Scythe": "席格勒赛斯",
"Silk": "席可",
"Silver Blade Aramintha": "白银刀刃的雅拉敏塔",
"Silver Rain": "银光骤雨",
"Sinful Angelica": "罪戾的安洁莉卡",
"Sira-Ren": "席拉-莲",
"Snow Crystal": "白雪水晶",
"Sol": "索尔",
"Solitaria of the Snow": "雪国的苏莉塔妮亚",
"Song of Stars": "星辰之歌",
"Sonia": "苏尼娅",
"Spear of a New Dawn": "开辟之枪",
"Specimen Sez": "实验体赛兹",
"Specter Tenebria": "幻影的泰妮布里雅",
"Spirit Eye Celine": "灵眼的瑟琳",
"Spirit's Breath": "精灵气息",
"Spooky Solayu Stories": "奇闻轶事录",
"Staff of Wisdom": "智慧的手杖",
"Star of the Deep Sea": "深海漂浮之星",
"Star Piercer": "破星者",
"Steadfast Gatekeeper": "坚定的看守者",
"Stella Harpa": "星之竖琴",
"Strak Gauntlet": "史特雷克拳套",
"Straze": "史瑞杰思",
"Succubus Mirror": "魅魔之镜",
"Summertime Iseria": "南国的伊赛丽亚",
"Super Duper Water Gun Shooter": "至尊水枪",
"Surin": "苏琳",
"Sven": "史宾",
"Sword of Ezera": "伊杰拉的圣剑",
"Sword of Holy Light": "圣光之剑",
"Sword of Judgment": "审判之剑",
"Sword of Summer Twilight": "夏夜闪刀",
"Sword of the Morning": "黎明剑",
"Sword of the Sun": "太阳之剑",
"Sword of Winter Shadow": "冬晷切刀",
"Silvertide Christy": "银波克莉丝媞",
"Seductive Flower": "诱惑之花",
"Tagehel's Ancient Book": "塔克赫尔古书",
"Tamarinne": "塔玛林尔",
"Taranor Guard": "塔拉诺尔禁卫队员",
"Taranor Royal Guard": "塔拉诺尔王宫士兵",
"Tear of the Desert": "沙漠之泪",
"Tempest Surin": "风云苏琳",
"Tenebria": "泰妮布里雅",
"The Guardian Star's Blessing": "守护星的祝福",
"Tieria": "黛莉亚",
"Time Matter": "时间的物质",
"Timeless Anchor": "永劫之锚",
"To a New World": "致崭新的时代",
"Top Model Luluca": "最强模特儿璐璐卡",
"Torn Sleeve": "撕裂的右衣袖",
"Touch of Rekos": "列科斯的救援",
"Troublemaker Crozet": "不法之徒克罗泽",
"Twilight Calamity": "落日之灾",
"Tywin": "泰温",
"Tyrant's Descent": "暴君的血统",
"Uberius's Tooth": "尤贝里乌斯的臼齿",
"Unfading Memories": "不凋零的回忆",
"Unseen Observer": "隐形的观察者",
"Upgraded Dragon Knuckles": "改良型龙指虎",
"Umbral Keystones": "暗影源石",
"Venus Orb": "金星宝珠",
"Victorious Flag": "胜战旗帜",
"Vildred": "维德瑞",
"Violet Talisman": "紫色护身符",
"Violet": "菲奥雷托",
"Vivian": "薇薇安",
"Wall of Order": "秩序护墙",
"Wanda": "汪达",
"Wanderer Silk": "流浪者席可",
"War Horn": "进攻号角",
"Watcher Schuri": "注视者修里",
"Water's Origin": "波涛的祈愿",
"Wild Angara": "野生安卡拉",
"Wind Rider": "乘风者",
"Wings of Light and Shadow": "明暗双翼",
"Wondrous Potion Vial": "灵药的试管",
"XIII. Death": "XIII. Death",
"XIV. Temperance": "XIV. Temperance",
"XVI. The Tower": "XVI. The Tower",
"XVIII. The Moon": "XVIII. The Moon",
"Yufine": "优芬妮",
"Yuna": "尤娜",
"Zahhak": "札哈克",
"Zealot Carmainerose": "传道者卡麦萝兹",
"Zeno": "杰诺",
"Zerato": "杰拉图",
"An Offer You Can't Refuse": "无法拒绝的提议",
"Benimaru's Tachi": "红丸之刀",
"Blazing Full Moon Trophy": "燃烧的满月奖杯",
"Brilliant Confidence": "闪耀的自信",
"Cutie Pando": "小可爱胖嘟",
"Fan of Light and Dark": "昏明之扇",
"Fullmetals Automail": "钢铁机械铠",
"Glo-Wings 21": "光辉羽翼21",
"Goblet of Oath": "誓言之杯",
"Golden Rose": "金玫瑰",
"Ignition Cloth Gloves": "发火布手套",
"Indestructible Gaiters": "金刚绑腿",
"Jack-O's Symbol": "洁克·欧的象征",
"Magic for Friends": "为了朋友的魔法",
"Mature Sunglasses": "成熟的墨镜",
"Nostalgic Music Box": "悲恋音乐盒",
"Prayer of Solitude": "孤独祈祷",
"Prelude to a New Era": "新时代的序幕",
"Records of Unity": "团结的记录",
"Sacred Tree Branch": "神木树枝",
"Scroll of Shadows": "暗影之书",
"Seal of Capture": "束缚之印",
"Sharpshooters Handgun": "神枪手的手枪",
"Sole Consolation": "唯一的慰藉",
"Spatiotemporal Fan": "时空折扇",
"Spear of Purification": "破邪之矛",
"Sphere of Inferno": "焚灭之球",
"Sphere of Sadism": "嗜虐之球",
"Sword of Autumn Eclipse": "秋端染刀",
"Sword of Cycling Seasons": "循环之剑",
"Aria": "艾莉雅",
"Abigail": "雅碧凯",
"Ainos 2.0": "艾诺斯 2.0",
"Amid": "雅咪德",
"Architect Laika": "策划者莱伊卡",
"Arunka": "亚露嘉",
"Astromancer Elena": "星辰的神谕艾蕾娜",
"Bad Cat Armin": "坏猫猫亚敏",
"Beehoo": "雨修",
"Benimaru": "红丸",
"Brieg": "布里克",
"Commander Pavel": "司令官帕贝尔",
"Death Dealer Ray": "死亡探究者雷伊",
"Edward Elric": "爱德华·艾力克",
"Eligos": "艾利戈斯",
"Hasol": "夏率",
"Holy Flame Adin": "圣炎的艾庭",
"Hwayoung": "和英",
"Infinite Horizon Achates": "未知可能性雅卡泰丝",
"Jack-O": "洁克·欧",
"Januta": "扎怒塔",
"Juni": "珠妮",
"Last Piece Karin": "最后的碎片卡琳",
"Lethe": "丽希",
"Lilka": "莉珈",
"Lionheart Cermia": "狮心王洁若米亚",
"Lone Crescent Bellona": "一轮孤月维尔萝娜",
"Lua": "路雅",
"Moon Bunny Dominiel": "月兔多米尼尔",
"Muwi": "武蔚",
"Navy Captain Landy": "海军上校兰蒂",
"Ocean Breeze Luluca": "海洋香气璐璐卡",
"Orte": "奥乐缇",
"Peacemaker Furious": "平衡的尤贝乌斯",
"Peira": "沛伊拉",
"Pirate Captain Flan": "海盗船长芙兰",
"Requiem Roana": "镇魂萝安纳",
"Riza Hawkeye": "莉莎·霍克爱",
"Roy Mustang": "罗伊·马斯坦古",
"Savior Adin": "救援者艾庭",
"Serene Purity Adin": "清玄的艾庭",
"Sharun": "莎伦",
"Shepherd Jena": "引导者捷娜",
"Summer Break Charlotte": "暑假夏绿蒂",
"Summer's Disciple Alexa": "夏日学生雅莉莎",
"Suthan": "斯坦",
"Sylvan Sage Vivian": "森之贤者薇薇安",
"Taeyou": "太悟",
"Talaz": "达拉士",
"Talia": "达黎儿",
"Twisted Eidolon Kayron": "扭曲亡灵凯隆",
"Unbound Knight Arowell": "自由骑士雅洛薇",
"Verdant Adin": "新绿的艾庭",
"Veronica": "贝洛妮卡",
"Vigilante Leader Glenn": "自卫队队长格伦",
"Yoonryoung": "尹凌",
"Yulha": "律荷",
"Zio": "智武",
"Midnight Gala Lilias": "夜宴莉莉亚斯",
"Urban Shadow Choux": "都市暗影小泡芙",
"Hostess of the Banquet": "宴会之主",
"Nahkwol": "落月",
"ae-GISELLE": "ae-GISELLE",
"ae-KARINA": "ae-KARINA",
"ae-NINGNING": "ae-NINGNING",
"ae-WINTER": "ae-WINTER",
"Laia": "莱雅",
"Elegiac Candles": "慰灵烛光",
"_comment_1": "角色神器结束",
"scales": "天秤座",
"lion": "狮子座",
"waterbearer": "水瓶座",
"archer": "射手座",
"crab": "巨蟹座",
"twins": "双子座",
"bull": "金牛座",
"fish": "双鱼座",
"maiden": "处女座",
"goat": "摩羯座",
"scorpion": "天蝎座",
"ram": "白羊座",
"knight": "骑士",
"warrior": "战士",
"assassin": "潜行者",
"mage": "魔导士",
"ranger": "射手",
"manauser": "精灵师",
"fire": "火",
"wind": "木",
"ice": "水",
"dark": "暗",
"light": "光",
"cp": "战斗力",
"atk": "战斗力",
"hp": "战斗力",
"spd": "战斗力",
"def": "战斗力",
"chc": "战斗力",
"chd": "战斗力",
"dac": "战斗力",
"eff": "战斗力",
"efr": "",
}
// I18nZhToEn 中文->英文映射表(自动生成)
var I18nZhToEn = func() map[string]string {
m := make(map[string]string, len(I18nEnToZh))
for k, v := range I18nEnToZh {
m[v] = k
}
return m
}()
type Logic struct {
cache map[string]map[string]string // lang -> key -> value
mutex sync.RWMutex
}
func New() *Logic {
return &Logic{
cache: make(map[string]map[string]string),
}
}
// 全局i18n实例
var globalI18nLogic *Logic
var globalI18nMutex sync.RWMutex
func init() {
globalI18nLogic = New()
}
// GetI18nLogic 获取全局i18n实例
func GetI18nLogic() *Logic {
globalI18nMutex.RLock()
defer globalI18nMutex.RUnlock()
return globalI18nLogic
}
// LoadFromDB 从数据库加载所有翻译到缓存
func (l *Logic) LoadFromDB(ctx context.Context) error {
var mappings []*entity.EpicI18NMappings
err := dao.EpicI18NMappings.Ctx(ctx).
Where(dao.EpicI18NMappings.Columns().Status, 1).
Where(dao.EpicI18NMappings.Columns().Deleted, 0).
Scan(&mappings)
if err != nil {
return fmt.Errorf("加载i18n数据失败: %v", err)
}
l.mutex.Lock()
defer l.mutex.Unlock()
// 重新构建缓存
l.cache = make(map[string]map[string]string)
// 新增同步数据库内容到I18nEnToZh备份
for _, m := range mappings {
if l.cache[m.Language] == nil {
l.cache[m.Language] = make(map[string]string)
}
l.cache[m.Language][m.KeyName] = m.Value
if m.Language == "zh" {
I18nEnToZh[m.KeyName] = m.Value
}
}
util.Info(ctx, "i18n缓存加载完成共", len(mappings), "条记录")
return nil
}
// Get 获取指定key的指定语言翻译
func (l *Logic) Get(ctx context.Context, lang, key string) string {
l.mutex.RLock()
defer l.mutex.RUnlock()
if m, ok := l.cache[lang]; ok {
if v, ok := m[key]; ok {
return v
}
}
return key // 找不到返回原文
}
// GetBatch 批量获取翻译
func (l *Logic) GetBatch(ctx context.Context, lang string, keys []string) map[string]string {
l.mutex.RLock()
defer l.mutex.RUnlock()
result := make(map[string]string)
if m, ok := l.cache[lang]; ok {
for _, key := range keys {
if v, ok := m[key]; ok {
result[key] = v
} else {
result[key] = key // 找不到返回原文
}
}
} else {
// 语言不存在,全部返回原文
for _, key := range keys {
result[key] = key
}
}
return result
}
// Refresh 刷新缓存
func (l *Logic) Refresh(ctx context.Context) error {
return l.LoadFromDB(ctx)
}
// Add 添加翻译
func (l *Logic) Add(ctx context.Context, key, lang, value, category string) error {
// 先保存到数据库
_, err := dao.EpicI18NMappings.Ctx(ctx).Data(g.Map{
dao.EpicI18NMappings.Columns().KeyName: key,
dao.EpicI18NMappings.Columns().Language: lang,
dao.EpicI18NMappings.Columns().Value: value,
dao.EpicI18NMappings.Columns().Category: category,
dao.EpicI18NMappings.Columns().Status: 1,
dao.EpicI18NMappings.Columns().CreateTime: gtime.Now(),
dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(),
}).Insert()
if err != nil {
return fmt.Errorf("添加翻译失败: %v", err)
}
// 更新缓存
l.mutex.Lock()
defer l.mutex.Unlock()
if l.cache[lang] == nil {
l.cache[lang] = make(map[string]string)
}
l.cache[lang][key] = value
util.Info(ctx, "添加翻译:", lang, key, "->", value)
return nil
}
// Update 更新翻译
func (l *Logic) Update(ctx context.Context, key, lang, value string) error {
// 更新数据库
_, err := dao.EpicI18NMappings.Ctx(ctx).
Where(dao.EpicI18NMappings.Columns().KeyName, key).
Where(dao.EpicI18NMappings.Columns().Language, lang).
Data(g.Map{
dao.EpicI18NMappings.Columns().Value: value,
dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(),
}).Update()
if err != nil {
return fmt.Errorf("更新翻译失败: %v", err)
}
// 更新缓存
l.mutex.Lock()
defer l.mutex.Unlock()
if l.cache[lang] == nil {
l.cache[lang] = make(map[string]string)
}
l.cache[lang][key] = value
util.Info(ctx, "更新翻译:", lang, key, "->", value)
return nil
}
// Delete 删除翻译
func (l *Logic) Delete(ctx context.Context, key, lang string) error {
// 软删除数据库记录
_, err := dao.EpicI18NMappings.Ctx(ctx).
Where(dao.EpicI18NMappings.Columns().KeyName, key).
Where(dao.EpicI18NMappings.Columns().Language, lang).
Data(g.Map{
dao.EpicI18NMappings.Columns().Deleted: 1,
dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(),
}).Update()
if err != nil {
return fmt.Errorf("删除翻译失败: %v", err)
}
// 从缓存中删除
l.mutex.Lock()
defer l.mutex.Unlock()
if m, ok := l.cache[lang]; ok {
delete(m, key)
}
util.Info(ctx, "删除翻译:", lang, key)
return nil
}
// GetByCategory 根据分类获取翻译
func (l *Logic) GetByCategory(ctx context.Context, lang, category string) (map[string]string, error) {
var mappings []*entity.EpicI18NMappings
err := dao.EpicI18NMappings.Ctx(ctx).
Where(dao.EpicI18NMappings.Columns().Language, lang).
Where(dao.EpicI18NMappings.Columns().Category, category).
Where(dao.EpicI18NMappings.Columns().Status, 1).
Where(dao.EpicI18NMappings.Columns().Deleted, 0).
Scan(&mappings)
if err != nil {
return nil, fmt.Errorf("获取分类翻译失败: %v", err)
}
result := make(map[string]string)
for _, m := range mappings {
result[m.KeyName] = m.Value
}
return result, nil
}
// ImportFromMap 从map批量导入翻译
func (l *Logic) ImportFromMap(ctx context.Context, lang string, mappings map[string]string, category string) error {
if len(mappings) == 0 {
return nil
}
// 批量插入数据库
var data []g.Map
for key, value := range mappings {
data = append(data, g.Map{
dao.EpicI18NMappings.Columns().KeyName: key,
dao.EpicI18NMappings.Columns().Language: lang,
dao.EpicI18NMappings.Columns().Value: value,
dao.EpicI18NMappings.Columns().Category: category,
dao.EpicI18NMappings.Columns().Status: 1,
dao.EpicI18NMappings.Columns().CreateTime: gtime.Now(),
dao.EpicI18NMappings.Columns().UpdateTime: gtime.Now(),
})
}
_, err := dao.EpicI18NMappings.Ctx(ctx).Data(data).Insert()
if err != nil {
return fmt.Errorf("批量导入翻译失败: %v", err)
}
// 更新缓存
l.mutex.Lock()
defer l.mutex.Unlock()
if l.cache[lang] == nil {
l.cache[lang] = make(map[string]string)
}
for key, value := range mappings {
l.cache[lang][key] = value
}
util.Info(ctx, "批量导入翻译完成:", lang, category, "共", len(mappings), "条")
return nil
}
// StartAutoRefresh 启动自动刷新
func (l *Logic) StartAutoRefresh(ctx context.Context) {
// 启动时加载
if err := l.LoadFromDB(ctx); err != nil {
util.Error(ctx, "初始加载i18n缓存失败:", err)
}
// 定时刷新(每小时)
go func() {
ticker := time.NewTicker(1 * time.Hour)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if err := l.Refresh(ctx); err != nil {
util.Error(ctx, "定时刷新i18n缓存失败:", err)
}
case <-ctx.Done():
return
}
}
}()
}
// En2Zh 英文转中文(静态映射,仅降级时使用)
func En2Zh(s string) string {
if v, ok := GetI18nLogic().cache["zh"][s]; ok {
return v
}
// 仅降级时才用备份
if v, ok := I18nEnToZh[s]; ok {
return v
}
return s
}
// Zh2En 中文转英文(静态映射,仅降级时使用)
func Zh2En(s string) string {
if v, ok := GetI18nLogic().cache["en"][s]; ok {
return v
}
// 仅降级时才用备份
if v, ok := I18nZhToEn[s]; ok {
return v
}
return s
}
// GetI18n 获取指定key的指定语言翻译优先使用数据库找不到则使用静态映射
func GetI18n(ctx context.Context, lang, key string) string {
// 优先使用数据库服务
if logic := GetI18nLogic(); logic != nil {
result := logic.Get(ctx, lang, key)
if result != key {
return result
}
}
// 数据库找不到,使用静态映射(仅支持中英文)
if lang == "zh" {
return En2Zh(key)
}
return key
}
// GetZh 获取中文翻译(便捷方法)
func GetZh(ctx context.Context, key string) string {
return GetI18n(ctx, "zh", key)
}
// GetEn 获取英文翻译(便捷方法)
func GetEn(ctx context.Context, key string) string {
return GetI18n(ctx, "en", key)
}
// GetI18nBatch 批量获取翻译
func GetI18nBatch(ctx context.Context, lang string, keys []string) map[string]string {
if logic := GetI18nLogic(); logic != nil {
return logic.GetBatch(ctx, lang, keys)
}
// 降级到静态映射
result := make(map[string]string)
for _, key := range keys {
result[key] = GetI18n(ctx, lang, key)
}
return result
}
// GetZhBatch 批量获取中文翻译(便捷方法)
func GetZhBatch(ctx context.Context, keys []string) map[string]string {
return GetI18nBatch(ctx, "zh", keys)
}
// GetEnBatch 批量获取英文翻译(便捷方法)
func GetEnBatch(ctx context.Context, keys []string) map[string]string {
return GetI18nBatch(ctx, "en", keys)
}
// RefreshI18n 刷新i18n缓存
func RefreshI18n(ctx context.Context) error {
if logic := GetI18nLogic(); logic != nil {
return logic.Refresh(ctx)
}
return nil
}
// AddI18n 添加翻译
func AddI18n(ctx context.Context, key, lang, value, category string) error {
if logic := GetI18nLogic(); logic != nil {
return logic.Add(ctx, key, lang, value, category)
}
return nil
}
// ImportI18nFromMap 从map批量导入翻译
func ImportI18nFromMap(ctx context.Context, lang string, mappings map[string]string, category string) error {
if logic := GetI18nLogic(); logic != nil {
return logic.ImportFromMap(ctx, lang, mappings, category)
}
return nil
}