import WuhuBase from "../WuhuBase"; import { chatDict, eventsDict, headerDict, propertyDict, sidebarDict } from "../../dictionary/translation"; import Log from "../Log"; import Timer from "../utils/Timer"; export default class Translate extends WuhuBase { className = 'Translate'; public translateVer: string = '1.0'; constructor() { super(); Log.info('翻译开始'); let start = new Timer(); // 时分秒转换 String.prototype.replaceHMS = function replaceHMS() { return this.replace('and', '') .replace('days', '天') .replace('days', '天') .replace('hours', '小时') .replace('hour', '小时') .replace('minutes', '分钟') .replace('minute', '分钟') .replace('seconds', '秒钟') .replace('second', '秒钟'); }; // 数词转换 a/an/some String.prototype.numWordTrans = function numWordTrans() { return this.replace(/\ban\b/, '1 个') .replace(/\ba\b/, '1 个') .replace(/\bsome\b/, '1 个') .replace(/([0-9])x\b/, '$1 个'); }; window.setTimeout(() => { this.headerTranslate(); this.sidebarTranslate(); this.chatTranslate(); this.playerSearchBoxTrans(); this.urlMatchPageTranslate(window.location.href); Log.info('翻译结束, 耗时' + start.getTimeMs()); }, 0); } public urlMatchPageTranslate(href: string): void { } private sidebarTranslate(): void { // 边栏 let sidebarTimeOut = 60; const sidebarInterval = setInterval(() => { // 60秒后取消定时 if ($('div[class^="sidebar"]').length === 0) { sidebarTimeOut--; if (sidebarTimeOut < 0) { clearInterval(sidebarInterval); } return; } // 边栏块标题 $('h2[class^="header"]').each((i, e) => { if (!sidebarDict[e.firstChild.nodeValue]) return; e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue]; }); // 边栏人物名字 $('span[class^="menu-name"]').each((i, e) => { e.firstChild.nodeValue = '名字:'; }); // 钱 等级 pt 天赋点 $('p[class^="point-block"]').each((i, e) => { if (sidebarDict[e.firstChild.firstChild.nodeValue]) e.firstChild.firstChild.nodeValue = sidebarDict[e.firstChild.firstChild.nodeValue]; }); // 4条 状态条 $('p[class^="bar-name"]').each((i, e) => { if (sidebarDict[e.firstChild.nodeValue]) e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue]; }); // 边栏菜单 $('span[class^="linkName"]').each((i, e) => { if (sidebarDict[e.firstChild.nodeValue]) e.firstChild.nodeValue = sidebarDict[e.firstChild.nodeValue]; }); // [use]按钮 if (document.querySelector('#pointsMerits')) $('#pointsMerits')[0].firstChild.nodeValue = '[使用]'; if (document.querySelector('#pointsPoints')) $('#pointsPoints')[0].firstChild.nodeValue = '[使用]'; if (document.querySelector('#pointsLevel')) $('#pointsLevel')[0].firstChild.nodeValue = '[升级]'; // 手机 区域菜单 $('div[class*="areas-mobile"] span:nth-child(2)').contents().each((i, e) => { //log(e); if (sidebarDict[e.nodeValue]) e.nodeValue = sidebarDict[e.nodeValue]; }); clearInterval(sidebarInterval); }, 1000); } private headerTranslate(): void { let headerRoot = document.querySelector('div#header-root'); if (headerRoot) { // const headerOB = new MutationObserver((_, observer) => { observer.disconnect(); headerTrans(); observer.observe(headerRoot, { childList: true, subtree: true, attributes: true }); }).observe(headerRoot, { childList: true, subtree: true, attributes: true }); const headerTrans = () => { // 搜索内容下拉框中的文字 已选中 let toggle = document.querySelector('div.find button.toggler.down'); if (toggle) { let text = toggle.innerText.trim(); if (headerDict[text]) toggle.innerText = headerDict[text]; } // pc端 搜索下拉框点击后的搜索类型文字 TODO 去除jq each $('div.find li.item').each((i, e) => { let $e = $(e); if (headerDict[$e.text()]) $e.text(headerDict[$e.text()]); }); // 手机端 搜索下拉框点击后的搜索类型文字 TODO 去除jq each $('li[class^="search-type-"] label').each((i, e) => { if (headerDict[$(e).text()]) $(e).text(headerDict[$(e).text()]); }); // 搜索框placeholder let searchInput = document.querySelector('input[class^="searchInput"]'); if (searchInput) { let searchInputPlaceholder = searchInput.getAttribute('placeholder').trim(); if (headerDict[searchInputPlaceholder]) searchInput.setAttribute('placeholder', headerDict[searchInputPlaceholder]); } // 高级搜索框 search by if (headerDict[document.querySelector('div#header-root legend.title').innerText]) { let $title = $('div#header-root legend.title'); $title.text(headerDict[$title.text()]); } // 高级搜索框的条件 左 键 $('ul.advancedSearchFormBody label.label').each((i, e) => { let $e = $(e); if (headerDict[$e.text()]) $e.text(headerDict[$e.text()]); }); // 高级搜索框的已选中 $('ul.advancedSearchFormBody div.select-wrapper button.toggler.down').each((i, e) => { let $e = $(e); if (headerDict[$e.text().trim()]) $e.text(headerDict[$e.text().trim()]); else if (propertyDict[$e.text().trim()]) $e.text(propertyDict[$e.text().trim()]); }); // 高级搜索的下拉选项 $('ul.advancedSearchFormBody li.item').each((i, e) => { let $e = $(e); if (headerDict[$e.text()]) $e.text(headerDict[$e.text()]); else if (propertyDict[$e.text()]) $e.text(propertyDict[$e.text()]); }); // 高级搜索的"Not" $('ul.advancedSearchFormBody label.search-condition-not').each((i, e) => { let $e = $(e); if (headerDict[$e.text()]) $e.text(headerDict[$e.text()]); }); // 高级搜索的"to" $('ul.advancedSearchFormBody label[for*="To"]').each((i, e) => { let $e = $(e); if (headerDict[$e.text()]) $e.text(headerDict[$e.text()]); }); // 高级搜索的reset search按钮 $('form.form-search-extend div.bottom button').each((i, e) => { let $e = $(e); if (headerDict[$e.text()]) $e.text(headerDict[$e.text()]); }); // log按钮“view log” const $view_log = $('div.recentHistory a[class^="link"] span[class^="text"]') if (headerDict[$view_log.text().trim()]) $view_log .text(headerDict[$view_log.text().trim()]); // 点击头像打开的菜单 $('ul.settings-menu span').each((i, e) => { let $e = $(e); if (headerDict[$e.text()] && e.childNodes.length === 1) $e.text(headerDict[$e.text()]); else if (e.childNodes.length === 3) if (headerDict[e.firstChild.nodeValue]) e.firstChild.nodeValue = headerDict[e.firstChild.nodeValue]; }); }; headerTrans(); } } private chatTranslate(): void { if (document.querySelector('div#chatRoot')) { const chatOB = new MutationObserver(_ => { chatOB.disconnect(); chatTrans(); chatOB.observe($('div#chatRoot').get(0), { childList: true, subtree: true, attributes: true }); }); const chatTrans = function chatTrans() { // 聊天框的标题 $('div#chatRoot div[class^="chat-box-title"] span[class^="name"]').each((i, e) => { let $e = $(e); if (chatDict[$e.text().trim()]) $e.text(chatDict[$e.text().trim()]); }); // 聊天设置的左边label $('div[class^="chat-settings-opts"] div[class*="label"]').each((i, e) => { let $e = $(e); if ($e.next().children('div.rc-slider').length > 0) { // 高度和宽度有响应式的% if (chatDict[$e.text().split(' ')[0]]) { $e.text($e.text().replace($e.text().split(' ')[0], chatDict[$e.text().split(' ')[0]])); } return; } if (chatDict[$e.text().trim()]) $e.text(chatDict[$e.text().trim()]); }); // 选项下拉栏 $('div[class^="dropdown-root"]').find('*').contents().each((i, e) => { if (e.nodeType !== 3) return; if (chatDict[e.nodeValue]) e.nodeValue = chatDict[e.nodeValue]; }); // 设置的两个选项 $('label[class^="privacy-label"]').each((i, e) => { let $e = $(e); if (chatDict[$e.text().trim()]) $e.text(chatDict[$e.text().trim()]); }); // people中的5个分类 faction friend... $('ul[class^="type-list"] li a').each((i, e) => { let $e = $(e); if (chatDict[$e.text().trim()]) $e.text(chatDict[$e.text().trim()]); }); // people中的列表添加框placeholder $('div.ac-wrapper input.ac-search').each((i, e) => { let $e = $(e); if (chatDict[$e.attr('placeholder')]) $e.attr('placeholder', chatDict[$e.attr('placeholder')]); }); // let $chatRootOverview = document.querySelector('div#chatRoot div[class^="overview"] > div > div:nth-child(2)'); if (eventsDict[$chatRootOverview.innerText.trim()]) { $chatRootOverview.innerText = eventsDict[$chatRootOverview.innerText.trim()]; } }; chatTrans(); chatOB.observe(document.querySelector('div#chatRoot'), { childList: true, subtree: true, attributes: true }); } } // 搜索玩家的4个分类按钮 private playerSearchBoxTrans(): void { const opt = { childList: true, subtree: true, }; new MutationObserver((mutation, observer) => { let peopleCat = document.querySelectorAll('ul.ac-options li a'); observer.disconnect(); mutation.forEach((e) => { if ((e.target).className === 'ac-wrapper') { peopleCat.forEach((e) => { if (chatDict[e.innerText.trim()]) e.innerText = chatDict[e.innerText.trim()]; }); } }) observer.observe(document.body, opt); }).observe(document.body, opt); } }