stable-diffusion-webui
204 строки · 5.6 Кб
1
2// localization = {} -- the dict with translations is created by the backend
3
4var ignore_ids_for_localization = {5setting_sd_hypernetwork: 'OPTION',6setting_sd_model_checkpoint: 'OPTION',7modelmerger_primary_model_name: 'OPTION',8modelmerger_secondary_model_name: 'OPTION',9modelmerger_tertiary_model_name: 'OPTION',10train_embedding: 'OPTION',11train_hypernetwork: 'OPTION',12txt2img_styles: 'OPTION',13img2img_styles: 'OPTION',14setting_random_artist_categories: 'OPTION',15setting_face_restoration_model: 'OPTION',16setting_realesrgan_enabled_models: 'OPTION',17extras_upscaler_1: 'OPTION',18extras_upscaler_2: 'OPTION',19};20
21var re_num = /^[.\d]+$/;22var re_emoji = /[\p{Extended_Pictographic}\u{1F3FB}-\u{1F3FF}\u{1F9B0}-\u{1F9B3}]/u;23
24var original_lines = {};25var translated_lines = {};26
27function hasLocalization() {28return window.localization && Object.keys(window.localization).length > 0;29}
30
31function textNodesUnder(el) {32var n, a = [], walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false);33while ((n = walk.nextNode())) a.push(n);34return a;35}
36
37function canBeTranslated(node, text) {38if (!text) return false;39if (!node.parentElement) return false;40
41var parentType = node.parentElement.nodeName;42if (parentType == 'SCRIPT' || parentType == 'STYLE' || parentType == 'TEXTAREA') return false;43
44if (parentType == 'OPTION' || parentType == 'SPAN') {45var pnode = node;46for (var level = 0; level < 4; level++) {47pnode = pnode.parentElement;48if (!pnode) break;49
50if (ignore_ids_for_localization[pnode.id] == parentType) return false;51}52}53
54if (re_num.test(text)) return false;55if (re_emoji.test(text)) return false;56return true;57}
58
59function getTranslation(text) {60if (!text) return undefined;61
62if (translated_lines[text] === undefined) {63original_lines[text] = 1;64}65
66var tl = localization[text];67if (tl !== undefined) {68translated_lines[tl] = 1;69}70
71return tl;72}
73
74function processTextNode(node) {75var text = node.textContent.trim();76
77if (!canBeTranslated(node, text)) return;78
79var tl = getTranslation(text);80if (tl !== undefined) {81node.textContent = tl;82}83}
84
85function processNode(node) {86if (node.nodeType == 3) {87processTextNode(node);88return;89}90
91if (node.title) {92let tl = getTranslation(node.title);93if (tl !== undefined) {94node.title = tl;95}96}97
98if (node.placeholder) {99let tl = getTranslation(node.placeholder);100if (tl !== undefined) {101node.placeholder = tl;102}103}104
105textNodesUnder(node).forEach(function(node) {106processTextNode(node);107});108}
109
110function localizeWholePage() {111processNode(gradioApp());112
113function elem(comp) {114var elem_id = comp.props.elem_id ? comp.props.elem_id : "component-" + comp.id;115return gradioApp().getElementById(elem_id);116}117
118for (var comp of window.gradio_config.components) {119if (comp.props.webui_tooltip) {120let e = elem(comp);121
122let tl = e ? getTranslation(e.title) : undefined;123if (tl !== undefined) {124e.title = tl;125}126}127if (comp.props.placeholder) {128let e = elem(comp);129let textbox = e ? e.querySelector('[placeholder]') : null;130
131let tl = textbox ? getTranslation(textbox.placeholder) : undefined;132if (tl !== undefined) {133textbox.placeholder = tl;134}135}136}137}
138
139function dumpTranslations() {140if (!hasLocalization()) {141// If we don't have any localization,142// we will not have traversed the app to find143// original_lines, so do that now.144localizeWholePage();145}146var dumped = {};147if (localization.rtl) {148dumped.rtl = true;149}150
151for (const text in original_lines) {152if (dumped[text] !== undefined) continue;153dumped[text] = localization[text] || text;154}155
156return dumped;157}
158
159function download_localization() {160var text = JSON.stringify(dumpTranslations(), null, 4);161
162var element = document.createElement('a');163element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));164element.setAttribute('download', "localization.json");165element.style.display = 'none';166document.body.appendChild(element);167
168element.click();169
170document.body.removeChild(element);171}
172
173document.addEventListener("DOMContentLoaded", function() {174if (!hasLocalization()) {175return;176}177
178onUiUpdate(function(m) {179m.forEach(function(mutation) {180mutation.addedNodes.forEach(function(node) {181processNode(node);182});183});184});185
186localizeWholePage();187
188if (localization.rtl) { // if the language is from right to left,189(new MutationObserver((mutations, observer) => { // wait for the style to load190mutations.forEach(mutation => {191mutation.addedNodes.forEach(node => {192if (node.tagName === 'STYLE') {193observer.disconnect();194
195for (const x of node.sheet.rules) { // find all rtl media rules196if (Array.from(x.media || []).includes('rtl')) {197x.media.appendMedium('all'); // enable them198}199}200}201});202});203})).observe(gradioApp(), {childList: true});204}205});206