Atcoder 中文版

翻译

  1. // ==UserScript==
  2. // @name Atcoder 中文版
  3. // @namespace http://tampermonkey.net/
  4. // @version 2024-08-15
  5. // @description 翻译
  6. // @author You
  7. // @match https://atcoder.jp/*
  8. // @run-at document-start
  9. // @grant none
  10. // @license GNU GPL v3
  11. // ==/UserScript==
  12. (function () {
  13. const TEXT = {
  14. "(local time)": "(本地时间)",
  15. "Active Users": "活跃用户",
  16. "Affiliation": "工作单位",
  17. "Algorithm": "算法竞赛",
  18. "All": "全部",
  19. "All Submissions": "所有提交",
  20. "All Users": "所有用户",
  21. "Auto Refresh": "自动刷新",
  22. "Back to Home": "返回主页",
  23. "Birth Year": "出生年份",
  24. "Category": "类别",
  25. "Change Password": "更换密码",
  26. "Change Photo": "更换头像",
  27. "Change/Verify Email address": "更改/验证电子邮件地址",
  28. "Clarifications": "提问",
  29. "Company": "公司信息",
  30. "Competition History": "历史比赛",
  31. "Contact": "联系方式",
  32. "Contest": "比赛",
  33. "Contest Archive": "比赛记录",
  34. "Contest Name": "比赛名字",
  35. "Contest Status": "比赛记录",
  36. "Country/Region": "国家/地区",
  37. "Custom Test": "自定义测试",
  38. "Customize": "自定义",
  39. "Duration": "持续时间",
  40. "Editorial": "题解",
  41. "Email Notifications": "邮箱提醒",
  42. "FAQ": "常见问题",
  43. "General Settings": "基本设置",
  44. "Glossary": "术语",
  45. "Heuristic": "启发式竞赛",
  46. "Heuristic Contest": "启发式比赛",
  47. "Highest Rating": "最高等级分",
  48. "Home": "首页",
  49. "Information": "公告",
  50. "Information Protection Policy": "信息保护政策",
  51. "Last Contest Result": "上次比赛结果",
  52. "Manage Fav": " 管理收藏",
  53. "More...": "更多...",
  54. "My Profile": "我的主页",
  55. "My Score": "我的分数",
  56. "My Submissions": "我的提交",
  57. "Nickname": "昵称",
  58. "Other": "其他",
  59. "Page Top": "页首",
  60. "Past Contests": "往届比赛",
  61. "Permanent Contests": "永久性比赛",
  62. "Present Contests": "当前比赛",
  63. "Privacy Policy": "隐私政策",
  64. "Profile": "简介",
  65. "Rank": "排名",
  66. "Ranking": "排名",
  67. "Rated Range": "等级范围",
  68. "Rating": "等级分",
  69. "Rating Distribution": "评级分布",
  70. "Recent Contests": "最近的比赛",
  71. "Refresh": "刷新",
  72. "Register": "报名",
  73. "Reset": "重置",
  74. "Restructuring of contests": "比赛调整",
  75. "Results": "结果",
  76. "Rule": "规则",
  77. "Search": "搜索",
  78. "Search in Archive": "在存档中搜索",
  79. "Settings": "设置",
  80. "Sign In": "登录",
  81. "Sign Out": "退出登录",
  82. "Sign Up": "注册",
  83. "Sponsored ABC": "赞助入门赛(ABC)",
  84. "Sponsored ARC": "赞助常规赛(ARC)",
  85. "Sponsored Heuristic Contest": "赞助启发式比赛",
  86. "Sponsored Parallel(rated)": "赞助平行赛(评级)",
  87. "Sponsored Parallel(unrated)": "赞助平行赛(未评级)",
  88. "Sponsored Tournament": "赞助锦标赛",
  89. "Standings": "排名",
  90. "Start Time": "开始时间",
  91. "Submit": "提交",
  92. "Tasks": "题目",
  93. "Terms of service": "服务条款",
  94. "The file size must be at most 1MB.": "文件大小不得超过1MB。",
  95. "The width and height must be at most 512px.": "宽度和高度不得超过512px。",
  96. "There is no clarifications yet.": "目前还没有提示。",
  97. "This user has not competed in a rated contest yet.": "该用户没有参加过有评级的比赛。",
  98. "This user has not competed yet.": "该用户没有参加过比赛。",
  99. "Top": "首页",
  100. "Unofficial(unrated)": "非官方(未评级)",
  101. "Upcoming Contests": "即将到来的比赛",
  102. "Update": "更新",
  103. "Upload": "上传",
  104. "User": "用户",
  105. "View all": "查看全部",
  106. "Virtual Participation": "虚拟参与",
  107. "Virtual Standings": "虚拟排名",
  108. "You can use only jpg/png files.": "您只能使用jpg/png文件。",
  109. "last update": "上次更新",
  110. "【Important Notice】 Please beware of fake sites impersonating AtCoder": "【重要提示】请注意假冒AtCoder的虚假网站"
  111. }
  112. function ObjSort(arys) {
  113. var newkey = Object.keys(arys).sort();
  114. var newObj = {};
  115. for (var i = 0; i < newkey.length; i++) newObj[newkey[i]] = arys[newkey[i]];
  116. return newObj; //返回排好序的新对象
  117. }
  118. console.log("词汇表:");
  119. console.log(ObjSort(TEXT));
  120. let cnt = 0, id, flag = sessionStorage["translate"], bflag = 0;
  121. if (flag == undefined) {
  122. flag = 1;
  123. sessionStorage["translate"] = 1;
  124. }
  125. function translate(x) {
  126. if (x.nodeType == 3) {
  127. let str = x.nodeValue, l = 0, ls = "", r = 0, rs = "";
  128. while (" \n\t".includes(str[l])) ls += str[l], l++;
  129. while (" \n\t".includes(str[str.length - 1 - r]) && str.length - 1 - r >= l) rs += str[str.length - 1 - r], r++;
  130. if (str[str.length - 1 - r] == ":") rs += ":", r++;
  131. if (TEXT[str.substring(l, str.length - r)] != undefined) {
  132. str = TEXT[str.substring(l, str.length - r)];
  133. x.old = x.nodeValue;
  134. x.nodeValue = ls + str + rs;
  135. }
  136. return;
  137. }
  138. let c = Array.from(x.childNodes)
  139. for (let i of c) translate(i);
  140. }
  141. function back(x) {
  142. if (x.nodeType == 3) {
  143. if (x.old != undefined) {
  144. x.nodeValue = x.old
  145. x.old = undefined;
  146. }
  147. return;
  148. }
  149. let c = Array.from(x.childNodes)
  150. for (let i of c) back(i);
  151. }
  152. function main() {
  153. if (bflag == 0) {
  154. let a = document.getElementsByClassName("nav navbar-nav navbar-right")[0];
  155. if (a != undefined) {
  156. bflag = 1;
  157. let bu = document.createElement("button");
  158. bu.innerText = (flag == 1) ? "关闭翻译" : "开启翻译";
  159. bu.onclick = function () {
  160. if (bu.innerText == "关闭翻译") {
  161. bu.innerText = "开启翻译";
  162. back(document.body);
  163. flag = 0;
  164. } else {
  165. bu.innerText = "关闭翻译";
  166. flag = 1;
  167. }
  168. sessionStorage["translate"] = flag;
  169. }
  170. a.appendChild(bu);
  171. }
  172. }
  173. if (flag != 0) translate(document.body);
  174. cnt++;
  175. if (cnt == 1000) {
  176. // 网页启动时高频刷新,启动后 1 秒降低刷新频率,降低压力
  177. clearInterval(id);
  178. setInterval(main, 100);
  179. }
  180. }
  181. id = setInterval(main, 1);
  182. })();