diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/install.py b/install.py new file mode 100644 index 0000000..356dcba --- /dev/null +++ b/install.py @@ -0,0 +1,10 @@ +import launch +import os + +req_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "requirements.txt") + +with open(req_file) as file: + for lib in file: + lib = lib.strip() + if not launch.is_installed(lib): + launch.run_pip(f"install {lib}", f"sd-webui-auto-language requirement: {lib}") \ No newline at end of file diff --git a/javascript/auto_localization.js b/javascript/auto_localization.js new file mode 100644 index 0000000..8babc11 --- /dev/null +++ b/javascript/auto_localization.js @@ -0,0 +1,727 @@ + +// this list no trans +var pass_keys = { + "BSRGAN":1, + "DDIM Eta":1, + "Trans Js":1, + "logSNR":1, + "DDPM":1, + "UniPCMultistep":1, + "LMSDiscrete":1, + "EulerDiscrete":1, + "Filewords":1, + "xformers":1, + "PNDM":1, + "vae":1, + "lms":1, + "pndm":1, + "ddim":1, + "dpmsolver":1, + "SGDNesterov":1, + "AdamW":1, + "DAdaptation":1, + "DPMSolverMultistep":1, + "DEISMultistep":1, + "HeunDiscrete":1, + "devilkkw":1, + "parrotzone":1, + "AdaFactor":1, + "adafactor":1, + "lowram":1, + "dpmsingle":1, + "veryslow":1, + "Perlin H":1, + "EulerAncestralDiscrete":1, + "DPMSolverSinglestep":1, + "LoRA":1 +} + +// is en +function containsEnWorld(text) { + if (text.length<=3) + return false + if(pass_keys[text]) + return false + if (/^[a-zA-Z\s]*[a-zA-Z][.?!]?$/.test(text)) { + return true; + } + return false +} + +function get_config(filePath) { + let request = new XMLHttpRequest(); + request.open("GET", 'trans/config', false);//Async + request.send(null); + if (request.responseText.length == 0) return ''; + + try{ + var json = JSON.parse(request.responseText) + return json.config; + }catch(e){ + } + return {} +} + +function auto_save_setting() { + var data = { + auto_language_enabled:gradioApp().querySelector('#auto_language_enabled input').checked, + show_en_enabled:gradioApp().querySelector('#show_en_enabled input').checked, + to_lan:gradioApp().querySelector('#auto_to_lang select').value, + transer:gradioApp().querySelector('#auto_langer_drop select').value + } + + + let request = new XMLHttpRequest(); + request.open("POST", 'trans/save_config', false);//Async + request.setRequestHeader("Content-Type", "application/json"); + request.send(JSON.stringify(data)); + if (request.responseText.length == 0) return ''; + + try{ + var json = JSON.parse(request.responseText) + if (json.error == 0) { + showToast('save settings successful') + } + }catch(e){ + } + return +} + +function local_trans_list(text_list) { + const list = Array.from(text_list); + if (list.length == 0) { + showToast('trans list is empty') + return + } + let request = new XMLHttpRequest(); + request.open("POST", `trans/local_trans_list`, true);//is Async + request.onreadystatechange = function() { + if (this.readyState === 4 && this.status === 200) { + auto_end_auto_trans() + } + }; + request.send(JSON.stringify(list)); +} + +function local_trans(text, save=true, is_async=true, en=false) { + if (text.length == 0) { + showToast('trans text is empty') + return + } + let request = new XMLHttpRequest(); + is_safe = save?1:0 + request.open("GET", `trans/local_trans?text=${text}&&save=${is_safe}&&en=${en}`, is_async);//is Async + request.send(null); + if (request.responseText.length == 0) return ''; + var json = JSON.parse(request.responseText) + return json.txt; +} + +function local_save_trans(text, tran) { + let request = new XMLHttpRequest(); + request.open("GET", `trans/local_save_trans?text=${text}&&tran=${tran}`, true);//Async + request.send(null); + +} + +function read_file(filePath) { + let request = new XMLHttpRequest(); + request.open("GET", `file=${filePath}`, false);// no async + request.send(null); + return request.responseText; +} + +function download_localization() { + try{ + var json = JSON.parse(read_file('localizations/my.json?time='+Date.now())) + Object.keys(json).forEach(function(key){ + localization[key] = json[key] + }) + }catch(e){ + + } +} + + +function getTranslation(text){ + if(! text) return undefined + + if(translated_lines[text] === undefined){ + original_lines[text] = 1 + } + + tl = localization[text] + if(tl !== undefined){ + if (tl==text) return undefined + translated_lines[tl] = 1 + + if(typeof(trans_config)!='undefined' && trans_config.show_en_enabled) + tl = text+'/'+tl + else + tl = text + }else{ + if (containsEnWorld(text)) { + // local_trans(text) + trans_config.trans_list.add(text) + } + } + + return tl +} + +function auto_change_lan(v){ +} + +function auto_change_transer(v){ +} + +function auto_change_language_enabled(v){ +} + +function auto_change_show_en_enabled(v){ +} + +function auto_end_auto_trans(){ + gradioApp().getElementById('auto_trans_btn').innerHTML="Start Auto Translate" + showToast('finish') +} + +function getActivePrompt() { + const currentTab = get_uiCurrentTabContent(); + switch (currentTab.id) { + case "tab_txt2img": + return currentTab.querySelector("#txt2img_prompt textarea"); + case "tab_img2img": + return currentTab.querySelector("#img2img_prompt textarea"); + } + return null; +} + +function getActiveNegativePrompt() { + const currentTab = get_uiCurrentTabContent(); + switch (currentTab.id) { + case "tab_txt2img": + return currentTab.querySelector("#txt2img_neg_prompt textarea"); + case "tab_img2img": + return currentTab.querySelector("#img2img_neg_prompt textarea"); + } + return null; +} + +function showProgress(progressbarContainer,atEnd,progress_call){ + var dateStart = new Date() + var wasEverActive = false + var parentProgressbar = progressbarContainer.parentNode + + var divProgress = document.createElement('div') + divProgress.className='progressDiv' + divProgress.style.display = "" + var divInner = document.createElement('div') + divInner.className='progress' + + divProgress.appendChild(divInner) + parentProgressbar.insertBefore(divProgress, progressbarContainer) + + var removeProgressBar = function(){ + setTitle("") + parentProgressbar.removeChild(divProgress) + + atEnd && atEnd() + } + + var fun = function(id_live_preview){ + request("./trans/progress", {}, function(res){ + progress_call && progress_call(res) + if(res.completed){ + removeProgressBar() + return + } + + var rect = progressbarContainer.getBoundingClientRect() + + if(rect.width){ + divProgress.style.width = rect.width + "px"; + } + + progressText = "" + + divInner.style.width = ((res.progress || 0) * 100.0) + '%' + divInner.style.background = res.progress ? "" : "transparent" + + if(res.progress > 0){ + progressText = ((res.progress || 0) * 100.0).toFixed(0) + '%' + } + + setTitle(progressText) + + if(res.textinfo && res.textinfo.indexOf("\n") == -1){ + progressText = res.textinfo + " " + progressText + } + + divInner.textContent = progressText + + var elapsedFromStart = (new Date() - dateStart) / 1000 + + if(elapsedFromStart > 5 && !res.active){ + removeProgressBar() + return + } + + setTimeout(() => { + fun(res.id_live_preview); + }, 500) + }, function(){ + removeProgressBar() + }) + } + + fun(0) +} + +function showToast(message) { + var toast = document.getElementById('toast'); + if (!toast) { + toast = document.createElement('div'); + toast.id = "toast"; + gradioApp().appendChild(toast); + } + + toast.innerHTML = message; + toast.style.opacity = 1; + setTimeout(() => { + toast.style.opacity = 0; + }, 2000); +} + +function hide_trans_dialg() { + const dialogs = document.querySelectorAll('[id^="dialog_"]'); + dialogs.forEach(dialog => { + dialog.remove(); + }); +} + +function show_trans_dialg(to_lan, top, left, title) { + if (document.getElementById('dialog_'+title)) { + return + } + // create draggable window + const windowDiv = document.createElement('div'); + windowDiv.style.position = 'absolute'; + windowDiv.style.top = top+'px'; + windowDiv.style.left = left+'px'; + windowDiv.style.width = '600px'; + windowDiv.style.height = '180px'; + windowDiv.style.border = 'none'; + windowDiv.style.background = '#f5f5f5'; + windowDiv.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.2)'; + windowDiv.style.zIndex = '9999'; + windowDiv.id = 'dialog_'+title + document.body.appendChild(windowDiv); + + // create title bar + const titleBar = document.createElement('div'); + titleBar.style.position = 'absolute'; + titleBar.style.top = '0px'; + titleBar.style.left = '0px'; + titleBar.style.width = '580px'; + titleBar.style.height = '30px'; + titleBar.style.background = '#4CAF50'; + titleBar.style.color = 'white'; + titleBar.style.fontSize = '16px'; + titleBar.style.display = 'flex'; + titleBar.style.alignItems = 'center'; + titleBar.style.justifyContent = 'space-between'; + titleBar.style.padding = '0px 10px'; + titleBar.innerHTML = title; + titleBar.draggable = true; + windowDiv.appendChild(titleBar); + + // create close button + const closeButton = document.createElement('button'); + closeButton.innerHTML = 'X'; + closeButton.style.position = 'absolute'; + closeButton.style.top = '5px'; + closeButton.style.right = '5px'; + closeButton.addEventListener('click', () => { + windowDiv.remove(); + }); + titleBar.appendChild(closeButton); + + + // make title bar draggable + let shiftX = 0; + let shiftY = 0; + let isDragging = false; + + titleBar.addEventListener('mousedown', function(event) { + if (event.target !== closeButton && event.target !== translateButton && event.target !== backButton && event.target !== inputBox) { + isDragging = true; + shiftX = event.clientX - windowDiv.getBoundingClientRect().left; + shiftY = event.clientY - windowDiv.getBoundingClientRect().top; + } + }); + + document.addEventListener('mousemove', function(event) { + if (isDragging) { + windowDiv.style.left = event.pageX - shiftX + 'px'; + windowDiv.style.top = event.pageY - shiftY + 'px'; + } + }); + + document.addEventListener('mouseup', function(event) { + isDragging = false; + }); + + + + // create input text box + const inputBox = document.createElement('textarea'); + inputBox.id='auto_input_strans_'+title + inputBox.style = ` + position: absolute; + top: 50px; + left: 10px; + width: 570px; + height: 80px; + border-radius: 5px; + border: none; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + font-size: 16px; + padding-left: 10px; + word-wrap: break-word; + overflow-wrap: break-word; + white-space: pre-wrap; + `; + inputBox.placeholder = 'Enter text to translate'; + windowDiv.appendChild(inputBox); + + const charCountLabel = document.createElement('label'); + charCountLabel.style = ` + position: absolute; + bottom: 27px; + left: 10px; + font-size: 16px; + color: #4CAF50; + `; + charCountLabel.innerHTML = ''; + inputBox.addEventListener('input', () => { + charCountLabel.innerHTML = inputBox.value.length + ' c'; + }); + windowDiv.appendChild(charCountLabel); + + const addButton = document.createElement('button'); + addButton.innerHTML = '+'; + addButton.style.position = 'absolute'; + addButton.style.top = '140px'; + addButton.style.left = '120px'; + addButton.style.width = '80px'; + addButton.style.height = '30px'; + addButton.style.borderRadius = '5px'; + addButton.style.border = 'none'; + addButton.style.background = '#4CAF50'; + addButton.style.color = 'white'; + addButton.style.fontSize = '16px'; + addButton.addEventListener('click', () => { + const inputText = inputBox.value; + if (inputText.length==0) {return} + const translatedText = local_trans(inputText, false, false, true); + if (translatedText.length==0 || translatedText==inputText) {return} + const prompt = getActivePrompt(); + if (prompt.value.length==0) + prompt.value = translatedText + else + prompt.value = prompt.value + ',' + translatedText + trans_config[title] = null + trans_config[title+'trans'] = null + }); + addButton.addEventListener('mousedown', () => { + addButton.style.background = '#3e8e41'; + }); + addButton.addEventListener('mouseup', () => { + addButton.style.background = '#4CAF50'; + }); + windowDiv.appendChild(addButton); + + // create translate button + const translateButton = document.createElement('button'); + translateButton.innerHTML = 'Translate En'; + translateButton.style.position = 'absolute'; + translateButton.style.top = '140px'; + translateButton.style.left = '240px'; + translateButton.style.width = '140px'; + translateButton.style.height = '30px'; + translateButton.style.borderRadius = '5px'; + translateButton.style.border = 'none'; + translateButton.style.background = '#4CAF50'; + translateButton.style.color = 'white'; + translateButton.style.fontSize = '16px'; + translateButton.addEventListener('click', () => { + const inputText = inputBox.value; + if (inputText.length==0) {return} + if (inputText == trans_config[title]) { + prompt.value = trans_config[title+'trans'] + }else{ + const translatedText = local_trans(inputText, false, false, true); + if (translatedText.length==0 || translatedText==inputText) {return} + const prompt = getActivePrompt(); + prompt.value = translatedText + trans_config[title] = inputText + trans_config[title+'trans'] = translatedText + } + }); + translateButton.addEventListener('mousedown', () => { + translateButton.style.background = '#3e8e41'; + }); + translateButton.addEventListener('mouseup', () => { + translateButton.style.background = '#4CAF50'; + }); + windowDiv.appendChild(translateButton); + + // create back button + const backButton = document.createElement('button'); + backButton.innerHTML = 'Translate '+to_lan; + backButton.style.position = 'absolute'; + backButton.style.top = '140px'; + backButton.style.left = '420px'; + backButton.style.width = '140px'; + backButton.style.height = '30px'; + backButton.style.borderRadius = '5px'; + backButton.style.border = 'none'; + backButton.style.background = '#4CAF50'; + backButton.style.color = 'white'; + backButton.style.fontSize = '16px'; + backButton.addEventListener('click', () => { + const prompt = getActivePrompt(); + const inputText = prompt.value; + if (inputText.length==0) {return} + if (inputText == trans_config[title+'trans']) { + inputBox.value = trans_config[title] + }else{ + const translatedText = local_trans(inputText, false, false); + if (translatedText.length==0 || translatedText==inputText) {return} + inputBox.value = translatedText + trans_config[title] = translatedText + trans_config[title+'trans'] = inputText + } + }); + backButton.addEventListener('mousedown', () => { + backButton.style.background = '#3e8e41'; + }); + backButton.addEventListener('mouseup', () => { + backButton.style.background = '#4CAF50'; + }); + windowDiv.appendChild(backButton); +} + +(function () { + const customCSS = ` + #toast { + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + padding: 10px 20px; + background-color: rgba(0, 0, 0, 0.7); + color: #fff; + border-radius: 5px; + z-index: 9999; + opacity: 0; + transition: opacity 0.3s ease-in-out; + } + ` + + function add_div(){ + // add btn + var txt_parent = gradioApp().getElementById('txt2img_tools') + var img_parent = gradioApp().getElementById('img2img_tools') + if(!txt_parent || !img_parent) return false; + if(!gradioApp().getElementById('txt_trans_prompt')){ + var txt_html = ` + + + ` + txt_parent.innerHTML+=txt_html + gradioApp().querySelector('#txt_trans_prompt').addEventListener('click', () => { + trans_config.cur_tab_index = get_tab_index('tabs') + show_trans_dialg(trans_config.to_lan, 21, 57, "txt2img Prompt") + } + ); + gradioApp().querySelector('#txt_trans_neprompt').addEventListener('click', () => { + trans_config.cur_tab_index = get_tab_index('tabs') + show_trans_dialg(trans_config.to_lan, 393, 57, "txt2img Negative Prompt") + } + ); + + var img_html = ` + + + ` + img_parent.innerHTML+=img_html + gradioApp().querySelector('#img_trans_prompt').addEventListener('click', () => { + trans_config.cur_tab_index = get_tab_index('tabs') + show_trans_dialg(trans_config.to_lan, 21, 57, "img2img Prompt") + } + ); + gradioApp().querySelector('#img_trans_neprompt').addEventListener('click', () => { + trans_config.cur_tab_index = get_tab_index('tabs') + show_trans_dialg(trans_config.to_lan, 393, 57, "img2img Negative Prompt") + } + ); + } + + var node = gradioApp().getElementById('auto_language_jsdiv') + if(!node) return false; + var session = node + const modal = document.createElement('div') + modal.innerHTML = ` +
The untranslated characters will be translated automatically and will not affect the old translations. Use the function in the lower right corner to easily check and quickly modify the current translation.1,Save the setting;2,Click start button;3,Reload your browser.
") + with gr.Row(): + with gr.Column(scale=80): + textbox_info = gr.Textbox(label='Translated Status', value=f'Auto Translate Num:{trans_succ}',readonly=True, elem_id="auto_textbox_info") + auto_trans_btn = gr.Button(value="Start Auto Translate", variant='primary', elem_id="auto_trans_btn") + with gr.Row(): + with gr.Column(scale=45): + text_lan = gr.Textbox(label="Text", lines=3, value="", elem_id="auto_text_lan", placeholder="your select language") + with gr.Column(): + with gr.Row(): + auto_trans_to_en = gr.Button(value=f'-->', elem_id="auto_trans_to_en") + with gr.Row(): + auto_trans_to_lan = gr.Button(value=f'<--', elem_id="auto_trans_to_lan") + + with gr.Column(scale=45): + text_lan_translated = gr.Textbox(label="Translated Text", lines=3, value="", elem_id="text_lan_translated", placeholder="english") + + + gr.HTML("