this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

eng support (#3)

authored by

Michael and committed by
GitHub
848e0f74 55ec8181

+774 -473
+334 -323
anime-data.ts
··· 1 + type AnimeItem = { 2 + titleZh: string; 3 + titleEn: string; 4 + score: number; 5 + }; 6 + 1 7 type Data = { 2 - [key: string]: { title: string; score: number }[]; 8 + [key: string]: AnimeItem[]; 3 9 }; 4 10 5 11 const data: Data = { 6 12 "2006": [ 7 - { title: "死亡笔记", score: 8.4 }, 8 - { title: "银魂", score: 8.7 }, 9 - { title: "寒蝉鸣泣之时", score: 8 }, 10 - { title: "Code Geass 反叛的鲁路修", score: 8.3 }, 11 - { title: "欢迎加入NHK!", score: 8.2 }, 12 - { title: "Fate/stay night", score: 7.1 }, 13 - { title: "凉宫春日的忧郁", score: 8.2 }, 14 - { title: "零之使魔", score: 7 }, 15 - { title: "黑礁", score: 7.8 }, 16 - { title: "Kanon", score: 7.7 }, 17 - { title: "娜娜", score: 8 }, 18 - { title: "×××HOLiC", score: 7.8 }, 19 - { title: "家庭教师HITMAN REBORN!", score: 7.5 }, 20 - { title: "樱兰高校男公关部", score: 7.6 }, 21 - { title: "蜂蜜与四叶草II", score: 8.5 }, 13 + { titleZh: "死亡笔记", titleEn: "Death Note", score: 8.4 }, 14 + { titleZh: "银魂", titleEn: "Gintama", score: 8.7 }, 15 + { titleZh: "寒蝉鸣泣之时", titleEn: "Higurashi When They Cry", score: 8 }, 16 + { titleZh: "Code Geass 反叛的鲁路修", titleEn: "Code Geass: Lelouch of the Rebellion", score: 8.3 }, 17 + { titleZh: "欢迎加入NHK!", titleEn: "Welcome to the N.H.K.", score: 8.2 }, 18 + { titleZh: "Fate/stay night", titleEn: "Fate/stay night", score: 7.1 }, 19 + { titleZh: "凉宫春日的忧郁", titleEn: "The Melancholy of Haruhi Suzumiya", score: 8.2 }, 20 + { titleZh: "零之使魔", titleEn: "The Familiar of Zero", score: 7 }, 21 + { titleZh: "黑礁", titleEn: "Black Lagoon", score: 7.8 }, 22 + { titleZh: "Kanon", titleEn: "Kanon", score: 7.7 }, 23 + { titleZh: "娜娜", titleEn: "NANA", score: 8 }, 24 + { titleZh: "×××HOLiC", titleEn: "×××HOLiC", score: 7.8 }, 25 + { titleZh: "家庭教师HITMAN REBORN!", titleEn: "Katekyo Hitman Reborn!", score: 7.5 }, 26 + { titleZh: "樱兰高校男公关部", titleEn: "Ouran High School Host Club", score: 7.6 }, 27 + { titleZh: "蜂蜜与四叶草II", titleEn: "Honey and Clover II", score: 8.5 }, 22 28 ], 23 29 "2007": [ 24 - { title: "幸运星", score: 8.3 }, 25 - { title: "CLANNAD", score: 8.3 }, 26 - { title: "天元突破 红莲螺岩", score: 8.6 }, 27 - { title: "旋风管家", score: 7.4 }, 28 - { title: "火影忍者疾风传", score: 7.6 }, 29 - { title: "悠久之翼", score: 7.9 }, 30 - { title: "赌博默示录", score: 7.9 }, 31 - { title: "永生之酒", score: 8.2 }, 32 - { title: "机动战士高达00", score: 7.6 }, 33 - { title: "再见绝望先生", score: 7.8 }, 34 - { title: "日在校园", score: 6.3 }, 35 - { title: "南家三姐妹", score: 7.6 }, 36 - { title: "DARKER THAN BLACK -黑之契约者-", score: 8 }, 37 - { title: "濑户的花嫁", score: 7.4 }, 38 - { title: "电脑线圈", score: 8.1 }, 39 - { title: "物怪", score: 8.2 }, 40 - { title: "向阳素描", score: 7.5 }, 41 - { title: "零之使魔 双月骑士", score: 6.9 }, 42 - { title: "sola", score: 7.2 }, 30 + { titleZh: "幸运星", titleEn: "Lucky Star", score: 8.3 }, 31 + { titleZh: "CLANNAD", titleEn: "CLANNAD", score: 8.3 }, 32 + { titleZh: "天元突破 红莲螺岩", titleEn: "Tengen Toppa Gurren Lagann", score: 8.6 }, 33 + { titleZh: "旋风管家", titleEn: "Hayate the Combat Butler", score: 7.4 }, 34 + { titleZh: "火影忍者疾风传", titleEn: "Naruto Shippuden", score: 7.6 }, 35 + { titleZh: "悠久之翼", titleEn: "ef: A Tale of Memories", score: 7.9 }, 36 + { titleZh: "赌博默示录", titleEn: "Kaiji: Ultimate Survivor", score: 7.9 }, 37 + { titleZh: "永生之酒", titleEn: "Baccano!", score: 8.2 }, 38 + { titleZh: "机动战士高达00", titleEn: "Mobile Suit Gundam 00", score: 7.6 }, 39 + { titleZh: "再见绝望先生", titleEn: "Sayonara, Zetsubou-Sensei", score: 7.8 }, 40 + { titleZh: "日在校园", titleEn: "School Days", score: 6.3 }, 41 + { titleZh: "南家三姐妹", titleEn: "Minami-ke", score: 7.6 }, 42 + { titleZh: "DARKER THAN BLACK -黑之契约者-", titleEn: "Darker than Black", score: 8 }, 43 + { titleZh: "濑户的花嫁", titleEn: "My Bride is a Mermaid", score: 7.4 }, 44 + { titleZh: "电脑线圈", titleEn: "Dennō Coil", score: 8.1 }, 45 + { titleZh: "物怪", titleEn: "Mononoke", score: 8.2 }, 46 + { titleZh: "向阳素描", titleEn: "Hidamari Sketch", score: 7.5 }, 47 + { titleZh: "零之使魔 双月骑士", titleEn: "The Familiar of Zero: Knight of the Twin Moons", score: 6.9 }, 48 + { titleZh: "sola", titleEn: "Sola", score: 7.2 }, 43 49 ], 44 50 "2008": [ 45 - { title: "出包王女", score: 6.9 }, 46 - { title: "龙与虎", score: 8 }, 47 - { title: "魔法禁书目录", score: 6.8 }, 48 - { title: "狼与香辛料", score: 7.8 }, 49 - { title: "夏目友人帐", score: 8 }, 50 - { title: "真实之泪", score: 7.5 }, 51 - { title: "神薙", score: 7.1 }, 52 - { title: "我的狐仙女友", score: 6.1 }, 53 - { title: "噬魂师", score: 7.4 }, 54 - { title: "黑执事", score: 7 }, 55 - { title: "俗・再见绝望先生", score: 7.8 }, 56 - { title: "鹡鸰女神", score: 6.2 }, 57 - { title: "强袭魔女", score: 7.1 }, 51 + { titleZh: "出包王女", titleEn: "To Love-Ru", score: 6.9 }, 52 + { titleZh: "龙与虎", titleEn: "Toradora!", score: 8 }, 53 + { titleZh: "魔法禁书目录", titleEn: "A Certain Magical Index", score: 6.8 }, 54 + { titleZh: "狼与香辛料", titleEn: "Spice and Wolf", score: 7.8 }, 55 + { titleZh: "夏目友人帐", titleEn: "Natsume's Book of Friends", score: 8 }, 56 + { titleZh: "真实之泪", titleEn: "True Tears", score: 7.5 }, 57 + { titleZh: "神薙", titleEn: "Kannagi", score: 7.1 }, 58 + { titleZh: "我的狐仙女友", titleEn: "Kanokon", score: 6.1 }, 59 + { titleZh: "噬魂师", titleEn: "Soul Eater", score: 7.4 }, 60 + { titleZh: "黑执事", titleEn: "Black Butler", score: 7 }, 61 + { titleZh: "俗・再见绝望先生", titleEn: "Zoku Sayonara Zetsubou Sensei", score: 7.8 }, 62 + { titleZh: "鹡鸰女神", titleEn: "Sekirei", score: 6.2 }, 63 + { titleZh: "强袭魔女", titleEn: "Strike Witches", score: 7.1 }, 58 64 ], 59 65 "2009": [ 60 - { title: "轻音少女", score: 8.2 }, 61 - { title: "钢之炼金术师 FULLMETAL ALCHEMIST", score: 8.8 }, 62 - { title: "化物语", score: 8.4 }, 63 - { title: "凉宫春日的忧郁 2009", score: 8 }, 64 - { title: "某科学的超电磁炮", score: 7.5 }, 65 - { title: "学生会的一己之见", score: 7.4 }, 66 - { title: "天降之物", score: 7.3 }, 67 - { title: "天才麻将少女", score: 7.5 }, 68 - { title: "白色相簿", score: 7.3 }, 69 - { title: "妖精的尾巴", score: 7.4 }, 70 - { title: "好想告诉你", score: 7.6 }, 66 + { titleZh: "轻音少女", titleEn: "K-ON!", score: 8.2 }, 67 + { titleZh: "钢之炼金术师 FULLMETAL ALCHEMIST", titleEn: "Fullmetal Alchemist: Brotherhood", score: 8.8 }, 68 + { titleZh: "化物语", titleEn: "Bakemonogatari", score: 8.4 }, 69 + { titleZh: "凉宫春日的忧郁 2009", titleEn: "The Melancholy of Haruhi Suzumiya (2009)", score: 8 }, 70 + { titleZh: "某科学的超电磁炮", titleEn: "A Certain Scientific Railgun", score: 7.5 }, 71 + { titleZh: "学生会的一己之见", titleEn: "Student Council's Discretion", score: 7.4 }, 72 + { titleZh: "天降之物", titleEn: "Heaven's Lost Property", score: 7.3 }, 73 + { titleZh: "天才麻将少女", titleEn: "Saki", score: 7.5 }, 74 + { titleZh: "白色相簿", titleEn: "White Album", score: 7.3 }, 75 + { titleZh: "妖精的尾巴", titleEn: "Fairy Tail", score: 7.4 }, 76 + { titleZh: "好想告诉你", titleEn: "Kimi ni Todoke", score: 7.6 }, 71 77 ], 72 78 "2010": [ 73 - { title: "吊带袜天使", score: 8 }, 74 - { title: "四叠半神话大系", score: 8.6 }, 75 - { title: "妄想学生会", score: 7.5 }, 76 - { title: "缘之空", score: 6.6 }, 77 - { title: "笨蛋,测验,召唤兽", score: 7.4 }, 78 - { title: "天使的心跳!", score: 7.5 }, 79 - { title: "无头骑士异闻录", score: 7.9 }, 80 - { title: "只有神知道的世界", score: 7.2 }, 81 - { title: "圣诞之吻SS", score: 7.3 }, 82 - { title: "我的妹妹哪有这么可爱!", score: 7.1 }, 83 - { title: "女仆咖啡厅", score: 7.8 }, 84 - { title: "亲吻姐姐", score: 6.7 }, 85 - { title: "迷糊餐厅", score: 7.5 }, 86 - { title: "学园默示录 HIGHSCHOOL OF THE DEAD", score: 6.7 }, 87 - { title: "荒川爆笑团", score: 7.5 }, 88 - { title: "天降之物f", score: 7.3 }, 89 - { title: "爆漫王。", score: 8 }, 90 - { title: "会长是女仆大人!", score: 6.9 }, 91 - { title: "圣痕炼金士", score: 6 }, 92 - { title: "空之音", score: 6.8 }, 79 + { titleZh: "吊带袜天使", titleEn: "Panty & Stocking with Garterbelt", score: 8 }, 80 + { titleZh: "四叠半神话大系", titleEn: "The Tatami Galaxy", score: 8.6 }, 81 + { titleZh: "妄想学生会", titleEn: "Seitokai Yakuindomo", score: 7.5 }, 82 + { titleZh: "缘之空", titleEn: "Yosuga no Sora", score: 6.6 }, 83 + { titleZh: "笨蛋,测验,召唤兽", titleEn: "Baka and Test", score: 7.4 }, 84 + { titleZh: "天使的心跳!", titleEn: "Angel Beats!", score: 7.5 }, 85 + { titleZh: "无头骑士异闻录", titleEn: "Durarara!!", score: 7.9 }, 86 + { titleZh: "只有神知道的世界", titleEn: "The World God Only Knows", score: 7.2 }, 87 + { titleZh: "圣诞之吻SS", titleEn: "Amagami SS", score: 7.3 }, 88 + { titleZh: "我的妹妹哪有这么可爱!", titleEn: "Oreimo", score: 7.1 }, 89 + { titleZh: "女仆咖啡厅", titleEn: "And Yet the Town Moves", score: 7.8 }, 90 + { titleZh: "亲吻姐姐", titleEn: "Kiss × Sis", score: 6.7 }, 91 + { titleZh: "迷糊餐厅", titleEn: "Working!", score: 7.5 }, 92 + { titleZh: "学园默示录 HIGHSCHOOL OF THE DEAD", titleEn: "High School of the Dead", score: 6.7 }, 93 + { titleZh: "荒川爆笑团", titleEn: "Arakawa Under the Bridge", score: 7.5 }, 94 + { titleZh: "天降之物f", titleEn: "Heaven's Lost Property f", score: 7.3 }, 95 + { titleZh: "爆漫王。", titleEn: "Bakuman", score: 8 }, 96 + { titleZh: "会长是女仆大人!", titleEn: "Maid Sama!", score: 6.9 }, 97 + { titleZh: "圣痕炼金士", titleEn: "Seikon no Qwaser", score: 6 }, 98 + { titleZh: "空之音", titleEn: "Sound of the Sky", score: 6.8 }, 93 99 ], 94 100 "2011": [ 95 - { title: "命运石之门", score: 8.8 }, 96 - { title: "日常", score: 8.5 }, 97 - { title: "Fate/Zero", score: 8.1 }, 98 - { title: "魔法少女小圆", score: 8.6 }, 99 - { title: "回转企鹅罐", score: 8 }, 100 - { title: "摇曳百合", score: 7.6 }, 101 - { title: "我们仍未知道那天所看见的花的名字。", score: 7.6 }, 102 - { title: "罪恶王冠", score: 6.5 }, 103 - { title: "花开伊吕波", score: 7.5 }, 104 - { title: "偶像大师", score: 8.3 }, 105 - { title: "GOSICK", score: 7.3 }, 106 - { title: "我的朋友很少", score: 6.8 }, 107 - { title: "猎人", score: 8.2 }, 108 - { title: "未来日记", score: 7.2 }, 109 - { title: "电波女与青春男", score: 7.1 }, 110 - { title: "这个是僵尸吗?", score: 6.8 }, 111 - { title: "赌博默示录 破戒录篇", score: 7.8 }, 112 - { title: "迷茫管家与懦弱的我", score: 6.6 }, 113 - { title: "纯白交响曲", score: 6.5 }, 114 - { title: "神的记事本", score: 6.7 }, 115 - { title: "BLOOD-C", score: 6 }, 116 - { title: "丹特丽安的书架", score: 7.1 }, 101 + { titleZh: "命运石之门", titleEn: "Steins;Gate", score: 8.8 }, 102 + { titleZh: "日常", titleEn: "Nichijou", score: 8.5 }, 103 + { titleZh: "Fate/Zero", titleEn: "Fate/Zero", score: 8.1 }, 104 + { titleZh: "魔法少女小圆", titleEn: "Puella Magi Madoka Magica", score: 8.6 }, 105 + { titleZh: "回转企鹅罐", titleEn: "Penguindrum", score: 8 }, 106 + { titleZh: "摇曳百合", titleEn: "YuruYuri", score: 7.6 }, 107 + { titleZh: "我们仍未知道那天所看见的花的名字。", titleEn: "AnoHana", score: 7.6 }, 108 + { titleZh: "罪恶王冠", titleEn: "Guilty Crown", score: 6.5 }, 109 + { titleZh: "花开伊吕波", titleEn: "Hanasaku Iroha", score: 7.5 }, 110 + { titleZh: "偶像大师", titleEn: "The Idolmaster", score: 8.3 }, 111 + { titleZh: "GOSICK", titleEn: "GOSICK", score: 7.3 }, 112 + { titleZh: "我的朋友很少", titleEn: "Haganai", score: 6.8 }, 113 + { titleZh: "猎人", titleEn: "Hunter x Hunter", score: 8.2 }, 114 + { titleZh: "未来日记", titleEn: "Future Diary", score: 7.2 }, 115 + { titleZh: "电波女与青春男", titleEn: "Ground Control to Psychoelectric Girl", score: 7.1 }, 116 + { titleZh: "这个是僵尸吗?", titleEn: "Is This a Zombie?", score: 6.8 }, 117 + { titleZh: "赌博默示录 破戒录篇", titleEn: "Kaiji: Against All Rules", score: 7.8 }, 118 + { titleZh: "迷茫管家与懦弱的我", titleEn: "Mayo Chiki!", score: 6.6 }, 119 + { titleZh: "纯白交响曲", titleEn: "Mashiro-iro Symphony", score: 6.5 }, 120 + { titleZh: "神的记事本", titleEn: "Heaven's Memo Pad", score: 6.7 }, 121 + { titleZh: "BLOOD-C", titleEn: "BLOOD-C", score: 6 }, 122 + { titleZh: "丹特丽安的书架", titleEn: "The Mystic Archives of Dantalian", score: 7.1 }, 117 123 ], 118 124 "2012": [ 119 - { title: "冰菓", score: 8.2 }, 120 - { title: "JOJO的奇妙冒险", score: 7.8 }, 121 - { title: "男子高中生的日常", score: 7.9 }, 122 - { title: "中二病也要谈恋爱!", score: 7.4 }, 123 - { title: "来自新世界", score: 8.2 }, 124 - { title: "伪物语", score: 7.8 }, 125 - { title: "Another", score: 7 }, 126 - { title: "樱花庄的宠物女孩", score: 7.4 }, 127 - { title: "心理测量者", score: 7.9 }, 128 - { title: "恶魔高校 D×D", score: 6.9 }, 129 - { title: "刀剑神域", score: 7.3 }, 130 - { title: "人类衰退之后", score: 7.9 }, 131 - { title: "Little Busters!", score: 7.1 }, 132 - { title: "潜行吧!奈亚子", score: 7 }, 133 - { title: "邻座的怪同学", score: 7.2 }, 134 - { title: "猫物语(黑)", score: 7.7 }, 135 - { title: "少女与战车", score: 7.6 }, 136 - { title: "心灵链环", score: 7.4 }, 137 - { title: "TARI TARI", score: 7.3 }, 138 - { title: "谜样女友X", score: 7 }, 139 - { title: "就算是哥哥只要有爱就没问题对吧", score: 5.9 }, 140 - { title: "散华礼弥", score: 6.8 }, 125 + { titleZh: "冰菓", titleEn: "Hyouka", score: 8.2 }, 126 + { titleZh: "JOJO的奇妙冒险", titleEn: "JoJo's Bizarre Adventure", score: 7.8 }, 127 + { titleZh: "男子高中生的日常", titleEn: "Daily Lives of High School Boys", score: 7.9 }, 128 + { titleZh: "中二病也要谈恋爱!", titleEn: "Love, Chunibyo & Other Delusions!", score: 7.4 }, 129 + { titleZh: "来自新世界", titleEn: "From the New World", score: 8.2 }, 130 + { titleZh: "伪物语", titleEn: "Nisemonogatari", score: 7.8 }, 131 + { titleZh: "Another", titleEn: "Another", score: 7 }, 132 + { titleZh: "樱花庄的宠物女孩", titleEn: "The Pet Girl of Sakurasou", score: 7.4 }, 133 + { titleZh: "心理测量者", titleEn: "Psychi-Pass", score: 7.9 }, 134 + { titleZh: "恶魔高校 D×D", titleEn: "High School DxD", score: 6.9 }, 135 + { titleZh: "刀剑神域", titleEn: "Sword Art Online", score: 7.3 }, 136 + { titleZh: "人类衰退之后", titleEn: "Humanity Has Declined", score: 7.9 }, 137 + { titleZh: "Little Busters!", titleEn: "Little Busters!", score: 7.1 }, 138 + { titleZh: "潜行吧!奈亚子", titleEn: "Nyaruko: Crawling with Love", score: 7 }, 139 + { titleZh: "邻座的怪同学", titleEn: "My Little Monster", score: 7.2 }, 140 + { titleZh: "猫物语(黑)", titleEn: "Nekomonogatari (Black)", score: 7.7 }, 141 + { titleZh: "少女与战车", titleEn: "Girls und Panzer", score: 7.6 }, 142 + { titleZh: "心灵链环", titleEn: "Kokoro Connect", score: 7.4 }, 143 + { titleZh: "TARI TARI", titleEn: "TARI TARI", score: 7.3 }, 144 + { titleZh: "谜样女友X", titleEn: "Mysterious Girlfriend X", score: 7 }, 145 + { titleZh: "就算是哥哥只要有爱就没问题对吧", titleEn: "OniAi", score: 5.9 }, 146 + { titleZh: "散华礼弥", titleEn: "Sankarea: Undying Love", score: 6.8 }, 141 147 ], 142 148 "2013": [ 143 - { title: "进击的巨人", score: 8.2 }, 144 - { title: "斩服少女", score: 8.1 }, 145 - { title: "我的青春恋爱物语果然有问题", score: 7.5 }, 146 - { title: "悠哉日常大王", score: 8 }, 147 - { title: "玉子市场", score: 7.2 }, 148 - { title: "向山进发", score: 7.1 }, 149 - { title: "约会大作战", score: 6.6 }, 150 - { title: "噬血狂袭", score: 6.6 }, 151 - { title: "来自风平浪静的明天", score: 7.5 }, 152 - { title: "我的妹妹哪有这么可爱。", score: 6.9 }, 153 - { title: "我不受欢迎,怎么想都是你们的错!", score: 6.9 }, 154 - { title: "境界的彼方", score: 6.8 }, 155 - { title: "我的脑内选项正在全力妨碍学园恋爱喜剧", score: 6.6 }, 156 - { title: "Fate/kaleid liner 魔法少女☆伊莉雅", score: 6.9 }, 157 - { title: "GJ部", score: 6.9 }, 158 - { title: "弹丸论破 希望学园与绝望高中生", score: 6.6 }, 159 - { title: "黄金拼图", score: 7.3 }, 160 - { title: "Love Live!", score: 7.2 }, 161 - { title: "我女友与青梅竹马的惨烈修罗场", score: 6.4 }, 162 - { title: "我的朋友很少NEXT", score: 6.7 }, 149 + { titleZh: "进击的巨人", titleEn: "Attack on Titan", score: 8.2 }, 150 + { titleZh: "斩服少女", titleEn: "Kill la Kill", score: 8.1 }, 151 + { titleZh: "我的青春恋爱物语果然有问题", titleEn: "My Teen Romantic Comedy SNAF", score: 7.5 }, 152 + { titleZh: "悠哉日常大王", titleEn: "Non Non Biyori", score: 8 }, 153 + { titleZh: "玉子市场", titleEn: "Tamako Market", score: 7.2 }, 154 + { titleZh: "向山进发", titleEn: "Yama no Susume", score: 7.1 }, 155 + { titleZh: "约会大作战", titleEn: "Date A Live", score: 6.6 }, 156 + { titleZh: "噬血狂袭", titleEn: "Strike the Blood", score: 6.6 }, 157 + { titleZh: "来自风平浪静的明天", titleEn: "Nagi-Asu: A Lull in the Sea", score: 7.5 }, 158 + { titleZh: "我的妹妹哪有这么可爱。2", titleEn: "Oreimo 2", score: 6.9 }, 159 + { titleZh: "我不受欢迎,怎么想都是你们的错!", titleEn: "WataMote", score: 6.9 }, 160 + { titleZh: "境界的彼方", titleEn: "Beyond the Boundary", score: 6.8 }, 161 + { titleZh: "我的脑内选项正在全力妨碍学园恋爱喜剧", titleEn: "My Brain's Little Options Are Doing Their Best to Hinder My School Romance Comedy", score: 6.6 }, 162 + { titleZh: "Fate/kaleid liner 魔法少女☆伊莉雅", titleEn: "Fate/kaleid liner 魔法少女☆イリヤ", score: 6.9 }, 163 + { titleZh: "GJ部", titleEn: "GJ Club", score: 6.9 }, 164 + { titleZh: "弹丸论破 希望学园与绝望高中生", titleEn: "Danganronpa: The Animation", score: 6.6 }, 165 + { titleZh: "黄金拼图", titleEn: "Golden Time", score: 7.3 }, 166 + { titleZh: "Love Live!", titleEn: "Love Live!", score: 7.2 }, 167 + { titleZh: "我女友与青梅竹马的惨烈修罗场", titleEn: "Oreshura", score: 6.4 }, 168 + { titleZh: "我的朋友很少NEXT", titleEn: "Haganai NEXT", score: 6.7 }, 163 169 ], 164 170 "2014": [ 165 - { title: "白箱", score: 8.7 }, 166 - { title: "四月是你的谎言", score: 8 }, 167 - { title: "Fate/stay night [Unlimited Blade Works]", score: 7.5 }, 168 - { title: "游戏人生", score: 7.7 }, 169 - { title: "乒乓", score: 8.7 }, 170 - { title: "甘城光辉游乐园", score: 7 }, 171 - { title: "寄生兽 生命的准则", score: 8 }, 172 - { title: "伪恋", score: 7.1 }, 173 - { title: "月刊少女野崎君", score: 7.8 }, 174 - { title: "请问您今天要来点兔子吗?", score: 7.3 }, 175 - { title: "斩·赤红之瞳!", score: 6.6 }, 176 - { title: "太空丹迪", score: 8 }, 177 - { title: "妄想学生会*", score: 7.6 }, 178 - { title: "东京喰种", score: 6.7 }, 179 - { title: "凭物语", score: 7.5 }, 180 - { title: "灰色的果实", score: 7.1 }, 181 - { title: "花物语", score: 7.3 }, 182 - { title: "农林", score: 6.6 }, 183 - { title: "魔法科高校的劣等生", score: 5.8 }, 184 - { title: "野良神", score: 7.1 }, 171 + { titleZh: "白箱", titleEn: "Shirobako", score: 8.7 }, 172 + { titleZh: "四月是你的谎言", titleEn: "Your Lie in April", score: 8 }, 173 + { titleZh: "Fate/stay night [Unlimited Blade Works]", titleEn: "Fate/stay night [Unlimited Blade Works]", score: 7.5 }, 174 + { titleZh: "游戏人生", titleEn: "No Game No Life", score: 7.7 }, 175 + { titleZh: "乒乓", titleEn: "Ping Pong", score: 8.7 }, 176 + { titleZh: "甘城光辉游乐园", titleEn: "Amagi Brilliant Park", score: 7 }, 177 + { titleZh: "寄生兽 生命的准则", titleEn: "Parasyte -the maxim-", score: 8 }, 178 + { titleZh: "伪恋", titleEn: "Nisekoi", score: 7.1 }, 179 + { titleZh: "月刊少女野崎君", titleEn: "Monthly Girls' Nozaki-kun", score: 7.8 }, 180 + { titleZh: "请问您今天要来点兔子吗?", titleEn: "Is the Order a Rabbit?", score: 7.3 }, 181 + { titleZh: "斩·赤红之瞳!", titleEn: "Akame ga Kill!", score: 6.6 }, 182 + { titleZh: "太空丹迪", titleEn: "Space Dandy", score: 8 }, 183 + { titleZh: "妄想学生会*", titleEn: "Seitokai Yakuindomo", score: 7.6 }, 184 + { titleZh: "东京喰种", titleEn: "Tokyo Ghoul", score: 6.7 }, 185 + { titleZh: "凭物语", titleEn: "Owarimonogatari: End Tale", score: 7.5 }, 186 + { titleZh: "灰色的果实", titleEn: "The Fruit of Grisaia", score: 7.1 }, 187 + { titleZh: "花物语", titleEn: "Hanamonogatari ", score: 7.3 }, 188 + { titleZh: "农林", titleEn: "Nourin", score: 6.6 }, 189 + { titleZh: "魔法科高校的劣等生", titleEn: "The Irregular at Magic High School", score: 5.8 }, 190 + { titleZh: "野良神", titleEn: "Noragami", score: 7.1 }, 185 191 ], 186 192 "2015": [ 187 - { title: "路人女主的养成方法", score: 7.2 }, 188 - { title: "暗杀教室", score: 7.3 }, 189 - { title: "一拳超人", score: 8 }, 190 - { title: "新妹魔王的契约者", score: 5.8 }, 191 - { title: "夏洛特", score: 6.3 }, 192 - { title: "OVERLORD", score: 6.9 }, 193 - { title: "监狱学园", score: 7.3 }, 194 - { title: "可塑性记忆", score: 7 }, 195 - { title: "在地下城寻求邂逅是否搞错了什么", score: 6.8 }, 196 - { title: "干物妹!小埋", score: 6.8 }, 197 - { title: "吹响!悠风号", score: 8.3 }, 198 - { title: "终物语", score: 7.8 }, 199 - { title: "旋转少女", score: 7.4 }, 200 - { title: "落第骑士英雄谭", score: 6.5 }, 201 - { title: "没有黄段子存在的无聊世界", score: 6.1 }, 193 + { titleZh: "路人女主的养成方法", titleEn: "Saekano: How to Raise a Boring Girlfriend", score: 7.2 }, 194 + { titleZh: "暗杀教室", titleEn: "Assassination Classroom", score: 7.3 }, 195 + { titleZh: "一拳超人", titleEn: "One Punch Man", score: 8 }, 196 + { titleZh: "新妹魔王的契约者", titleEn: "The Testament of Sister New Devil", score: 5.8 }, 197 + { titleZh: "夏洛特", titleEn: "Charlotte", score: 6.3 }, 198 + { titleZh: "OVERLORD", titleEn: "Overlord", score: 6.9 }, 199 + { titleZh: "监狱学园", titleEn: "Prison School", score: 7.3 }, 200 + { titleZh: "可塑性记忆", titleEn: "Plastic Memories", score: 7 }, 201 + { titleZh: "在地下城寻求邂逅是否搞错了什么", titleEn: "Is it wrong to Try to Pick Up Girls in a Dungeon?", score: 6.8 }, 202 + { titleZh: "干物妹!小埋", titleEn: "Himouto! Umaru-chan", score: 6.8 }, 203 + { titleZh: "吹响!悠风号", titleEn: "Sound! Euphonium", score: 8.3 }, 204 + { titleZh: "终物语", titleEn: "Owarimonogatari", score: 7.8 }, 205 + { titleZh: "旋转少女", titleEn: "The Rolling Girls", score: 7.4 }, 206 + { titleZh: "落第骑士英雄谭", titleEn: "Chivalry of a Failed Knight", score: 6.5 }, 207 + { titleZh: "没有黄段子存在的无聊世界", titleEn: "Shimoneta", score: 6.1 }, 202 208 ], 203 209 "2016": [ 204 - { title: "为美好的世界献上祝福!", score: 7.6 }, 205 - { title: "3月的狮子", score: 8.3 }, 206 - { title: "ReLIFE", score: 7.7 }, 207 - { title: "齐木楠雄的灾难", score: 7.7 }, 208 - { title: "Re:从零开始的异世界生活", score: 7.4 }, 209 - { title: "只有我不存在的城市", score: 7.7 }, 210 - { title: "灵能百分百", score: 7.8 }, 211 - { title: "灰与幻想的格林姆迦尔", score: 7.5 }, 212 - { title: "这个美术社大有问题!", score: 7.3 }, 213 - { title: "轻拍翻转小魔女", score: 7.5 }, 214 - { title: "飞翔的魔女", score: 7.5 }, 215 - { title: "NEW GAME!", score: 7.4 }, 216 - { title: "在下坂本,有何贵干?", score: 6.5 }, 217 - { title: "昭和元禄落语心中", score: 8.2 }, 218 - { title: "无彩限的怪灵世界", score: 6.2 }, 219 - { title: "线上游戏的老婆不可能是女生?", score: 6 }, 220 - { title: "亚人", score: 7.3 }, 221 - { title: "甲铁城的卡巴内利", score: 5.9 }, 222 - { title: "剑风传奇", score: 6.8 }, 210 + { titleZh: "为美好的世界献上祝福!", titleEn: "Kono Suba", score: 7.6 }, 211 + { titleZh: "3月的狮子", titleEn: "March Comes in Like a Lion", score: 8.3 }, 212 + { titleZh: "ReLIFE", titleEn: "ReLIFE", score: 7.7 }, 213 + { titleZh: "齐木楠雄的灾难", titleEn: "The Disastrous Life of Saiki K.", score: 7.7 }, 214 + { titleZh: "Re:从零开始的异世界生活", titleEn: "Re:Zero ", score: 7.4 }, 215 + { titleZh: "只有我不存在的城市", titleEn: "Erased", score: 7.7 }, 216 + { titleZh: "灵能百分百", titleEn: "Mob Psycho 100", score: 7.8 }, 217 + { titleZh: "灰与幻想的格林姆迦尔", titleEn: "Grimgar of Fantasy and Ash", score: 7.5 }, 218 + { titleZh: "这个美术社大有问题!", titleEn: "This Art Club Has a Problem!", score: 7.3 }, 219 + { titleZh: "轻拍翻转小魔女", titleEn: "Flip Flappers", score: 7.5 }, 220 + { titleZh: "飞翔的魔女", titleEn: "Flying Witch", score: 7.5 }, 221 + { titleZh: "NEW GAME!", titleEn: "NEW GAME!", score: 7.4 }, 222 + { titleZh: "在下坂本,有何贵干?", titleEn: "Haven't You Heard? I'm Sakamoto", score: 6.5 }, 223 + { titleZh: "昭和元禄落语心中", titleEn: "Descending Stories: Showa Genroku Rakugo Shinju", score: 8.2 }, 224 + { titleZh: "无彩限的怪灵世界", titleEn: "Myriad Colors Phantom World", score: 6.2 }, 225 + { titleZh: "线上游戏的老婆不可能是女生?", titleEn: "And You Thought There Is Never a Girl Online? ", score: 6 }, 226 + { titleZh: "亚人", titleEn: "Ajin: Demi-Human", score: 7.3 }, 227 + { titleZh: "甲铁城的卡巴内利", titleEn: "Kabaneri of the Iron Fortress", score: 5.9 }, 228 + { titleZh: "剑风传奇", titleEn: "Berserk", score: 6.8 }, 223 229 ], 224 230 "2017": [ 225 - { title: "少女终末旅行", score: 8.1 }, 226 - { title: "来自深渊", score: 8.2 }, 227 - { title: "小林家的龙女仆", score: 7.4 }, 228 - { title: "狂赌之渊", score: 7 }, 229 - { title: "末日时在做什么?有没有空?可以来拯救吗?", score: 7.6 }, 230 - { title: "月色真美", score: 7.9 }, 231 - { title: "重启咲良田", score: 7.9 }, 232 - { title: "BanG Dream!", score: 6.4 }, 233 - { title: "幼女战记", score: 7.2 }, 234 - { title: "小魔女学园", score: 7.7 }, 235 - { title: "Just Because!", score: 7.3 }, 236 - { title: "埃罗芒阿老师", score: 6.6 }, 237 - { title: "人渣的本愿", score: 6.6 }, 238 - { title: "珈百璃的堕落", score: 7.1 }, 239 - { title: "笨女孩", score: 6.6 }, 240 - { title: "黑色五叶草", score: 6.5 }, 241 - { title: "如果有妹妹就好了。", score: 6.6 }, 242 - { title: "徒然喜欢你", score: 7.1 }, 243 - { title: "不正经的魔术讲师与禁忌教典", score: 6.2 }, 231 + { titleZh: "少女终末旅行", titleEn: "Girls' Last Tour", score: 8.1 }, 232 + { titleZh: "来自深渊", titleEn: "Made in Abyss", score: 8.2 }, 233 + { titleZh: "小林家的龙女仆", titleEn: "Miss Kobayashi's Dragon Maid", score: 7.4 }, 234 + { titleZh: "狂赌之渊", titleEn: "Kakegurui", score: 7 }, 235 + { titleZh: "末日时在做什么?有没有空?可以来拯救吗?", titleEn: "WorldEnd", score: 7.6 }, 236 + { titleZh: "月色真美", titleEn: "Tsuki ga Kirei", score: 7.9 }, 237 + { titleZh: "重启咲良田", titleEn: "Sagrada Reset", score: 7.9 }, 238 + { titleZh: "BanG Dream!", titleEn: "BanG Dream!", score: 6.4 }, 239 + { titleZh: "幼女战记", titleEn: "Saga of Tanya the Evil", score: 7.2 }, 240 + { titleZh: "小魔女学园", titleEn: "Little Witch Academia", score: 7.7 }, 241 + { titleZh: "Just Because!", titleEn: "Just Because!", score: 7.3 }, 242 + { titleZh: "埃罗芒阿老师", titleEn: "Eromanga Sensei", score: 6.6 }, 243 + { titleZh: "人渣的本愿", titleEn: "Scum's Wish", score: 6.6 }, 244 + { titleZh: "珈百璃的堕落", titleEn: "Gabriel DropOut", score: 7.1 }, 245 + { titleZh: "笨女孩", titleEn: "Aho-Girl", score: 6.6 }, 246 + { titleZh: "黑色五叶草", titleEn: "Black Clover", score: 6.5 }, 247 + { titleZh: "如果有妹妹就好了。", titleEn: "A Sister's All You Need", score: 6.6 }, 248 + { titleZh: "徒然喜欢你", titleEn: "Tsuredure Children", score: 7.1 }, 249 + { titleZh: "不正经的魔术讲师与禁忌教典", titleEn: "Akashic Records of Bastard Magic Instructor", score: 6.2 }, 244 250 ], 245 251 "2018": [ 246 - { title: "摇曳露营△", score: 8.2 }, 247 - { title: "碧蓝之海", score: 7.8 }, 248 - { title: "赛马娘 Pretty Derby", score: 7 }, 249 - { title: "紫罗兰永恒花园", score: 7.5 }, 250 - { title: "强风吹拂", score: 8.3 }, 251 - { title: "少女☆歌剧 Revue Starlight", score: 7.9 }, 252 - { title: "擅长捉弄的高木同学", score: 7.5 }, 253 - { title: "佐贺偶像是传奇", score: 7.8 }, 254 - { title: "比宇宙更远的地方", score: 8.2 }, 255 - { title: "青春笨蛋少年不做兔女郎学姐的梦", score: 7.4 }, 256 - { title: "哥布林杀手", score: 6.7 }, 257 - { title: "终将成为你", score: 7.8 }, 258 - { title: "DARLING in the FRANXX", score: 6.2 }, 259 - { title: "来玩游戏吧", score: 7.6 }, 260 - { title: "邪神与厨二病少女", score: 7 }, 261 - { title: "恋如雨止", score: 7.5 }, 262 - { title: "关于我转生变成史莱姆这档事", score: 6.6 }, 263 - { title: "黄金神威", score: 7.5 }, 252 + { titleZh: "摇曳露营△", titleEn: "Yuru Camp△", score: 8.2 }, 253 + { titleZh: "碧蓝之海", titleEn: "Grand Blue", score: 7.8 }, 254 + { titleZh: "赛马娘 Pretty Derby", titleEn: "Umamusume Pretty Derby", score: 7 }, 255 + { titleZh: "紫罗兰永恒花园", titleEn: "Violet Evergarden", score: 7.5 }, 256 + { titleZh: "强风吹拂", titleEn: "Run with the Wind", score: 8.3 }, 257 + { titleZh: "少女☆歌剧 Revue Starlight", titleEn: "Shōjo☆gekijō Revue Starlight", score: 7.9 }, 258 + { titleZh: "擅长捉弄的高木同学", titleEn: "Teasing Master Takagi-san", score: 7.5 }, 259 + { titleZh: "佐贺偶像是传奇", titleEn: "Zombie Land Saga", score: 7.8 }, 260 + { titleZh: "比宇宙更远的地方", titleEn: "A Place Further Than the Universe", score: 8.2 }, 261 + { titleZh: "青春笨蛋少年不做兔女郎学姐的梦", titleEn: "Rascal Does Not Dream of Bunny Girl Senpai", score: 7.4 }, 262 + { titleZh: "哥布林杀手", titleEn: "Goblin Slayer", score: 6.7 }, 263 + { titleZh: "终将成为你", titleEn: "Bloom into You", score: 7.8 }, 264 + { titleZh: "DARLING in the FRANXX", titleEn: "DARLING in the FRANXX", score: 6.2 }, 265 + { titleZh: "来玩游戏吧", titleEn: "Gamers!", score: 7.6 }, 266 + { titleZh: "邪神与厨二病少女", titleEn: "Dropkick on My Devil!", score: 7 }, 267 + { titleZh: "恋如雨止", titleEn: "After the Rain", score: 7.5 }, 268 + { titleZh: "关于我转生变成史莱姆这档事", titleEn: "That Time I Got Reincarnated as a Slime", score: 6.6 }, 269 + { titleZh: "黄金神威", titleEn: "Golden Kamuy", score: 7.5 }, 264 270 ], 265 271 "2019": [ 266 - { title: "冰海战记", score: 8.3 }, 267 - { title: "辉夜大小姐想让我告白~天才们的恋爱头脑战~", score: 7.8 }, 268 - { title: "街角魔族", score: 7.5 }, 269 - { title: "鬼灭之刃", score: 7.3 }, 270 - { title: "炎炎消防队", score: 6.5 }, 271 - { title: "女高中生的无所事事", score: 7.6 }, 272 - { title: "慎重勇者 ~这个勇者明明超强却过分慎重~", score: 6.9 }, 273 - { title: "天使降临到了我身边!", score: 7.3 }, 274 - { title: "不吉波普不笑", score: 7.3 }, 275 - { title: "笨拙之极的上野", score: 6.5 }, 276 - { title: "五等分的新娘", score: 6 }, 277 - { title: "约定的梦幻岛", score: 7.6 }, 278 - { title: "只要可爱即使是变态你也会喜欢我吧?", score: 6.1 }, 279 - { title: "Fate/Grand Order -绝对魔兽战线巴比伦尼亚-", score: 6.8 }, 280 - { title: "家有女友", score: 6.3 }, 281 - { title: "君主·埃尔梅罗二世事件簿 魔眼收集列车 Grace note", score: 6.7 }, 282 - { title: "石纪元", score: 7.2 }, 272 + { titleZh: "冰海战记", titleEn: "Vinland Saga", score: 8.3 }, 273 + { titleZh: "辉夜大小姐想让我告白~天才们的恋爱头脑战~", titleEn: "Kaguya-sama wa Kokurasetai: Tensai-tachi no Renai Zunōsen", score: 7.8 }, 274 + { titleZh: "街角魔族", titleEn: "The Demon Girl Next Door", score: 7.5 }, 275 + { titleZh: "鬼灭之刃", titleEn: "Demon Slayer", score: 7.3 }, 276 + { titleZh: "炎炎消防队", titleEn: "Fire Force", score: 6.5 }, 277 + { titleZh: "女高中生的无所事事", titleEn: "Wasteful Days of High School Girls", score: 7.6 }, 278 + { titleZh: "慎重勇者 ~这个勇者明明超强却过分慎重~", titleEn: "Cautious Hero: ", score: 6.9 }, 279 + { titleZh: "天使降临到了我身边!", titleEn: "Angels' 3Piece!", score: 7.3 }, 280 + { titleZh: "不吉波普不笑", titleEn: "Boogiepop and Others", score: 7.3 }, 281 + { titleZh: "笨拙之极的上野", titleEn: "How Clumsy You Are, Miss Ueno", score: 6.5 }, 282 + { titleZh: "五等分的新娘", titleEn: "The Quintessential Quintuplets", score: 6 }, 283 + { titleZh: "约定的梦幻岛", titleEn: "Yakusoku no Neverland", score: 7.6 }, 284 + { titleZh: "只要可爱即使是变态你也会喜欢我吧?", titleEn: "Hensuki", score: 6.1 }, 285 + { titleZh: "Fate/Grand Order -绝对魔兽战线巴比伦尼亚-", titleEn: "Fate/Grand Order -Absolute Demonic Front: Babylonia-", score: 6.8 }, 286 + { titleZh: "家有女友", titleEn: "Kanojo, Okarishimasu", score: 6.3 }, 287 + { titleZh: "君主·埃尔梅罗二世事件簿 魔眼收集列车 Grace note", titleEn: "The Case Files of Lord El-Melloi II: Rail Zeppelin Grace Note", score: 6.7 }, 288 + { titleZh: "石纪元", titleEn: "Dr. Stone", score: 7.2 }, 283 289 ], 284 290 "2020": [ 285 - { title: "异种族风俗娘评鉴指南", score: 7.7 }, 286 - { title: "魔女之旅", score: 7.1 }, 287 - { title: "安达与岛村", score: 7.3 }, 288 - { title: "异度侵入", score: 7.5 }, 289 - { title: "别对映像研出手!", score: 8.1 }, 290 - { title: "咒术回战", score: 7.1 }, 291 - { title: "总之就是非常可爱", score: 6.3 }, 292 - { title: "隐瞒之事", score: 7.7 }, 293 - { title: "虚构推理", score: 6.3 }, 294 - { title: "恋爱小行星", score: 6.9 }, 295 - { title: "你与我最后的战场,亦或是世界起始的圣战", score: 5.5 }, 296 - { title: "邪神与厨二病少女’", score: 7.3 }, 297 - { title: "转生成为了只有乙女游戏破灭Flag的邪恶大小姐", score: 6.5 }, 298 - { title: "在魔王城说晚安", score: 7 }, 299 - { title: "租借女友", score: 5.8 }, 291 + { titleZh: "异种族风俗娘评鉴指南", titleEn: "Ishuzoku Reviewers", score: 7.7 }, 292 + { titleZh: "魔女之旅", titleEn: "Wandering Witch: The Journey of Elaina", score: 7.1 }, 293 + { titleZh: "安达与岛村", titleEn: "Adachi and Shimamura", score: 7.3 }, 294 + { titleZh: "异度侵入", titleEn: "ID:INVADED", score: 7.5 }, 295 + { titleZh: "别对映像研出手!", titleEn: "Keep Your Hands Off Eizouken!", score: 8.1 }, 296 + { titleZh: "咒术回战", titleEn: "Jujutsu Kaisen", score: 7.1 }, 297 + { titleZh: "总之就是非常可爱", titleEn: "Tonikawa: Over the Moon For You", score: 6.3 }, 298 + { titleZh: "隐瞒之事", titleEn: "Kakushigoto", score: 7.7 }, 299 + { titleZh: "虚构推理", titleEn: "In/Spectre", score: 6.3 }, 300 + { titleZh: "恋爱小行星", titleEn: "Koisuru Asteroid", score: 6.9 }, 301 + { titleZh: "你与我最后的战场,亦或是世界起始的圣战", titleEn: "Our Last Crusade or the Rise of a New World", score: 5.5 }, 302 + { titleZh: "邪神与厨二病少女' ", titleEn: "Dropkick on My Devil!", score: 7.3 }, 303 + { titleZh: "转生成为了只有乙女游戏破灭Flag的邪恶大小姐", titleEn: "My Next Life as a Villainess: All Routes Lead to Doom!", score: 6.5 }, 304 + { titleZh: "在魔王城说晚安", titleEn: "Sleepy Princess in the Demon Castle", score: 7 }, 305 + { titleZh: "租借女友", titleEn: "Rent-A-Girlfriend", score: 5.8 }, 300 306 ], 301 307 "2021": [ 302 - { title: "86 -不存在的战区-", score: 7.6 }, 303 - { title: "无职转生~", score: 7.9 }, 304 - { title: "回复术士的重来人生", score: 6.2 }, 305 - { title: "奇巧计程车", score: 8.5 }, 306 - { title: "打了300年的史莱姆,不知不觉就练到了满级", score: 6.3 }, 307 - { title: "漂流少年", score: 7.8 }, 308 - { title: "堀与宫村", score: 6.8 }, 309 - { title: "派遣战斗员!", score: 6.3 }, 310 - { title: "古见同学有交流障碍症", score: 7 }, 311 - { title: "奇蛋物语", score: 6.8 }, 312 - { title: "我们的重制人生", score: 6.4 }, 313 - { title: "看得见的女孩", score: 6.8 }, 314 - { title: "异世界迷宫黑心企业", score: 6.7 }, 315 - { title: "女神宿舍的宿管君。", score: 5.8 }, 308 + { titleZh: "86 -不存在的战区-", titleEn: "86 -Eighty-Six-", score: 7.6 }, 309 + { titleZh: "无职转生~", titleEn: "Mushoku Tensei: Jobless Reincarnation", score: 7.9 }, 310 + { titleZh: "回复术士的重来人生", titleEn: "Redo of Healer", score: 6.2 }, 311 + { titleZh: "奇巧计程车", titleEn: "Odd Taxi", score: 8.5 }, 312 + { titleZh: "打了300年的史莱姆,不知不觉就练到了满级", titleEn: "I’ve Been Killing Slimes for 300 Years and Maxed Out My Level", score: 6.3 }, 313 + { titleZh: "漂流少年", titleEn: "Sonny Boy", score: 7.8 }, 314 + { titleZh: "堀与宫村", titleEn: "Horimiya", score: 6.8 }, 315 + { titleZh: "派遣战斗员!", titleEn: "Combatants Will Be Dispatched!", score: 6.3 }, 316 + { titleZh: "古见同学有交流障碍症", titleEn: "Komi Can't Communicate", score: 7 }, 317 + { titleZh: "奇蛋物语", titleEn: "Wonder Egg Priority", score: 6.8 }, 318 + { titleZh: "我们的重制人生", titleEn: "Remake Our Life!", score: 6.4 }, 319 + { titleZh: "看得见的女孩", titleEn: "Mieruko-chan", score: 6.8 }, 320 + { titleZh: "异世界迷宫黑心企业", titleEn: "The Dungeon of Black Company", score: 6.7 }, 321 + { titleZh: "女神宿舍的宿管君。", titleEn: "Megami-ryō no Ryōbo-kun", score: 5.8 }, 316 322 ], 317 323 "2022": [ 318 - { title: "孤独摇滚!", score: 8.4 }, 319 - { title: "莉可丽丝", score: 6.3 }, 320 - { title: "想要成为影之实力者!", score: 7.1 }, 321 - { title: "夏日重现", score: 7.5 }, 322 - { title: "异世界舅舅", score: 7.6 }, 323 - { title: "更衣人偶坠入爱河", score: 7.2 }, 324 - { title: "彻夜之歌", score: 7.4 }, 325 - { title: "测不准的阿波连同学", score: 6.4 }, 326 - { title: "间谍过家家", score: 7.2 }, 327 - { title: "不道德公会", score: 7.1 }, 328 - { title: "链锯人", score: 6.9 }, 329 - { title: "明日同学的水手服", score: 7.5 }, 330 - { title: "契约之吻", score: 6.9 }, 331 - { title: "相合之物", score: 7.8 }, 324 + { titleZh: "孤独摇滚!", titleEn: "Bocchi the Rock!", score: 8.4 }, 325 + { titleZh: "莉可丽丝", titleEn: "Lycoris Recoil", score: 6.3 }, 326 + { titleZh: "想要成为影之实力者!", titleEn: "The Eminence in Shadow", score: 7.1 }, 327 + { titleZh: "夏日重现", titleEn: "Summer Time Rendering", score: 7.5 }, 328 + { titleZh: "异世界舅舅", titleEn: "Uncle from Another World", score: 7.6 }, 329 + { titleZh: "更衣人偶坠入爱河", titleEn: "My Dress-Up Darling", score: 7.2 }, 330 + { titleZh: "彻夜之歌", titleEn: "Call of the Night", score: 7.4 }, 331 + { titleZh: "测不准的阿波连同学", titleEn: "Aharen Is Indecipherable", score: 6.4 }, 332 + { titleZh: "间谍过家家", titleEn: "SPY×FAMILY", score: 7.2 }, 333 + { titleZh: "不道德公会", titleEn: "Immoral Guild", score: 7.1 }, 334 + { titleZh: "链锯人", titleEn: "Chainsaw Man", score: 6.9 }, 335 + { titleZh: "明日同学的水手服", titleEn: "Akebi's Sailor Uniform", score: 7.5 }, 336 + { titleZh: "契约之吻", titleEn: "Engage Kiss", score: 6.9 }, 337 + { titleZh: "相合之物", titleEn: "Sasaki and Miyano", score: 7.8 }, 332 338 ], 333 339 "2023": [ 334 - { title: "葬送的芙莉莲", score: 8.5 }, 335 - { title: "药屋少女的呢喃", score: 7.5 }, 336 - { title: "BanG Dream! It's MyGO!!!!!", score: 8.1 }, 337 - { title: "我心里危险的东西", score: 7.8 }, 338 - { title: "超超超超超喜欢你的100个女朋友", score: 7.3 }, 339 - { title: "别当欧尼酱了!", score: 7.6 }, 340 - { title: "跃动青春", score: 7.7 }, 341 - { title: "宝可梦 地平线", score: 7.5 }, 342 - { title: "香格里拉·弗陇提亚~屎作猎人向神作发起挑战~", score: 6.4 }, 343 - { title: "无神世界的神明活动", score: 6.8 }, 344 - { title: "我推的孩子", score: 7.4 }, 345 - { title: "天国大魔境", score: 7.8 }, 346 - { title: "异世界悠闲农家", score: 6.4 }, 340 + { titleZh: "葬送的芙莉莲", titleEn: "Frieren: Beyond Journey's End", score: 8.5 }, 341 + { titleZh: "药屋少女的呢喃", titleEn: "The Apothecary Diaries", score: 7.5 }, 342 + { titleZh: "BanG Dream! It's MyGO!!!!!", titleEn: "BanG Dream! It's MyGO!!!!!", score: 8.1 }, 343 + { titleZh: "我心里危险的东西", titleEn: "The Dangers in My Heart", score: 7.8 }, 344 + { titleZh: "超超超超超喜欢你的100个女朋友", titleEn: "The 100 Girlfriends Who Really Love You", score: 7.3 }, 345 + { titleZh: "别当欧尼酱了!", titleEn: "Onimai: I'm Now Your Sister!", score: 7.6 }, 346 + { titleZh: "跃动青春", titleEn: "Skip and Loafer", score: 7.7 }, 347 + { titleZh: "宝可梦 地平线", titleEn: "Pokémon Horizons", score: 7.5 }, 348 + { titleZh: "香格里拉·弗陇提亚~屎作猎人向神作发起挑战~", titleEn: "Shangri-La Frontier", score: 6.4 }, 349 + { titleZh: "无神世界的神明活动", titleEn: "KamiKatsu: Working for God in a Godless World", score: 6.8 }, 350 + { titleZh: "我推的孩子", titleEn: "Oshi no Ko", score: 7.4 }, 351 + { titleZh: "天国大魔境", titleEn: "Heavenly Delusion", score: 7.8 }, 352 + { titleZh: "异世界悠闲农家", titleEn: "Farming Life in Another World", score: 6.4 }, 347 353 ], 348 354 "2024": [ 349 - { title: "败犬女主太多了!", score: 8 }, 350 - { title: "GIRLS BAND CRY", score: 7.6 }, 351 - { title: "胆大党", score: 7.5 }, 352 - { title: "义妹生活", score: 7.3 }, 353 - { title: "迷宫饭", score: 7.8 }, 354 - { title: "我独自升级", score: 6.5 }, 355 - { title: "小市民系列", score: 6.1 }, 356 - { title: "梦想成为魔法少女", score: 7 }, 357 - { title: "青之箱", score: 6.8 }, 358 - { title: "2.5次元的诱惑", score: 6.7 }, 359 - { title: "地。 ―关于地球的运动―", score: 6.2 }, 360 - { title: "失忆投捕", score: 7.9 }, 361 - { title: "不时轻声地以俄语遮羞的邻座艾莉同学", score: 5.6 }, 362 - { title: "悲喜渔生", score: 7.3 }, 363 - { title: "亚托莉 -我挚爱的时光-", score: 6.3 }, 364 - { title: "缘结甘神家", score: 5.9 }, 355 + { titleZh: "败犬女主太多了!", titleEn: "Too Many Losing Heroines!", score: 8 }, 356 + { titleZh: "GIRLS BAND CRY", titleEn: "GIRLS BAND CRY", score: 7.6 }, 357 + { titleZh: "胆大党", titleEn: "Dandadan", score: 7.5 }, 358 + { titleZh: "义妹生活", titleEn: "Gimai Seikatsu", score: 7.3 }, 359 + { titleZh: "迷宫饭", titleEn: "Delicious in Dungeon", score: 7.8 }, 360 + { titleZh: "我独自升级", titleEn: "Solo Leveling", score: 6.5 }, 361 + { titleZh: "小市民系列", titleEn: "Shoshimin", score: 6.1 }, 362 + { titleZh: "梦想成为魔法少女", titleEn: "Gushing over Magical Girls", score: 7 }, 363 + { titleZh: "青之箱", titleEn: "Blue Box", score: 6.8 }, 364 + { titleZh: "2.5次元的诱惑", titleEn: "2.5 Dimensional Seduction", score: 6.7 }, 365 + { titleZh: "地。 ―关于地球的运动―", titleEn: "Orb: On the Movements of the Earth", score: 6.2 }, 366 + { titleZh: "失忆投捕", titleEn: "The Elusive Samurai", score: 7.9 }, 367 + { titleZh: "不时轻声地以俄语遮羞的邻座艾莉同学", titleEn: "Alya Sometimes Hides Her Feelings in Russian", score: 5.6 }, 368 + { titleZh: "悲喜渔生", titleEn: "Fisherman's Songs", score: 7.3 }, 369 + { titleZh: "亚托莉 -我挚爱的时光-", titleEn: "Atri: My Dear Moments", score: 6.3 }, 370 + { titleZh: "缘结甘神家", titleEn: "The Elusive Samurai", score: 5.9 }, 365 371 ], 372 + }; 373 + 374 + // 添加一个辅助函数来根据语言获取动画标题 375 + export const getAnimeTitle = (anime: AnimeItem, language: 'zh' | 'en'): string => { 376 + return language === 'zh' ? anime.titleZh : anime.titleEn; 366 377 }; 367 378 368 379 export default data;
+1 -1
index.html
··· 3 3 <head> 4 4 <meta charset="UTF-8"> 5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 - <title>动画世代</title> 6 + <title>Anime Sedai | 动画世代</title> 7 7 <link rel="stylesheet" href="/src/index.css"> 8 8 </head> 9 9 <body>
+31
src/LanguageToggle.tsx
··· 1 + import { useI18n } from './i18n-context' 2 + 3 + export const LanguageToggle = () => { 4 + const { language, setLanguage, t } = useI18n() 5 + 6 + return ( 7 + <div className="flex items-center gap-2"> 8 + <span className="text-sm text-gray-600">{t('language')}:</span> 9 + <button 10 + className={`px-3 py-1 text-sm rounded transition-colors ${ 11 + language === 'zh' 12 + ? 'bg-blue-500 text-white' 13 + : 'bg-gray-200 text-gray-700 hover:bg-gray-300' 14 + }`} 15 + onClick={() => setLanguage('zh')} 16 + > 17 + {t('chinese')} 18 + </button> 19 + <button 20 + className={`px-3 py-1 text-sm rounded transition-colors ${ 21 + language === 'en' 22 + ? 'bg-blue-500 text-white' 23 + : 'bg-gray-200 text-gray-700 hover:bg-gray-300' 24 + }`} 25 + onClick={() => setLanguage('en')} 26 + > 27 + {t('english')} 28 + </button> 29 + </div> 30 + ) 31 + }
+148 -140
src/app.tsx
··· 1 - import { useMemo, useRef, useState } from "react" 2 - import animeData from "../anime-data" 1 + import { useMemo, useRef, useState, useEffect } from "react" 2 + import animeData, { getAnimeTitle } from "../anime-data" 3 3 import { domToBlob } from "modern-screenshot" 4 4 import { toast } from "sonner" 5 5 import { usePersistState } from "./hooks" 6 + import { useI18n } from "./i18n-context" 7 + import { LanguageToggle } from "./LanguageToggle" 8 + import { getPromptTemplate } from "./i18n" 6 9 7 10 export const App = () => { 11 + const { t, language } = useI18n() 8 12 const [selectedAnime, setSelectedAnime] = usePersistState<string[]>( 9 13 "selectedAnime", 10 14 [] 11 15 ) 12 16 13 17 const wrapper = useRef<HTMLDivElement>(null) 18 + 19 + useEffect(() => { 20 + document.title = t('title') 21 + }, [language, t]) 14 22 15 23 const imageToBlob = async () => { 16 24 if (!wrapper.current) return ··· 59 67 60 68 const [promptType, setPromptType] = useState<"normal" | "zako">("zako") 61 69 const prompt = useMemo(() => { 62 - const preset = 63 - promptType === "normal" 64 - ? `以下是用户的动画观看记录,请生成一个锐评。` 65 - : `你是一个精通二次元文化的傲娇雌小鬼,需要根据用户提供的动画观看记录,用雌小鬼惯用的嘲讽语气混合动画圈梗生成锐评报告。要求: 66 - 1. 结构模板 67 - - 列出5-6个嘲讽段落 68 - - 每个段落的所有内容请务必都包含在 ">> 标签" 开始的一行之后!! 69 - - 每一个嘲讽段落的主题都应当不同,且应当尖锐 70 - - 你应当大量地使用“杂鱼”、“❤”、“杂鱼~”、“杂鱼❤~”,“不会吧不会吧”等雌小鬼常用词汇 71 - - 不要在输出的报告中写题目以及任何 markdown 样式,这非常,非常重要!! 72 - 2. 内容规则 73 - - 一些常见的梗类型: 74 - - 冷门番暴露癖(例:"看这种没人听的冷门番,大哥哥该不会在等弹幕里出现'同类'吧?杂鱼❤") 75 - - 补番速度羞辱(例:"三年才看十部?杂鱼哥哥的补番速度比柯南破案还慢呢~") 76 - - 类型单一化(例:"全是异世界?大哥哥的想象力比史莱姆还黏稠呢~") 77 - - 标题长度玩梗(例:"《打了300年史莱姆》这种标题...杂鱼哥哥该不会真信能活300年吧?") 78 - - 所有内容必须包含在 ">> 标签" 行之后 79 - - 想一下还有哪些适合用来嘲讽的梗,但不要太多,否则会显得很杂乱 80 - 3. 示例: 81 - """ 82 - >> 补番龟速の杂鱼❤ 83 - 84 - 不会吧不会吧?从2006到2024年只啃了三部动画?杂鱼哥哥的补番速度比吉良吉影的日常还慢呢❤~等你看完新番,人类都移民火星了杂鱼~杂鱼❤~ 85 - 86 - >> 冷门番の孤独癖❤ 87 - 88 - 太空丹迪和异世界舅舅?看这种没人讨论的冷门番,杂鱼哥哥该不会在弹幕里蹲“同类”吧❤~不会真以为自己是宇宙第一鉴赏家吧?杂鱼❤~ 89 - 90 - >> 番量贫瘠の杂鱼❤ 91 - 92 - 三部动画就敢自称阿宅?杂鱼哥哥的番单比史莱姆还稀薄呢❤~不会吧不会吧,该不会把补番当成就系统刷吧?杂鱼❤~杂鱼~ 93 - 94 - >> ... 95 - 96 - ... 97 - 98 - >> ... 99 - 100 - ... 101 - """ 102 - 103 - 现在开始分析用户的动画观看记录,按上述格式输出锐评报告。 104 - ` 70 + const templates = getPromptTemplate(language) 71 + const preset = promptType === "normal" ? templates.normal : templates.zako 105 72 106 73 return ` 107 74 ${preset} 108 - 用户动画观看记录:(下面的年份是动画发布的年份) 75 + ${t('watched') === 'Watched' ? 'User anime viewing record: (the year below is the anime release year)' : '用户动画观看记录:(下面的年份是动画发布的年份)'} 109 76 ${Object.keys(animeData) 110 77 .map((year) => { 111 78 const items = animeData[year] || [] ··· 114 81 115 82 const sliceItems = items.slice(0, 12) 116 83 const watched = sliceItems 117 - .filter((item) => selectedAnime.includes(item.title)) 118 - .map((item) => item.title) 84 + .filter((item) => selectedAnime.includes(getAnimeTitle(item, 'zh'))) 85 + .map((item) => getAnimeTitle(item, language)) 119 86 .join(", ") 120 87 const unWatched = sliceItems 121 - .filter((item) => !selectedAnime.includes(item.title)) 122 - .map((item) => item.title) 88 + .filter((item) => !selectedAnime.includes(getAnimeTitle(item, 'zh'))) 89 + .map((item) => getAnimeTitle(item, language)) 123 90 .join(", ") 124 91 125 92 return [ 126 - `**${year}年**:`, 127 - `看过: ${watched || "无"}`, 128 - `没看过: ${unWatched || "无"}`, 93 + `**${year}${t('year')}**:`, 94 + `${t('watched')}: ${watched || t('none')}`, 95 + `${t('notWatched')}: ${unWatched || t('none')}`, 129 96 ] 130 97 .filter(Boolean) 131 98 .join("\n") ··· 133 100 .filter(Boolean) 134 101 .join("\n")} 135 102 `.trim() 136 - }, [selectedAnime, promptType]) 103 + }, [selectedAnime, promptType, language, t]) 104 + 105 + const totalAnime = Object.values(animeData).flatMap((year) => { 106 + return year.map((item) => getAnimeTitle(item, 'zh')).slice(0, 12) 107 + }).length 137 108 138 109 return ( 139 110 <> 140 111 <div className="flex flex-col gap-4 pb-10"> 141 - <div className="p-4 flex flex-col md:items-center "> 142 - <div 143 - className="flex flex-col border border-b-0 bg-white w-fit" 144 - ref={wrapper} 145 - > 146 - <div className="border-b justify-between p-2 text-lg font-bold flex"> 147 - <h1> 148 - 动画世代<span className="remove"> - 点击选择你看过的动画</span> 149 - <span className="ml-2 text-zinc-400 font-medium"> 150 - anime-sedai.egoist.dev 112 + <div className="p-4 flex flex-col md:items-center"> 113 + <div className="flex justify-end mb-4"> 114 + <LanguageToggle /> 115 + </div> 116 + <div className="w-full overflow-x-auto"> 117 + <div 118 + className="flex flex-col border border-b-0 bg-white w-fit mx-auto" 119 + ref={wrapper} 120 + > 121 + <div className="border-b justify-between p-2 text-lg font-bold flex"> 122 + <h1> 123 + {t('title')}<span className="remove"> - {t('subtitle')}</span> 124 + <span className="ml-2 text-zinc-400 font-medium"> 125 + {t('website')} 126 + </span> 127 + </h1> 128 + <span className="shrink-0 whitespace-nowrap"> 129 + {t('watchedCount', { count: selectedAnime.length, total: totalAnime })} 151 130 </span> 152 - </h1> 153 - <span className="shrink-0 whitespace-nowrap"> 154 - 我看过 {selectedAnime.length}/ 155 - { 156 - Object.values(animeData).flatMap((year) => { 157 - return year.map((item) => item.title).slice(0, 12) 158 - }).length 159 - }{" "} 160 - 部动画 161 - </span> 162 - </div> 163 - {Object.keys(animeData).map((year) => { 164 - const items = animeData[year] || [] 165 - return ( 166 - <div key={year} className="flex border-b"> 167 - <div className="bg-red-500 shrink-0 text-white flex items-center font-bold justify-center p-1 size-16 md:size-20 border-black"> 168 - {year} 169 - </div> 170 - <div className="flex shrink-0"> 171 - {items.slice(0, 12).map((item) => { 172 - const isSelected = selectedAnime.includes(item.title) 173 - return ( 174 - <button 175 - key={item.title} 176 - className={`size-16 md:size-20 border-l break-all text-center shrink-0 inline-flex items-center p-1 overflow-hidden justify-center cursor-pointer text-sm ${ 177 - isSelected ? "bg-green-500" : "hover:bg-zinc-100" 178 - }`} 179 - title={item.title} 180 - onClick={() => { 181 - setSelectedAnime((prev) => { 182 - if (isSelected) { 183 - return prev.filter( 184 - (title) => title !== item.title 185 - ) 186 - } 187 - return [...prev, item.title] 188 - }) 189 - }} 190 - > 191 - <span className="leading-tight w-full line-clamp-3"> 192 - {item.title} 193 - </span> 194 - </button> 195 - ) 196 - })} 131 + </div> 132 + {Object.keys(animeData).map((year) => { 133 + const items = animeData[year] || [] 134 + return ( 135 + <div key={year} className="flex border-b"> 136 + <div className={` 137 + bg-red-500 shrink-0 text-white flex items-center font-bold justify-center p-1 border-black 138 + h-16 md:h-20 139 + ${language === 'en' ? 'w-16 md:w-20' : 'w-16 md:w-20'} 140 + `}> 141 + <span className={`${language === 'en' ? 'text-sm md:text-base' : 'text-base'} text-center`}> 142 + {year} 143 + </span> 144 + </div> 145 + <div className="flex shrink-0"> 146 + {items.slice(0, 12).map((item) => { 147 + const animeKey = getAnimeTitle(item, 'zh') 148 + const displayTitle = getAnimeTitle(item, language) 149 + const isSelected = selectedAnime.includes(animeKey) 150 + return ( 151 + <button 152 + key={animeKey} 153 + className={` 154 + h-16 md:h-20 155 + ${language === 'en' ? 'w-20 md:w-24' : 'w-16 md:w-20'} 156 + border-l break-all text-center shrink-0 inline-flex items-center 157 + p-1 overflow-hidden justify-center cursor-pointer 158 + ${language === 'en' ? 'text-xs' : 'text-sm'} 159 + ${isSelected ? "bg-green-500" : "hover:bg-zinc-100"} 160 + transition-colors duration-200 161 + `} 162 + title={displayTitle} 163 + onClick={() => { 164 + setSelectedAnime((prev) => { 165 + if (isSelected) { 166 + return prev.filter( 167 + (title) => title !== animeKey 168 + ) 169 + } 170 + return [...prev, animeKey] 171 + }) 172 + }} 173 + > 174 + <span className={`leading-tight w-full ${language === 'en' ? 'line-clamp-4' : 'line-clamp-3'}`}> 175 + {displayTitle} 176 + </span> 177 + </button> 178 + ) 179 + })} 180 + {Array.from({ length: Math.max(0, 12 - items.length) }, (_, index) => ( 181 + <div 182 + key={`empty-${index}`} 183 + className={` 184 + h-16 md:h-20 185 + ${language === 'en' ? 'w-20 md:w-24' : 'w-16 md:w-20'} 186 + border-l bg-gray-50 187 + `} 188 + /> 189 + ))} 190 + <div className="w-0 h-16 md:h-20 border-r" /> 191 + </div> 197 192 </div> 198 - </div> 199 - ) 200 - })} 193 + ) 194 + })} 195 + </div> 201 196 </div> 202 197 </div> 203 198 ··· 208 203 onClick={() => { 209 204 setSelectedAnime( 210 205 Object.values(animeData).flatMap((year) => { 211 - return year.map((item) => item.title).slice(0, 12) 206 + return year.map((item) => getAnimeTitle(item, 'zh')).slice(0, 12) 212 207 }) 213 208 ) 214 209 }} 215 210 > 216 - 全选 211 + {t('selectAll')} 217 212 </button> 218 213 219 214 {selectedAnime.length > 0 && ( ··· 224 219 setSelectedAnime([]) 225 220 }} 226 221 > 227 - 清除 222 + {t('clear')} 228 223 </button> 229 224 )} 230 225 ··· 233 228 className="border rounded-md px-4 py-2 inline-flex" 234 229 onClick={() => { 235 230 toast.promise(copyImage(), { 236 - success: "复制成功", 237 - loading: "复制中", 231 + success: t('copySuccess'), 232 + loading: t('copying'), 238 233 error(error) { 239 - return `复制失败: ${ 240 - error instanceof Error ? error.message : "未知错误" 241 - }` 234 + return t('copyFailed', { 235 + error: error instanceof Error ? error.message : t('unknownError') 236 + }) 242 237 }, 243 238 }) 244 239 }} 245 240 > 246 - 复制图片 241 + {t('copyImage')} 247 242 </button> 248 243 249 244 <button ··· 251 246 className="border rounded-md px-4 py-2 inline-flex" 252 247 onClick={() => { 253 248 toast.promise(downloadImage(), { 254 - success: "下载成功", 255 - loading: "下载中", 249 + success: t('downloadSuccess'), 250 + loading: t('downloading'), 256 251 error(error) { 257 - return `下载失败: ${ 258 - error instanceof Error ? error.message : "未知错误" 259 - }` 252 + return t('downloadFailed', { 253 + error: error instanceof Error ? error.message : t('unknownError') 254 + }) 260 255 }, 261 256 }) 262 257 }} 263 258 > 264 - 下载图片 259 + {t('downloadImage')} 265 260 </button> 266 261 </div> 267 262 ··· 269 264 <div className="border focus-within:ring-2 ring-pink-500 focus-within:border-pink-500 rounded-md"> 270 265 <div className="flex items-center justify-between p-2 border-b"> 271 266 <div className="flex items-center gap-2"> 272 - <span>锐评提示词</span> 267 + <span>{t('promptType')}</span> 273 268 <select 274 269 className="border rounded-md" 275 270 value={promptType} ··· 277 272 setPromptType(e.currentTarget.value as any) 278 273 }} 279 274 > 280 - <option value="normal">普通</option> 281 - <option value="zako">杂鱼❤</option> 275 + <option value="normal">{t('promptNormal')}</option> 276 + <option value="zako">{t('promptZako')}</option> 282 277 </select> 283 278 </div> 284 279 ··· 288 283 className="text-sm text-zinc-500 hover:bg-zinc-100 px-1.5 h-7 flex items-center rounded-md" 289 284 onClick={() => { 290 285 navigator.clipboard.writeText(prompt) 291 - toast.success("复制成功") 286 + toast.success(t('copySuccess')) 292 287 }} 293 288 > 294 - 复制 289 + {t('copy')} 295 290 </button> 296 291 297 292 <button ··· 303 298 )}` 304 299 }} 305 300 > 306 - 在 ChatWise 中打开 (需要先安装) 301 + {t('openInChatWise')} 307 302 </button> 308 303 </div> 309 304 </div> ··· 317 312 </div> 318 313 319 314 <div className="mt-2 text-center"> 320 - 历年关注最多的动画,数据来自 bgm.tv,由 315 + {t('footer')} 321 316 <a 322 - href="https://x.com/localhost_4173" 317 + href={language === 'zh' ? "https://x.com/localhost_4173" : "https://x.com/localhost_5173"} 323 318 target="_blank" 324 319 className="underline" 325 320 > 326 - 低空飞行 321 + {language === 'zh' ? '低空飞行' : 'egoist'} 327 322 </a> 328 - 制作, 323 + {t('madeBy')} 329 324 <a 330 325 href="https://github.com/egoist/anime-sedai" 331 326 target="_blank" 332 327 className="underline" 333 328 > 334 - 查看代码 329 + {t('viewCode')} 335 330 </a> 336 331 </div> 337 332 333 + {language === 'en' && ( 334 + <div className="text-center text-sm text-gray-600"> 335 + English version is translated by{' '} 336 + <a 337 + href="https://mhh0318.github.io/" 338 + target="_blank" 339 + className="underline" 340 + > 341 + h1t 342 + </a> 343 + </div> 344 + )} 345 + 338 346 <div className="text-center"> 339 - 作者的其它产品:{" "} 347 + {t('otherProducts')} 340 348 <a 341 349 href="https://chatwise.app" 342 350 target="_blank" ··· 345 353 <img src="https://chatwise.app/favicon.png" className="size-4" />{" "} 346 354 ChatWise 347 355 </a> 348 - , 一个优雅的 AI 聊天客户端 356 + {t('aiChatClient')} 349 357 </div> 350 358 </div> 351 359 </>
+29 -7
src/hooks.ts
··· 1 - import { useEffect } from "react"; 2 - import { useState } from "react"; 1 + import { useEffect, useState, useCallback } from "react"; 3 2 4 3 export const usePersistState = <T>(key: string, initialValue: T) => { 5 4 const [state, setState] = useState<T>(() => { 6 - const item = localStorage.getItem(key); 7 - return item ? JSON.parse(item) : initialValue; 5 + try { 6 + const item = localStorage.getItem(key); 7 + return item ? JSON.parse(item) : initialValue; 8 + } catch (error) { 9 + console.error(`Error loading ${key} from localStorage:`, error); 10 + return initialValue; 11 + } 8 12 }); 9 13 14 + const setValue = useCallback((value: T | ((prevState: T) => T)) => { 15 + setState(currentState => { 16 + const newValue = value instanceof Function ? value(currentState) : value; 17 + 18 + try { 19 + localStorage.setItem(key, JSON.stringify(newValue)); 20 + } catch (error) { 21 + console.error(`Error saving ${key} to localStorage:`, error); 22 + } 23 + 24 + return newValue; 25 + }); 26 + }, [key]); 27 + 10 28 useEffect(() => { 11 - localStorage.setItem(key, JSON.stringify(state)); 12 - }, [state]); 29 + try { 30 + localStorage.setItem(key, JSON.stringify(state)); 31 + } catch (error) { 32 + console.error(`Error saving ${key} to localStorage:`, error); 33 + } 34 + }, [key, state]); 13 35 14 - return [state, setState] as const; 36 + return [state, setValue] as const; 15 37 };
+64
src/i18n-context.tsx
··· 1 + import React, { createContext, useContext, useState, useEffect } from 'react' 2 + import type { ReactNode } from 'react' 3 + import { translations, type Language } from './i18n' 4 + 5 + interface I18nContextType { 6 + language: Language 7 + setLanguage: (lang: Language) => void 8 + t: (key: keyof typeof translations.zh, interpolations?: Record<string, string | number>) => string 9 + isZh: boolean 10 + isEn: boolean 11 + } 12 + 13 + const I18nContext = createContext<I18nContextType | undefined>(undefined) 14 + 15 + export const I18nProvider = ({ children }: { children: ReactNode }) => { 16 + const [language, setLanguageState] = useState<Language>(() => { 17 + try { 18 + const saved = localStorage.getItem('language') 19 + return saved ? JSON.parse(saved) : 'zh' 20 + } catch { 21 + return 'zh' 22 + } 23 + }) 24 + 25 + const setLanguage = (newLanguage: Language) => { 26 + setLanguageState(newLanguage) 27 + try { 28 + localStorage.setItem('language', JSON.stringify(newLanguage)) 29 + } catch (error) { 30 + console.error('Failed to save language to localStorage:', error) 31 + } 32 + } 33 + 34 + const t = (key: keyof typeof translations.zh, interpolations?: Record<string, string | number>) => { 35 + const currentTranslations = translations[language] 36 + let text = currentTranslations[key] || translations.zh[key] || key 37 + 38 + if (interpolations) { 39 + Object.entries(interpolations).forEach(([placeholder, value]) => { 40 + text = text.replace(new RegExp(`{{${placeholder}}}`, 'g'), String(value)) 41 + }) 42 + } 43 + 44 + return text 45 + } 46 + 47 + const value: I18nContextType = { 48 + language, 49 + setLanguage, 50 + t, 51 + isZh: language === 'zh', 52 + isEn: language === 'en' 53 + } 54 + 55 + return <I18nContext.Provider value={value}>{children}</I18nContext.Provider> 56 + } 57 + 58 + export const useI18n = () => { 59 + const context = useContext(I18nContext) 60 + if (!context) { 61 + throw new Error('useI18n must be used within an I18nProvider') 62 + } 63 + return context 64 + }
+162
src/i18n.ts
··· 1 + export type Language = 'zh' | 'en' 2 + 3 + export const translations = { 4 + zh: { 5 + title: '动画世代', 6 + subtitle: '点击选择你看过的动画', 7 + website: 'anime-sedai.egoist.dev', 8 + watchedCount: '我看过 {{count}}/{{total}} 部动画', 9 + selectAll: '全选', 10 + clear: '清除', 11 + copyImage: '复制图片', 12 + downloadImage: '下载图片', 13 + copySuccess: '复制成功', 14 + downloadSuccess: '下载成功', 15 + copyFailed: '复制失败: {{error}}', 16 + downloadFailed: '下载失败: {{error}}', 17 + copying: '复制中', 18 + downloading: '下载中', 19 + unknownError: '未知错误', 20 + promptType: '锐评提示词', 21 + promptNormal: '普通', 22 + promptZako: '杂鱼❤', 23 + copy: '复制', 24 + openInChatWise: '在 ChatWise 中打开 (需要先安装)', 25 + footer: '历年关注最多的动画,数据来自 bgm.tv,由', 26 + madeBy: '制作,', 27 + viewCode: '查看代码', 28 + otherProducts: '作者的其它产品: ', 29 + aiChatClient: ', 一个优雅的 AI 聊天客户端', 30 + year: '年', 31 + watched: '看过', 32 + notWatched: '没看过', 33 + none: '无', 34 + language: '语言', 35 + chinese: '中文', 36 + english: 'English' 37 + }, 38 + en: { 39 + title: 'Anime Sedai', 40 + subtitle: 'Click to select anime you have watched', 41 + website: 'anime-sedai.egoist.dev', 42 + watchedCount: 'I have watched {{count}}/{{total}} anime', 43 + selectAll: 'Select All', 44 + clear: 'Clear', 45 + copyImage: 'Copy Image', 46 + downloadImage: 'Download Image', 47 + copySuccess: 'Copy successful', 48 + downloadSuccess: 'Download successful', 49 + copyFailed: 'Copy failed: {{error}}', 50 + downloadFailed: 'Download failed: {{error}}', 51 + copying: 'Copying', 52 + downloading: 'Downloading', 53 + unknownError: 'Unknown error', 54 + promptType: 'Review Prompt', 55 + promptNormal: 'Normal', 56 + promptZako: 'Zako❤', 57 + copy: 'Copy', 58 + openInChatWise: 'Open in ChatWise (installation required)', 59 + footer: 'Most watched anime by year, data from bgm.tv, made by ', 60 + madeBy: ', ', 61 + viewCode: 'View Code', 62 + otherProducts: 'Other products by the author: ', 63 + aiChatClient: ', an elegant AI chat client', 64 + year: '', 65 + watched: 'Watched', 66 + notWatched: 'Not Watched', 67 + none: 'None', 68 + language: 'Language', 69 + chinese: '中文', 70 + english: 'English' 71 + } 72 + } 73 + 74 + export const getPromptTemplate = (lang: Language) => { 75 + if (lang === 'zh') { 76 + return { 77 + normal: `以下是用户的动画观看记录,请生成一个锐评。`, 78 + zako: `你是一个精通二次元文化的傲娇雌小鬼,需要根据用户提供的动画观看记录,用雌小鬼惯用的嘲讽语气混合动画圈梗生成锐评报告。要求: 79 + 1. 结构模板 80 + - 列出5-6个嘲讽段落 81 + - 每个段落的所有内容请务必都包含在 ">> 标签" 开始的一行之后!! 82 + - 每一个嘲讽段落的主题都应当不同,且应当尖锐 83 + - 你应当大量地使用"杂鱼"、"❤"、"杂鱼~"、"杂鱼❤~","不会吧不会吧"等雌小鬼常用词汇 84 + - 不要在输出的报告中写题目以及任何 markdown 样式,这非常,非常重要!! 85 + 2. 内容规则 86 + - 一些常见的梗类型: 87 + - 冷门番暴露癖(例:"看这种没人听的冷门番,大哥哥该不会在等弹幕里出现'同类'吧?杂鱼❤") 88 + - 补番速度羞辱(例:"三年才看十部?杂鱼哥哥的补番速度比柯南破案还慢呢~") 89 + - 类型单一化(例:"全是异世界?大哥哥的想象力比史莱姆还黏稠呢~") 90 + - 标题长度玩梗(例:"《打了300年史莱姆》这种标题...杂鱼哥哥该不会真信能活300年吧?") 91 + - 所有内容必须包含在 ">> 标签" 行之后 92 + - 想一下还有哪些适合用来嘲讽的梗,但不要太多,否则会显得很杂乱 93 + 3. 示例: 94 + """ 95 + >> 补番龟速の杂鱼❤ 96 + 97 + 不会吧不会吧?从2006到2024年只啃了三部动画?杂鱼哥哥的补番速度比吉良吉影的日常还慢呢❤~等你看完新番,人类都移民火星了杂鱼~杂鱼❤~ 98 + 99 + >> 冷门番の孤独癖❤ 100 + 101 + 太空丹迪和异世界舅舅?看这种没人讨论的冷门番,杂鱼哥哥该不会在弹幕里蹲"同类"吧❤~不会真以为自己是宇宙第一鉴赏家吧?杂鱼❤~ 102 + 103 + >> 番量贫瘠の杂鱼❤ 104 + 105 + 三部动画就敢自称阿宅?杂鱼哥哥的番单比史莱姆还稀薄呢❤~不会吧不会吧,该不会把补番当成就系统刷吧?杂鱼❤~杂鱼~ 106 + 107 + >> ... 108 + 109 + ... 110 + 111 + >> ... 112 + 113 + ... 114 + """ 115 + 116 + 现在开始分析用户的动画观看记录,按上述格式输出锐评报告。` 117 + } 118 + } else { 119 + return { 120 + normal: `The following is the user's anime viewing record, please generate a sharp review.`, 121 + zako: `You are a proud and arrogant anime otaku girl who needs to generate a sharp review report based on the user's anime viewing record using the sarcastic tone commonly used by tsundere characters mixed with anime culture memes. Requirements: 122 + 1. Structure template 123 + - List 5-6 sarcastic paragraphs 124 + - All content in each paragraph must be included after a line starting with ">> tag"!! 125 + - Each sarcastic paragraph should have a different theme and should be sharp 126 + - You should extensively use terms like "Zako", "❤", "Zako~", "Zako❤~", "No way no way" and other commonly used tsundere vocabulary 127 + - Do not write titles or any markdown styles in the output report, this is very, very important!! 128 + 2. Content rules 129 + - Some common meme types: 130 + - Obscure anime exposure fetish (e.g., "Watching such obscure anime that no one talks about, big brother wouldn't be waiting for 'fellow fans' to appear in the comments, would you? Zako❤") 131 + - Anime watching speed shaming (e.g., "Only ten shows in three years? Big brother's anime completion speed is slower than Conan solving cases~") 132 + - Type singularity (e.g., "All isekai? Big brother's imagination is stickier than slime~") 133 + - Title length memes (e.g., "Titles like 'I've Been Killing Slimes for 300 Years'... Zako brother wouldn't really believe you can live 300 years, would you?") 134 + - All content must be included after ">> tag" lines 135 + - Think of other suitable memes for sarcasm, but not too many, otherwise it will seem cluttered 136 + 3. Example: 137 + """ 138 + >> Turtle-speed anime completion Zako❤ 139 + 140 + No way no way? Only watched three anime from 2006 to 2024? Big brother's anime completion speed is slower than Kira Yoshikage's daily routine❤~ By the time you finish watching new anime, humans will have migrated to Mars, Zako~Zako❤~ 141 + 142 + >> Obscure anime loner fetish❤ 143 + 144 + Space Dandy and Uncle from Another World? Watching such obscure anime that no one discusses, big brother wouldn't be lurking in the comments waiting for "fellow fans", would you❤~ You wouldn't really think you're the universe's number one connoisseur, would you? Zako❤~ 145 + 146 + >> Meager anime count Zako❤ 147 + 148 + Three anime and you dare call yourself an otaku? Big brother's anime list is thinner than slime❤~ No way no way, you wouldn't treat anime completion like an achievement system, would you? Zako❤~Zako~ 149 + 150 + >> ... 151 + 152 + ... 153 + 154 + >> ... 155 + 156 + ... 157 + """ 158 + 159 + Now start analyzing the user's anime viewing record and output a sharp review report according to the above format.` 160 + } 161 + } 162 + }
+5 -2
src/main.tsx
··· 2 2 import ReactDOM from "react-dom/client" 3 3 import { App } from "./app" 4 4 import { Toaster } from "sonner" 5 + import { I18nProvider } from "./i18n-context" 5 6 6 7 ReactDOM.createRoot(document.getElementById("app")!).render( 7 8 <React.StrictMode> 8 - <App /> 9 - <Toaster /> 9 + <I18nProvider> 10 + <App /> 11 + <Toaster /> 12 + </I18nProvider> 10 13 </React.StrictMode> 11 14 ) 12 15