Translator | 2026

Chat Translation Assistant

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==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());
                }
            }
        }
    });
})();