Path: blob/master/javascript/localization.js
3055 views
1// localization = {} -- the dict with translations is created by the backend23var ignore_ids_for_localization = {4setting_sd_hypernetwork: 'OPTION',5setting_sd_model_checkpoint: 'OPTION',6modelmerger_primary_model_name: 'OPTION',7modelmerger_secondary_model_name: 'OPTION',8modelmerger_tertiary_model_name: 'OPTION',9train_embedding: 'OPTION',10train_hypernetwork: 'OPTION',11txt2img_styles: 'OPTION',12img2img_styles: 'OPTION',13setting_random_artist_categories: 'OPTION',14setting_face_restoration_model: 'OPTION',15setting_realesrgan_enabled_models: 'OPTION',16extras_upscaler_1: 'OPTION',17extras_upscaler_2: 'OPTION',18};1920var re_num = /^[.\d]+$/;21var re_emoji = /[\p{Extended_Pictographic}\u{1F3FB}-\u{1F3FF}\u{1F9B0}-\u{1F9B3}]/u;2223var original_lines = {};24var translated_lines = {};2526function hasLocalization() {27return window.localization && Object.keys(window.localization).length > 0;28}2930function textNodesUnder(el) {31var n, a = [], walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false);32while ((n = walk.nextNode())) a.push(n);33return a;34}3536function canBeTranslated(node, text) {37if (!text) return false;38if (!node.parentElement) return false;3940var parentType = node.parentElement.nodeName;41if (parentType == 'SCRIPT' || parentType == 'STYLE' || parentType == 'TEXTAREA') return false;4243if (parentType == 'OPTION' || parentType == 'SPAN') {44var pnode = node;45for (var level = 0; level < 4; level++) {46pnode = pnode.parentElement;47if (!pnode) break;4849if (ignore_ids_for_localization[pnode.id] == parentType) return false;50}51}5253if (re_num.test(text)) return false;54if (re_emoji.test(text)) return false;55return true;56}5758function getTranslation(text) {59if (!text) return undefined;6061if (translated_lines[text] === undefined) {62original_lines[text] = 1;63}6465var tl = localization[text];66if (tl !== undefined) {67translated_lines[tl] = 1;68}6970return tl;71}7273function processTextNode(node) {74var text = node.textContent.trim();7576if (!canBeTranslated(node, text)) return;7778var tl = getTranslation(text);79if (tl !== undefined) {80node.textContent = tl;81}82}8384function processNode(node) {85if (node.nodeType == 3) {86processTextNode(node);87return;88}8990if (node.title) {91let tl = getTranslation(node.title);92if (tl !== undefined) {93node.title = tl;94}95}9697if (node.placeholder) {98let tl = getTranslation(node.placeholder);99if (tl !== undefined) {100node.placeholder = tl;101}102}103104textNodesUnder(node).forEach(function(node) {105processTextNode(node);106});107}108109function localizeWholePage() {110processNode(gradioApp());111112function elem(comp) {113var elem_id = comp.props.elem_id ? comp.props.elem_id : "component-" + comp.id;114return gradioApp().getElementById(elem_id);115}116117for (var comp of window.gradio_config.components) {118if (comp.props.webui_tooltip) {119let e = elem(comp);120121let tl = e ? getTranslation(e.title) : undefined;122if (tl !== undefined) {123e.title = tl;124}125}126if (comp.props.placeholder) {127let e = elem(comp);128let textbox = e ? e.querySelector('[placeholder]') : null;129130let tl = textbox ? getTranslation(textbox.placeholder) : undefined;131if (tl !== undefined) {132textbox.placeholder = tl;133}134}135}136}137138function dumpTranslations() {139if (!hasLocalization()) {140// If we don't have any localization,141// we will not have traversed the app to find142// original_lines, so do that now.143localizeWholePage();144}145var dumped = {};146if (localization.rtl) {147dumped.rtl = true;148}149150for (const text in original_lines) {151if (dumped[text] !== undefined) continue;152dumped[text] = localization[text] || text;153}154155return dumped;156}157158function download_localization() {159var text = JSON.stringify(dumpTranslations(), null, 4);160161var element = document.createElement('a');162element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));163element.setAttribute('download', "localization.json");164element.style.display = 'none';165document.body.appendChild(element);166167element.click();168169document.body.removeChild(element);170}171172document.addEventListener("DOMContentLoaded", function() {173if (!hasLocalization()) {174return;175}176177onUiUpdate(function(m) {178m.forEach(function(mutation) {179mutation.addedNodes.forEach(function(node) {180processNode(node);181});182});183});184185localizeWholePage();186187if (localization.rtl) { // if the language is from right to left,188(new MutationObserver((mutations, observer) => { // wait for the style to load189mutations.forEach(mutation => {190mutation.addedNodes.forEach(node => {191if (node.tagName === 'STYLE') {192observer.disconnect();193194for (const x of node.sheet.rules) { // find all rtl media rules195if (Array.from(x.media || []).includes('rtl')) {196x.media.appendMedium('all'); // enable them197}198}199}200});201});202})).observe(gradioApp(), {childList: true});203}204});205206207