채팅 번역 도우미
// ==UserScript==
// @name Translator | 2026
// @namespace https://github.com/GameSketchers
// @version 0.1
// @description Chat Translation Assistant
// @description:tr Sohbet Çeviri Yardımcısı
// @description:pt Assistente de Tradução de Chat
// @description:ru Помощник перевода чата
// @description:es Asistente de Traducción de Chat
// @description:fr Assistant de Traduction de Chat
// @description:de Chat-Übersetzungsassistent
// @description:ja チャット翻訳アシスタント
// @description:ko 채팅 번역 도우미
// @description:zh 聊天翻译助手
// @description:ar مساعد ترجمة الدردشة
// @author Qwyua
// @match *://gartic.io/*
// @run-at document-end
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @connect translate.googleapis.com
// @license MIT
// ==/UserScript==
// obsolescencethysen istegi uzerine
/gartic\.io$/.test(location.host)&&(()=>{
const onElementAdded4=(s,c,m=1)=>{let o,d=0,p=e=>(d||c(e),m||(d=1,o?.disconnect())),t=()=>{o?.disconnect(),d=0,o=new MutationObserver(r=>{for(let i=0;i<r.length;i++)for(let n of r[i].addedNodes)n.nodeType===1&&(n.matches?.(s)?p(n):(n.querySelector?.(s)&&p(n.querySelector(s))))}),o.observe(document.documentElement,{childList:1,subtree:1});document.querySelector(s)&&p(document.querySelector(s))};t();return{stop:()=>(o?.disconnect(),d=1),start:()=>(o?.disconnect(),t()),get active(){return!d}}};
;(o=>o[Object.keys(o).find(k=>location.href.includes(k))]?.())({
gartic:()=>{
new class{
constructor(){
const w=unsafeWindow
this._translator=w._translator||(w._translator={})
Object.defineProperty(this._translator,"self",{value:this,enumerable:0,configurable:1,writable:1})
onElementAdded4("div#screenRoom",e=>{let g,c,k,f=n=>n&&!g&&(n.tag==1&&(c=n.stateNode?.props?.children?.[0]?._owner?.stateNode)&&(g=this._translator._game=c._game)&&(g._chat=c._chatElem,this.joinedRoom(g)),!g&&f(n.child));for(k in e)/^__r/.test(k)&&f(e[k])},1)
this.langs={
"none": "Off",
"en": "English",
"tr": "Türkçe",
"pt": "Português",
"ru": "Русский",
"es": "Español",
"fr": "Français",
"de": "Deutsch",
"it": "Italiano",
"zh": "中文",
"hi": "हिन्दी",
"ar": "العربية",
"bn": "বাংলা",
"ja": "日本語",
"ko": "한국어"
}
this.readLanguage=localStorage.getItem("readLanguage")||"auto"
this.seenLanguage=localStorage.getItem("seenLanguage")||(navigator.language||navigator.userLanguage)
this.sendLanguage=localStorage.getItem("sendLanguage")||"none"
this.translateActive=!1
this.smartMode=1
this.spamDejected=0
this.messageQueue = [];
}
isOnlySymbols = (msg) => !/[\p{L}\p{N}]/u.test(msg);
async translate(MMq,tLang,rLang) {
const isArray = Array.isArray(MMq);
const query = isArray?MMq.map(m=>encodeURIComponent(m)).join('&q='):encodeURIComponent(MMq);
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${rLang||"auto"}&tl=${tLang}&dt=t&q=${query}`;
return new Promise(resolve=>{
GM_xmlhttpRequest({
method: 'GET',
url: url,
onload:(x)=>{
const data=JSON.parse(x.responseText);
isArray&&(resolve(data[0].map(item=>item[0])),0);
!isArray&&(()=>{
const result=data[2]==this.readLanguage?MMq:data[0][0][0];
const fail=!result&&this.translateActive;
this.spamDejected=fail?this.spamDejected+1:0;
(fail&&this.spamDejected>=5)&&(document.querySelector("#Translation button").click(),this.spamDejected=0);
resolve(result||MMq);
})();
},
onerror:()=>resolve(MMq)
});
});
}
async joinedRoom(){
onElementAdded4("#chat h5",h5=>{document.getElementById('TranslationTrigger')||(this.h5=h5,this.injectHTML())},0);
this.timeoutId = null;
this.addCHATMessage = this._translator._game._socket._callbacks["$11"][0].bind(this._translator._game._socket._callbacks["$11"][0]);
this._translator._game._socket._callbacks["$11"][0]=async(playerID,message)=>{
this.isOnlySymbols(message)||message.length<5||this._translator._game._id==playerID||!this.translateActive||this.sendLanguage=="auto"||this.seenLanguage=='none'?this.addCHATMessage(playerID,message):(
this.messageQueue.push({playerID,message}),
this.timeoutId && clearTimeout(this.timeoutId),
this.timeoutId=setTimeout(async()=>{
const translated = await this.translate(this.messageQueue.map(m=>m.message),this.seenLanguage);
this.messageQueue.forEach((q,w)=>this.addCHATMessage(q.playerID,translated[w]||q.message));
this.messageQueue=[];
this.timeoutId=null;
},600)
);
};
this.sendMessageCHAT=this._translator._game.message.bind(this._translator._game);
this._translator._game.message=async(t)=>{
this.isOnlySymbols(t)||!this.translateActive||this.sendLanguage=="auto"||this.sendLanguage=='none'?this.sendMessageCHAT(t):(async()=>{
const Mq=await this.translate(t,this.sendLanguage);
this.sendMessageCHAT(this.smartMode?this.simplifyText(Mq):Mq);
})()
}
}
syncPos=()=>{const{bottom:b,right:r}=this.h5.getBoundingClientRect();Object.assign(this.control.style,{top:`${b+8}px`,left:`${r-190}px`})};
setLanguage=(q,w)=>{this[q+"Language"]=w;localStorage.setItem(q+"Language",w)};
startStopTranslation(q){this.translateActive=q.classList.toggle('active');q.textContent=this.translateActive?'ON':'OFF'}
switchSmartMode(q){this.smartMode=q.classList.toggle('active');q.textContent=this.smartMode?'ON':'OFF'}
simplifyText(m){
let t=m.toLowerCase().replace(/[!?.,;:()\[\]{}"']/g,'');
const s={you:'u',are:'re',your:'ur',"you're":'ur',because:'cuz',please:'pls',thanks:'thx',language:'lang',okay:'ok'};
Object.entries(s).forEach(([k,v])=>t=t.replace(new RegExp(`\\b${k}\\b`,'g'),v));
return t;
}
injectHTML() {
this.trigger = Object.assign(document.createElement('span'),{
id: 'TranslationTrigger',
textContent: '\uE941',
onclick:e=>{e.stopPropagation();this.control.style.display=this.control.style.display==='block'?'none':(this.syncPos(),'block')},
style: 'font-family:ico;color:#3080cb;cursor:pointer;margin-left:8px;font-size:15px;vertical-align:middle;display:inline-block;transform:rotate(20deg)'
});
this.h5.appendChild(this.trigger);
this.control = Object.assign(document.createElement('div'),{
id:'Translation',
onchange:(q)=>{this._translator?.self.setLanguage(q.target.id,q.target.value)},
innerHTML: `<style>#Translation{position:fixed;display:none;background:#11223e;border:2px solid #234476;border-radius:6px;padding:12px;width:190px;z-index:9e6;box-shadow:0 6px 20px #000;box-sizing:border-box;font-family:sans-serif}#Translation div{display:flex;align-items:center;margin-bottom:5px;gap:8px}#Translation label{font-size:12px;font-weight:700;color:#8bb4e7;width:45px;flex-shrink:0}#Translation div div{display:flex;flex:1;gap:4px}#Translation select{background:#1b335a;border:1px solid #2d558d;color:#fff;border-radius:4px;font-size:12px;padding:4px;width:100%;cursor:pointer;outline:none}#Translation button{width:100%;padding:7px;border:none;border-radius:4px;font-weight:900;font-size:12px;cursor:pointer;color:#fff;transition:transform .1s;background:#ef4444;box-shadow:0 2px 0 #dc2626}#Translation button.active{background:#22c55e;box-shadow:0 2px 0 #16a34a}#Translation button:first-of-type:not(.active)~div{opacity:.5}#Translation button:active{transform:scale(.97)}</style><button onclick="_translator.self.startStopTranslation(this)" style="margin-bottom:8px">OFF</button><div><label>RECV</label><div><select id="read" style="display:none"></select><select id="seen"></select></div></div><div><label>SEND</label><div><select id="send"></select></div></div><div><label>SMART MODE</label><button onclick="_translator.self.switchSmartMode(this)" class="active" style="width:unset">ON</button></div>`
});
document.body.appendChild(this.control);
this.control.querySelectorAll('select').forEach(q=>{q.innerHTML=Object.entries(this.langs).map(([k,v])=>`<option ${k===this[`${q.id}Language`]?'selected':''} value=${k}>${v}</option>`).join('')});
document.addEventListener('mousedown',e=>{!this.control.contains(e.target)&&e.target!==this.trigger&&(this.control.style.display='none')});
window.addEventListener('resize',()=>this.control.style.display=='block'&&this.syncPos());
}
}
}
});
})();