SteamDB_CN

SteamDB汉化插件

当前为 2021-12-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name SteamDB_CN
  3. // @name:zh-CN SteamDB汉化
  4. // @namespace https://blog.chrxw.com
  5. // @version 1.15
  6. // @description SteamDB汉化插件
  7. // @description:zh-cn SteamDB汉化插件
  8. // @author Chr_
  9. // @match https://steamdb.info/*
  10. // @supportURL https://steamcn.com/t339531-1-1
  11. // @license AGPL-3.0
  12. // @icon https://blog.chrxw.com/favicon.ico
  13. // @resource data https://gitee.com/chr_a1/gm_scripts/raw/master/SteamDB/lang_zh_CN.json
  14. // @grant GM_addStyle
  15. // @grant GM_getResourceText
  16. // @grant GM_registerMenuCommand
  17. // ==/UserScript==
  18.  
  19.  
  20. (function () {
  21. 'use strict';
  22. const DEBUG = window.localStorage['dbg_mode'] == '开';
  23. const OUTPUT = window.localStorage['out_word'] == '开';
  24.  
  25. GM_registerMenuCommand(`调试汉化文本: ${DEBUG ? '开' : '关'}】`, () => {
  26. window.localStorage['dbg_mode'] = DEBUG ? '关' : '开';
  27. window.location.reload();
  28. });
  29.  
  30. GM_registerMenuCommand(`在控制台输出未匹配文本: ${OUTPUT ? '开' : '关'}】`, () => {
  31. window.localStorage['out_word'] = OUTPUT ? '关' : '开';
  32. window.location.reload();
  33. });
  34.  
  35. document.querySelector('html').getAttribute('lang') = 'zh-CN';
  36.  
  37. let Locales;
  38.  
  39. if (DEBUG) {
  40. const template = '{"DOC":{"更新时间":"调试模式","贡献名单":["调试模式"]},\n"STATIC":\n{\n\n},\n"INPUT":\n{\n\n},\n"DYNAMIC":\n{\n\n}\n}';
  41. const box = document.createElement('div');
  42. box.style.cssText = 'display:flex;';
  43. const text = document.createElement('textarea');
  44. text.style.cssText = 'width:90%;height:250px;resize:vertical;';
  45. box.appendChild(text);
  46. const action = document.createElement('div');
  47. action.style.cssText = 'width:10%;height:100%';
  48. box.appendChild(action);
  49. const btnSave = document.createElement('button');
  50. btnSave.innerText = '保存并刷新';
  51. btnSave.addEventListener('click', () => {
  52. const raw = text.value.trim();
  53. if (!raw) {
  54. alert('翻译文本不能为空!!!');
  55. } else {
  56. try {
  57. JSON.parse(raw);
  58. window.localStorage['sdb_lang'] = raw;
  59. window.location.reload();
  60. } catch (e) {
  61. alert('翻译文本不是有效的JSON格式!!!');
  62. }
  63. }
  64. });
  65. btnSave.style.cssText = 'width:100%;height:50px;';
  66. action.appendChild(btnSave);
  67. const btnReset = document.createElement('button');
  68. btnReset.textContent = '清空文本';
  69. btnReset.addEventListener('click', () => {
  70. window.localStorage['sdb_lang'] = template;
  71. window.location.reload();
  72. });
  73. btnReset.style.cssText = 'width:100%;height:50px;';
  74. action.appendChild(btnReset);
  75.  
  76. const father = document.getElementById('main');
  77. father.insertBefore(box, father.firstChild);
  78. const customLang = window.localStorage['sdb_lang'] ?? template;
  79. text.value = customLang;
  80. Locales = JSON.parse(customLang);
  81. } else {
  82. Locales = JSON.parse(GM_getResourceText("data"));
  83. }
  84.  
  85. //计时
  86. var Start = new Date().getTime();
  87.  
  88. {//静态元素
  89. for (const [css, dic] of Object.entries(Locales.STATIC)) {
  90. if (OUTPUT) { console.log(`〖${css}〗`); }
  91. const elements = document.querySelectorAll(css);
  92. if (elements.length > 0) {
  93. for (let i = 0; i < elements.length; i++) {
  94. const element = elements[i];
  95. if (element.childElementCount === 0) {//节点内部无其他元素
  96. const raw = element.innerText?.trim();
  97. if (!raw || raw.length <= 2) { continue; }
  98. const txt = dic[raw];
  99. if (txt) {
  100. element.innerText = txt;
  101. } else if (OUTPUT) {
  102. console.log(`"${raw}": "",`);
  103. }
  104. } else {//节点内部有其他元素
  105. const nodes = element.childNodes;
  106. for (let j = 0; j < nodes.length; j++) {
  107. const node = nodes[j];
  108. if (node.nodeType === Node.TEXT_NODE) {
  109. const raw = node.textContent?.trim();
  110. if (!raw || raw.length <= 2) { continue; }
  111. const txt = dic[raw];
  112. if (txt) {
  113. node.textContent = txt;
  114. } else if (OUTPUT) {
  115. console.log(`"${raw}": "",`);
  116. }
  117. }
  118. }
  119. }
  120. }
  121. } else {
  122. if (OUTPUT) { console.warn(`CSS选择器未匹配到任何元素: ${css}`); }
  123. }
  124. }
  125. }
  126.  
  127. {//输入框
  128. const inputs = Locales.INPUT;
  129. if (OUTPUT) { console.log('〖输入框〗'); }
  130. const elements = document.querySelectorAll("input");
  131. for (let i = 0; i < elements.length; i++) {
  132. const element = elements[i];
  133. const raw = element.placeholder;
  134. if (!raw) { continue; }
  135. const txt = inputs[raw];
  136. if (txt) {
  137. element.placeholder = txt;
  138. } else if (OUTPUT) {
  139. console.log(`"${raw}": "",`);
  140. }
  141. }
  142. }
  143.  
  144.  
  145.  
  146. const { script: { version } } = GM_info;
  147. const { DOC: { "更新时间": update, "贡献名单": contribution } } = Locales;
  148.  
  149. // call your function
  150. var End = new Date().getTime();
  151. console.log('执行耗时', `${End - Start} ms`);
  152. console.log('=================================');
  153. console.log(`插件版本: ${version}`);
  154. console.log(`更新时间: ${update}`);
  155. console.log(`贡献名单: ${contribution.join(', ')}`);
  156. // // 创建一个观察器实例并传入回调函数
  157. // const observer = new MutationObserver((mutationsList, observer) => {
  158. // // Use traditional 'for loops' for IE 11
  159. // for (let mutation of mutationsList) {
  160. // console.log(mutation);
  161.  
  162. // }
  163.  
  164. // });
  165.  
  166. // // 以上述配置开始观察目标节点
  167. // observer.observe(document.body, { childList: true, subtree: true });
  168.  
  169. // // 之后,可停止观察
  170. // observer.disconnect();
  171.  
  172. GM_addStyle('.tabnav-tabs>a{min-width:80px;}');
  173. })();