localization.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // localization = {} -- the dict with translations is created by the backend
  2. ignore_ids_for_localization={
  3. setting_sd_hypernetwork: 'OPTION',
  4. setting_sd_model_checkpoint: 'OPTION',
  5. setting_realesrgan_enabled_models: 'OPTION',
  6. modelmerger_primary_model_name: 'OPTION',
  7. modelmerger_secondary_model_name: 'OPTION',
  8. modelmerger_tertiary_model_name: 'OPTION',
  9. train_embedding: 'OPTION',
  10. train_hypernetwork: 'OPTION',
  11. txt2img_styles: 'OPTION',
  12. img2img_styles: 'OPTION',
  13. setting_random_artist_categories: 'SPAN',
  14. setting_face_restoration_model: 'SPAN',
  15. setting_realesrgan_enabled_models: 'SPAN',
  16. extras_upscaler_1: 'SPAN',
  17. extras_upscaler_2: 'SPAN',
  18. }
  19. re_num = /^[\.\d]+$/
  20. re_emoji = /[\p{Extended_Pictographic}\u{1F3FB}-\u{1F3FF}\u{1F9B0}-\u{1F9B3}]/u
  21. original_lines = {}
  22. translated_lines = {}
  23. function hasLocalization() {
  24. return window.localization && Object.keys(window.localization).length > 0;
  25. }
  26. function textNodesUnder(el){
  27. var n, a=[], walk=document.createTreeWalker(el,NodeFilter.SHOW_TEXT,null,false);
  28. while(n=walk.nextNode()) a.push(n);
  29. return a;
  30. }
  31. function canBeTranslated(node, text){
  32. if(! text) return false;
  33. if(! node.parentElement) return false;
  34. var parentType = node.parentElement.nodeName
  35. if(parentType=='SCRIPT' || parentType=='STYLE' || parentType=='TEXTAREA') return false;
  36. if (parentType=='OPTION' || parentType=='SPAN'){
  37. var pnode = node
  38. for(var level=0; level<4; level++){
  39. pnode = pnode.parentElement
  40. if(! pnode) break;
  41. if(ignore_ids_for_localization[pnode.id] == parentType) return false;
  42. }
  43. }
  44. if(re_num.test(text)) return false;
  45. if(re_emoji.test(text)) return false;
  46. return true
  47. }
  48. function getTranslation(text){
  49. if(! text) return undefined
  50. if(translated_lines[text] === undefined){
  51. original_lines[text] = 1
  52. }
  53. tl = localization[text]
  54. if(tl !== undefined){
  55. translated_lines[tl] = 1
  56. }
  57. return tl
  58. }
  59. function processTextNode(node){
  60. var text = node.textContent.trim()
  61. if(! canBeTranslated(node, text)) return
  62. tl = getTranslation(text)
  63. if(tl !== undefined){
  64. node.textContent = tl
  65. }
  66. }
  67. function processNode(node){
  68. if(node.nodeType == 3){
  69. processTextNode(node)
  70. return
  71. }
  72. if(node.title){
  73. tl = getTranslation(node.title)
  74. if(tl !== undefined){
  75. node.title = tl
  76. }
  77. }
  78. if(node.placeholder){
  79. tl = getTranslation(node.placeholder)
  80. if(tl !== undefined){
  81. node.placeholder = tl
  82. }
  83. }
  84. textNodesUnder(node).forEach(function(node){
  85. processTextNode(node)
  86. })
  87. }
  88. function dumpTranslations(){
  89. var dumped = {}
  90. if (localization.rtl) {
  91. dumped.rtl = true
  92. }
  93. Object.keys(original_lines).forEach(function(text){
  94. if(dumped[text] !== undefined) return
  95. dumped[text] = localization[text] || text
  96. })
  97. return dumped
  98. }
  99. function download_localization() {
  100. var text = JSON.stringify(dumpTranslations(), null, 4)
  101. var element = document.createElement('a');
  102. element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
  103. element.setAttribute('download', "localization.json");
  104. element.style.display = 'none';
  105. document.body.appendChild(element);
  106. element.click();
  107. document.body.removeChild(element);
  108. }
  109. if(hasLocalization()) {
  110. onUiUpdate(function (m) {
  111. m.forEach(function (mutation) {
  112. mutation.addedNodes.forEach(function (node) {
  113. processNode(node)
  114. })
  115. });
  116. })
  117. document.addEventListener("DOMContentLoaded", function () {
  118. processNode(gradioApp())
  119. if (localization.rtl) { // if the language is from right to left,
  120. (new MutationObserver((mutations, observer) => { // wait for the style to load
  121. mutations.forEach(mutation => {
  122. mutation.addedNodes.forEach(node => {
  123. if (node.tagName === 'STYLE') {
  124. observer.disconnect();
  125. for (const x of node.sheet.rules) { // find all rtl media rules
  126. if (Array.from(x.media || []).includes('rtl')) {
  127. x.media.appendMedium('all'); // enable them
  128. }
  129. }
  130. }
  131. })
  132. });
  133. })).observe(gradioApp(), { childList: true });
  134. }
  135. })
  136. }