1class Devnagri { 2 constructor() { 3 this.arr_nodes = {}; 4 this.arr_translated_text = {}; 5 this.document_url = ""; 6 this.document_url_full = document.URL; 7 this.translation_api_retry_counter = 3; 8 this.missingTranslationPercentageOffsetForRetry = 8; 9 this.apiCounter = 0; 10 this.prevURL = ''; 11 this.translationData = {}; 12 this.objectMappingapiCounter = 0; 13 this.objectMappingData = {}; 14 this.sentenceData = {}; 15 this.prevSentenceData = []; 16 this.traversing_completion_timer; 17 this.translation_api_global_data = false; 18 this.translation_api_global_data_by_local_key; 19 this.default_lang_code; 20 this.source_lang_code; 21 this.target_lang_code; 22 this.meta_prefix = "DOTAMETA_"; 23 this.webpage_language = (document.documentElement.lang == 'en') ? 'hi' : document.documentElement.lang; 24 this.api_baseurl = `https://${window.location.hostname}/${this.webpage_language}/dotaapi`; 25 //this.api_baseurl = `http://proxy.devnagri.live/api`; 26 // this.cdn_css_link = "https://cdn.devnagri.com/css/devnagri_dota_mg_dev.css"; 27 //this.cdn_css_link = "http://localhost:5500/devnagri_dota_merged_dev.css"; 28 this.cdn_css_link = 29 `https://${window.location.hostname}/${this.webpage_language}/dota.css`; 30 31 this.login_api_url = `${this.api_baseurl}/auth/login`; 32 this.status_api_url = `${this.api_baseurl}/status`; 33 this.page_view_api_url = `${this.api_baseurl}/page-views`; 34 this.context_editor_api = `${this.api_baseurl}/save-translations`; 35 this.translation_api_url = ""; 36 this.update_api_url = ""; 37 this.api_key = ""; 38 39 this.page_view_api_count = 0; 40 41 this.subdomainObjectStore; 42 this.lang; 43 this.should_render_ui; 44 this.update_global_data_timeout; 45 this.renderUICounter = 1; 46 this.user_lat = 0; 47 this.user_long = 0; 48 this.user_ip = ""; 49 this.db = ""; 50 51 this.traverse_whole_dom = true; 52 53 this.requested_domain = ""; 54 this.domain = ""; 55 this.linkedDomains = []; 56 this.config; 57 58 this.url_object = new URL(document.URL); 59 this.web_owner = false; 60 if ( 61 this.url_object.searchParams.has("dota-token") && 62 this.url_object.searchParams.has("language_code") 63 ) { 64 this.document_url = this.url_object.origin; 65 if (!this.document_url.endsWith("/")) { 66 this.document_url = this.document_url + "/"; 67 } 68 this.web_owner = true; 69 this.dota_token = this.url_object.searchParams.get("dota-token"); 70 this.selected_lang_code = 71 this.url_object.searchParams.get("language_code"); 72 } 73 74 // check if page lang code exist.. 75 if (localStorage.getItem("devnagri_source_lang_code")) { 76 this.source_lang_code = localStorage.getItem("devnagri_source_lang_code"); 77 } else { 78 this.source_lang_code = "en"; 79 localStorage.setItem("devnagri_source_lang_code", this.source_lang_code); 80 } 81 //check if default lang code exist.. 82 if (localStorage.getItem("devnagri_default_lang_code")) { 83 this.default_lang_code = localStorage.getItem( 84 "devnagri_default_lang_code" 85 ); 86 } 87 88 this.subscription_status_active; 89 this.enable_object_mapping = false; 90 this.subdomain_object_urls_hash_map = {}; 91 this.subdomain_object_urls_hash_map_local = {}; 92 93 this.enable_blacklist = false;
94 this.blacklist_ids = []; 95 this.blacklist_classes = []; 96 97 this.frame_ids = [ 98 "nv_box_content-iframe_22196", 99 "nv_leadform_content-iframe_1810", 100 ]; 101 102 this.frames_translation_status_map = {}; 103 this.script_type = "live"; // proxy/live 104 this.status_api_global_data = {}; 105 106 this.enable_object_mapping = false; 107 this.subdomain_object_urls_hash_map = {}; 108 this.subdomain_object_urls_hash_map_local = {}; 109 110 this.up_arrow_svg_content = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="17px" height="17px" viewBox="0 0 17 17" version="1.1"><defs><filter id="alpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feColorMatrix type="matrix" in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><mask id="mask100"> <g filter="url(#alpha)"><rect x="0" y="0" width="17" height="17" style="fill:rgb(0%,0%,0%);fill-opacity:0.968627;stroke:none;"/> </g></mask><clipPath id="clip100"> <rect x="0" y="0" width="17" height="17"/></clipPath><g id="surface105" clip-path="url(#clip100)"><path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 8.550781 5.761719 C 8.789062 5.746094 9.003906 5.808594 9.195312 5.949219 C 10.910156 7.433594 12.628906 8.910156 14.347656 10.386719 C 14.550781 10.703125 14.550781 11.023438 14.347656 11.339844 C 14.03125 11.644531 13.6875 11.683594 13.3125 11.457031 C 11.765625 10.144531 10.222656 8.824219 8.6875 7.496094 C 7.152344 8.824219 5.609375 10.144531 4.0625 11.457031 C 3.628906 11.707031 3.261719 11.632812 2.957031 11.238281 C 2.828125 10.941406 2.851562 10.65625 3.027344 10.386719 C 4.746094 8.910156 6.464844 7.433594 8.175781 5.949219 C 8.296875 5.867188 8.421875 5.804688 8.550781 5.761719 Z M 8.550781 5.761719 "/></g></defs><g id="surface100"><use xlink:href="#surface105" mask="url(#mask100)"/></g></svg>`; 111 this.devngari_logo_svg_content = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30px" height="30px" viewBox="0 0 30 30" version="1.1"><defs><filter id="alpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feColorMatrix type="matrix" in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><mask id="mask0"> <g filter="url(#alpha)"><rect x="0" y="0" width="30" height="30" style="fill:rgb(0%,0%,0%);fill-opacity:0.960784;stroke:none;"/> </g></mask><clipPath id="clip1"> <rect x="0" y="0" width="30" height="30"/></clipPath><g id="surface5" clip-path="url(#clip1)"><path style=" stroke:none;fill-rule:evenodd;fill:rgb(27.843137%,60.392157%,83.137255%);fill-opacity:1;" d="M 12.679688 -0.0820312 C 14.171875 -0.0820312 15.664062 -0.0820312 17.15625 -0.0820312 C 18.871094 0.238281 20.5 0.839844 22.042969 1.722656 C 22.40625 2.699219 22.601562 3.707031 22.625 4.753906 C 22.519531 6.222656 22.296875 7.667969 21.960938 9.097656 C 15.101562 9.058594 8.253906 9.058594 1.410156 9.097656 C 2.898438 5.191406 5.605469 2.433594 9.53125 0.820312 C 10.578125 0.4375 11.628906 0.136719 12.679688 -0.0820312 Z M 12.679688 -0.0820312 "/></g><mask id="mask1"> <g filter="url(#alpha)"><rect x="0" y="0" width="30" height="30" style="fill:rgb(0%,0%,0%);fill-opacity:0.831373;stroke:none;"/> </g></mask><clipPath id="clip2"> <rect x="0" y="0" width="30" height="30"/></clipPath><g id="surface8" clip-path="url(#clip2)"><path style=" stroke:none;fill-rule:evenodd;fill:rgb(27.843137%,60.392157%,83.137255%);fill-opacity:1;" d="M 25.773438 4.835938 C 27.074219 5.988281 27.960938 7.410156 28.425781 9.097656 C 27.390625 9.015625 26.339844 9.015625 25.277344 9.097656 C 25.566406 7.691406 25.730469 6.273438 25.773438 4.835938 Z M 25.773438 4.835938 "/></g><mask id="mask2"> <g filter="url(#alpha)"><rect x="0" y="0" width="30" height="30" style="fill:rgb(0%,0%,0%);fill-opacity:0.956863;stroke:none;"/> </g></mask><clipPath id="clip3"> <rect x="0" y="0" width="30" height="30"/></clipPath><g id="surface11" clip-path="url(#clip3)"><path style=" stroke:none;fill-rule:evenodd;fill:rgb(27.843137%,60.392157%,83.137255%);fill-opacity:1;" d="M 28.921875 18.277344 C 26.078125 25.617188 20.664062 29.03125 12.679688 28.523438 C 6.808594 27.28125 2.886719 23.867188 0.910156 18.277344 C 0.507812 17.003906 0.34375 15.695312 0.414062 14.34375 C 0.382812 13.234375 0.492188 12.140625 0.746094 11.066406 C 7.
111652344 10.902344 14.558594 10.847656 21.464844 10.902344 C 21.019531 12.988281 20.523438 15.066406 19.972656 17.132812 C 19.09375 16.082031 18.152344 15.070312 17.15625 14.097656 C 14.941406 12.75 12.675781 12.695312 10.359375 13.933594 C 8.136719 15.09375 6.5625 16.8125 5.636719 19.097656 C 5.613281 22.628906 7.300781 25.007812 10.691406 26.230469 C 12.453125 26.613281 14.109375 26.339844 15.664062 25.410156 C 16.628906 24.671875 17.597656 23.933594 18.5625 23.195312 C 18.4375 23.839844 18.300781 24.496094 18.148438 25.164062 C 18.203125 25.273438 18.257812 25.382812 18.316406 25.492188 C 19.199219 25.875 20.082031 26.257812 20.96875 26.640625 C 22.261719 21.453125 23.535156 16.261719 24.777344 11.066406 C 26.214844 10.847656 27.652344 10.847656 29.089844 11.066406 C 29.339844 12.140625 29.449219 13.234375 29.417969 14.34375 C 29.492188 15.695312 29.324219 17.003906 28.921875 18.277344 Z M 28.921875 18.277344 "/></g><mask id="mask3"> <g filter="url(#alpha)"><rect x="0" y="0" width="30" height="30" style="fill:rgb(0%,0%,0%);fill-opacity:0.956863;stroke:none;"/> </g></mask><clipPath id="clip4"> <rect x="0" y="0" width="30" height="30"/></clipPath><g id="surface14" clip-path="url(#clip4)"><path style=" stroke:none;fill-rule:evenodd;fill:rgb(27.843137%,60.392157%,83.137255%);fill-opacity:1;" d="M 14.335938 15.328125 C 16.777344 14.933594 18.324219 15.890625 18.976562 18.195312 C 17.332031 20.972656 15.011719 22.992188 12.015625 24.261719 C 10.820312 24.847656 9.660156 24.792969 8.535156 24.097656 C 7.367188 22.707031 7.230469 21.203125 8.121094 19.589844 C 8.640625 18.695312 9.328125 17.957031 10.195312 17.378906 C 11.496094 16.511719 12.878906 15.832031 14.335938 15.328125 Z M 14.335938 15.328125 "/></g><mask id="mask4"> <g filter="url(#alpha)"><rect x="0" y="0" width="30" height="30" style="fill:rgb(0%,0%,0%);fill-opacity:0.898039;stroke:none;"/> </g></mask><clipPath id="clip5"> <rect x="0" y="0" width="30" height="30"/></clipPath><g id="surface17" clip-path="url(#clip5)"><path style=" stroke:none;fill-rule:evenodd;fill:rgb(17.647059%,49.803922%,72.941176%);fill-opacity:1;" d="M 0.910156 18.277344 C 2.886719 23.867188 6.808594 27.28125 12.679688 28.523438 C 20.664062 29.03125 26.078125 25.617188 28.921875 18.277344 C 27.480469 24.621094 23.558594 28.503906 17.15625 29.917969 C 15.664062 29.917969 14.171875 29.917969 12.679688 29.917969 C 6.277344 28.503906 2.351562 24.621094 0.910156 18.277344 Z M 0.910156 18.277344 "/></g></defs><g id="surface1"><use xlink:href="#surface5" mask="url(#mask0)"/><use xlink:href="#surface8" mask="url(#mask1)"/><use xlink:href="#surface11" mask="url(#mask2)"/><use xlink:href="#surface14" mask="url(#mask3)"/><use xlink:href="#surface17" mask="url(#mask4)"/></g></svg>`; 112 this.edit_button_svg_content = `<svg style="color: #3B85BA;pointer-events: none;" width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-3"><path d="M12 20h9"></path><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path></svg>`; 113 this.seo_button_svg_content = `<svg style="fill: #EF6A16;pointer-events: none;" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 511.999 511.999" style="enable-background:new 0 0 511.999 511.999;" xml:space="preserve"><g><g><path d="M359.409,120.63c-10.387,0-20.155,4.045-27.5,11.391c-3.255,3.254-3.255,8.529-0.001,11.784c3.254,3.253,8.53,3.255,11.783,0.001c4.199-4.198,9.782-6.511,15.718-6.511c12.256,0,22.228,9.971,22.228,22.228v92.642c0,12.256-9.972,22.227-22.228,22.227c-12.256,0-22.228-9.971-22.228-22.227v-87.087c0-4.602-3.729-8.332-8.332-8.332c-4.603,0-8.332,3.731-8.332,8.332v87.087c0,21.445,17.446,38.891,38.892,38.891c21.446,0,38.892-17.446,38.892-38.891v-92.642C398.3,138.076,380.854,120.63,359.409,120.63z"/></g></g><g><g><path d="M283.083,274.391h-46.968v-60.216h29.415c4.603,0,8.332-3.731,8.332-8.332c0-4.602-3.729-8.332-8.332-8.332h-29.415v-60.216h46.968v-0.001c4.603,0,8.332-3.731,8.332-8.332c0-4.601-3.729-8.332-8.332-8.332h-55.3c-4.602,0-8.332,3.731-8.332,8.332v153.761c0,4.602,3.731,8.332,8.332,8.332h55.3c4.603,0,8.332-3.731,8.332-8.332S287.686,274.391,283.083,274.391z"/></g></g><g><g><path d="M149.684,197.51c-10.652,0-19.317-8.667-19.317-19.317v-21.58c0-10.653,8.665-19.318,19.317-19.318c10.652,0,19.318,8.667,19.318,19.318c0,4.602,3.731,8.332,8.332,8.332c4.601,0,8.332-3.731,8.332-8.332c0-19.84-16.141-35.983-35.983-35.983c-19.84,0-35.981,16.142-35.981,35.983v21.58c0,19.84,16.141,35.981,35.981,35.981c10.652,0,19.318,8.667,19.318,19.318v21.58c0,10.652-8.665,19.317-19.318,19.317c-10.652,0-19.317-8.667-19.317-19.317c0-4.602-3.731-8.332-8.332-8.332c-4.601,0-8.332,3.731-8.332,8.332c0,19.84,16.141,35.981,35.981,35.981c19.84,0,35.983-16.141,35.983-35.981v-21.58C185.666,213.652,169.525,197.51,
113149.684,197.51z"/></g></g><g><g><path d="M471.246,24.766H40.754C18.283,24.766,0,43.049,0,65.52v59.227c0,4.602,3.731,8.332,8.332,8.332c4.601,0,8.332-3.731,8.332-8.332V65.52c0-13.284,10.807-24.09,24.09-24.09h430.492c13.284,0,24.09,10.807,24.09,24.09v284.411h-52.21c-4.602,0-8.332,3.731-8.332,8.332s3.731,8.332,8.332,8.332h52.21v15.273c0,13.284-10.807,24.09-24.09,24.09h-155.41H196.164H40.754c-13.284,0-24.09-10.807-24.09-24.09v-15.273h398.688c4.602,0,8.332-3.731,8.332-8.332s-3.731-8.332-8.332-8.332H16.664V152.522c0-4.602-3.731-8.332-8.332-8.332c-4.601,0-8.332,3.73-8.332,8.332V381.87c0,22.472,18.283,40.754,40.754,40.754H183.54l-20.494,47.945h-40.034c-4.602,0-8.332,3.731-8.332,8.332s3.731,8.332,8.332,8.332h265.975c4.602,0,8.332-3.731,8.332-8.332s-3.731-8.332-8.332-8.332h-40.034l-20.494-47.945h142.786c22.472,0,40.754-18.282,40.754-40.754V65.52C512,43.049,493.717,24.766,471.246,24.766z M330.83,470.568H181.17l14.238-33.31h121.185L330.83,470.568z"/></g></g><g><g><path d="M262.924,379.679c-1.914-2.906-5.583-4.299-8.952-3.457c-3.517,0.879-6.116,4.048-6.291,7.67c-0.364,7.534,9.106,11.629,14.33,6.172C264.674,387.282,265.089,382.887,262.924,379.679z"/></g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>`; 114 this.close_button_svg_content = `<svg style="fill: #ED2408;pointer-events: none;" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 475.2 475.2" style="enable-background:new 0 0 475.2 475.2;" xml:space="preserve"><g><g><path d="M405.6,69.6C360.7,24.7,301.1,0,237.6,0s-123.1,24.7-168,69.6S0,174.1,0,237.6s24.7,123.1,69.6,168s104.5,69.6,168,69.6s123.1-24.7,168-69.6s69.6-104.5,69.6-168S450.5,114.5,405.6,69.6z M386.5,386.5c-39.8,39.8-92.7,61.7-148.9,61.7s-109.1-21.9-148.9-61.7c-82.1-82.1-82.1-215.7,0-297.8C128.5,48.9,181.4,27,237.6,27s109.1,21.9,148.9,61.7C468.6,170.8,468.6,304.4,386.5,386.5z"/><path d="M342.3,132.9c-5.3-5.3-13.8-5.3-19.1,0l-85.6,85.6L152,132.9c-5.3-5.3-13.8-5.3-19.1,0c-5.3,5.3-5.3,13.8,0,19.1l85.6,85.6l-85.6,85.6c-5.3,5.3-5.3,13.8,0,19.1c2.6,2.6,6.1,4,9.5,4s6.9-1.3,9.5-4l85.6-85.6l85.6,85.6c2.6,2.6,6.1,4,9.5,4c3.5,0,6.9-1.3,9.5-4c5.3-5.3,5.3-13.8,0-19.1l-85.4-85.6l85.6-85.6C347.6,146.7,347.6,138.2,342.3,132.9z"/></g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>`; 115 this.save_button_svg_content = `<svg style="fill: #52C7A5;pointer-events: none;" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 486 486" style="enable-background:new 0 0 486 486;" xml:space="preserve"><g><g><path d="M473.7,485.75c6.8,0,12.3-5.5,12.3-12.3v-359.8c0-3.6-1.6-7-4.3-9.3L363,2.85c-0.2-0.2-0.4-0.3-0.6-0.4c-0.3-0.2-0.5-0.4-0.8-0.6c-0.4-0.2-0.7-0.4-1.1-0.6c-0.3-0.1-0.6-0.3-0.9-0.4c-0.4-0.2-0.9-0.3-1.3-0.4c-0.3-0.1-0.6-0.2-0.9-0.2c-0.8-0.1-1.5-0.2-2.3-0.2H12.3C5.5,0.05,0,5.55,0,12.35v461.3c0,6.8,5.5,12.3,12.3,12.3h461.4V485.75z M384.5,461.25h-283v-184.1c0-3.7,3-6.6,6.6-6.6h269.8c3.7,0,6.6,3,6.6,6.6V461.25z M161.8,24.45h180.9v127.8c0,0.8-0.6,1.4-1.4,1.4h-178c-0.8,0-1.4-0.7-1.4-1.4V24.45H161.8z M24.6,24.45h112.8v127.8c0,14.3,11.6,25.9,25.9,25.9h178c14.3,0,25.9-11.6,25.9-25.9V38.75l94.2,80.6v341.9H409v-184.1c0-17.2-14-31.1-31.1-31.1H108.1c-17.2,0-31.1,14-31.1,31.1v184.2H24.6V24.45z"/><path d="M227.4,77.65h53.8v32.6c0,6.8,5.5,12.3,12.3,12.3s12.3-5.5,12.3-12.3v-44.8c0-6.8-5.5-12.3-12.3-12.3h-66.1c-6.8,0-12.3,5.5-12.3,12.3S220.7,77.65,227.4,77.65z"/><path d="M304.5,322.85h-123c-6.8,0-12.3,5.5-12.3,12.3s5.5,12.3,12.3,12.3h123c6.8,0,12.3-5.5,12.3-12.3S311.3,322.85,304.5,322.85z"/><path d="M304.5,387.75h-123c-6.8,0-12.3,5.5-12.3,12.3s5.5,12.3,12.3,12.3h123c6.8,0,12.3-5.5,12.3-12.3S311.3,387.75,304.5,387.75z"/></g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>`; 116 117 //this.expiry_token_time = localStorage.getItem("devnagri_token_expiry_time"); 118 this.edit_mode_enabled = false; 119 this.content_editable = []; 120 121 // meta editor variables 122 this.meta_count = 0; 123 this.metatag_arr = {}; 124 this.metatag_arr.TITLE = { 125 tag: "TITLE", 126 engText: document.title, 127 translatedText: document.title, 128 }; 129 this.metatag_key = ""; 130 131 // sentence merging vars 132 this.enable_sentence_merging = false;
133 this.sentence_merging_initial_url_date = "2025-11-16T06:55:06.113Z"; 134 this.sentence_merging_fallback_url_date = "2010-09-14T06:55:06.113Z"; 135 this.sentence_nodes = {}; 136 this.sentence_nodes_by_orig_text = {} 137 this.sentence_parents = ["P", "LI", "H1", "H2", "H3", "H4", "H5", "H6"]; 138 this.sentence_children = ["#TEXT", "SPAN", "STRONG", "B", "I", "BR", "A"]; 139 140 this.sentence_merge_separator_send = ' <span class="tag small tag-open tag-close">||</span> '; 141 this.sentence_merge_separator_receive = '<span class="tag small tag-open tag-close">||</span>'; 142 // sentence merging vars end 143 144 // private variables for getters and setters 145 this._log_level = 0; 146 this._access_token = ""; 147 this._default_lang_code = ""; 148 this._selected_lang_code = ""; 149 this._lang_status_map; 150 this._expiry_token_time = ""; 151 152 this.print = this.print.bind(this); 153 this.initTranslation = this.initTranslation.bind(this); 154 this.startTraversingNow = this.startTraversingNow.bind(this); 155 this.addNodeToArray = this.addNodeToArray.bind(this); 156 this.checkNodeType = this.checkNodeType.bind(this); 157 this.traverseNodes = this.traverseNodes.bind(this); 158 this.checkIfTraversingCompleted = 159 this.checkIfTraversingCompleted.bind(this); 160 161 this.GetTranslationsApi = this.GetTranslationsApi.bind(this); 162 163 this.FormatTranslations = this.FormatTranslations.bind(this); 164 this.updateNodesWithTranslatedText = 165 this.updateNodesWithTranslatedText.bind(this); 166 this.sentenceUpdateApi = this.sentenceUpdateApi.bind(this); 167 this.translate = this.translate.bind(this); 168 this.setTranslatedTextToNode = this.setTranslatedTextToNode.bind(this); 169 this.setTranslatedTextToElement = 170 this.setTranslatedTextToElement.bind(this); 171 this.checkIfStringIsHindi = this.checkIfStringIsHindi.bind(this); 172 this.checkIfStringIsPunjabi = this.checkIfStringIsPunjabi.bind(this); 173 this.checkIfStringIsTamil = this.checkIfStringIsTamil.bind(this); 174 this.checkIfStringIsGujrati = this.checkIfStringIsGujrati.bind(this); 175 this.checkIfStringIsKannad = this.checkIfStringIsKannad.bind(this); 176 this.checkIfStringIsBengali = this.checkIfStringIsBengali.bind(this); 177 this.checkIfStringIsTelugu = this.checkIfStringIsTelugu.bind(this); 178 this.checkIfStringIsMalyalam = this.checkIfStringIsMalyalam.bind(this); 179 this.checkIfStringIsAssamese = this.checkIfStringIsAssamese.bind(this); 180 this.checkIfStringIsOdia = this.checkIfStringIsOdia.bind(this); 181 this.checkIfStringIsArabic = this.checkIfStringIsArabic.bind(this); 182 this.checkIfStringIsJapanese = this.checkIfStringIsJapanese.bind(this); 183 this.checkIfStringIsChinese = this.checkIfStringIsChinese.bind(this); 184 this.checkIfStringIsIndonesian = this.checkIfStringIsIndonesian.bind(this); 185 this.checkIfStringIsUrdu = this.checkIfStringIsUrdu.bind(this); 186 187 this.checkIfStringIsLocal = this.checkIfStringIsLocal.bind(this); 188 189 this.calculateMissingTranslationPercentage = 190 this.calculateMissingTranslationPercentage.bind(this); 191 this.updateGlobalData = this.updateGlobalData.bind(this); 192 193 this.callApiRequest = this.callApiRequest.bind(this); 194 this.authenticate = this.authenticate.bind(this); 195 this.loginApi = this.loginApi.bind(this); 196 this.subscriptionStatusApi = this.subscriptionStatusApi.bind(this); 197 this.get_user_location = this.get_user_location.bind(this); 198 this.openDropdown = this.openDropdown.bind(this); 199 this.openProxyDropdown = this.openProxyDropdown.bind(this); 200 this.setEventHandlerOfProxyDropDown = 201 this.setEventHandlerOfProxyDropDown.bind(this); 202 this.removeInternalLinkFromUrl = this.removeInternalLinkFromUrl.bind(this); 203 this.storeValuesInIndexDB = this.storeValuesInIndexDB.bind(this); 204 this.addValuesInIndexObject = this.addValuesInIndexObject.bind(this); 205 this.getValuesInIndexObject = this.getValuesInIndexObject.bind(this); 206 this.getParticularValueFromIndexDB = 207 this.getParticularValueFromIndexDB.bind(this); 208 this.traverseAndSetTranslationOfWholePage = 209 this.traverseAndSetTranslationOfWholePage.bind(this); 210 this.cleanString = this.cleanString.bind(this); 211 this.cleanExistingTranslationObj = 212 this.cleanExistingTranslationObj.bind(this); 213 214 this.replaceEnglishDomainWithLocalDomain = 215 this.replaceEnglishDomainWithLocalDomain.bind(this); 216 217 this.getLocalObjectUrl = this.getLocalObjectUrl.bind(this); 218 this.getLocalObjectAlt = this.getLocalObjectAlt.bind(this); 219 this.formatUrl = this.formatUrl.bind(this); 220 this.removeTrailingSlashesFromUrl = 221 this.removeTrailingSlashesFromUrl.bind(this); 222 this.domNodeInsertedHandler = this.domNodeInsertedHandler.bind(this); 223 this.translateAllFramesOnPage = this.translateAllFramesOnPage.bind(this); 224 this.cssLinkInjection = this.cssLinkInjection.bind(this); 225 this.isProxy = this.isProxy.bind(this); 226 this.isLiveJs = this.isLiveJs.bind(this); 227 228 this.checkAuthenticationToken = this.checkAuthenticationToken.bind(this); 229 230 this.renderTranslateUI = this.renderTranslateUI.bind(this); 231 this.activeLanguage = this.activeLanguage.bind(this); 232 this.onLangSelection = this.onLangSelection.bind(this); 233 this.removeExistingProxyDropdown = 234 this.removeExistingProxyDropdown.bind(this); 235 236 this.getObjectUrlsApi = this.getObjectUrlsApi.bind(this); 237 this.setDropdownPosition = this.setDropdownPosition.bind(this); 238 this.isTextTranslatedText = this.isTextTranslatedText.bind(this); 239 this.formatTranslationDataByLocalKey = 240 this.formatTranslationDataByLocalKey.bind(this); 241 242 this.isNodeASentence = this.isNodeASentence.bind(this); 243 this.isUrlLangStatusActive = this.isUrlLangStatusActive.bind(this); 244 245 246 this.setTranslatedContentToSentenceParent = 247 this.setTranslatedContentToSentenceParent.bind(this); 248 249 this.setTranslatedTextToSentenceMapChildren = 250 this.setTranslatedTextToSentenceMapChildren.bind(this); 251 252 this.setTranslatedContentToSentenceParent = 253 this.setTranslatedContentToSentenceParent.bind(this); 254 255 this.setTranslatedContentToSentenceNodes = 256 this.setTranslatedContentToSentenceNodes.bind(this); 257
258 this.getSentenceCombinedOriginalText = this.getSentenceCombinedOriginalText.bind(this); 259 260 261 } 262 263 get log_level() { 264 if (this._log_level) { 265 return this._log_level; 266 } 267 const logLevelFromLocalStorage = localStorage.getItem("log_level"); 268 if (logLevelFromLocalStorage) { 269 const allowedLevels = [0, 1, 2, 3, 4]; 270 if (!allowedLevels.includes(Number(logLevelFromLocalStorage))) { 271 console.warn( 272 `LOG_LEVEL ${logLevelFromLocalStorage} is not valid. Using default value: 0` 273 ); 274 return 0; 275 } 276 277 this._log_level = logLevelFromLocalStorage; 278 return logLevelFromLocalStorage; 279 } 280 return 0; 281 } 282 283 set log_level(val) { 284 this._log_level = val; 285 localStorage.setItem("log_level", val); 286 } 287 get access_token() { 288 if (this._access_token) { 289 return this._access_token; 290 } 291 const tokenFromLocalStorage = localStorage.getItem("devnagri_access_token"); 292 if (tokenFromLocalStorage) { 293 this._access_token = tokenFromLocalStorage; 294 return tokenFromLocalStorage; 295 } 296 return ""; 297 } 298 299 set access_token(val) { 300 this._access_token = val; 301 localStorage.setItem("devnagri_access_token", val); 302 } 303 304 get expiry_token_time() { 305 if (this._expiry_token_time) { 306 return this._expiry_token_time; 307 } 308 const tokenExpiryTimeFromLocalStorage = localStorage.getItem("devnagri_token_expiry_time"); 309 if (tokenExpiryTimeFromLocalStorage) { 310 this._expiry_token_time = tokenExpiryTimeFromLocalStorage; 311 return tokenExpiryTimeFromLocalStorage; 312 } 313 return ""; 314 } 315 316 set expiry_token_time(val) { 317 this._expiry_token_time = val; 318 localStorage.setItem("devnagri_token_expiry_time", val); 319 } 320 321 get default_lang_code() { 322 if (this._default_lang_code) { 323 return this._default_lang_code; 324 } 325 const codeFromLocalStorage = localStorage.getItem( 326 "devnagri_default_lang_code" 327 ); 328 if (codeFromLocalStorage) { 329 this._default_lang_code = codeFromLocalStorage; 330 return codeFromLocalStorage; 331 } 332 return "en"; 333 } 334 335 set default_lang_code(val) { 336 this._default_lang_code = val; 337 localStorage.setItem("devnagri_default_lang_code", val); 338 } 339 340 get selected_lang_code() { 341 if (this._selected_lang_code) { 342 return this._selected_lang_code; 343 } 344 const codeFromLocalStorage = localStorage.getItem( 345 "devnagri_selected_lang_code" 346 ); 347 if (codeFromLocalStorage) { 348 this._selected_lang_code = codeFromLocalStorage; 349 return codeFromLocalStorage; 350 } 351 return "en"; 352 } 353 354 set selected_lang_code(val) { 355 this._selected_lang_code = val; 356 localStorage.setItem("devnagri_selected_lang_code", val); 357 } 358 359 get lang_status_map() { 360 if (this._lang_status_map) { 361 return this._lang_status_map; 362 } 363 const itemFromLocalStorage = localStorage.getItem( 364 "devnagri_lang_status_map" 365 ); 366 if (itemFromLocalStorage) { 367 const parsedObj = JSON.parse(itemFromLocalStorage); 368 this._selected_lang_code = parsedObj; 369 return parsedObj; 370 } 371 return {}; 372 } 373 374 set lang_status_map(val) { 375 this._lang_status_map = val; 376 localStorage.setItem("devnagri_lang_status_map", JSON.stringify(val)); 377 } 378 379 isProxy() { 380 return this.script_type === "proxy"; 381 } 382 383 isLiveJs() { 384 return this.script_type === "live"; 385 } 386 387 // authenticate user by login and subscription status apis 388 async authenticate(apiKey) { 389 try { 390 let loginPromise = await this.loginApi(this.login_api_url, apiKey); 391 if (loginPromise) { 392 let subscriptionPromise = await this.subscriptionStatusApi( 393 this.status_api_url 394 ); 395 if (subscriptionPromise.data.subscription === "ACTIVE") { 396 return subscriptionPromise; 397 } 398 } 399 } catch (err) {} 400 } 401 402 // this function is used for authentication 403 async loginApi(url, apiKey) { 404 try { 405 const res = await fetch(url, { 406 method: "POST", 407 headers: { 408 "Content-Type": "application/json", 409 }, 410 body: JSON.stringify({ 411 api_key: apiKey, 412 }), 413 }); 414 const data = await res.json(); 415 if (data.access_token) { 416 this.access_token = data.access_token; 417 let expires_in = new Date().getTime() * 1000 + data.expires_in; 418 this.expiry_token_time = expires_in; 419 if(this.isLiveJs()){ 420 if(this.web_owner){ 421 this.default_lang_code = this.url_object.searchParams.get("language_code"); 422 }else{ 423 if(data.default_lang_code){ 424 this.default_lang_code = data.default_lang_code 425 } 426 } 427 } 428 return data; 429 } else { 430 return false;
431 } 432 } catch (err) { 433 throw err; 434 } 435 } 436 437 // this function is used for injecting css link in case of live js 438 cssLinkInjection() { 439 return; 440 let cssFile = document.createElement("link"); 441 cssFile.rel = "stylesheet"; 442 cssFile.id = "dota_css"; 443 cssFile.href = `${this.cdn_css_link}?${+new Date()}`; 444 // cssFile.href = `http://localhost:5500/devnagri_dota_merged_dev.css`; 445 446 document.head.appendChild(cssFile); 447 } 448 449 // wrapper function for api calls to handle auth errors 450 async callApiRequest(reqFunction) { 451 try { 452 return await reqFunction(); 453 } catch (error) { 454 // handle auth error 455 if ( 456 error && 457 error.response && 458 [401, 403, "401", "403"].includes(error.response.status) 459 ) { 460 const authResponse = await this.authenticate(this.api_key); 461 if (authResponse) { 462 return await reqFunction(); 463 } 464 } else { 465 throw error; 466 } 467 } 468 } 469 470 // remove nbsp from string 471 replaceNbsps(str) { 472 let re = new RegExp(String.fromCharCode(160), "g"); 473 return str.replace(re, " "); 474 } 475 476 formatUrl(url = "") { 477 let trimmedUrl = url.trim(); 478 return this.removeTrailingSlashesFromUrl(trimmedUrl); 479 } 480 481 removeTrailingSlashesFromUrl(url) { 482 if (url.endsWith("/")) { 483 return this.removeTrailingSlashesFromUrl(url.slice(0, -1)); 484 } 485 return url; 486 } 487 488 isExactMatch(str, match) { 489 return new RegExp(`\\b${this.escapeRegExpMatch(match)}\\b`).test(str) 490 } 491 492 compareArrays = (a, b) => 493 a.length === b.length && a.every((element, index) => element === b[index]); 494 495 escapeRegExpMatch(s) { 496 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); 497 } 498 499 keepOnlyAlphabets(str) { 500 let re = new RegExp(/[^a-zA-Z]/g); 501 return str.replace(re, ""); 502 } 503 504 removeExtraSpacesInMiddle(str){ 505 if(str){ 506 let str1 = str.replace(/(\r\n|\n|\r|\t)/gm, " "); 507 //let str2 = str1.replace(/[^\x20-\x7E]/gmi, "");; 508 let str2 = str1.replace(/[^\x20-\x7Eâ¢Â®Â©â¹]/gmi, ""); 509 return str2.replace(/ +/g, ' '); 510 } 511 return str 512 } 513 514 515 cleanString(str = "", trim = true) { 516 let outputString = str; 517 let removeNbspRegEx = new RegExp(String.fromCharCode(160), "g"); 518 outputString = outputString.replace(removeNbspRegEx, " "); 519 outputString = outputString.replace(new RegExp("/<!--.*-->/s", "g"), ""); 520 outputString = outputString.replace(new RegExp("~<!--(.*?)-->~s", "g"), ""); 521 outputString = outputString.replace(new RegExp("~<!--(.*?)-->~s", "g"), ""); 522 outputString = outputString.replace( 523 new RegExp("/<!--(.|s)*?-->/", "g"), 524 "" 525 ); 526 outputString = outputString.replace( 527 new RegExp("/<!--(.|s)*?-->/", "g"), 528 "" 529 ); 530 outputString = outputString.replace("\n", ""); 531 outputString = outputString.replace("\r", ""); 532 outputString = outputString.replace("\t", ""); 533 outputString = outputString.replace("\xc2\xa0", ""); 534 outputString = outputString.replace( 535 new RegExp("/^[^a-zA-Z0-9]+$/", "g"), 536 "" 537 ); 538 outputString = outputString.replace(new RegExp("/^d+$/", "g"), ""); 539 outputString = outputString.replace( 540 new RegExp("/^[^a-zA-Z0-9]+d+$/", "g"), 541 "" 542 ); 543 outputString = this.removeExtraSpacesInMiddle(outputString) 544 if (trim) { 545 outputString = outputString.trim(); 546 } 547 outputString = outputString.length > 0 ? outputString : ""; 548 549 if (isNaN(outputString)) { 550 return outputString; 551 } else { 552 return ""; 553 } 554 // return outputString; 555 } 556 557 removeCurrencyFromText(str) { 558 let re = new RegExp(/[0-9.,%k]/g); 559 return str.replace(re, ""); 560 } 561 562 removeSpecialCharacters(str) { 563 let re = new RegExp(/[^a-zA-Z0-9]/g); 564 return str.replace(re, ""); 565 } 566 567 cleanExistingTranslationObj = (exitingObj) => { 568 const newObj = {}; 569 Object.keys(exitingObj).forEach((key) => { 570 newObj[this.cleanString(key)] = exitingObj[key]; 571 }); 572 return newObj; 573 }; 574 575 removeInternalLinkFromUrl(url = "", keepQueryParams = false) { 576 const hashIndex = url.indexOf("#"); 577 const questionIndex = url.indexOf("?"); 578 const internalLinkExist = hashIndex > 0; 579 const queryExist = questionIndex > 0; 580 const queryIsAfterInternalLink = questionIndex > hashIndex; 581 if (internalLinkExist) { 582 if (keepQueryParams && queryExist && queryIsAfterInternalLink) { 583 return url.slice(0, hashIndex) + url.slice(questionIndex, url.length); 584 } 585 586 return url.slice(0, hashIndex); 587 } 588 return url; 589 } 590 591 // this function is used to add english text as key in object(this.arr_nodes) 592 addNodeToArray( 593 text, 594 node, 595 isNodeASentenceChildren = false, 596 sentenceParentId = "", 597 subSentencePosition, 598 attributeKeyName="" 599 ) { 600 601 if(this.globalCheckIfStringIsLocal(text)){ 602 return ; 603 } 604 605 if (text.includes("img_point_of_sale")) { 606 this.print(3, "IMG NODE in addNodeToArray", { 607 alt: node.alt, 608 cleanString: this.cleanString(text), 609 node, 610 isLocal: this.checkIfStringIsLocal(text), 611 isTranslatedText: this.isTextTranslatedText(text), 612 }); 613 } 614 if (this.checkIfStringIsLocal(text)) { 615 return; 616 } 617 618 if (!isNodeASentenceChildren && this.isTextTranslatedText(text)) { 619 return; 620 } 621 622 //For Currency issue https://stage.idfcfirstbank.com/credit-card/classic 623 /*const textWithoutNums = this.removeCurrencyFromText(text); 624 625 if (!textWithoutNums) { 626 return; 627 } 628 629 const textWithoutSpecialChars = 630 this.removeSpecialCharacters(textWithoutNums); 631 632 if (!textWithoutSpecialChars) { 633 return; 634 }*/ 635 636 let txt = text.replaceAll("\n", " "); 637 txt = this.replaceNbsps(txt); 638 txt = txt.trim(); 639 txt = this.cleanString(txt); 640 let translatedText = this.cleanString(txt); 641 642 if (text.includes("img_point_of_sale")) { 643 this.print( 644 3, 645 "IMG NODE in addNodeToArray", 646 node.alt, 647 this.cleanString(text), 648 node 649 ); 650 } 651 652 if (isNodeASentenceChildren) { 653 this.print( 654 3, 655 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 624 ~ Devnagri ~ isNodeASentenceChildren", 656 isNodeASentenceChildren, 657 sentenceParentId 658 ); 659 660 if ( 661 this.sentence_nodes[sentenceParentId] && 662 this.sentence_nodes[sentenceParentId].children 663 ) { 664 this.print( 665 3, 666 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 624 ~ Devnagri ~ pushing node", 667 node 668 ); 669 670 this.sentence_nodes[sentenceParentId] = { 671 children: this.sentence_nodes[sentenceParentId].children.find(item=> ( 672 item.subSentencePosition === subSentencePosition || 673 this.cleanString(item.original_text).toLowerCase() === this.cleanString(text).toLowerCase() || 674 this.cleanString(item.translated_text).toLowerCase() === this.cleanString(text).toLowerCase().replaceAll(this.sentence_merge_separator_send, this.sentence_merge_separator_receive) 675 )) ? this.sentence_nodes[sentenceParentId].children : [ 676 ...this.sentence_nodes[sentenceParentId].children, 677 { 678 node, 679 text: this.cleanString(text), 680 translated_text: this.cleanString(text), 681 original_text: text, 682 subSentencePosition: subSentencePosition, 683 }, 684 ], 685 parentNode: this.sentence_nodes[sentenceParentId].parentNode, 686 };
687 const combinedOriginalText = this.getSentenceCombinedOriginalText( 688 this.sentence_nodes[sentenceParentId] 689 ); 690 this.sentence_nodes[sentenceParentId].original_text = 691 combinedOriginalText; 692 693 const combinedTranslatedText = 694 this.translation_api_global_data[combinedOriginalText]; 695 696 if (combinedTranslatedText) { 697 this.sentence_nodes[sentenceParentId].translated_text = 698 combinedTranslatedText; 699 700 this.setTranslatedContentToSentenceParent( 701 this.sentence_nodes[sentenceParentId] 702 ); 703 } 704 } 705 return; 706 } 707 708 if (this.translation_api_global_data[this.cleanString(text)]) { 709 translatedText = this.translation_api_global_data[this.cleanString(text)]; 710 711 let origText = this.cleanString(text, false); 712 // origText = text.replaceAll("\n", " "); 713 // origText = this.replaceNbsps(origText); 714 const trimmedText = this.cleanString(text); 715 const translatedTextWithSpaces = origText.replace( 716 trimmedText, 717 translatedText 718 ); 719 this.setTranslatedTextToElement(node, translatedTextWithSpaces, origText); 720 } 721 722 if (!Object.keys(this.arr_nodes).includes(this.cleanString(txt))) { 723 this.arr_nodes[`${this.cleanString(txt)}`] = { 724 translatedText: translatedText, 725 originalText: this.cleanString(text), 726 nodes: [node], 727 attributeKeyName, 728 ...(isNodeASentenceChildren 729 ? { 730 isNodeASentenceChildren, 731 sentenceParentId: [sentenceParentId], 732 subSentencePosition: [subSentencePosition], 733 } 734 : {}), 735 }; 736 } else { 737 // node is already in arr_nodes 738 if (isNodeASentenceChildren) { 739 // text already exists in a node as sentence children 740 if ( 741 this.arr_nodes[`${this.cleanString(txt)}`].isNodeASentenceChildren 742 ) { 743 if ( 744 !this.arr_nodes[ 745 `${this.cleanString(txt)}` 746 ].sentenceParentId.includes(sentenceParentId) 747 ) { 748 this.arr_nodes[`${this.cleanString(txt)}`].sentenceParentId.push( 749 sentenceParentId 750 ); 751 this.arr_nodes[`${this.cleanString(txt)}`].subSentencePosition.push( 752 subSentencePosition 753 ); 754 } 755 } else { 756 this.arr_nodes[`${this.cleanString(txt)}`].isNodeASentenceChildren = 757 isNodeASentenceChildren; 758 this.arr_nodes[`${this.cleanString(txt)}`].sentenceParentId = [ 759 sentenceParentId, 760 ]; 761 this.arr_nodes[`${this.cleanString(txt)}`].subSentencePosition = [ 762 subSentencePosition, 763 ]; 764 } 765 } 766 767 this.arr_nodes[`${this.cleanString(txt)}`].nodes.push(node); 768 } 769 } 770 771 // sentence merging functions 772 getXPathForElement(el, xml) { 773 let xpath = ""; 774 let pos, tempitem2; 775 776 while (el !== xml.documentElement) { 777 pos = 0; 778 tempitem2 = el; 779 while (tempitem2) { 780 if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { 781 // If it is ELEMENT_NODE of the same name 782 pos += 1; 783 } 784 tempitem2 = tempitem2.previousSibling; 785 } 786 787 xpath = `*[name()='${el.nodeName}' and namespace-uri()='${ 788 el.namespaceURI ?? "" 789 }'][${pos}]/${xpath}`; 790 791 el = el.parentNode; 792 } 793 xpath = `/*[name()='${xml.documentElement.nodeName}' and namespace-uri()='${ 794 el.namespaceURI ?? "" 795 }']/${xpath}`; 796 xpath = xpath.replace(/\/$/, ""); 797 return xpath; 798 } 799 800 isNodeASentence(node) { 801 if(!this.enable_sentence_merging){ 802 return false 803 } 804 let result = true; 805 const parentName = node.nodeName.toUpperCase(); 806 if (this.sentence_parents.includes(parentName)) { 807 if (node.childNodes.length > 1) { 808 for (let innerNode of node.childNodes) { 809 const childName = innerNode.nodeName.toUpperCase(); 810 if (!this.sentence_children.includes(childName)) { 811 result = false;
812 } else { 813 if (innerNode.childNodes.length > 1) { 814 result = false; 815 } 816 } 817 } 818 } else { 819 result = false; 820 } 821 } else { 822 result = false; 823 } 824 return result; 825 } 826 827 setTranslatedTextToSentenceMapChildren = (sentenceMap) => { 828 const obj = {}; 829 Object.entries(sentenceMap).forEach(([key, value]) => { 830 if(this.cleanString(value.original_text) !== this.cleanString(value.translated_text)){ 831 let translatedTextsArr = [] 832 if(value.translated_text){ 833 translatedTextsArr = value.translated_text.split(this.sentence_merge_separator_receive); 834 } 835 836 const children = value.children.map((child, index) => { 837 child.translated_text = translatedTextsArr[index]; 838 return child; 839 }); 840 value.children = children; 841 } 842 obj[key] = value; 843 }); 844 return obj; 845 }; 846 847 setTranslatedTextToSentenceObj = (sentenceObj) => { 848 if(this.cleanString(sentenceObj.original_text) === this.cleanString(sentenceObj.translated_text)){ 849 return 850 } 851 this.print(3,"setTranslatedTextToSentenceObj",sentenceObj) 852 let translatedTextsArr = [] 853 if(sentenceObj.translated_text){ 854 translatedTextsArr = sentenceObj.translated_text.split(this.sentence_merge_separator_receive); 855 } 856 857 const children = sentenceObj.children.map((child, index) => { 858 child.translated_text = translatedTextsArr[index] ? translatedTextsArr[index] : ""; 859 return child; 860 }); 861 sentenceObj.children = children; 862 return sentenceObj; 863 }; 864 865 setTranslatedContentToSentenceParent(sentenceObj) { 866 const sentenceParent = this.setTranslatedTextToSentenceObj(sentenceObj); 867 this.print( 868 3, 869 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1331 ~ Devnagri ~ setTranslatedContentToSentenceParent ~ sentenceObj", 870 sentenceParent 871 ); 872 873 if ( 874 sentenceParent && 875 sentenceParent.children && 876 Array.isArray(sentenceParent.children) && 877 sentenceParent.children.length > 0 878 ) { 879 sentenceParent.children.forEach((child) => { 880 this.print( 881 3, 882 "setTranslatedContentToSentenceParent setTranslatedContentToSentenceNodes this.setTranslatedTextToElement", 883 { 884 node: child.node, 885 translated_text: child.translated_text, 886 text: child.text, 887 } 888 ); 889 if(child.original_text && !this.isTextTranslatedText(child.original_text)){ 890 let origText = this.cleanString(child.original_text, false); 891 const trimmedText = this.cleanString(child.original_text); 892 const translatedTextWithSpaces = origText.replace( 893 trimmedText, 894 child.translated_text 895 ); 896 this.setTranslatedTextToElement( 897 child.node, 898 translatedTextWithSpaces, 899 child.original_text, 900 ); 901 } 902 903 }); 904 } 905 } 906 907 setTranslatedContentToSentenceNodes(sentenceNodes) { 908 Object.values(sentenceNodes).forEach( 909 this.setTranslatedContentToSentenceParent 910 ); 911 } 912 913 getSentenceCombinedOriginalText(sentenceNode) { 914 let text = ""; 915 sentenceNode.children.forEach((child, index) => { 916 text += `${index > 0 ? this.sentence_merge_separator_send : ""}${ 917 child.text 918 }`; 919 }); 920 return text; 921 } 922 923 // sentence merging functions end 924 925 // this function is used for handling the nodes text with different-2 cases 926 checkNodeType( 927 node, 928 isNodeASentenceChildren = false, 929 sentenceParentId = "", 930 subSentencePosition 931 ) { 932 if (node.parentElement && node.parentElement.nodeName == "STYLE") { 933 return; 934 } 935 936 switch (node.nodeName) { 937 case "#text": { 938 if (node.textContent.trim().length != 0) { 939 try { 940 let nodeParent = node.parentElement; 941 if ( 942 nodeParent &&
943 nodeParent.nodeName.toLowerCase() != "devnagri_text" && 944 nodeParent.nodeName.toLowerCase() != "title" 945 ) { 946 if (this.web_owner) { 947 let newElement = document.createElement("devnagri_text"); 948 newElement.setAttribute("english_text", node.textContent); 949 newElement.textContent = node.textContent; 950 node.replaceWith(newElement); 951 this.addNodeToArray( 952 node.textContent, 953 newElement, 954 isNodeASentenceChildren, 955 sentenceParentId, 956 subSentencePosition 957 ); 958 } else { 959 // let newElement = document.createElement("devnagri_text"); 960 // newElement.setAttribute("english_text", node.textContent); 961 // newElement.textContent = node.textContent; 962 // node.setAttribute("english_text", node.textContent); 963 // node.replaceWith(newElement); 964 // this.addNodeToArray(node.textContent, newElement); 965 this.addNodeToArray( 966 node.textContent, 967 node, 968 isNodeASentenceChildren, 969 sentenceParentId, 970 subSentencePosition 971 ); 972 } 973 } else { 974 if ( 975 node.parentElement && 976 node.parentElement.nodeName == "TITLE" && 977 node.textContent == document.title 978 ) { 979 this.addNodeToArray(this.meta_prefix + node.textContent, node); 980 break; 981 } 982 if (node.textContent.trim().length != 0) { 983 this.addNodeToArray(node.textContent, node); 984 } 985 } 986 } catch (error) { 987 let newElement = document.createElement("devnagri_text"); 988 newElement.setAttribute("english_text", node.textContent); 989 newElement.textContent = node.textContent; 990 node.replaceWith(newElement); 991 this.addNodeToArray(node.textContent, newElement); 992 } 993 } 994 break; 995 } 996 case "META": { 997 if ( 998 (node.name && 999 [ 1000 "DESCRIPTION", 1001 "TITLE", 1002 "KEYWORDS", 1003 "TWITTER:TITLE", 1004 "TWITTER:DESCRIPTION", 1005 ].includes(node.name.toUpperCase())) || 1006 (node.getAttribute("property") && 1007 ["OG:TITLE", "OG:DESCRIPTION"].includes( 1008 node.getAttribute("property").toUpperCase() 1009 )) 1010 ) { 1011 if (node.name) { 1012 this.metatag_key = node.nodeName + "-" + node.name; 1013 if (!this.metatag_arr[`${this.metatag_key}`]) { 1014 this.metatag_arr[`${this.metatag_key}`] = { 1015 tag: node.nodeName, 1016 name: node.name, 1017 content: node.content, 1018 engText: node.content, 1019 translatedText: node.content, 1020 }; 1021 } 1022 } else if (node.getAttribute("property")) { 1023 this.metatag_key = 1024 node.nodeName + "-" + node.getAttribute("property"); 1025 if (!this.metatag_arr[`${this.metatag_key}`]) { 1026 this.metatag_arr[`${this.metatag_key}`] = { 1027 tag: node.nodeName, 1028 property: node.getAttribute("property"), 1029 content: node.content, 1030 engText: node.content, 1031 translatedText: node.content, 1032 }; 1033 } 1034 } 1035 this.addNodeToArray(this.meta_prefix + node.content, node); 1036 } 1037 break; 1038 } 1039 1040 case "INPUT": { 1041 if (node.type === "button") { 1042 if (node.value.trim().length != 0) { 1043 this.addNodeToArray(node.value, node); 1044 } 1045 } else { 1046 if (node.type === "submit") { 1047 if (node.value.trim().length != 0) { 1048 this.addNodeToArray(node.value, node); 1049 } 1050 } 1051 1052 if (node.placeholder.trim().length != 0) { 1053 this.addNodeToArray(node.placeholder, node); 1054 } 1055 1056 // if (node.title.trim().length != 0) { 1057 // this.addNodeToArray(node.title, node); 1058 // } 1059 1060 if (node.type != "hidden" && node.title.trim().length != 0) { 1061 this.addNodeToArray(node.title, node); 1062 } 1063 } 1064 1065 break; 1066 } 1067 case "TEXTAREA": { 1068 if (node.placeholder.trim().length != 0) { 1069 this.addNodeToArray(node.placeholder, node); 1070 } 1071 1072 if (node.title.trim().length != 0) { 1073 this.addNodeToArray(node.title, node); 1074 } 1075 1076 break; 1077 } 1078 case "IMG": { 1079 if (this.enable_object_mapping) { 1080 if (this.subdomain_object_urls_hash_map_local[node.src]) { 1081 break; 1082 } 1083 } 1084 this.print(3, "IMG Node", node.alt, node); 1085 1086 if (node.alt.trim().length != 0) {
1087 this.addNodeToArray(this.meta_prefix + node.alt, node); 1088 } 1089 1090 if (node.title.trim().length != 0) { 1091 this.addNodeToArray(this.meta_prefix + node.title, node); 1092 } 1093 break; 1094 } 1095 case "SCRIPT": { 1096 break; 1097 } 1098 default: { 1099 } 1100 } 1101 if (node && node.parentElement && node.parentElement.title) { 1102 this.addNodeToArray(node.parentElement.title, node.parentElement, undefined, undefined, undefined, 'title'); 1103 } 1104 } 1105 1106 replaceEnglishDomainWithLocalDomain({ url, englishDomain, localDomain }) { 1107 let hrefUrl = url; 1108 if (this.domain && !this.domain.includes("www")) { 1109 // hrefUrl = hrefUrl.replaceAll("https://www.", "https://"); 1110 // hrefUrl = hrefUrl.replaceAll("http://www.", "http://"); 1111 1112 if(hrefUrl.includes(this.domain)){ 1113 hrefUrl = hrefUrl.replaceAll("https://www.", "https://"); 1114 hrefUrl = hrefUrl.replaceAll("http://www.", "http://"); 1115 } 1116 1117 } 1118 1119 const englishDomainWithoutProtocol = englishDomain 1120 .replaceAll("https://", "") 1121 .replaceAll("http://", ""); 1122 const localDomainWithoutProtocol = localDomain 1123 .replaceAll("https://", "") 1124 .replaceAll("http://", ""); 1125 1126 const secureEnglishDomain = `https://${englishDomainWithoutProtocol}`; 1127 const secureLocalDomain = `https://${localDomainWithoutProtocol}`; 1128 1129 const unsecureEnglishDomain = `http://${englishDomainWithoutProtocol}`; 1130 const unsecureLocalDomain = `http://${localDomainWithoutProtocol}`; 1131 1132 let hrefUrlSlash = `${hrefUrl}/`; 1133 1134 if (hrefUrlSlash.includes(localDomainWithoutProtocol + "/")) { 1135 return hrefUrl; 1136 } 1137 1138 let newUrl = hrefUrl; 1139 newUrl = newUrl.replaceAll(secureEnglishDomain, secureLocalDomain); 1140 newUrl = newUrl.replaceAll(unsecureEnglishDomain, unsecureLocalDomain); 1141 return newUrl; 1142 } 1143 1144 getLocalObjectUrl(englishUrl) { 1145 return this.subdomain_object_urls_hash_map[this.formatUrl(englishUrl)] && 1146 this.subdomain_object_urls_hash_map[this.formatUrl(englishUrl)]?.local_url 1147 ? this.subdomain_object_urls_hash_map[englishUrl]?.local_url 1148 : ""; 1149 } 1150 1151 getLocalObjectAlt(englishUrl) { 1152 return this.subdomain_object_urls_hash_map[this.formatUrl(englishUrl)] && 1153 this.subdomain_object_urls_hash_map[this.formatUrl(englishUrl)].alt_text 1154 ? this.subdomain_object_urls_hash_map[englishUrl].alt_text 1155 : ""; 1156 } 1157 1158 // this function is used for traversing the HTML dom 1159 traverseNodes( 1160 node, 1161 callback, 1162 isNodeASentenceChildren = false, 1163 sentenceParentId = "", 1164 subSentencePosition 1165 ) { 1166 const blacklistedTags = [ 1167 "SCRIPT", 1168 "VIDEO", 1169 "IFRAME", 1170 "STYLE", 1171 "NOSCRIPT", 1172 "LINK", 1173 "SVG", 1174 "RECT", 1175 "PATH", 1176 "G", 1177 "CLIPPATH", 1178 ]; //handling the script tag 1179 1180 if (this.enable_object_mapping) { 1181 if ( 1182 node && 1183 node.nodeName && 1184 node.nodeName.toUpperCase() === "IMG" && 1185 node.src 1186 ) { 1187 if (node.src) { 1188 this.print( 1189 3, 1190 "ð ~ file: objectEnglishUrl devnagri-dota-merged-client-dev.js ~ line 632 ~ Devnagri ~ traverseNodes ~ node.src", 1191 node.src 1192 ); 1193 1194 let localUrl = ""; 1195 let objectEnglishUrl = ""; 1196 // url is absolute 1197 if (node.src.includes("http")) { 1198 objectEnglishUrl = node.src.replaceAll( 1199 this.requested_domain, 1200 this.domain 1201 ); 1202 } else { 1203 objectEnglishUrl = `${this.domain}/${node.src}`; 1204 } 1205 this.print( 1206 3, 1207 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 640 ~ Devnagri ~ traverseNodes ~ objectEnglishUrl", 1208 objectEnglishUrl 1209 ); 1210 1211 localUrl = this.getLocalObjectUrl(objectEnglishUrl); 1212 1213 const localAlt = this.getLocalObjectAlt(objectEnglishUrl); 1214 1215 if (localUrl) { 1216 node.src = localUrl; 1217 } 1218 if (localAlt) { 1219 node.alt = localAlt; 1220 } 1221 } 1222 1223 if (node.getAttribute("srcset")) { 1224 const value = node.getAttribute("srcset"); 1225 let valueWithLocalLinks = value; 1226
1227 Object.values(this.subdomain_object_urls_hash_map).forEach( 1228 (object) => { 1229 valueWithLocalLinks = valueWithLocalLinks.replaceAll( 1230 this.formatUrl(object.english_url), 1231 this.formatUrl(object.local_url) 1232 ); 1233 } 1234 ); 1235 node.setAttribute("srcset", valueWithLocalLinks); 1236 } 1237 1238 if (node.getAttribute("data-lazy-srcset")) { 1239 const value = node.getAttribute("data-lazy-srcset"); 1240 let valueWithLocalLinks = value; 1241 Object.values(this.subdomain_object_urls_hash_map).forEach( 1242 (object) => { 1243 valueWithLocalLinks = valueWithLocalLinks.replaceAll( 1244 this.formatUrl(object.english_url), 1245 this.formatUrl(object.local_url) 1246 ); 1247 } 1248 ); 1249 node.setAttribute("data-lazy-srcset", valueWithLocalLinks); 1250 } 1251 if (node.getAttribute("data-lazy-src")) { 1252 const value = node.getAttribute("data-lazy-src"); 1253 let valueWithLocalLinks = value; 1254 1255 Object.values(this.subdomain_object_urls_hash_map).forEach( 1256 (object) => { 1257 valueWithLocalLinks = valueWithLocalLinks.replaceAll( 1258 this.formatUrl(object.english_url), 1259 this.formatUrl(object.local_url) 1260 ); 1261 } 1262 ); 1263 node.setAttribute("data-lazy-src", valueWithLocalLinks); 1264 } 1265 } 1266 } 1267 1268 if (node && node.nodeName && node.nodeName.toUpperCase() === "A" && node.title) 1269 { 1270 this.addNodeToArray( 1271 node.title, 1272 node 1273 ); 1274 } 1275 1276 if ( 1277 node && 1278 node.nodeName && 1279 node.nodeName.toUpperCase() === "A" && 1280 node.href 1281 ) { 1282 let localObjectUrl = ""; 1283 let objectEnglishUrl = ""; 1284 // url is absolute 1285 if (node.href.includes("http")) { 1286 objectEnglishUrl = node.href.replaceAll( 1287 this.requested_domain, 1288 this.domain 1289 ); 1290 } else { 1291 objectEnglishUrl = `${this.domain}/${node.href}`; 1292 } 1293 localObjectUrl = this.getLocalObjectUrl(objectEnglishUrl); 1294 1295 if (localObjectUrl) { 1296 node.setAttribute("href", localObjectUrl); 1297 } else { 1298 let localLink = this.replaceEnglishDomainWithLocalDomain({ 1299 url: node.href, 1300 englishDomain: this.domain, 1301 localDomain: this.requested_domain, 1302 }); 1303 1304 1305 1306 if (this.linkedDomains) { 1307 let default_lang_code = this.default_lang_code; 1308 let linkedDomains = []; 1309 for(let linkedDomain of this.linkedDomains){ 1310 if(linkedDomain.code == default_lang_code){ 1311 linkedDomains.push(linkedDomain); 1312 } 1313 } 1314 linkedDomains.forEach((linkedDomain) => { 1315 localLink = this.replaceEnglishDomainWithLocalDomain({ 1316 url: node.href, 1317 englishDomain: linkedDomain.domain, 1318 localDomain: linkedDomain.subdomain, 1319 }); 1320 }); 1321 } 1322 if (localLink && localLink !== node.href) { 1323 node.setAttribute("href", localLink); 1324 } 1325 } 1326 } 1327 1328 if(node && node.getAttribute){ 1329 if (this.enable_blacklist) { 1330 // node blacklist by class condition 1331 var th = this; 1332 if (
1333 this.blacklist_classes 1334 .map( 1335 (item) => 1336 node.getAttribute("class") && 1337 th.isExactMatch(node.getAttribute("class"), item) 1338 ) 1339 .some(Boolean) 1340 ) { 1341 this.print( 1342 3, 1343 "ignoring element with classname " + node.getAttribute("class") 1344 ); 1345 1346 return; 1347 } 1348 1349 // node blacklist by id condition 1350 if ( 1351 node && 1352 node.getAttribute && 1353 node.getAttribute("id") && 1354 this.blacklist_ids.includes(node.getAttribute("id")) 1355 ) { 1356 this.print( 1357 3, 1358 "ignoring element with id " + node.getAttribute("id") 1359 ); 1360 return; 1361 } 1362 } 1363 } 1364 1365 if (node.childNodes && node.childNodes.length > 0) { 1366 if (!blacklistedTags.includes(node.nodeName.toUpperCase())) { 1367 if (node.getAttribute("class") === "optionElement") { 1368 return true; 1369 } 1370 1371 if (this.enable_blacklist) { 1372 // node blacklist by class condition 1373 var th = this; 1374 if (
1375 this.blacklist_classes 1376 .map( 1377 (item) => 1378 node.getAttribute("class") && 1379 th.isExactMatch(node.getAttribute("class"), item) 1380 ) 1381 .some(Boolean) 1382 ) { 1383 this.print( 1384 3, 1385 "ignoring element with classname " + node.getAttribute("class") 1386 ); 1387 1388 return; 1389 } 1390 1391 // node blacklist by id condition 1392 if ( 1393 node && 1394 node.getAttribute && 1395 node.getAttribute("id") && 1396 this.blacklist_ids.includes(node.getAttribute("id")) 1397 ) { 1398 this.print( 1399 3, 1400 "ignoring element with id " + node.getAttribute("id") 1401 ); 1402 return; 1403 } 1404 } 1405 1406 if ( 1407 node && 1408 node.getAttribute && 1409 (node.getAttribute("id") === "devnagri_outermostdiv" || 1410 node.getAttribute("id") === "devnagri_dropdown" || 1411 node.getAttribute("id") === "newstab" || 1412 node.getAttribute("id") === "photostab") 1413 ) { 1414 this.print(3, "ignoring devnagri_outermostdiv"); 1415 return; 1416 } 1417 1418 if (this.isNodeASentence(node)) { 1419 const parentId = this.getXPathForElement(node, document); 1420 if (!this.sentence_nodes[parentId]) { 1421 this.sentence_nodes[parentId] = { 1422 parentNode: node, 1423 children: [], 1424 }; 1425 } 1426 1427 for (let [index, innerNode] of node.childNodes.entries()) { 1428 this.traverseNodes( 1429 innerNode, 1430 callback, 1431 true, 1432 this.getXPathForElement(node, document), 1433 index 1434 ); 1435 } 1436 } else { 1437 for (let innerNode of node.childNodes) { 1438 this.traverseNodes( 1439 innerNode, 1440 callback, 1441 isNodeASentenceChildren, 1442 sentenceParentId, 1443 subSentencePosition 1444 ); 1445 } 1446 } 1447 } 1448 } else { 1449 if (callback) 1450 callback( 1451 node, 1452 isNodeASentenceChildren, 1453 sentenceParentId, 1454 subSentencePosition 1455 ); 1456 } 1457 } 1458 1459 areAllNodesTranslated(nodesObj) { 1460 let areAllNodesTranslated = true; 1461 Object.keys(nodesObj).forEach((key) => { 1462 if ( 1463 nodesObj[key].translatedText === key && 1464 !this.checkIfStringIsLocal(nodesObj[key].translatedText) 1465 ) { 1466 areAllNodesTranslated = false; 1467 return true; 1468 } 1469 }); 1470 1471 return areAllNodesTranslated; 1472 } 1473 1474 async checkIfTraversingCompleted() { 1475 this.print( 1476 3, 1477 "UPDATE CHECK Check if traversing completed or not", 1478 this.translation_api_global_data, 1479 this.arr_nodes 1480 ); 1481 await this.updateNodesWithTranslatedText(this.translation_api_global_data); 1482 this.print( 1483 3, 1484 "checkIfTraversingCompleted this.access_token", 1485 this.access_token 1486 ); 1487 this.updateGlobalData(); 1488 } 1489 1490 // get user's lat long 1491 get_user_location() { 1492 if (navigator.geolocation) { 1493 navigator.geolocation.getCurrentPosition((position) => { 1494 let lat = position.coords.latitude; 1495 let long = position.coords.longitude; 1496 this.user_lat = lat; 1497 this.user_long = long; 1498 }); 1499 } 1500 } 1501 1502 formatTranslationDataByLocalKey(translationDataByOrigKey) { 1503 const translationDataObjByLocalKey = {}; 1504 for (const [key, value] of Object.entries(translationDataByOrigKey)) { 1505 translationDataObjByLocalKey[value.toLowerCase()] = key; 1506 } 1507 return translationDataObjByLocalKey; 1508 } 1509 1510 splitCompoundSentencesFromTranslationSentences(translationSentences) { 1511 const compoundSentences = []; 1512 const splittedCompoundSentences = []; 1513 translationSentences.forEach((item) => { 1514 if (item.sentence.includes("##{{}}##")) { 1515 compoundSentences.push(item); 1516 } 1517 }); 1518 1519 compoundSentences.forEach((item) => { 1520 const splittedSentences = item.sentence.split("##{{}}##"); 1521 const splittedTranslation = item.translation.split("##{{}}##");
1522 splittedSentences.forEach((sentence, index) => { 1523 const obj = { 1524 sentence: sentence, 1525 translation: splittedTranslation[index] 1526 ? splittedTranslation[index] 1527 : "", 1528 }; 1529 splittedCompoundSentences.push(obj); 1530 }); 1531 }); 1532 1533 const simpleSentences = translationSentences.filter( 1534 (item) => !item.sentence.includes("##{{}}##") 1535 ); 1536 const sentences = simpleSentences.concat(splittedCompoundSentences); 1537 this.print( 1538 3, 1539 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1145 ~ Devnagri ~ splitCompoundSentencesFromTranslationSentences ~ sentences", 1540 sentences 1541 ); 1542 return sentences; 1543 } 1544 1545 // this function is used for calling translate api and here we get specified language text i.e. hindi 1546 async GetTranslationsApi() { 1547 try { 1548 if (this.source_lang_code === this.selected_lang_code) { 1549 return {}; 1550 } 1551 1552 if ( 1553 this.status_api_global_data && 1554 this.status_api_global_data.enable_object_mapping 1555 ) { 1556 this.enable_object_mapping = true; 1557 await this.getObjectUrlsApi(); 1558 } 1559 1560 const documentUrlWithoutInternalLink = this.removeInternalLinkFromUrl( 1561 this.document_url_full 1562 ); 1563 1564 const currentPageUrlObj = new URL(documentUrlWithoutInternalLink); 1565 currentPageUrlObj.searchParams.delete("language_code"); 1566 currentPageUrlObj.searchParams.delete("mode"); 1567 currentPageUrlObj.searchParams.delete("dota-token"); 1568 1569 const translation_api_base_url = `${this.api_baseurl}/translations?language_code=${this.selected_lang_code}&url=${currentPageUrlObj}`; 1570 var translation_api_url = translation_api_base_url; 1571 // + 1572 // "&language_code=" + 1573 // lang_code; 1574 //this.prevURL = this.prevURL ? this.prevURL : currentPageUrlObj; 1575 //console.log("td2", this.prevURL.href); 1576 //console.log("td3", currentPageUrlObj.href); 1577 if(!this.apiCounter && (String(this.prevURL) != String(currentPageUrlObj.href))) 1578 { 1579 this.prevURL = this.prevURL ? this.prevURL : currentPageUrlObj.href; 1580 this.translationData = await this.callApiRequest(async () => { 1581 const res = await fetch(translation_api_url, { 1582 method: "GET", 1583 headers: { 1584 Authorization: `Bearer ${this.access_token}`, 1585 }, 1586 }); 1587 if (res.status === 401 || res.status === 403) { 1588 throw { response: res }; 1589 } 1590 const response = await res.json(); 1591 return response; 1592 }); 1593 ++this.apiCounter; 1594 } 1595 1596 if (this.translationData.message === "success") { 1597 this.print(3, "Translation Response Received"); 1598 this.print( 1599 3, 1600 "Translation Response Received Sentences" + 1601 JSON.stringify(this.translationData.sentences) 1602 ); 1603 1604 // sentence merging changes start 1605 if(this.enable_sentence_merging) { 1606 const origSentenceDataMap = await this.FormatTranslations( 1607 this.translationData.sentences 1608 ); 1609 1610 this.print( 1611 3, 1612 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1383 ~ Devnagri ~ GetTranslationsApi ~ origSentenceDataMap", 1613 origSentenceDataMap 1614 ); 1615 1616 const sentenceNodesMapByOrigText = {}; 1617 Object.entries(this.sentence_nodes).forEach(([key, value]) => { 1618 sentenceNodesMapByOrigText[value.original_text] = Object.assign( 1619 { 1620 parentId: key, 1621 translated_text: origSentenceDataMap[value.original_text] 1622 ? origSentenceDataMap[value.original_text] 1623 : value.original_text, 1624 }, 1625 value 1626 ); 1627 this.sentence_nodes[key].translated_text = origSentenceDataMap[ 1628 value.original_text 1629 ] 1630 ? origSentenceDataMap[value.original_text] 1631 : value.original_text; 1632 }); 1633 1634 this.print( 1635 3, 1636 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1389 ~ Devnagri ~ GetTranslationsApi ~ sentenceNodesMapByOrigText", 1637 sentenceNodesMapByOrigText 1638 ); 1639 1640 this.sentence_nodes_by_orig_text = sentenceNodesMapByOrigText; 1641 1642 this.setTranslatedTextToSentenceMapChildren( 1643 this.sentence_nodes_by_orig_text 1644 ); 1645 1646 this.setTranslatedTextToSentenceMapChildren(this.sentence_nodes); 1647 1648 this.setTranslatedContentToSentenceNodes( 1649 this.sentence_nodes 1650 ); 1651 } 1652 // sentence merging changes end 1653 1654 this.translation_api_global_data = await this.FormatTranslations( 1655 this.translationData.sentences 1656 ); 1657 1658 this.translation_api_global_data_by_local_key = 1659 this.formatTranslationDataByLocalKey( 1660 this.translation_api_global_data 1661 ); 1662 1663 if (this.status_api_global_data && !this.status_api_global_data.is_demo) { 1664 //await this.storeValuesInIndexDB(this.translation_api_global_data); 1665 } 1666 1667 await this.updateNodesWithTranslatedText( 1668 this.translation_api_global_data 1669 ); 1670 } 1671 1672 return this.translationData; 1673 } catch (error) { 1674 throw error; 1675 } 1676 } 1677 1678 async FormatTranslations(sentences) { 1679 sentences.map((x) => { 1680 this.arr_translated_text[this.cleanString(x.sentence)] = x.translation; 1681 }); 1682 return this.arr_translated_text; 1683 } 1684 1685 // print api log to console 1686 print(level, ...data) { 1687 if (level <= this.log_level) { 1688 if (level === 1) { 1689 return console.error(`DevLog-${level} ${new Date()} | `, ...data); 1690 } 1691 if (level === 2) { 1692 return console.warn(`DevLog-${level} ${new Date()} | `, ...data); 1693 } 1694 return console.log(`DevLog-${level} ${new Date()} | `, ...data); 1695 } 1696 } 1697 // this function is used for set the hindi text in object(nodeTextObject) 1698 async updateNodesWithTranslatedText(translationData) { 1699 this.print(3, "Translated Text Updating Started"); 1700 let nodesCount = Object.keys(this.arr_nodes).length; 1701 if (!translationData || nodesCount == 0) { 1702 return; 1703 } 1704 let missingTranslations = []; 1705 for (let key of Object.keys(this.arr_nodes)) { 1706 let txtOriginal = key; 1707 if (txtOriginal.startsWith(this.meta_prefix)) { 1708 txtOriginal = txtOriginal.replace(this.meta_prefix, ""); 1709 } 1710 if (translationData[txtOriginal] && this.arr_nodes[txtOriginal]) { 1711 this.arr_nodes[txtOriginal].translatedText = 1712 translationData[txtOriginal] 1713 1714 } else { 1715 if (!missingTranslations.includes(key)) { 1716 if (this.cleanString(key).length > 0) { 1717 missingTranslations.push(key); 1718 this.print( 1719 2, 1720 "translation not found for key = '" + this.cleanString(key) + "'" 1721 ); 1722 } 1723 // missingTranslations.push(key); 1724 } 1725 } 1726 } 1727
1728 let cleanedMissingTranslation = missingTranslations.map((x) => { 1729 return this.cleanString(x); 1730 }); 1731 1732 cleanedMissingTranslation = cleanedMissingTranslation.filter( 1733 (item) => item.length > 1 1734 ); 1735 1736 // this.translate(localStorage.getItem("devnagri_default_lang_code")); 1737 this.translate(this.selected_lang_code); 1738 1739 let missingPercentage = 1740 (cleanedMissingTranslation.length * 100) / nodesCount; 1741 1742 this.print( 1743 3, 1744 "translation missing number = " + 1745 cleanedMissingTranslation.length + 1746 " missing percentage = " + 1747 missingPercentage + 1748 " total nodes = " + 1749 nodesCount + 1750 JSON.stringify(cleanedMissingTranslation) 1751 ); 1752 // Call Get Api again if missing text percentage is more than 5 %, Can be adjusted as per requirements 1753 if (missingPercentage > this.missingTranslationPercentageOffsetForRetry) { 1754 // There are some pending translation Object in this.arr_nodes, so will call get api after few seconds to get updated text 1755 // call get translation api after 1.5 second 1756 this.translation_api_retry_counter--; 1757 if (this.translation_api_retry_counter > 0) { 1758 setTimeout(async () => { 1759 this.GetTranslationsApi(); 1760 }, 1500); 1761 } 1762 } 1763 1764 // if(missingPercentage > 5){ 1765 // this.print(3,"Showing Loader",missingPercentage,this.missingTranslationPercentageOffsetForRetry) 1766 // 1767 // this.showLoader() 1768 // }else{ 1769 // // this.print(3,"Hiding Loader",missingPercentage,this.missingTranslationPercentageOffsetForRetry) 1770 // // this.hideLoader() 1771 // } 1772 } 1773 1774 checkIfStringIsHindi(string) { 1775 const regex = /[\u0900-\u097F]/; 1776 return regex.test(string); 1777 } 1778 1779 checkIfStringIsPunjabi(string) { 1780 const regex = /[\u0A00-\u0A7F]/; 1781 return regex.test(string); 1782 } 1783 1784 checkIfStringIsTamil(string) { 1785 const regex = /[\u0B80-\u0BFF]/; 1786 return regex.test(string); 1787 } 1788 1789 checkIfStringIsGujrati(string) { 1790 const regex = /[\u0A80-\u0AFF]/; 1791 return regex.test(string); 1792 } 1793 1794 checkIfStringIsKannad(string) { 1795 const regex = /[\u0C80-\u0CFF]/; 1796 return regex.test(string); 1797 } 1798 1799 checkIfStringIsBengali(string) { 1800 const regex = /[\u0980-\u09FF]/; 1801 return regex.test(string); 1802 } 1803 1804 checkIfStringIsTelugu(string) { 1805 const regex = /[\u0C00-\u0C7F]/; 1806 return regex.test(string); 1807 } 1808 1809 checkIfStringIsMalyalam(string) { 1810 const regex = /[\u0D02-\u0D4D]/; 1811 return regex.test(string); 1812 } 1813 1814 checkIfStringIsAssamese(string) { 1815 const bengaliRegex = /[\u0980-\u09FF]/; 1816 //const tirhutaRegex = /[\u011480-\u0114DF]/; 1817 //return bengaliRegex.test(string) || tirhutaRegex.test(string); 1818 return bengaliRegex.test(string); 1819 } 1820 1821 checkIfStringIsOdia(string) { 1822 const regex = /[\u0B00-\u0B7F]/; 1823 return regex.test(string); 1824 } 1825 1826 checkIfStringIsArabic(string) { 1827 const regex = /[\u0600-\u06FF]/; 1828 return regex.test(string); 1829 } 1830 1831 checkIfStringIsJapanese(string) { 1832 const kanjiRegex = /[\u4E00-\u9FBF]/; 1833 const hiraganaRegex = /[\u3040-\u309F]/; 1834 const katakanaRegex = /[\u30A0-\u30FF]/; 1835 1836 return ( 1837 kanjiRegex.test(string) || 1838 hiraganaRegex.test(string) || 1839 katakanaRegex.test(string) 1840 ); 1841 } 1842 1843 checkIfStringIsChinese(string) { 1844 const regex = /[\u4E00-\u9FFF]/; 1845 return regex.test(string); 1846 } 1847 1848 checkIfStringIsIndonesian(string) { 1849 const regex = /[\u1B00-\u1B7F]/; 1850 return regex.test(string); 1851 } 1852 1853 checkIfStringIsUrdu(string) { 1854 const regex1 = /[\u0600-\u06FF]/; 1855 const regex2 = /[\u0750-\u077F]/; 1856 const regex3 = /[\uFB50-\uFDFF]/; 1857 const regex4 = /[\uFE70-\uFEFF]/; 1858 1859 return ( 1860 regex1.test(string) || 1861 regex2.test(string) || 1862 regex3.test(string) || 1863 regex4.test(string) 1864 ); 1865 } 1866 1867 checkIfStringIsEnglish(string) { 1868 const regex = /[a-z]/; 1869 return regex.test(string.toLowerCase()); 1870 } 1871 1872 checkIfStringIsLocal(string, hinglishResult = false) { 1873 this.print( 1874 4, 1875 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1217 ~ Devnagri ~ checkIfStringIsLocal ~ string", 1876 this.selected_lang_code,
1877 string 1878 ); 1879 if (this.selected_lang_code === this.source_lang_code) { 1880 return false; 1881 } 1882 1883 switch (this.selected_lang_code) { 1884 case "hi": { 1885 return this.checkIfStringIsHindi(string); 1886 } 1887 case "pa": { 1888 return this.checkIfStringIsPunjabi(string); 1889 } 1890 case "ta": { 1891 return this.checkIfStringIsTamil(string); 1892 } 1893 case "gu": { 1894 return this.checkIfStringIsGujrati(string); 1895 } 1896 case "kn": { 1897 return this.checkIfStringIsKannad(string); 1898 } 1899 case "bn": { 1900 return this.checkIfStringIsBengali(string); 1901 } 1902 case "mr": { 1903 return this.checkIfStringIsHindi(string); 1904 } 1905 case "te": { 1906 return this.checkIfStringIsTelugu(string); 1907 } 1908 case "ml": { 1909 return this.checkIfStringIsMalyalam(string); 1910 } 1911 case "as": { 1912 return this.checkIfStringIsAssamese(string); 1913 } 1914 case "or": { 1915 return this.checkIfStringIsOdia(string); 1916 } 1917 case "ar": { 1918 return this.checkIfStringIsArabic(string); 1919 } 1920 case "ja": { 1921 return this.checkIfStringIsJapanese(string); 1922 } 1923 case "zh": { 1924 return this.checkIfStringIsChinese(string); 1925 } 1926 case "id": { 1927 return this.checkIfStringIsIndonesian(string); 1928 } 1929 case "ur": { 1930 return this.checkIfStringIsUrdu(string); 1931 } 1932 case "hi-EN": { 1933 return hinglishResult; 1934 } 1935 default: { 1936 return false; 1937 } 1938 } 1939 } 1940 1941 // indexDb methods start 1942 async storeValuesInIndexDB(textObject) { 1943 let dbReq = indexedDB.open("devnagriTranslationText", 1); 1944 const dbReqPromise = await new Promise((resolve, reject) => { 1945 dbReq.addEventListener("upgradeneeded", (event) => { 1946 this.db = event.target.result; 1947 this.devnagriCreateDataBaseStore = this.db.createObjectStore( 1948 this.subdomainObjectStore, 1949 { 1950 autoIncrement: true, 1951 } 1952 ); 1953 }); 1954 dbReq.addEventListener("success", async (event) => { 1955 this.db = event.target.result; 1956 await this.addValuesInIndexObject(this.db, textObject); 1957 resolve(); 1958 }); 1959 dbReq.addEventListener("error", () => { 1960 reject(null); 1961 }); 1962 }); 1963 1964 return dbReqPromise; 1965 } 1966 1967 /* old code 1968 * async addValuesInIndexObject(db, textObject) { 1969 // // Start a database transaction and get the notes object store 1970 const indexDBValues = await new Promise(async (resolve, reject) => { 1971 this.print(3, "this.subdomainObjectStore", this.subdomainObjectStore); 1972 let tx = await db.transaction([this.subdomainObjectStore], "readwrite"); 1973 let store = await tx.objectStore(this.subdomainObjectStore); 1974 for (let key of Object.keys(textObject)) { 1975 await store.put(textObject[key], key); 1976 } 1977 1978 // Wait for the database transaction to complete 1979 tx.oncomplete = function () {}; 1980 tx.addEventListener("error", () => { 1981 reject(null); 1982 }); 1983 resolve(); 1984 }); 1985 return indexDBValues; 1986 } 1987*/ 1988 1989async addValuesInIndexObject(db, textObject) { 1990 try{ 1991 // // Start a database transaction and get the notes object store 1992 const indexDBValues = await new Promise(async (resolve, reject) => { 1993 this.print(3, "this.subdomainObjectStore", this.subdomainObjectStore); 1994 let tx = await db.transaction([this.subdomainObjectStore], "readwrite"); 1995 let store = await tx.objectStore(this.subdomainObjectStore); 1996 for (let key of Object.keys(textObject)) { 1997 await store.put(textObject[key], key); 1998 } 1999 2000 // Wait for the database transaction to complete 2001 tx.oncomplete = function () {}; 2002 tx.addEventListener("error", () => { 2003 reject(null); 2004 }); 2005 resolve(); 2006 }); 2007 return indexDBValues; 2008 }catch (error) { 2009 this.print(1,"error in addValuesInIndexObject",error) 2010 } 2011 } 2012 2013 async getParticularValueFromIndexDB(text) { 2014 let dbOpenRequest = window.indexedDB.open("devnagriTranslationText", 1); 2015 const obStore = await new Promise((resolve, reject) => { 2016 dbOpenRequest.addEventListener("success", () => { 2017 this.db = dbOpenRequest.result; 2018 2019 var tx = this.db.transaction([this.subdomainObjectStore], "readwrite"); 2020 2021 // Wait for the database transaction to complete 2022 tx.oncomplete = function () { 2023 // this.print(3,"stored note!"); 2024 }; 2025 tx.onerror = function () { 2026 // this.print(3, 2027 // " object get value error storing note " + event.target.errorCode 2028 // ); 2029 }; 2030 2031 var obStore = tx.objectStore(this.subdomainObjectStore); 2032 resolve(obStore); 2033 }); 2034 dbOpenRequest.addEventListener("error", () => { 2035 reject(null); 2036 }); 2037 }); 2038 const translatedText = await new Promise((resolve, reject) => { 2039 if (typeof text == "string") { 2040 var objectStoreRequest = obStore.get(text); 2041 2042 objectStoreRequest.addEventListener("success", () => { 2043 var result = objectStoreRequest.result; 2044 resolve(result); 2045 }); 2046 objectStoreRequest.addEventListener("error", () => { 2047 reject(null); 2048 }); 2049 } else { 2050 reject(null); 2051 } 2052 }); 2053 return translatedText; 2054 } 2055 2056 async getValuesInIndexObject() { 2057 let dbOpenRequest = window.indexedDB.open("devnagriTranslationText", 1); 2058 2059 const obStore = await new Promise(async (resolve, reject) => { 2060 dbOpenRequest.addEventListener("success", async () => { 2061 this.db = dbOpenRequest.result; 2062 2063 var tx = await this.db.transaction( 2064 [this.subdomainObjectStore], 2065 "readwrite" 2066 ); 2067 2068 // Wait for the database transaction to complete 2069 tx.oncomplete = function () { 2070 // this.print(3,"stored note!"); 2071 }; 2072 tx.onerror = function (event) { 2073 // this.print(3, 2074 // " object get value error storing note " + event.target.errorCode 2075 // ); 2076 }; 2077 2078 var obStore = await tx.objectStore(this.subdomainObjectStore); 2079 resolve(obStore); 2080 }); 2081 dbOpenRequest.addEventListener("error", () => { 2082 // this.print(3,"error"); 2083 reject(null); 2084 }); 2085 }); 2086 2087 const getAllValuesFromDB = await new Promise(async (resolve, reject) => { 2088 var request = await obStore.openCursor(); 2089 2090 request.addEventListener("success", async (event) => { 2091 let cursor = await event.target.result; 2092 if (cursor) { 2093 let key = await cursor.primaryKey; 2094 let value = await cursor.value; 2095 if (this.translation_api_global_data) { 2096 this.translation_api_global_data[this.cleanString(key)] = 2097 await value; 2098 if (Object.keys(this.arr_nodes).includes(this.cleanString(key))) { 2099 this.arr_nodes[`${this.cleanString(key)}`].translatedText = 2100 this.translation_api_global_data[this.cleanString(key)]; 2101 } 2102 } 2103 await cursor.continue(); 2104 } else { 2105 resolve(request); 2106 } 2107 }); 2108 request.addEventListener("error", () => { 2109 // this.print(3,"error"); 2110 reject(null); 2111 }); 2112 }); 2113 return; 2114 } 2115 2116 // indexDb methods end 2117 2118 isTextTranslatedText(text="") { 2119 const textWithoutMeta = text.replace(this.meta_prefix, ""); 2120 const textWithReplacedSeperator = textWithoutMeta.replaceAll(this.sentence_merge_separator_send,this.sentence_merge_separator_receive) 2121 if(!textWithReplacedSeperator){ 2122 return true 2123 } 2124 if(!this.translation_api_global_data_by_local_key){ 2125 return true 2126 } 2127 return !!this.translation_api_global_data_by_local_key[ 2128 textWithReplacedSeperator.toLowerCase() 2129 ]; 2130 } 2131 2132 //update api function calling 2133 async sentenceUpdateApi() { 2134 try { 2135 this.print(3, "Update Api Started");
2136 this.print(3, "this sentenceUpdateApi", this); 2137 this.print(2, "sentenceUpdateApi this.access_token", this.access_token); 2138 this.print( 2139 3, 2140 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1725 ~ Devnagri ~ sentenceUpdateApi ~ this.arr_nodes", 2141 Object.keys(this.arr_nodes).length 2142 ); 2143 2144 let arrSentences = []; 2145 2146 for (let key of Object.keys(this.arr_nodes)) { 2147 if (!arrSentences.includes(this.cleanString(key))) { 2148 arrSentences.push(this.cleanString(key)); 2149 } 2150 } 2151 2152 arrSentences = arrSentences.filter( 2153 (sentence) => 2154 !this.checkIfStringIsLocal(sentence, false) && 2155 !this.isTextTranslatedText(sentence) 2156 ); 2157 2158 const documentUrlWithoutInternalLink = this.removeInternalLinkFromUrl( 2159 this.document_url_full 2160 ); 2161 2162 let mergedSentences = [] 2163 if(this.enable_sentence_merging){ 2164 mergedSentences =Object.values(this.sentence_nodes).map( 2165 (item) => item.original_text 2166 ); 2167 } 2168 2169 mergedSentences = mergedSentences.filter( 2170 (sentence) => 2171 !this.checkIfStringIsLocal(sentence, false) 2172 // && 2173 // !this.isTextTranslatedText(sentence) 2174 ); 2175 2176 const sentences = arrSentences.concat(mergedSentences); 2177 if(!this.compareArrays(this.prevSentenceData, sentences)) 2178 { 2179 this.prevSentenceData = sentences; 2180 this.sentenceData = await this.callApiRequest(async () => { 2181 const res = await fetch(this.update_api_url, { 2182 method: "POST", 2183 headers: { 2184 "Content-Type": "application/json", 2185 Authorization: `Bearer ${this.access_token}`, 2186 }, 2187 body: JSON.stringify({ 2188 url: documentUrlWithoutInternalLink, 2189 language_code: this.default_lang_code, 2190 sentences: sentences, 2191 }), 2192 }); 2193 if (res.status === 401 || res.status === 403) { 2194 throw { response: res }; 2195 } 2196 const response = await res.json(); 2197 return response; 2198 }); 2199 } 2200 this.print(3, "Update Api Completed"); 2201 return this.sentenceData; 2202 } catch (error) { 2203 throw error; 2204 } 2205 } 2206 2207 // this function is used for setting hindi text in html dom 2208 setTranslatedTextToNode(node) { 2209 node.nodes.forEach((element) => { 2210 const originalText = node.originalText; 2211 const trimmedText = originalText.trim(); 2212 const translatedText = node.translatedText; 2213 const translatedTextWithSpaces = originalText.replace( 2214 trimmedText, 2215 translatedText 2216 ); 2217 2218 this.setTranslatedTextToElement( 2219 element, 2220 translatedTextWithSpaces, 2221 originalText, 2222 node.disableOrigTextCheck, 2223 node.attributeKeyName 2224 ); 2225 }); 2226 } 2227 2228 // this function is used for setting hindi text to html dom element 2229 setTranslatedTextToElement( 2230 element, 2231 translatedText, 2232 originalText, 2233 disableOrigTextCheck = false, 2234 attributeKeyName="" 2235 ) { 2236 if (this.selected_lang_code !== this.source_lang_code) { 2237 if ( 2238 this.isTextTranslatedText(this.cleanString(originalText)) || 2239 ( 2240 this.isTextTranslatedText(element.textContent) && 2241 element.nodeName && 2242 !["META","INPUT","TEXTAREA","IMG"].includes(element.nodeName) 2243 ) 2244 ) { 2245 return; 2246 } 2247 } 2248 2249 if(attributeKeyName === "title"){ 2250 this.print(3,"setTranslatedTextToElement setting title",{ element, 2251 translatedText, 2252 originalText, 2253 disableOrigTextCheck, 2254 attributeKeyName, 2255 textInNode: element.title 2256 }) 2257 if (originalText && element && element.title) { 2258 if ( 2259 this.cleanString(element.title.trim().toLowerCase()) === this.cleanString(originalText.trim().toLowerCase()) || disableOrigTextCheck 2260 ) { 2261 element.title = translatedText; 2262 } 2263 } 2264 return 2265 } 2266 2267 if (element.nodeName == "INPUT") { 2268 if (element.type === "button") { 2269 if (element.value === originalText) { 2270 element.value = translatedText; 2271 } 2272 } else { 2273 if (element.type === "submit") { 2274 if (element.value === originalText) { 2275 element.value = translatedText; 2276 } 2277 } 2278 2279 if (element.placeholder === originalText) { 2280 element.placeholder = translatedText; 2281 } 2282 2283 // if (element.title && element.title === originalText) { 2284 // element.title = translatedText; 2285 // } 2286 2287 if (element.type != "hidden") { 2288 if (element.title && element.title === originalText) { 2289 element.title = translatedText; 2290 } 2291 } 2292 } 2293 } else if (element.nodeName == "META") { 2294 if ( 2295 (element.name && 2296 [ 2297 "DESCRIPTION",
2298 "TITLE", 2299 "KEYWORDS", 2300 "TWITTER:TITLE", 2301 "TWITTER:DESCRIPTION", 2302 ].includes(element.name.toUpperCase())) || 2303 (element.getAttribute("property") && 2304 ["OG:TITLE", "OG:DESCRIPTION"].includes( 2305 element.getAttribute("property").toUpperCase() 2306 )) 2307 ) { 2308 if (translatedText.startsWith(this.meta_prefix)) { 2309 translatedText = translatedText.replace(this.meta_prefix, ""); 2310 } 2311 element.content = translatedText; 2312 // meta editor 2313 if (element.name) { 2314 this.metatag_key = element.nodeName + "-" + element.name; 2315 this.metatag_arr[`${this.metatag_key}`] = { 2316 ...this.metatag_arr[`${this.metatag_key}`], 2317 content: element.content, 2318 translatedText: element.content, 2319 }; 2320 } else if (element.getAttribute("property")) { 2321 this.metatag_key = 2322 element.nodeName + "-" + element.getAttribute("property"); 2323 this.metatag_arr[`${this.metatag_key}`] = { 2324 ...this.metatag_arr[`${this.metatag_key}`], 2325 2326 content: element.content, 2327 translatedText: element.content, 2328 }; 2329 } 2330 } 2331 } else if (element.nodeName == "TEXTAREA") { 2332 if ( 2333 element.placeholder && 2334 element.placeholder.replaceAll("\n", "").trim().toLowerCase() === 2335 originalText.replaceAll("\n", "").trim().toLowerCase() 2336 ) { 2337 element.placeholder = translatedText; 2338 } 2339 2340 if (element.title && element.title === originalText) { 2341 element.title = translatedText; 2342 } 2343 2344 } else if (element.nodeName == "IMG") { 2345 if (translatedText.startsWith(this.meta_prefix)) { 2346 translatedText = translatedText.replace(this.meta_prefix, ""); 2347 } 2348 if (originalText.startsWith(this.meta_prefix)) { 2349 originalText = originalText.replace(this.meta_prefix, ""); 2350 } 2351 if ( 2352 element.alt && 2353 element.alt.replaceAll("\n", "").trim().toLowerCase() === 2354 originalText.replaceAll("\n", "").trim().toLowerCase() 2355 ) { 2356 element.alt = translatedText; 2357 } 2358 2359 if ( 2360 element.title && 2361 element.title.replaceAll("\n", "").trim().toLowerCase() === 2362 originalText.replaceAll("\n", "").trim().toLowerCase() 2363 ) { 2364 element.title = translatedText; 2365 } 2366 } else if (element.nodeName == "A") { 2367 //if (element.title && element.title.replaceAll("\n", "").trim().toLowerCase() === originalText.replaceAll("\n", "").trim().toLowerCase()) 2368 { 2369 element.title = translatedText; 2370 } 2371 } else { 2372 if (translatedText.startsWith(this.meta_prefix)) { 2373 translatedText = translatedText.replace(this.meta_prefix, ""); 2374 } 2375 if (originalText.startsWith(this.meta_prefix)) { 2376 originalText = originalText.replace(this.meta_prefix, ""); 2377 } 2378 2379 if ( 2380 this.cleanString(element.textContent.toLowerCase()) === 2381 this.cleanString(originalText.toLowerCase()) || 2382 disableOrigTextCheck || 2383 this.isLiveJs() 2384 ) { 2385 // to prevent triggering of DOMCharacterDataModified event even if we have english text. 2386 // if( this.checkIfStringIsHindi(translatedText)){ 2387 2388 if ( 2389 (this.cleanString(originalText) != this.cleanString(translatedText) && 2390 this.checkIfStringIsLocal(translatedText, true)) || 2391 disableOrigTextCheck 2392 ) { 2393 element.textContent = translatedText; 2394 } 2395 2396 // element.textContent = translatedText; 2397 } 2398 } 2399 } 2400 2401 // this function is used for setting hindi text in html dom 2402 translate(langCode) { 2403 this.print(3, "Translation started now - " + langCode); 2404 if ( 2405 this.arr_nodes !== "undefined" && 2406 this.translation_api_global_data != false 2407 ) { 2408 if (langCode != this.source_lang_code) { 2409 //selected language is not the same as page source language 2410 for (let key of Object.keys(this.arr_nodes)) { 2411 this.setTranslatedTextToNode({ 2412 ...this.arr_nodes[`${this.cleanString(key)}`], 2413 // disableOrigTextCheck: true, 2414 }); 2415 } 2416 } else { 2417 // convert the translation back to the original lanaguage 2418 2419 for (let key of Object.keys(this.arr_nodes)) { 2420 for (let key of Object.keys(this.arr_nodes)) { 2421 this.setTranslatedTextToNode({ 2422 ...this.arr_nodes[`${this.cleanString(key)}`], 2423 translatedText: `${this.cleanString(key)}`, 2424 disableOrigTextCheck: true, 2425 }); 2426 } 2427 } 2428 // translate sentence nodes back to english
2429 Object.keys(this.sentence_nodes).forEach(key=>{ 2430 let children = [] 2431 if(this.sentence_nodes[key] && this.sentence_nodes[key].children){ 2432 children = this.sentence_nodes[key].children 2433 } 2434 if(children && Array.isArray(children)){ 2435 children.forEach(child =>{ 2436 const originalText = child.original_text; 2437 if(child.node){ 2438 this.setTranslatedTextToNode({ 2439 nodes:[child.node], 2440 translatedText: `${this.cleanString(originalText)}`, 2441 disableOrigTextCheck: true, 2442 originalText:originalText 2443 }); 2444 } 2445 }) 2446 } 2447 }) 2448 } 2449 } 2450 this.metatag_arr.TITLE = { 2451 ...this.metatag_arr.TITLE, 2452 translatedText: document.title, 2453 }; 2454 } 2455 2456 // start whole dom translation 2457 startTraversingNow() { 2458 this.print(3, "Traversing Started"); 2459 this.traverseNodes(document.head, this.checkNodeType); 2460 this.traverseNodes(document.body, this.checkNodeType); 2461 this.print(3, "Traversing Completed"); 2462 } 2463 2464 isUrlLangStatusActive(selected_lang_code) { 2465 const statusMap = this.lang_status_map; 2466 return statusMap[selected_lang_code] === "ACTIVE"; 2467 } 2468 2469 //this function is used for checking the status like active,inactive of authentication 2470 async subscriptionStatusApi(status_api_url) { 2471 try { 2472 const res = await fetch(status_api_url, { 2473 method: "POST", 2474 headers: { 2475 "Content-Type": "application/json", 2476 Authorization: `Bearer ${this.access_token}`, 2477 }, 2478 body: JSON.stringify({ 2479 url: this.document_url_full, 2480 language_code: this.selected_lang_code, 2481 //ip: this.user_ip, 2482 //browser: navigator.userAgent, 2483 //timezone: new Date(), 2484 //referrer: this.document_url, 2485 //browserLanguage: navigator.language, 2486 //sizeScreenWidth: screen.width, 2487 //sizeScreenHeight: screen.height, 2488 //location permission granted here for getting lat and long 2489 //latitude: this.user_lat, 2490 //longitude: this.user_long, 2491 }), 2492 }); 2493 if (res.status === 401) { 2494 throw { response: res }; 2495 } 2496 const response = await res.json(); 2497 this.status_api_global_data = response.data; 2498 2499 // enable sentence merging as per url date start 2500 let urlDate = this.sentence_merging_fallback_url_date 2501 if(this.status_api_global_data.url_date){ 2502 urlDate = this.status_api_global_data.url_date 2503 } 2504 2505 if(new Date(urlDate) > new Date(this.sentence_merging_initial_url_date)){ 2506 this.print(3,"Enabling sentence merging") 2507 this.enable_sentence_merging = true 2508 }else{ 2509 this.print(3,"Disabling sentence merging") 2510 this.enable_sentence_merging = false 2511 } 2512 // enable sentence merging as per url date end 2513 2514 if (response && response.data && response.data.enableLanguageDropdownUI) { 2515 this.should_render_ui = "native"; 2516 } else { 2517 this.should_render_ui = "custom"; 2518 } 2519 2520 if ( 2521 response.data.urlStatusArray && 2522 Array.isArray(response.data.urlStatusArray) 2523 ) { 2524 const langStatusMap = {}; 2525 response.data.urlStatusArray.forEach((item) => { 2526 langStatusMap[item.code] = item.status; 2527 }); 2528 this.lang_status_map = langStatusMap; 2529 } 2530 2531 if ( 2532 this.isLiveJs() && 2533 this.status_api_global_data.enableSubdomainRedirect && 2534 !this.web_owner 2535 ) { 2536 this.selected_lang_code = this.source_lang_code; 2537 } 2538 2539 if ( 2540 this.isProxy() && 2541 this.status_api_global_data.urlStatus === "INACTIVE" 2542 ) { 2543 this.print(2, "Redirecting to ", this.document_url_full); 2544 window.location.replace(this.document_url_full); 2545 } 2546 2547 // if(!this.page_view_api_count && (this.selected_lang_code != this.status_api_global_data.source_lang_code)){ 2548 // Promise.all([ 2549 // this.pageViewsApi(this.page_view_api_url) 2550 // ]); 2551 // } 2552 // ++this.page_view_api_count; 2553 2554 if ( 2555 this.status_api_global_data && 2556 this.status_api_global_data.enable_object_mapping 2557 // this.isProxy() 2558 ) { 2559 this.enable_object_mapping = true; 2560 await this.getObjectUrlsApi(); 2561 } 2562 2563 this.print( 2564 3, 2565 "ð ~ file: devnagri-dota-client.js ~ line 1270 ~ Devnagri ~ subscriptionStatusApi ~ response.data", 2566 response.data 2567 ); 2568 if ( 2569 (this.status_api_global_data.enableSubdomainRedirect || 2570 this.isProxy()) && 2571 !this.web_owner 2572 ) { 2573 localStorage.setItem("devnagri_default_lang_code", "en"); 2574 localStorage.setItem("devnagri_selected_lang_code", "en"); 2575 } 2576 this.lang = response.data.languages; 2577 2578 const enable_exclude_block = response.data 2579 ? !!response.data.enable_exclude_block 2580 : false;
2581 2582 const exclude_blocks = 2583 response.data && response.data.exclude_blocks 2584 ? response.data.exclude_blocks 2585 : []; 2586 2587 this.enable_blacklist = enable_exclude_block; 2588 2589 if (enable_exclude_block) { 2590 let blacklist_data = exclude_blocks.map((item) => item.selector); 2591 this.blacklist_data = blacklist_data; 2592 const id_selectors = blacklist_data.filter((item) => 2593 item.includes("#") 2594 ); 2595 this.blacklist_ids = id_selectors.map((selector) => 2596 selector.replaceAll("#", "") 2597 ); 2598 const class_selectors = blacklist_data.filter((item) => 2599 item.includes(".") 2600 ); 2601 this.blacklist_classes = class_selectors.map((selector) => 2602 selector.replaceAll(".", "") 2603 ); 2604 } 2605 2606 if (this.isProxy()) { 2607 this.linkedDomains = response.data.linked_domains; 2608 } 2609 this.frame_ids = response.data.iframe_ids; 2610 this.frame_ids.forEach( 2611 (frameId) => (this.frames_translation_status_map[frameId] = true) 2612 ); 2613 this.setDropdownPosition(response.data.ui_position); 2614 2615 return response; 2616 } catch (err) { 2617 this.print(1,err) 2618 throw err; 2619 } 2620 } 2621 2622 async pageViewsApi(page_view_api_url) { 2623 try { 2624 const res = await fetch(page_view_api_url, { 2625 method: "POST", 2626 headers: { 2627 "Content-Type": "application/json", 2628 Authorization: `Bearer ${this.access_token}`, 2629 }, 2630 body: JSON.stringify({ 2631 url: this.document_url_full, 2632 language_code: this.selected_lang_code, 2633 ip: this.user_ip, 2634 browser: navigator.userAgent, 2635 timezone: new Date(), 2636 referrer: this.document_url, 2637 browserLanguage: navigator.language, 2638 sizeScreenWidth: screen.width, 2639 sizeScreenHeight: screen.height, 2640 //location permission granted here for getting lat and long 2641 latitude: this.user_lat, 2642 longitude: this.user_long, 2643 }), 2644 }); 2645 if (res.status === 401) { 2646 throw { response: res }; 2647 } 2648 const response = await res.json(); 2649 return response; 2650 } catch (err) { 2651 this.print(1,err) 2652 throw err; 2653 } 2654 } 2655 2656 async traverseAndSetTranslationOfWholePage() { 2657 this.print(3, "traverseNodes Traversing whole dom"); 2658 if (this.status_api_global_data && !this.status_api_global_data.is_demo) { 2659 //await this.getValuesInIndexObject(); 2660 } 2661 this.startTraversingNow(); 2662 this.print( 2663 3, 2664 "traverseAndSetTranslationOfWholePage this.access_token ", 2665 this.access_token 2666 ); 2667 await this.checkIfTraversingCompleted(); 2668 this.traverse_whole_dom = false; 2669 } 2670 2671 translateAllFramesOnPage() { 2672 const frameElements = document.querySelectorAll("iframe"); 2673 frameElements.forEach((element) => { 2674 if (element && element.contentDocument && element.contentDocument.body) { 2675 const frameId = element.getAttribute("id"); 2676 if (frameId && this.frame_ids.includes(frameId)) { 2677 if (this.frames_translation_status_map[frameId] === true) { 2678 if (element.contentDocument.body.childElementCount > 0) { 2679 this.print( 2680 3, 2681 "-> Translating IFRAME element.childElementCount", 2682 element.contentDocument.body.childElementCount 2683 ); 2684 this.print( 2685 3, 2686 "-> Translating IFRAME element.contentDocument.body", 2687 frameId, 2688 element.contentDocument.body 2689 ); 2690 2691 const obj = { target: element.contentDocument.body }; 2692 this.domNodeInsertedHandler(obj); 2693 this.frames_translation_status_map[frameId] = false; 2694 } 2695 } 2696 } 2697 2698 // element.contentDocument.addEventListener("DOMNodeInserted", 2699 // this.domNodeInsertedHandler 2700 // ) 2701 // element.contentDocument.body.addEventListener("hover", 2702 // (event)=>{ 2703 // this.print(3,"IFRAME hover triggered",event.target) 2704 // } 2705 // ) 2706 // element.contentDocument.body.addEventListener("DOMCharacterDataModified", (event) => { 2707 // this.print(3,"IFRAME DOMCharacterDataModified listener triggered", event.target) 2708 // const cleanValue = this.cleanString(event.target.textContent); 2709 // if (cleanValue) {
2710 // this.traverseNodes(event.target, this.checkNodeType); 2711 // } 2712 // }) 2713 // element.contentDocument.body.addEventListener("DOMContentLoaded", 2714 // this.domNodeInsertedHandler 2715 // ) 2716 } 2717 }); 2718 } 2719 2720 async domNodeInsertedHandler(event) { 2721 2722 // if(window.location.pathname == '/covid-19' || window.location.pathname == '/covid-19/'){ 2723 // return; 2724 // } 2725 2726 this.print(3, "domNodeInsertedHandler called", event.target); 2727 if(event && event.target && event.target.parentElement){ 2728 if (this.enable_blacklist) { 2729 const parentElement = event.target.parentElement; 2730 var th = this; 2731 // node blacklist by class condition 2732 if ( 2733 this.blacklist_classes 2734 .map( 2735 (item) => 2736 parentElement && 2737 parentElement.getAttribute && 2738 parentElement.getAttribute("class") && 2739 th.isExactMatch(parentElement.getAttribute("class"), item) 2740 ) 2741 .some(Boolean) 2742 ) { 2743 this.print( 2744 3, 2745 "ignoring element with classname " + 2746 parentElement.getAttribute("class") 2747 ); 2748 2749 return; 2750 } 2751 2752 // node blacklist by id condition 2753 if ( 2754 parentElement && 2755 parentElement.getAttribute && 2756 parentElement.getAttribute("id") &&
2757 this.blacklist_ids.includes( 2758 parentElement.getAttribute("id") 2759 ) 2760 ) { 2761 this.print( 2762 3, 2763 "ignoring element with id " + 2764 parentElement.getAttribute("id") 2765 ); 2766 return; 2767 } 2768 } 2769 } 2770 // const frameElements = document.querySelectorAll('iframe'); 2771 2772 // frameElements.forEach((element) => { 2773 // this.print(3,"IFRAME Adding listener to element ", element) 2774 // element.removeEventListener("dblclick",(event)=>{ 2775 // this.print(3,"IFRAME dblclick event triggered") 2776 // this.domNodeInsertedHandler(event) 2777 // }); 2778 // element.click() 2779 // element.removeEventListener("DOMContentLoaded", this.domNodeInsertedHandler); 2780 // element.removeEventListener("load", this.domNodeInsertedHandler); 2781 // element.contentDocument.addEventListener('load', 2782 // this.domNodeInsertedHandler 2783 // ); 2784 2785 // element.style.visibility = "hidden"; 2786 // 2787 // setTimeout(()=>{ 2788 // element.style.visibility = "visible"; 2789 // },0) 2790 2791 // element.contentDocument.addEventListener('dblclick', 2792 // this.domNodeInsertedHandler 2793 // ); 2794 // 2795 // element.contentDocument.body.addEventListener('dblclick',(event)=>{ 2796 // this.print(3,"IFRAME body dblclick event triggered",event.target); 2797 // }); 2798 // this.print(3,"-> IFRAME element.contentDocument.body", element.contentDocument.body); 2799 2800 // this.domNodeInsertedHandler(element.contentDocument.body) 2801 // element.contentDocument.body.addEventListener('DOMContentLoaded',()=>{ 2802 // this.print(3,"IFRAME body DOMContentLoaded event triggered"); 2803 // }); 2804 // 2805 // element.contentDocument.body.addEventListener('load',()=>{ 2806 // this.print(3,"IFRAME body load event triggered"); 2807 // }); 2808 2809 // element.contentDocument.addEventListener("DOMCharacterDataModified", (event) => { 2810 // this.print(3,"IFRAME DOMCharacterDataModified listener triggered", event.target) 2811 // const cleanValue = this.cleanString(event.target.textContent); 2812 // if (cleanValue) { 2813 // this.traverseNodes(event.target, this.checkNodeType); 2814 // } 2815 // }) 2816 // 2817 // element.contentDocument.addEventListener("DOMContentLoaded", 2818 // this.domNodeInsertedHandler 2819 // ) 2820 // element.contentDocument.addEventListener("DOMNodeInserted",(event)=>{ 2821 // this.print(3,"IFRAME DOMNodeInserted listener triggered", event.target) 2822 // this.domNodeInsertedHandler(event) 2823 // }) 2824 // }) 2825 2826 const drawingNodes = ["RECT", "PATH", "G", "CLIPPATH"]; 2827 2828 if (drawingNodes.includes(event.target.nodeName.toUpperCase())) { 2829 return; 2830 } 2831 2832 const unformattedFullUrl = this.isProxy() 2833 ? document.URL.replaceAll( 2834 this.config.requested_domain, 2835 this.config.domain 2836 ) 2837 : document.URL; 2838 2839 const urlObj = new URL(document.URL); 2840 urlObj.searchParams.delete("mode"); 2841 urlObj.searchParams.delete("dota-token"); 2842 urlObj.searchParams.delete("language_code"); 2843 2844 const urlString = urlObj.toString(); 2845 2846 // const fullURL = this.isProxy() 2847 // ? document.URL.replaceAll( 2848 // this.config.requested_domain, 2849 // this.config.domain 2850 // ) 2851 // : document.URL; 2852 2853 const fullURL = this.isProxy() 2854 ? urlString.replaceAll(this.config.requested_domain, this.config.domain) 2855 : urlString; 2856 2857 if ( 2858 event.target && 2859 event.target.parentElement && 2860 event.target.parentElement.nodeName == "STYLE" 2861 ) { 2862 return; 2863 } 2864 2865 // no need to handle text node as it will be handled by DOMCharacterDataModified event 2866 // if (event.target.nodeName === "#text") { 2867 // return; 2868 // } 2869 2870 // clear translation data and re traverse whole dom on url change in case of SPA 2871 // this.traverse_whole_dom = true; 2872 2873 this.print(3, "domNodeInsertedHandler urls", { 2874 document_url_full: this.document_url_full, 2875 fullURL, 2876 }); 2877 2878 if (this.document_url_full !== unformattedFullUrl) { 2879 // this.showLoader(); 2880 this.document_url_full = fullURL; 2881 this.translation_api_url = `${this.api_baseurl}/translations?url=${this.document_url_full}`; 2882 2883 this.arr_nodes = {}; 2884 this.sentence_nodes = {} 2885 this.sentence_nodes_by_orig_text = {} 2886 2887 this.document_url = document.URL; 2888 this.translation_api_retry_counter = 1; 2889 this.missingTranslationPercentageOffsetForRetry = 1; 2890 // this.translation_api_global_data = {}; 2891 this.traverse_whole_dom = true; 2892 console.time("get_values_from_index_db"); 2893 if (this.status_api_global_data && !this.status_api_global_data.is_demo) { 2894 //await this.getValuesInIndexObject(); 2895 } 2896 2897 this.GetTranslationsApi(); 2898 console.timeEnd("get_values_from_index_db"); 2899 // this.startTraversingNow(); 2900 // await this.checkIfTraversingCompleted(); 2901 2902 if ( 2903 this.isProxy() || 2904 this.status_api_global_data.enableSubdomainRedirect 2905 ) { 2906 this.callApiRequest(() => 2907 this.subscriptionStatusApi(this.status_api_url) 2908 ); 2909 } 2910 } 2911 this.translation_api_retry_counter = 1; 2912 this.missingTranslationPercentageOffsetForRetry = 1;
2913 this.traverseNodes(event.target, this.checkNodeType); 2914 this.print( 2915 3, 2916 "domNodeInsertedHandler this.access_token ", 2917 this.access_token 2918 ); 2919 await this.checkIfTraversingCompleted(); 2920 } 2921 2922 // this function is used for checking authentication which follows flow like first login,status,renderui and then translation 2923 async checkAuthenticationToken(expiryTime, apiKey) { 2924 this.print(3, "in checkAuthenticationToken", expiryTime); 2925 2926 try { 2927 let date = new Date(); 2928 // if there is expiry time 2929 if (expiryTime) { 2930 let currentTime = date.getTime() + 1000 * 1 * 60 * 5; // here we added 5 minute offset, we wil get new auth token 5 minute before it expires 2931 // if there is expiry time which has been expired 2932 if (currentTime > expiryTime) { 2933 console.log("in checkAuthenticationToken expiryTime expired", currentTime, expiryTime); 2934 localStorage.removeItem("devnagri_token"); 2935 localStorage.removeItem("devnagri_token_expiry_time"); 2936 // just generating new token 2937 let loginPromise = await this.loginApi(this.login_api_url, apiKey); 2938 if (loginPromise) { 2939 let subscriptionPromise = await this.subscriptionStatusApi( 2940 this.status_api_url 2941 ); 2942 this.print( 2943 3, 2944 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1648 ~ Devnagri ~ checkAuthenticationToken ~ subscriptionPromise", 2945 subscriptionPromise 2946 ); 2947 if (this.web_owner) { 2948 if (subscriptionPromise.data.subscription == "ACTIVE") { 2949 this.enable_object_mapping = 2950 subscriptionPromise.data.subscription.enable_object_mapping; 2951 this.renderTranslateUI(); 2952 this.subscription_status_active = true; 2953 this.print(3, "setting this.subscription_status_active", true); 2954 let translationPromise = await this.GetTranslationsApi(); 2955 } else { 2956 this.subscription_status_active = false; 2957 this.print(3, "setting this.subscription_status_active", false); 2958 } 2959 } else { 2960 if (subscriptionPromise.data.subscription == "ACTIVE") { 2961 this.renderTranslateUI(); 2962 if (subscriptionPromise.data.urlStatus == "ACTIVE") { 2963 this.enable_object_mapping = 2964 subscriptionPromise.data.subscription.enable_object_mapping; 2965 this.subscription_status_active = true; 2966 this.print( 2967 3, 2968 "setting this.subscription_status_active", 2969 true 2970 ); 2971 let translationPromise = await this.GetTranslationsApi(); 2972 } else { 2973 this.subscription_status_active = false; 2974 this.print( 2975 3, 2976 "setting this.subscription_status_active", 2977 false 2978 ); 2979 } 2980 } else { 2981 this.subscription_status_active = false; 2982 this.print(3, "setting this.subscription_status_active", false); 2983 } 2984 } 2985 } 2986 } 2987 // if there is expiry time which has not been expired 2988 else { 2989 let subscriptionPromise = await this.subscriptionStatusApi( 2990 this.status_api_url 2991 ); 2992 this.print( 2993 3, 2994 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1648 ~ Devnagri ~ checkAuthenticationToken ~ subscriptionPromise", 2995 subscriptionPromise 2996 ); 2997 if (this.web_owner) { 2998 if (subscriptionPromise.data.subscription == "ACTIVE") { 2999 this.enable_object_mapping = 3000 subscriptionPromise.data.subscription.enable_object_mapping; 3001 this.renderTranslateUI(); 3002 this.subscription_status_active = true; 3003 this.print(3, "setting this.subscription_status_active", true); 3004 let translationPromise = await this.GetTranslationsApi(); 3005 } else { 3006 this.subscription_status_active = false;
3007 this.print(3, "setting this.subscription_status_active", false); 3008 } 3009 } else { 3010 if (subscriptionPromise.data.subscription == "ACTIVE") { 3011 this.renderTranslateUI(); 3012 if (subscriptionPromise.data.urlStatus == "ACTIVE") { 3013 this.enable_object_mapping = 3014 subscriptionPromise.data.subscription.enable_object_mapping; 3015 this.subscription_status_active = true; 3016 this.print(3, "setting this.subscription_status_active", true); 3017 3018 let translationPromise = await this.GetTranslationsApi(); 3019 } else { 3020 this.subscription_status_active = false; 3021 this.print(3, "setting this.subscription_status_active", false); 3022 } 3023 } else { 3024 this.subscription_status_active = false; 3025 this.print(3, "setting this.subscription_status_active", false); 3026 } 3027 } 3028 } 3029 } else { 3030 let currentTime = date.getTime() + 1000 * 1 * 60 * 5; 3031 // if there is no expiry time then here expiry time will be generated 3032 this.print(3, "in checkAuthenticationToken no expiryTime"); 3033 console.log("in checkAuthenticationToken no expiryTime", currentTime); 3034 3035 if (localStorage.getItem("devnagri_token")) { 3036 localStorage.removeItem("devnagri_token"); 3037 } 3038 if (localStorage.getItem("devnagri_token_expiry_time")) { 3039 localStorage.removeItem("devnagri_token_expiry_time"); 3040 } 3041 let loginPromise = await this.loginApi(this.login_api_url, apiKey); 3042 if (loginPromise) { 3043 let subscriptionPromise = await this.subscriptionStatusApi( 3044 this.status_api_url 3045 ); 3046 this.print( 3047 3, 3048 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1648 ~ Devnagri ~ checkAuthenticationToken ~ subscriptionPromise", 3049 subscriptionPromise 3050 ); 3051 if (subscriptionPromise.data.subscription == "ACTIVE") { 3052 this.renderTranslateUI(); 3053 if (subscriptionPromise.data.urlStatus == "ACTIVE") { 3054 this.subscription_status_active = true; 3055 let translationPromise = await this.GetTranslationsApi(); 3056 if ( 3057 translationPromise && 3058 translationPromise.message == "success" 3059 ) { 3060 } else { 3061 } 3062 } 3063 } else if ( 3064 subscriptionPromise.data.subscription == "ACTIVE" && 3065 this.web_owner 3066 // && 3067 // subscriptionPromise.data.urlStatus != "ACTIVE" 3068 ) { 3069 this.subscription_status_active = true; 3070 this.renderTranslateUI(); 3071 let translationPromise = await this.GetTranslationsApi(); 3072 if (translationPromise && translationPromise.message == "success") { 3073 } else { 3074 } 3075 } 3076 } 3077 } 3078 // return true; 3079 } catch (err) { 3080 this.print( 3081 3, 3082 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 1738 ~ Devnagri ~ checkAuthenticationToken ~ err", 3083 err.message 3084 ); 3085 throw err; 3086 } 3087 } 3088 3089 removeExistingProxyDropdown() { 3090 const dropdownElements = document.getElementsByClassName( 3091 "devnagri_outermostdivclass" 3092 ); 3093 this.print( 3094 3, 3095 "removeExistingProxyDropdown proxy dropdownElements", 3096 dropdownElements.length, 3097 dropdownElements 3098 ); 3099 3100 if (dropdownElements && dropdownElements[0]) { 3101 dropdownElements[0].remove(); 3102 // dropdownElements.forEach(dropdown=>dropdown.remove()) 3103 } 3104 3105 // this.print(3,"removeExistingProxyDropdown proxy dropdown", dropdown) 3106 // if(dropdown){ 3107 // dropdown.remove() 3108 // } 3109 } 3110 3111 setDropdownPosition(ui_position) { 3112 this.print( 3113 3, 3114 "ð ~ setDropdownPosition file: devnagri-dota-merged-client-dev.js ~ line 1777 ~ Devnagri ~ setDropdownPosition ~ ui_position", 3115 ui_position 3116 ); 3117 if (ui_position) { 3118 if (ui_position.right != "") { 3119 this.ui_right = ui_position.right; 3120 } else { 3121 if (!ui_position.left) { 3122 this.ui_right = `3%`; 3123 } 3124 } 3125 3126 if (ui_position.bottom != "") { 3127 this.ui_bottom = ui_position.bottom; 3128 } else { 3129 this.ui_bottom = `4%`; 3130 } 3131 3132 if (ui_position.left != "") { 3133 this.ui_left = ui_position.left; 3134 } 3135 } else { 3136 this.ui_right = `3%`; 3137 this.ui_bottom = `4%`; 3138 } 3139 } 3140 3141 static initializeTranslation(config) { 3142 const devnagri = new Devnagri() 3143 devnagri.initTranslation(config) 3144 return devnagri; 3145 } 3146
3147 async initTranslation(config) { 3148 3149 addEventListener('DOMContentLoaded', (event) => { 3150 let favIcons = document.getElementsByTagName("link"); 3151 for(let favIcon of favIcons){ 3152 //console.log(favIcon.getAttribute("rel")) 3153 if(favIcon.getAttribute("rel") == "shortcut icon"){ 3154 //console.log(favIcon.getAttribute("rel")) 3155 let Linkhref = favIcon.getAttribute("href"); 3156 favIcon.setAttribute("href" , Linkhref.replace(`${document.documentElement.lang}/`, "")); 3157 } 3158 } 3159 3160 let LakhArray = {"hi": "लाà¤","pa": "ਲੱà¨","ta": "லà®à¯à®à®®à¯","gu": "લાàª","bn": "লà¦à§à¦·","kn": "ಲà²à³à²·","mr": "लाà¤","te": "à°²à°à±à°·à°²à±","ml": "à´²à´àµà´·à´","as": "লাà¦","or": "ଲà¬àଷ"}; 3161 let LakhContent = document.getElementsByClassName("postfix_name"); 3162 let languageCode = document.querySelector("html").getAttribute('lang'); 3163 for(let l of LakhContent){ 3164 l.innerHTML = ` + ${LakhArray[languageCode]}`; 3165 } 3166 3167 // let LakhContent = document.getElementsByClassName("postfix_name"); 3168 // if(LakhContent){ 3169 // if (document.documentElement.lang == "as") { 3170 // for(let l of LakhContent){ 3171 // l.innerHTML = ` + লাà¦`; 3172 // } 3173 // } 3174 // } 3175 3176 // let covid19Icon = document.querySelector(".covid-19-new"); 3177 // if(covid19Icon){ 3178 // covid19Icon.getElementsByTagName('a')[0].innerHTML = `<i class="covid-19-icon">Covid-19 in India</i>`; 3179 // } 3180 3181 // let twitterIcon = document.getElementsByClassName("social-content"); 3182 // if(twitterIcon){ 3183 // if (twitterIcon.length > 1) { 3184 // twitterIcon[1].getElementsByTagName('a')[0].innerHTML = `<i class="twitter-icon"></i>MyGov Twitter`; 3185 // } else { 3186 // twitterIcon[0].getElementsByTagName('a')[0].innerHTML = `<i class="twitter-icon"></i>MyGov Twitter`; 3187 // } 3188 // } 3189 }); 3190 3191 3192 this.print(3, "config: ", config); 3193 const proxy_config_keys = [ 3194 // "accessToken", 3195 "domain", 3196 "requested_domain", 3197 "siteUrl", 3198 "linkedDomains", 3199 "existingTranslations", 3200 ]; 3201 // at-least one of proxy keys exists in the config object 3202 if (proxy_config_keys.map((key) => config[key]).some(Boolean)) { 3203 this.script_type = "proxy"; 3204 } 3205 3206 // for live js mode default lang code will be set in login api 3207 if(this.isProxy()){ 3208 if (!config.default_lang_code) { 3209 config.default_lang_code = "en"; 3210 } 3211 this.default_lang_code = config.default_lang_code 3212 } 3213 3214 if (!config.ui_mode) { 3215 config.ui_mode = "custom"; 3216 } 3217 3218 if (!config.apiKey) { 3219 return; 3220 } 3221 // if (!config.accessToken && this.isProxy()) { 3222 // return; 3223 // } 3224 3225 // consider ui mode as native in case of context editor. 3226 if (this.web_owner) { 3227 config.ui_mode = "native"; 3228 } 3229 3230 if (config.ui_mode) { 3231 this.should_render_ui = config.ui_mode; 3232 } 3233 3234 this.print(3, "isProxy", this.isProxy()); 3235 3236 // if(this.isProxy()){ 3237 // requestAnimationFrame(() => { 3238 // setTimeout(() => { 3239 // document.addEventListener("DOMContentLoaded",this.removeExistingProxyDropdown) 3240 // },0); 3241 // }); 3242 // // this.removeExistingProxyDropdown() 3243 // } 3244 3245 if (!this.access_token) { 3246 await this.loginApi(this.login_api_url, config.apiKey); 3247 } 3248 3249 this.api_key = config.apiKey; 3250 3251 this.document_url = config.domain; 3252 3253 this.document_url_full = this.isProxy() 3254 ? document.URL.replaceAll(config.requested_domain, config.domain) 3255 : document.URL; 3256 3257 this.subdomainObjectStore = this.isProxy() 3258 ? this.default_lang_code 3259 : config.target_lang_code; 3260 this.print(3, "this.subdomainObjectStore", this.subdomainObjectStore); 3261 3262 if (this.isLiveJs() || this.isProxy()) { 3263 if (this.isLiveJs()) { 3264 // if (config.ui_mode.toLowerCase() != "custom") { 3265 this.cssLinkInjection(); 3266 // } 3267 } 3268 3269 if (this.isProxy()) { 3270 this.cssLinkInjection(); 3271 this.web_owner = false;
3272 } 3273 3274 // this.setDropdownPosition(config.ui_position); 3275 3276 // used selected lang code for because in upper portion of the code we already picked code from query param and assigned it to selected_lang_code 3277 this.default_lang_code = this.web_owner 3278 ? this.selected_lang_code 3279 : this.default_lang_code; 3280 if (this.selected_lang_code === this.source_lang_code) { 3281 this.selected_lang_code = this.default_lang_code; 3282 } 3283 // select by def english 3284 // if (!localStorage.getItem("devnagri_selected_lang_code")) { 3285 // localStorage.setItem( 3286 // "devnagri_selected_lang_code", 3287 // this.source_lang_code 3288 // ); 3289 // } 3290 this.print(3, "before checkAuthenticationToken"); 3291 this.print(3, "checkAuthenticationToken", this.checkAuthenticationToken); 3292 const result = await this.checkAuthenticationToken( 3293 this.expiry_token_time, 3294 config.apiKey 3295 ); 3296 this.print(3, "after checkAuthenticationToken"); 3297 3298 this.print( 3299 3, 3300 "ð ~ file: devnagri-dota-client.js ~ line 1710 ~ Devnagri ~ initTranslation ~ this.access_token", 3301 this.access_token 3302 ); 3303 this.print( 3304 3, 3305 "ð ~ file: devnagri-dota-client.js ~ line 1710 ~ Devnagri ~ initTranslation ~ this.subscription_status_active", 3306 this.subscription_status_active 3307 ); 3308 if (this.subscription_status_active) { 3309 // if ( 3310 // this.status_api_global_data && 3311 // this.status_api_global_data.enable_object_mapping 3312 // // this.isProxy() 3313 // ) { 3314 // await this.getObjectUrlsApi(); 3315 // } 3316 3317 this.startTraversingNow(); 3318 await this.checkIfTraversingCompleted(); 3319 // set text direction rtl for urdu 3320 const rtlLangs = ["ur","ar"] 3321 if (rtlLangs.includes(this.selected_lang_code)) { 3322 console.log("setting text direction rtl for urdu") 3323 document.body.setAttribute("dir", "rtl"); 3324 }else{ 3325 console.log("setting text direction ltr for other langs"); 3326 document.body.setAttribute("dir", "ltr"); 3327 } 3328 } 3329 } 3330 3331 // const enableDynamicTranslation = !(config.domain && (config.domain.includes("devnagri") || config.domain.includes("fourtek"))) 3332 const enableDynamicTranslation = !config.enable_static_content; 3333 // this.print(3,"-> enableDynamicTranslation", enableDynamicTranslation); 3334 3335 this.enable_object_mapping = config.enable_object_mapping; 3336 3337 this.translation_api_url = `${this.api_baseurl}/translations?rl=${this.document_url_full}`; 3338 this.update_api_url = `${this.api_baseurl}/translations`; 3339 3340 this.target_lang_code = config.target_lang_code; 3341 3342 this.api_key = config.apiKey; 3343 this.translation_api_global_data = this.isProxy() 3344 ? this.cleanExistingTranslationObj(config.existingTranslations) 3345 : {}; 3346 3347 if (enableDynamicTranslation) { 3348 if (this.translation_api_global_data) { 3349 if (this.status_api_global_data && !this.status_api_global_data.is_demo) { 3350 //this.storeValuesInIndexDB(this.translation_api_global_data); 3351 } 3352 } 3353 } 3354 3355 if (this.isProxy()) { 3356 this.domain = config.domain; 3357 this.requested_domain = config.requested_domain; 3358 // this.linkedDomains = config.linkedDomains; 3359 this.subdomain_object_urls_hash_map = 3360 config.subdomain_object_urls_hash_map; 3361 // this.enable_blacklist = config.enable_blacklist; 3362 // this.blacklist_classes = config.blacklist_classes; 3363 // this.blacklist_ids = config.blacklist_ids; 3364 } 3365 3366 // if ( 3367 // config.subdomain_object_urls_hash_map && 3368 // typeof config.subdomain_object_urls_hash_map === "object" 3369 // ) { 3370 // const objectsArr = Object.values(config.subdomain_object_urls_hash_map); 3371 // const localObjectUrlsHashMap = {}; 3372 // objectsArr.forEach((object) => { 3373 // localObjectUrlsHashMap[object.local_url] = object; 3374 // }); 3375 // this.subdomain_object_urls_hash_map_local = localObjectUrlsHashMap; 3376 // } 3377 3378 this.config = config; 3379 3380 this.frame_ids.forEach( 3381 (frameId) => (this.frames_translation_status_map[frameId] = true) 3382 ); 3383 3384 if (enableDynamicTranslation) { 3385 if (this.isProxy()) { 3386 // document.addEventListener("DOMCharacterDataModified", (event) => { 3387 // if (!this.edit_mode_enabled) { 3388 // if (this.source_lang_code === this.selected_lang_code) { 3389 // return; 3390 // } 3391 // if (this.source_lang_code !== this.selected_lang_code) { 3392 // const cleanValue = this.cleanString(event.target.textContent); 3393 // if (cleanValue && !this.isTextTranslatedText(cleanValue)) { 3394 // if (this.enable_blacklist) { 3395 // const parentElement = event.target.parentElement; 3396 // var th = this;
3397 // // node blacklist by class condition 3398 // if ( 3399 // this.blacklist_classes 3400 // .map( 3401 // (item) => 3402 // parentElement && 3403 // parentElement.getAttribute("class") && 3404 // th.isExactMatch(parentElement.getAttribute("class"), item) 3405 // ) 3406 // .some(Boolean) 3407 // ) { 3408 // this.print( 3409 // 3, 3410 // "ignoring element with classname " + 3411 // parentElement.getAttribute("class") 3412 // ); 3413 3414 // return; 3415 // } 3416 3417 // // node blacklist by id condition 3418 // if ( 3419 // parentElement && 3420 // parentElement.getAttribute && 3421 // parentElement.getAttribute("id") && 3422 // this.blacklist_ids.includes( 3423 // parentElement.getAttribute("id") 3424 // ) 3425 // ) { 3426 // this.print( 3427 // 3, 3428 // "ignoring element with id " + 3429 // parentElement.getAttribute("id") 3430 // ); 3431 // return; 3432 // } 3433 // } 3434 3435 // const node = event.target; 3436 // if(this.enable_sentence_merging && node && node.parentElement && this.isNodeASentence(node.parentElement)){ 3437 // this.traverseNodes(node.parentElement, this.checkNodeType); 3438 // }else{ 3439 // this.traverseNodes(event.target, this.checkNodeType); 3440 // } 3441 // } 3442 // } 3443 // } 3444 // }); 3445 3446 // Create a MutationObserver instance 3447 const observer = new MutationObserver((mutationsList) => { 3448 for (const mutation of mutationsList) { 3449 if (mutation.type === 'characterData') { 3450 const event = mutation; 3451 if (!this.edit_mode_enabled) { 3452 if (this.source_lang_code === this.selected_lang_code) { 3453 return; 3454 } 3455 if (this.source_lang_code !== this.selected_lang_code) { 3456 const cleanValue = this.cleanString(event.target.textContent); 3457 if (cleanValue && !this.isTextTranslatedText(cleanValue)) { 3458 if (this.enable_blacklist) { 3459 const parentElement = event.target.parentElement; 3460 var th = this; 3461 // node blacklist by class condition 3462 if (
3463 this.blacklist_classes 3464 .map( 3465 (item) => 3466 parentElement && 3467 parentElement.getAttribute("class") && 3468 th.isExactMatch(parentElement.getAttribute("class"), item) 3469 ) 3470 .some(Boolean) 3471 ) { 3472 this.print( 3473 3, 3474 "ignoring element with classname " + 3475 parentElement.getAttribute("class") 3476 ); 3477 3478 return; 3479 } 3480 3481 // node blacklist by id condition 3482 if ( 3483 parentElement && 3484 parentElement.getAttribute && 3485 parentElement.getAttribute("id") && 3486 this.blacklist_ids.includes( 3487 parentElement.getAttribute("id") 3488 ) 3489 ) { 3490 this.print( 3491 3, 3492 "ignoring element with id " + 3493 parentElement.getAttribute("id") 3494 ); 3495 return; 3496 } 3497 } 3498 3499 const node = event.target; 3500 if(this.enable_sentence_merging && node && node.parentElement && this.isNodeASentence(node.parentElement)){ 3501 this.traverseNodes(node.parentElement, this.checkNodeType); 3502 }else{ 3503 this.traverseNodes(event.target, this.checkNodeType); 3504 } 3505 } 3506 } 3507 } 3508 } 3509 } 3510 }); 3511 3512 // Start observing the document for character data changes 3513 observer.observe(document.body, { 3514 characterData: true, 3515 subtree: true 3516 }); 3517 } 3518 3519 // for getting notify dynamic rendering 3520 // document.addEventListener("DOMNodeInserted", (e) => { 3521 // this.print(3, "DOMNodeInserted"); 3522 // if (!this.edit_mode_enabled) { 3523 // if (this.source_lang_code === this.selected_lang_code) { 3524 // return; 3525 // } 3526 // if ( 3527 // Object.values(this.frames_translation_status_map).some((val) => val) 3528 // ) { 3529 // this.translateAllFramesOnPage(); 3530 // } 3531 // this.domNodeInsertedHandler(e); 3532 // } 3533 3534 // // fix for a tag 3535 // if (this.isProxy()) { 3536 // const aTags = document.getElementsByTagName("a"); 3537 // //Get Language DropDown A Tags 3538 // const aTagsLanguageSwitcher = document.getElementsByClassName("language-link "); 3539 // let aTagsLanguageSwitcherArray = []; 3540 // for(let aTagLS of aTagsLanguageSwitcher){ 3541 // aTagsLanguageSwitcherArray.push(aTagLS.getAttribute("href")); 3542 // } 3543 3544 // var devnagriLanguageSwitcherArray = []; 3545 // /* for (let i = 0; i < this.status_api_global_data.subdomains.length; i++) { 3546 // if(this.status_api_global_data.subdomains[i].code != 'en'){ 3547 // devnagriLanguageSwitcherArray.push(this.status_api_global_data.subdomains[i].subdomain); 3548 // } 3549 // } */ 3550 3551 3552 // const devnagriLanguageSwitcher = document.querySelectorAll(".devnagri_optionElement a"); 3553 // for(let aTagDLS of devnagriLanguageSwitcher){ 3554 // if(aTagDLS.parentElement.getAttribute("devnagri_lang_code_attribute") != 'en'){ 3555 // devnagriLanguageSwitcherArray.push(aTagDLS.getAttribute("href")); 3556 // } 3557 // } 3558 3559 // for(let aTag of aTags){ 3560 // let href = aTag.getAttribute("href"); 3561 3562 // //Prevent for Language Dropdown 3563 // if(aTagsLanguageSwitcherArray.includes(href)){ 3564 // continue; 3565 // } 3566 3567 // if(devnagriLanguageSwitcherArray.includes(href)){ 3568 // continue; 3569 // } 3570 // if(['kn', 'ml', 'ta', 'hi'].includes(document.documentElement.lang)){ 3571 // if(href && !href.includes(`https://${window.location.hostname}/${document.documentElement.lang}`) && href.includes(`https://${window.location.hostname}`)){ 3572 // aTag.setAttribute("href", href.replace(`${this.domain}`, `https://${window.location.hostname}/${document.documentElement.lang}`)); 3573 // } 3574 // if(href && href[0] == "/"){ 3575 3576 // aTag.setAttribute("href", href.replace(`/`, `https://${window.location.hostname}/${document.documentElement.lang}/`)); 3577 // } 3578 // }else{ 3579 // if(href && !href.includes(`https://${window.location.hostname}`)){ 3580 // aTag.setAttribute("href", href.replace(`${this.domain}`, `https://${window.location.hostname}`)); 3581 // } 3582 // if(href && href[0] == "/"){ 3583 3584 // aTag.setAttribute("href", href.replace(`/`, `https://${window.location.hostname}/`)); 3585 // } 3586 // } 3587 // } 3588 // } 3589 // }); 3590 3591 // Create a MutationObserver instance 3592 const observer = new MutationObserver((mutationsList) => { 3593 for (const mutation of mutationsList) { 3594 if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { 3595 this.print(3, "DOMNodeInserted"); 3596 if (!this.edit_mode_enabled) { 3597 if (this.source_lang_code === this.selected_lang_code) { 3598 return; 3599 } 3600 if (Object.values(this.frames_translation_status_map).some((val)
3600=> val)) { 3601 this.translateAllFramesOnPage(); 3602 } 3603 this.domNodeInsertedHandler(mutation); 3604 } 3605 3606 // fix for a tag 3607 if (this.isProxy()) { 3608 const aTags = document.getElementsByTagName("a"); 3609 // Get Language DropDown A Tags 3610 const aTagsLanguageSwitcher = document.getElementsByClassName("language-link "); 3611 let aTagsLanguageSwitcherArray = []; 3612 for (let aTagLS of aTagsLanguageSwitcher) { 3613 aTagsLanguageSwitcherArray.push(aTagLS.getAttribute("href")); 3614 } 3615 3616 var devnagriLanguageSwitcherArray = []; 3617 /* for (let i = 0; i < this.status_api_global_data.subdomains.length; i++) { 3618 if(this.status_api_global_data.subdomains[i].code != 'en'){ 3619 devnagriLanguageSwitcherArray.push(this.status_api_global_data.subdomains[i].subdomain); 3620 } 3621 } */ 3622 3623 const devnagriLanguageSwitcher = document.querySelectorAll(".devnagri_optionElement a"); 3624 for (let aTagDLS of devnagriLanguageSwitcher) { 3625 if (aTagDLS.parentElement.getAttribute("devnagri_lang_code_attribute") != 'en') { 3626 devnagriLanguageSwitcherArray.push(aTagDLS.getAttribute("href")); 3627 } 3628 } 3629 3630 for (let aTag of aTags) { 3631 let href = aTag.getAttribute("href"); 3632 3633 // Prevent for Language Dropdown 3634 if (aTagsLanguageSwitcherArray.includes(href)) { 3635 continue; 3636 } 3637 3638 if (devnagriLanguageSwitcherArray.includes(href)) { 3639 continue; 3640 } 3641 if (['kn', 'ml', 'ta', 'hi'].includes(document.documentElement.lang)) { 3642 if (href && !href.includes(`https://${window.location.hostname}/${document.documentElement.lang}`) && href.includes(`https://${window.location.hostname}`)) { 3643 aTag.setAttribute("href", href.replace(`${this.domain}`, `https://${window.location.hostname}/${document.documentElement.lang}`)); 3644 } 3645 if (href && href[0] == "/") { 3646 aTag.setAttribute("href", href.replace(`/`, `https://${window.location.hostname}/${document.documentElement.lang}/`)); 3647 } 3648 } else { 3649 if (href && !href.includes(`https://${window.location.hostname}`)) { 3650 aTag.setAttribute("href", href.replace(`${this.domain}`, `https://${window.location.hostname}`)); 3651 } 3652 if (href && href[0] == "/") { 3653 aTag.setAttribute("href", href.replace(`/`, `https://${window.location.hostname}/`)); 3654 } 3655 } 3656 } 3657 } 3658 } 3659 } 3660 }); 3661
3662 // Start observing the document for added nodes 3663 observer.observe(document.body, { 3664 childList: true, 3665 attributes: true, 3666 characterData: true, 3667 subtree: true 3668 }); 3669 this.GetTranslationsApi(); 3670 } 3671 3672 if (this.isProxy()) { 3673 if (enableDynamicTranslation) { 3674 // this.get_user_location(); 3675 await this.callApiRequest(() => 3676 this.subscriptionStatusApi(this.status_api_url) 3677 ); 3678 } 3679 } 3680 } 3681 3682 async delay(ms) { 3683 return new Promise((res) => setTimeout(res, ms)); 3684 } 3685 3686 async updateGlobalData() { 3687 if (!this.update_global_data_timeout) { 3688 const self = this; 3689 this.print(3, "updateGlobalData this.access_token", this.access_token); 3690 3691 this.update_global_data_timeout = setTimeout(async () => { 3692 this.print( 3693 3, 3694 "updateGlobalData timeout this.access_token", 3695 self.access_token 3696 ); 3697 //if(this.apiCounter <= 1) 3698 { 3699 await this.sentenceUpdateApi(); 3700 await this.delay(2000); 3701 await this.GetTranslationsApi(); 3702 } 3703 if (this.traverse_whole_dom) { 3704 this.traverseAndSetTranslationOfWholePage(); 3705 } 3706 this.update_global_data_timeout = null; 3707 }, 3000); 3708 } 3709 } 3710 3711 async calculateMissingTranslationPercentage() { 3712 let translationData = this.translation_api_global_data; 3713 let nodesCount = Object.keys(this.arr_nodes).length; 3714 if (!translationData || nodesCount == 0) { 3715 return; 3716 } 3717 let missingTranslations = []; 3718 for (let key of Object.keys(this.arr_nodes)) { 3719 let txtOriginal = key; 3720 if (txtOriginal.startsWith(this.meta_prefix)) { 3721 txtOriginal = txtOriginal.replace(this.meta_prefix, ""); 3722 } 3723 if (translationData[this.cleanString(txtOriginal)]) { 3724 this.arr_nodes[this.cleanString(key)].translatedText = 3725 translationData[this.cleanString(txtOriginal)]; 3726 } else { 3727 if (!missingTranslations.includes(key)) { 3728 missingTranslations.push(key); 3729 } 3730 this.print( 3731 2, 3732 "translation not found for key = '" + key + "'", 3733 translationData 3734 ); 3735 } 3736 } 3737 3738 let missingPercentage = (missingTranslations.length * 100) / nodesCount; 3739 this.print( 3740 2, 3741 "translation missing number = " + 3742 missingTranslations.length + 3743 " missing percentage = " + 3744 missingPercentage + 3745 " total nodes = " + 3746 nodesCount 3747 ); 3748 return missingPercentage; 3749 } 3750 3751 // Live js methodes 3752 // async checkAuthenticationToken(expiryTime, apiKey) { 3753 // try { 3754 // // if there is expiry time 3755 // if (expiryTime) { 3756 // let date = new Date(); 3757 // let currentTime = date.getTime() + 1000 * 1 * 60 * 5; // here we added 5 minute offset, we wil get new auth token 5 minute before it expires 3758 // // if there is expiry time which has been expired 3759 // if (currentTime > expiryTime) { 3760 // localStorage.removeItem("devnagri_token"); 3761 // localStorage.removeItem("devnagri_token_expiry_time"); 3762 // // just generating new token 3763 // let loginPromise = await this.loginApi(this.login_api_url, apiKey); 3764 // if (loginPromise) { 3765 // let subscriptionPromise = await this.subscriptionStatusApi( 3766 // this.status_api_url 3767 // ); 3768 // if (this.web_owner) { 3769 // if (subscriptionPromise.data.subscription == "ACTIVE") { 3770 // this.enable_object_mapping = 3771 // subscriptionPromise.data.subscription.enable_object_mapping; 3772 // this.renderTranslateUI(); 3773 // this.subscription_status_active = true; 3774 // this.print(3, "setting this.subscription_status_active", true); 3775 // let translationPromise = await this.GetTranslationsApi(); 3776 // } else { 3777 // this.subscription_status_active = false; 3778 // this.print(3, "setting this.subscription_status_active", false); 3779 // } 3780 // } else { 3781 // if (subscriptionPromise.data.subscription == "ACTIVE") { 3782 // this.renderTranslateUI(); 3783 3784 // if (subscriptionPromise.data.urlStatus == "ACTIVE") { 3785 // this.enable_object_mapping = 3786 // subscriptionPromise.data.subscription.enable_object_mapping; 3787 // this.subscription_status_active = true; 3788 // this.print( 3789 // 3, 3790 // "setting this.subscription_status_active", 3791 // true 3792 // ); 3793 // let translationPromise = await this.GetTranslationsApi(); 3794 // } else { 3795 // this.subscription_status_active = false;
3796 // this.print( 3797 // 3, 3798 // "setting this.subscription_status_active", 3799 // false 3800 // ); 3801 // } 3802 // } else { 3803 // this.subscription_status_active = false; 3804 // this.print(3, "setting this.subscription_status_active", false); 3805 // } 3806 // } 3807 // } 3808 // } 3809 // // if there is expiry time which has not been expired 3810 // else { 3811 // let subscriptionPromise = await this.subscriptionStatusApi( 3812 // this.status_api_url 3813 // ); 3814 // if (this.web_owner) { 3815 // if (subscriptionPromise.data.subscription == "ACTIVE") { 3816 // this.enable_object_mapping = 3817 // subscriptionPromise.data.subscription.enable_object_mapping; 3818 // this.renderTranslateUI(); 3819 // this.subscription_status_active = true; 3820 // this.print(3, "setting this.subscription_status_active", true); 3821 // let translationPromise = await this.GetTranslationsApi(); 3822 // } else { 3823 // this.subscription_status_active = false; 3824 // this.print(3, "setting this.subscription_status_active", false); 3825 // } 3826 // } else { 3827 // if (subscriptionPromise.data.subscription == "ACTIVE") { 3828 // this.renderTranslateUI(); 3829 // if (subscriptionPromise.data.urlStatus == "ACTIVE") { 3830 // this.enable_object_mapping = 3831 // subscriptionPromise.data.subscription.enable_object_mapping; 3832 // this.subscription_status_active = true; 3833 // this.print(3, "setting this.subscription_status_active", true); 3834 3835 // let translationPromise = await this.GetTranslationsApi(); 3836 // } else { 3837 // this.subscription_status_active = false; 3838 // this.print(3, "setting this.subscription_status_active", false); 3839 // } 3840 // } else { 3841 // this.subscription_status_active = false; 3842 // this.print(3, "setting this.subscription_status_active", false); 3843 // } 3844 // } 3845 // } 3846 // } 3847 // // if there is no expiry time then here expiry time will be generated 3848 // else { 3849 // if (localStorage.getItem("devnagri_token")) { 3850 // localStorage.removeItem("devnagri_token"); 3851 // } 3852 // if (localStorage.getItem("devnagri_token_expiry_time")) { 3853 // localStorage.removeItem("devnagri_token_expiry_time"); 3854 // } 3855 // let loginPromise = await this.loginApi(this.login_api_url, apiKey); 3856 // if (loginPromise) { 3857 // let subscriptionPromise = await this.subscriptionStatusApi( 3858 // this.status_api_url 3859 // ); 3860 // if (subscriptionPromise.data.subscription == "ACTIVE") { 3861 // this.renderTranslateUI(); 3862 // let translationPromise = await this.GetTranslationsApi(); 3863 // if (translationPromise && translationPromise.message == "success") { 3864 // } else { 3865 // } 3866 // } else if ( 3867 // subscriptionPromise.data.subscription == "ACTIVE" && 3868 // this.web_owner && 3869 // subscriptionPromise.data.urlStatus != "ACTIVE" 3870 // ) { 3871 // this.renderTranslateUI(); 3872 // let translationPromise = await this.GetTranslationsApi(); 3873 // if (translationPromise && translationPromise.message == "success") { 3874 // } else { 3875 // } 3876 // } 3877 // } 3878 // } 3879 // return true; 3880 // } catch (err) { 3881 // throw err; 3882 // } 3883 // } 3884 3885 renderTranslateUI() { 3886 this.print(3, "renderTranslateUI", { 3887 should_render_ui: this.should_render_ui, 3888 renderUICounter: this.renderUICounter, 3889 }); 3890 // this.removeExistingProxyDropdown(); 3891 // if (this.isProxy()) { 3892 // this.setEventHandlerOfProxyDropDown(); 3893 // return; 3894 // } 3895 3896 if ( 3897 this.should_render_ui && 3898 this.should_render_ui.toLowerCase() === "custom" 3899 ) { 3900 return true; 3901 } 3902 3903 if (this.renderUICounter < 1) { 3904 return true; 3905 } 3906 3907 let outerMostDiv = document.createElement("div"); 3908 outerMostDiv.id = "devnagri_outermostdiv"; 3909 outerMostDiv.setAttribute("class", "devnagri_outermostdivclass"); 3910 let position = " z-index: 2147483647;position:fixed;"; 3911 3912 if (this.ui_bottom) { 3913 position += `bottom:${this.ui_bottom};`; 3914 } 3915 if (this.ui_left) { 3916 position += `left:${this.ui_left};`; 3917 } 3918 if (this.ui_right) { 3919 position += `right:${this.ui_right};`; 3920 } 3921 3922 // if (this.ui_top) { 3923 // position += `top:${this.ui_top};`; 3924 // } 3925 outerMostDiv.style.cssText = position; 3926 3927 this.initialdiv = document.createElement("div"); 3928 this.initialdiv.id = "devnagri_outermostdiv"; 3929 this.initialdiv.classList.add("devnagri_open_button"); 3930 3931 if (this.web_owner) { 3932 this.WebOwnerEnableButton(); 3933 } 3934 3935 let div4 = document.createElement("div"); 3936 div4.setAttribute("style", "float:left"); 3937 3938 let logo = document.createElement("div"); 3939 logo.classList.add("devnagri_logo", "Devnagri-tooltip-toggle-pencil"); 3940 logo.id = "devnagri_optionElementt"; 3941 logo.setAttribute("style", "background-color:white"); 3942 logo.setAttribute("data-tooltip", "Powered By Devnagri"); 3943 logo.innerHTML = this.devngari_logo_svg_content; 3944 3945 div4.appendChild(logo); 3946 this.initialdiv.appendChild(div4); 3947 let div5 = document.createElement("div"); 3948 div5.setAttribute("style", "float:left"); 3949 this.defaultLanguage = document.createElement("h3"); 3950 this.defaultLanguage.setAttribute("style", "background-color:white"); 3951 this.defaultLanguage.classList.add("devnagri_written_lang"); 3952 this.defaultLanguage.id = "devnagri_optionElementt"; 3953 this.defaultLanguage.innerText = ""; 3954 this.defaultLanguage.onclick = () => this.openDropdown(); 3955 div5.appendChild(this.defaultLanguage); 3956 this.initialdiv.appendChild(div5); 3957 3958 let div6 = document.createElement("div"); 3959 div6.setAttribute("style", "float:left"); 3960 let upArrow = document.createElement("div"); 3961 upArrow.classList.add("devnagri_upArrow"); 3962 upArrow.id = "devnagri_optionElementt"; 3963 upArrow.setAttribute("style", "background-color:white"); 3964 upArrow.onclick = () => this.openDropdown(); 3965 upArrow.innerHTML = this.up_arrow_svg_content; 3966 div6.appendChild(upArrow); 3967 this.initialdiv.appendChild(div6); 3968 3969 let body = document.getElementsByTagName("body")[0]; 3970 3971 if (this.status_api_global_data) { 3972 body.appendChild(this.initialdiv); 3973 if (document.querySelector(".devnagri_owner_button")) { 3974 document.querySelector(".devnagri_owner_button").style.display = "none"; 3975 } 3976 if (document.querySelector(".devnagri_vl")) { 3977 document.querySelector(".devnagri_vl").style.display = "none"; 3978 } 3979 if (this.default_lang_code == "en") { 3980 if (document.querySelector(".devnagri_owner_button")) { 3981 document.querySelector(".devnagri_owner_button").style.display = 3982 "none"; 3983 document.querySelector(".devnagri_vl").style.display = "none"; 3984 } 3985 } else { 3986 if (document.querySelector(".devnagri_owner_button")) { 3987 document.querySelector(".devnagri_owner_button").style.display = 3988 "block"; 3989 } 3990 if (document.querySelector(".devnagri_vl")) { 3991 document.querySelector(".devnagri_vl").style.display = "block"; 3992 } 3993 } 3994 } 3995 outerMostDiv.appendChild(this.initialdiv); 3996 document.body.insertBefore(this.initialdiv, document.body[0]); 3997 let div = document.createElement("div"); 3998 div.id = "devnagri_dropdown"; 3999 div.className = "devnagri_container"; 4000 div.setAttribute("devnagri_option", "devnagri_optionElement"); 4001 var ul = document.createElement("ul"); 4002 ul.setAttribute("type", "none"); 4003 div.appendChild(ul); 4004 4005 var enableSubdomainRedirect = 4006 this.status_api_global_data.enableSubdomainRedirect || this.isProxy(); 4007 4008 if (enableSubdomainRedirect && !this.web_owner) { 4009 for (let i = 0; i < this.status_api_global_data.subdomains.length; i++) { 4010 let li = document.createElement("li"); 4011 4012/*const isSubfolder = this.status_api_global_data.subdomains[i].subdomain.includes("/") 4013let path = location.pathname 4014 4015if(isSubfolder){ 4016 let pathArr = path.split("/") 4017 pathArr.shift(); 4018 pathArr.shift(); 4019 path = "/" + pathArr.join("/") 4020}*/ 4021 //console.log("testing",`${location.protocol}//${this.status_api_global_data.subdomains[i].subdomain}${path}${location.search}`, location, this.status_api_global_data.subdomains[i]) 4022 4023 let anchorTag = document.createElement("a"); 4024 anchorTag.setAttribute("id", "devnagri_subdomain"); 4025 /*anchorTag.setAttribute( 4026 "href", 4027 ` ${location.protocol}//${this.status_api_global_data.subdomains[i].subdomain}${location.pathname}${location.search}` 4028 );*/ 4029 4030//const isSubfolder = this.status_api_global_data.subdomains[i].subdomain.includes("/") 4031 const currentSubdomain = this.status_api_global_data.subdomains.find(subdomain => subdomain.code === this.selected_lang_code) 4032 const isSubfolder = currentSubdomain && currentSubdomain.subdomain && currentSubdomain.subdomain.includes("/") 4033//console.log("renderTranslateUI", "currentSubdomain", currentSubdomain, "this.selected_lang_code", this.selected_lang_code); 4034 4035let path = location.pathname 4036 4037if(isSubfolder){ 4038 let pathArr = path.split("/") 4039 pathArr.shift(); 4040 pathArr.shift(); 4041 path = "/" + pathArr.join("/") 4042 4043anchorTag.setAttribute( 4044 "href", 4045 ` ${location.protocol}//${this.status_api_global_data.subdomains[i].subdomain}${path}${location.search}`) 4046} 4047else 4048{ 4049 anchorTag.setAttribute( 4050 "href", 4051 ` ${location.protocol}//${this.status_api_global_data.subdomains[i].subdomain}${location.pathname}${location.search}` 4052 ); 4053} 4054 anchorTag.innerHTML = this.status_api_global_data.subdomains[i].name; 4055 li.appendChild(anchorTag); 4056 li.setAttribute("id", "devnagri_li"); 4057 li.setAttribute( 4058 "devnagri_lang_code_attribute", 4059 this.status_api_global_data.subdomains[i].code 4060 ); 4061 li.setAttribute("class", "devnagri_optionElement"); 4062 ul.appendChild(li); 4063 } 4064 } else { 4065 for (let i = 0; i < this.lang.length; i++) { 4066 let li = document.createElement("li"); 4067 let splitStr = this.lang[i].name.split("-"); 4068 li.setAttribute("id", "devnagri_li"); 4069 li.innerHTML = splitStr[splitStr.length - 1].trim(); 4070 li.setAttribute("devnagri_lang_code_attribute", this.lang[i].code); 4071 li.setAttribute("class", "devnagri_optionElement"); 4072 li.onclick = () => { 4073 this.onLangSelection(this.lang[i].code); 4074 }; 4075 ul.appendChild(li); 4076 } 4077 } 4078 4079 outerMostDiv.appendChild(div); 4080 outerMostDiv.appendChild(this.initialdiv); 4081 4082 document.body.insertBefore(outerMostDiv, document.body[1]); 4083 4084 // document.body.insertBefore(div, document.body[1]); 4085 const selected_lang = localStorage.getItem("devnagri_selected_lang_code") 4086 ? localStorage.getItem("devnagri_selected_lang_code") 4087 : this.default_lang_code; 4088 4089 this.activeLanguage(this.selected_lang_code); 4090 --this.renderUICounter; 4091 4092 this.print(3, "renderTranslateUI", { 4093 should_render_ui: this.should_render_ui, 4094 renderUICounter: this.renderUICounter, 4095 }); 4096 } 4097 4098 // make avtive lang with blue color 4099 activeLanguage(selected_lang_code) { 4100 if ( 4101 this.should_render_ui && 4102 this.should_render_ui.toLowerCase() === "custom" 4103 ) { 4104 return true; 4105 } 4106 if ( 4107 (this.status_api_global_data.enableSubdomainRedirect || this.isProxy()) && 4108 !this.web_owner 4109 ) { 4110 let x = document.querySelectorAll("#devnagri_li"); 4111 4112 for (let i = 0; i < x.length; i++) { 4113 if ( 4114 x[i].getAttribute("devnagri_lang_code_attribute") == 4115 selected_lang_code 4116 ) { 4117 if (x[i].firstChild) { 4118 this.defaultLanguage.innerText = x[i].firstChild.innerText; 4119 x[i].firstChild.setAttribute("style", "color:blue"); 4120 } 4121 } else { 4122 if (x[i].firstChild) { 4123 x[i].firstChild.removeAttribute("style"); 4124 } 4125 } 4126 } 4127 } else { 4128 let x = document.querySelectorAll("#devnagri_li"); 4129 for (let i = 0; i < x.length; i++) { 4130 if ( 4131 x[i].getAttribute("devnagri_lang_code_attribute") == 4132 selected_lang_code 4133 ) { 4134 this.defaultLanguage.innerText = x[i].innerText; 4135 x[i].setAttribute("style", "color:blue"); 4136 } else { 4137 x[i].removeAttribute("style"); 4138 } 4139 } 4140 } 4141 } 4142 4143 // in context editor when web owner edit anything 4144 DataAttributeDataChangeListioner() { 4145 let element = document.querySelector(".devnagri_unsavedChanges"); 4146 if (element) { 4147 element.remove(); 4148 } 4149 let divForUnSavedChange = document.createElement("div");
4150 divForUnSavedChange.innerText = "You have unsaved changes"; 4151 divForUnSavedChange.classList.add("devnagri_unsavedChanges"); 4152 divForUnSavedChange.id = "devnagri_optionElementt"; 4153 let outerMostDiv = document.getElementById("devnagri_outermostdiv"); 4154 outerMostDiv.appendChild(divForUnSavedChange); 4155 // body.appendChild(divForUnSavedChange); 4156 } 4157 4158 //this will add event listener when web owner edit any text 4159 AddDataAttributeDataChangeListioner() { 4160 if (this.web_owner) { 4161 this.RemoveDataAttributeDataChangeListioner(); 4162 window.addEventListener( 4163 "DOMCharacterDataModified", 4164 this.DataAttributeDataChangeListioner 4165 ); 4166 } 4167 } 4168 //this will remove event listener 4169 RemoveDataAttributeDataChangeListioner() { 4170 window.removeEventListener( 4171 "DOMCharacterDataModified", 4172 this.DataAttributeDataChangeListioner 4173 ); 4174 } 4175 // available languages for dropdpwn when ui_mode is custom 4176 availableLanguages() { 4177 if ( 4178 this.should_render_ui && 4179 this.should_render_ui.toLowerCase() === "custom" 4180 ) { 4181 return true; 4182 } 4183 return this.lang; 4184 } 4185 4186 // toggling(display) language button 4187 openDropdown() { 4188 if ( 4189 this.should_render_ui && 4190 this.should_render_ui.toLowerCase() === "custom" 4191 ) { 4192 return true; 4193 } 4194 let x = document.getElementById("devnagri_dropdown"); 4195 if (x && x.style.display === "block") { 4196 x.style.display = "none"; 4197 } else { 4198 var width; 4199 let dotaSelectContainer = document.querySelector(".devnagri_open_button"); 4200 if (dotaSelectContainer) { 4201 width = dotaSelectContainer.offsetWidth; 4202 } 4203 4204 let dropdownContainer = document.getElementById("devnagri_dropdown"); 4205 4206 if (dropdownContainer) { 4207 dropdownContainer.setAttribute("style", `width:${width}px;`); 4208 } 4209 x.style.display = "block"; 4210 } 4211 } 4212 // for closing dropdown 4213 closeDropdown() { 4214 if ( 4215 this.should_render_ui && 4216 this.should_render_ui.toLowerCase() === "custom" 4217 ) { 4218 return true; 4219 } 4220 let id = document.getElementById("devnagri_dropdown"); 4221 if (id.style.display === "block") { 4222 id.style.display = "none"; 4223 } 4224 } 4225 // make avtive lang with blue color 4226 activeLanguage(selected_lang_code) { 4227 if ( 4228 this.should_render_ui && 4229 this.should_render_ui.toLowerCase() === "custom" 4230 ) { 4231 return true; 4232 } 4233 if ( 4234 (this.status_api_global_data.enableSubdomainRedirect || this.isProxy()) && 4235 !this.web_owner 4236 ) { 4237 let x = document.querySelectorAll("#devnagri_li"); 4238 4239 for (let i = 0; i < x.length; i++) { 4240 if ( 4241 x[i].getAttribute("devnagri_lang_code_attribute") == 4242 selected_lang_code 4243 ) { 4244 if (x[i].firstChild) { 4245 this.defaultLanguage.innerText = x[i].firstChild.innerText; 4246 x[i].firstChild.setAttribute("style", "color:blue"); 4247 } 4248 } else { 4249 if (x[i].firstChild) { 4250 x[i].firstChild.removeAttribute("style"); 4251 } 4252 } 4253 } 4254 } else { 4255 let x = document.querySelectorAll("#devnagri_li"); 4256 for (let i = 0; i < x.length; i++) { 4257 if ( 4258 x[i].getAttribute("devnagri_lang_code_attribute") == 4259 selected_lang_code 4260 ) { 4261 this.defaultLanguage.innerText = x[i].innerText; 4262 x[i].setAttribute("style", "color:blue"); 4263 } else { 4264 x[i].removeAttribute("style"); 4265 } 4266 } 4267 } 4268 } 4269 4270 // All below function is used for context editor 4271 4272 // this function will atfirst translate webpage into english language so that english text of every node will be saved in english_att attribute 4273 contentEdit(node) { 4274 switch (node.nodeName) { 4275 case "#text": { 4276 if (node.textContent.trim().length != 0) { 4277 node.english_attr = node.textContent; 4278 } 4279 break; 4280 } 4281 4282 default: { 4283 } 4284 } 4285 } 4286 // it will create ui button for send,cancel and seo icon 4287 async webOwner() { 4288 let div1 = document.createElement("div"); 4289 div1.setAttribute("style", "float:left"); 4290 let seo_button = document.createElement("div"); 4291 seo_button.classList.add("devnagri_seo"); 4292 seo_button.id = "devnagri_seo_button_id"; 4293 seo_button.setAttribute("style", "background-color:white"); 4294 seo_button.innerHTML = this.seo_button_svg_content; 4295 seo_button.onclick = () => { 4296 this.seo_ui(); 4297 }; 4298 div1.appendChild(seo_button); 4299 this.initialdiv.insertBefore(div1, this.initialdiv.children[0]); 4300 let div2 = document.createElement("div"); 4301 div2.setAttribute("style", "float:left"); 4302 let send_button = document.createElement("div"); 4303 send_button.classList.add("devnagri_owner_send_button"); 4304 send_button.setAttribute("style", "background-color:white"); 4305 send_button.id = "devnagri_optionElementt"; 4306 send_button.innerHTML = this.save_button_svg_content; 4307 4308 send_button.onclick = () => { 4309 let body = document.getElementsByTagName("body")[0]; 4310 this.checkingContentEditable(document.body); 4311 this.print( 4312 3, 4313 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 2631 ~ Devnagri ~ webOwner ~ this.content_editable.length", 4314 this.content_editable.length 4315 ); 4316 if (this.content_editable.length && !this.unAuthApiResponse) { 4317 let div = document.createElement("div"); 4318 div.classList.add("Devnagri-ring"); 4319 div.id = "Devnagri-loader"; 4320 let position = " z-index: 2147483647;position:fixed;"; 4321 let bottom; 4322 let right; 4323 let left; 4324 if (this.ui_bottom) { 4325 bottom = parseInt(this.ui_bottom) + 26 + "%"; 4326 position = position + `bottom:${bottom};`; 4327 } 4328 if (this.ui_left) { 4329 left = parseInt(this.ui_left) + 7 + "%"; 4330 position += `left:${left};`; 4331 } 4332 if (this.ui_right) { 4333 right = parseInt(this.ui_right) + 7 + "%"; 4334 position += `right:${right};`; 4335 } 4336 div.style.cssText = position; 4337 let outerMostDiv = document.getElementById("devnagri_outermostdiv"); 4338 outerMostDiv.appendChild(div); 4339 // let outerMostDiv = document.getElementById("devnagri_outermostdiv"); 4340 // outerMostDiv.appendChild(div); 4341 body.appendChild(div); 4342 this.saveChangesUI(); 4343 this.webOwnerSend(); 4344 } 4345 }; 4346 div2.appendChild(send_button); 4347 this.initialdiv.insertBefore(div2, this.initialdiv.children[1]); 4348 let div3 = document.createElement("div"); 4349 4350 div3.setAttribute("style", "float:left");
4351 let cancel_button = document.createElement("div"); 4352 cancel_button.classList.add("devnagri_owner_cancel_button"); 4353 cancel_button.innerHTML = this.close_button_svg_content; 4354 cancel_button.id = "devnagri_optionElementt"; 4355 cancel_button.setAttribute("style", "background-color:white"); 4356 cancel_button.onclick = () => this.webOwnerCancel(); 4357 4358 div3.appendChild(cancel_button); 4359 this.initialdiv.insertBefore(div3, this.initialdiv.children[2]); 4360 let verticalLineDiv = document.createElement("div"); 4361 verticalLineDiv.setAttribute("style", "float:left"); 4362 let vl = document.createElement("div"); 4363 vl.classList.add("devnagri_vl"); 4364 vl.setAttribute("id", "devnagri_vl_seo"); 4365 verticalLineDiv.appendChild(vl); 4366 this.initialdiv.insertBefore(verticalLineDiv, this.initialdiv.children[1]); 4367 } 4368 4369 // this will create dynamically ui for seo so that seo thing meta and title can be edited 4370 seo_ui() { 4371 this.seoUI = !this.seoUI; 4372 if (this.seoUI) { 4373 } else { 4374 let tag = document.querySelector(".devnagri_dynamic_container"); 4375 tag.remove(); 4376 return; 4377 } 4378 4379 let body = document.getElementsByTagName("body")[0]; 4380 let mainDiv = document.createElement("div"); 4381 mainDiv.classList.add("devnagri_dynamic_container"); 4382 body.appendChild(mainDiv); 4383 let div = document.createElement("div"); 4384 div.classList.add("dynamic_container"); 4385 mainDiv.appendChild(div); 4386 let divForheader = document.createElement("div"); 4387 div.appendChild(divForheader); 4388 let h1 = document.createElement("h3"); 4389 h1.innerText = this.source_lang_code.toUpperCase(); 4390 h1.classList.add("devnagri_h1_eng"); 4391 h1.setAttribute("style", "margin-bottom:0"); 4392 divForheader.appendChild(h1); 4393 let h2 = document.createElement("h3"); 4394 h2.setAttribute("style", "margin-bottom:0"); 4395 h2.classList.add("devnagri_h1_def_lang"); 4396 h2.innerText = 4397 this.default_lang_code.toUpperCase() + " (Manual Translation)"; 4398 let iconForArrow = document.createElement("div"); 4399 iconForArrow.classList.add("devnagri_divForArrow"); 4400 divForheader.appendChild(iconForArrow); 4401 divForheader.appendChild(h2); 4402 4403 for (let key of Object.keys(this.metatag_arr)) { 4404 let divLabelInput = document.createElement("div"); 4405 divLabelInput.classList.add("devnagri_div_lable_input"); 4406 let label = document.createElement("label"); 4407 label.innerText = key; 4408 label.classList.add("devnagri_label"); 4409 let input = document.createElement("textarea"); 4410 input.value = this.metatag_arr[`${key}`].engText; 4411 input.rows = 4; 4412 input.cols = 30; 4413 input.placeholder = "english text"; 4414 input.setAttribute("disabled", true); 4415 input.classList.add("devnagri_form-control"); 4416 let br = document.createElement("br"); 4417 divLabelInput.appendChild(label); 4418 divLabelInput.appendChild(br); 4419 let divinput = document.createElement("div"); 4420 divLabelInput.appendChild(divinput); 4421 let divforinputandfig = document.createElement("div"); 4422 divforinputandfig.setAttribute("style", "float:left"); 4423 divforinputandfig.appendChild(input); 4424 divinput.appendChild(divforinputandfig); 4425 let editedinput = document.createElement("textarea"); 4426 editedinput.classList.add("devnagri_form-control"); 4427 editedinput.value = this.metatag_arr[`${key}`].translatedText; 4428 editedinput.placeholder = "Manual Text"; 4429 editedinput.id = "devnagri_textarea"; 4430 editedinput.rows = 4; 4431 editedinput.cols = 30; 4432 editedinput.onchange = (e) => { 4433 this.metatag_arr[`${key}`].translatedText = e.target.value; 4434 }; 4435 editedinput.style.cssText = `margin-left:15px;`; 4436 let divforinputandfig2 = document.createElement("div"); 4437 divforinputandfig2.setAttribute("style", "float:left"); 4438 divforinputandfig2.appendChild(editedinput); 4439 divinput.appendChild(divforinputandfig2); 4440 div.appendChild(divLabelInput); 4441 } 4442 let buttonSubmit = document.createElement("div"); 4443 buttonSubmit.classList.add("devnagri_seo_submit"); 4444 buttonSubmit.setAttribute("style", "background-color:white"); 4445 buttonSubmit.onclick = () => { 4446 this.seoUI = !this.seoUI; 4447 this.seoEditedText(); 4448 div.remove(); 4449 this.AddDataAttributeDataChangeListioner(); 4450 }; 4451 let buttonCancel = document.createElement("div"); 4452 buttonCancel.classList.add("devnagri_seo_cancel"); 4453 buttonCancel.setAttribute("style", "background-color:white"); 4454 buttonCancel.onclick = () => { 4455 this.seoUI = !this.seoUI; 4456 div.remove(); 4457 this.renderUICounter = 0; 4458 }; 4459 let divForSendCancel = document.createElement("div");
4460 divForSendCancel.setAttribute( 4461 "style", 4462 "padding: 15px 12px;display: inline-block" 4463 ); 4464 divForSendCancel.appendChild(buttonSubmit); 4465 divForSendCancel.appendChild(buttonCancel); 4466 div.appendChild(divForSendCancel); 4467 } 4468 4469 // this function willl call patch api for sending edited meta tag 4470 seoEditedText() { 4471 for (let key of Object.keys(this.metatag_arr)) { 4472 this.content_editable.push({ 4473 sentence: this.metatag_arr[`${key}`].engText, 4474 translation: this.metatag_arr[`${key}`].translatedText, 4475 }); 4476 } 4477 this.contextEditorPatchApi(); 4478 this.content_editable.length = 0; 4479 } 4480 4481 // this function is used for reloading when text is edited but don't want to send text to api 4482 webOwnerCancel() { 4483 location.reload(); 4484 } 4485 4486 //this function will will compare the old object with new edited object and then save the edited thext into new object 4487 checkingContentEditable(node) { 4488 //handling the script tag and other unnecessary text 4489 let blacklistedTags = [ 4490 "IMG", 4491 "VIDEO", 4492 "IFRAME", 4493 "NOSCRIPT", 4494 "STYLE", 4495 "SCRIPT", 4496 ]; 4497 4498 if (node.childNodes && node.childNodes.length > 0) { 4499 if (!blacklistedTags.includes(node.nodeName.toUpperCase())) { 4500 for (let innerNode of node.childNodes) { 4501 this.checkingContentEditable(innerNode); 4502 } 4503 } 4504 } else { 4505 if ( 4506 node.parentElement.getAttribute("id") === "devnagri_optionElementt" || 4507 node.parentElement.getAttribute("class") === "devnagri_optionElement" || 4508 node.parentElement.getAttribute("devnagri_option") === 4509 "devnagri_optionElement" 4510 ) { 4511 return true; 4512 } else { 4513 switch (node.nodeName) { 4514 case "#text": { 4515 if (node.textContent.trim().length != 0) { 4516 let txt = node.textContent.replaceAll("\n", " "); 4517 txt = this.replaceNbsps(txt); 4518 4519 txt = txt.trim(); 4520 4521 //node.parentElement.setAttribute("english_name", node.textContent); 4522 if (node.parentElement.getAttribute("english_text")) { 4523 var engSentence = node.parentElement 4524 .getAttribute("english_text") 4525 .trim(); 4526 } 4527 let editedTranslatedText = txt; 4528 4529 if ( 4530 this.arr_nodes[`${engSentence}`] && 4531 editedTranslatedText !== 4532 this.arr_nodes[`${engSentence}`].translatedText 4533 ) { 4534 this.content_editable.push({ 4535 sentence: engSentence, 4536 translation: editedTranslatedText, 4537 }); 4538 } 4539 } 4540 break; 4541 } 4542 4543 case "SCRIPT": { 4544 break; 4545 } 4546 default: { 4547 } 4548 } 4549 } 4550 } 4551 } 4552 4553 // this function is used for sending the new edited text 4554 async webOwnerSend() { 4555 this.changedContextEditor = true; 4556 if (!localStorage.getItem("devnagri_selected_lang_code")) { 4557 } 4558 this.checkingContentEditable(document.body); 4559 this.content_editable = this.content_editable.filter( 4560 (v, i, a) => a.findIndex((t) => t.sentence === v.sentence) === i 4561 ); 4562 4563 var loader = document.getElementById("Devnagri-loader"); 4564 var button = document.querySelector(".devnagri_owner_send_button"); 4565 if (this.content_editable.length == 0) { 4566 if (loader) { 4567 loader.remove(); 4568 } 4569 return; 4570 } 4571 let isSuccess = await this.contextEditorPatchApi(loader); 4572 if (isSuccess && isSuccess.message == "success") { 4573 if (loader) { 4574 loader.remove(); 4575 } 4576 for (let i = 0; i < this.content_editable.length; i++) { 4577 this.arr_nodes[`${this.content_editable[i].sentence}`].translatedText = 4578 this.content_editable[i].translation; 4579 } 4580 for (let i = 0; i < this.content_editable.length; i++) { 4581 this.setTranslatedTextToNode({ 4582 ...this.arr_nodes[`${this.content_editable[i].sentence}`], 4583 translatedText: this.content_editable[i].translation, 4584 }); 4585 } 4586 button.onclick = () => { 4587 if (!localStorage.getItem("devnagri_selected_lang_code")) { 4588 return; 4589 } 4590 this.content_editable.length = 0; 4591 let oldArr = this.content_editable.length; 4592 4593 this.checkingContentEditable(document.body); 4594 4595 if (oldArr != this.content_editable.length) { 4596 let div = document.createElement("div"); 4597 div.classList.add("Devnagri-ring"); 4598 div.id = "Devnagri-loader"; 4599 // let body = document.getElementsByTagName("body")[0]; 4600 // body.appendChild(div); 4601 let position = "z-index: 2147483647;position:fixed;"; 4602 let bottom; 4603 let right; 4604 let left; 4605 if (this.ui_bottom) { 4606 bottom = parseInt(this.ui_bottom) + 26 + "%"; 4607 position = position + `bottom:${bottom};`; 4608 } 4609 if (this.ui_left) { 4610 left = parseInt(this.ui_left) + 7 + "%"; 4611 position += `left:${left};`; 4612 } 4613 if (this.ui_right) { 4614 right = parseInt(this.ui_right) + 7 + "%"; 4615 position += `right:${right};`; 4616 } 4617 div.style.cssText = position; 4618 let outerMostDiv = document.getElementById("devnagri_outermostdiv"); 4619 outerMostDiv.appendChild(div); 4620 4621 this.webOwnerSend(); 4622 this.saveChangesUI(); 4623 } 4624 }; 4625 } 4626 } 4627 4628 extractSentencesFromArrNodes(arr_nodes) { 4629 let arrSentences = []; 4630 4631 for (let key of Object.keys(arr_nodes)) { 4632 if (!arrSentences.includes(this.cleanString(key))) { 4633 arrSentences.push(this.cleanString(key)); 4634 } 4635 } 4636 4637 arrSentences = arrSentences.filter( 4638 (sentence) => 4639 !this.checkIfStringIsLocal(sentence, false) && 4640 !this.isTextTranslatedText(sentence) 4641 ); 4642 return arrSentences; 4643 } 4644 4645 extractSubSentenceNodesFromArrNodes(arr_nodes) { 4646 const subSentenceNodes = {};
4647 Object.entries(arr_nodes).forEach(([key, value]) => { 4648 if (value.isNodeASentenceChildren) { 4649 subSentenceNodes[key] = value; 4650 } 4651 }); 4652 return subSentenceNodes; 4653 } 4654 4655 groudSubSentenceNodesByParent(subSentenceNodes) { 4656 const subSentencesGroupedByParent = {}; 4657 Object.entries(subSentenceNodes).forEach(([key, value]) => { 4658 value.sentenceParentId.forEach((id) => { 4659 // const obj = JSON.parse(JSON.stringify(value)); 4660 const obj = Object.assign({}, value); 4661 obj.sentenceParentId = Array.from(value.sentenceParentId); 4662 obj.subSentencePosition = Array.from(value.subSentencePosition); 4663 obj.nodes = Array.from(value.nodes); 4664 let currentParentIdIndex = obj.sentenceParentId.findIndex( 4665 (item) => item === id 4666 ); 4667 if (currentParentIdIndex > -1) { 4668 obj.sentenceParentId = id; 4669 obj.subSentencePosition = 4670 obj.subSentencePosition[currentParentIdIndex]; 4671 if (subSentencesGroupedByParent[id]) { 4672 subSentencesGroupedByParent[id].push(obj); 4673 } else { 4674 subSentencesGroupedByParent[id] = [obj]; 4675 } 4676 } 4677 }); 4678 }); 4679 return subSentencesGroupedByParent; 4680 } 4681 4682 // this function will call the save -translation patch api for sending newly added edited text to server 4683 async contextEditorPatchApi(loader) { 4684 try { 4685 // if (!localStorage.getItem("devnagri_token")) { 4686 // return; 4687 // } 4688 4689 if (!this.access_token) { 4690 return; 4691 } 4692 4693 if ( 4694 this.url_object.searchParams.has("dota-token") && 4695 this.url_object.searchParams.has("language_code") 4696 ) { 4697 this.document_url = this.url_object.origin + this.url_object.pathname; 4698 if (!this.document_url.endsWith("/")) { 4699 this.document_url = this.document_url + "/"; 4700 } 4701 } 4702 4703 // sentence breaking prevent changes start 4704 /* 4705 // this.print(3, "this.content_editable", this.content_editable); 4706 const editedSentences = Array.from(this.content_editable); 4707 4708 const editedSentencesMap = {}; 4709 editedSentences.forEach((item) => { 4710 editedSentencesMap[item.sentence] = item.translation; 4711 }); 4712 4713 const isEditedSentencePartOfSentence = {}; 4714 4715 this.print( 4716 3, 4717 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3804 ~ Devnagri ~ contextEditorPatchApi ~ editedSentences", 4718 editedSentences 4719 ); 4720 4721 const allSentences = this.extractSentencesFromArrNodes(this.arr_nodes); 4722 this.print( 4723 3, 4724 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3800 ~ Devnagri ~ contextEditorPatchApi ~ allSentences", 4725 allSentences 4726 ); 4727 4728 let subSentenceNodes = this.extractSubSentenceNodesFromArrNodes( 4729 this.arr_nodes 4730 ); 4731 this.print( 4732 3, 4733 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3804 ~ Devnagri ~ contextEditorPatchApi ~ subSentenceNodes", 4734 subSentenceNodes 4735 ); 4736 4737 const parentIdsWithEditedSentence = []; 4738 4739 editedSentences.forEach((sentenceObj) => { 4740 if (subSentenceNodes[sentenceObj.sentence]) { 4741 const parentIds = 4742 subSentenceNodes[sentenceObj.sentence].sentenceParentId; 4743 parentIdsWithEditedSentence.push(...parentIds); 4744 isEditedSentencePartOfSentence[sentenceObj.sentence] = true; 4745 } 4746 }); 4747 4748 const subSentencesGroupedByParent = 4749 this.groudSubSentenceNodesByParent(subSentenceNodes); 4750 4751 this.print( 4752 3, 4753 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3806 ~ Devnagri ~ contextEditorPatchApi ~ subSentencesGroupedByParent", 4754 subSentencesGroupedByParent 4755 ); 4756 4757 this.print( 4758 3, 4759 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3840 ~ Devnagri ~ Object.entries ~ parentIdsWithEditedSentence", 4760 parentIdsWithEditedSentence 4761 ); 4762 4763 const filteredSubSentencesGroupedByParent = {}; 4764 4765 Object.entries(subSentencesGroupedByParent).forEach(([key, value]) => { 4766 if (parentIdsWithEditedSentence.includes(key)) { 4767 filteredSubSentencesGroupedByParent[key] = value; 4768 } 4769 }); 4770 this.print( 4771 3, 4772 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3838 ~ Devnagri ~ contextEditorPatchApi ~ filteredSubSentencesGroupedByParent", 4773 filteredSubSentencesGroupedByParent 4774 ); 4775 4776 const compoundSentences = []; 4777 Object.values(filteredSubSentencesGroupedByParent).forEach((item) => { 4778 const sortedItems = item.sort((a, b) => 4779 a.subSentencePosition > b.subSentencePosition ? 1 : -1 4780 ); 4781 4782 let origText = ""; 4783 let transText = "";
4784 sortedItems.forEach((item, index) => { 4785 origText = `${origText}${item.originalText}${ 4786 index < sortedItems.length - 1 ? "##{{}}##" : "" 4787 }`; 4788 transText = `${transText}${ 4789 editedSentencesMap[item.originalText] 4790 ? editedSentencesMap[item.originalText] 4791 : item.translatedText 4792 }${index < sortedItems.length - 1 ? "##{{}}##" : ""}`; 4793 }); 4794 4795 compoundSentences.push({ 4796 sentence: origText, 4797 translation: transText, 4798 }); 4799 }); 4800 4801 this.print( 4802 3, 4803 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3807 ~ Devnagri ~ contextEditorPatchApi ~ compoundSentences", 4804 compoundSentences 4805 ); 4806 4807 const simpleSentences = editedSentences.filter( 4808 (item) => !isEditedSentencePartOfSentence[item.sentence] 4809 ); 4810 this.print( 4811 3, 4812 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3894 ~ Devnagri ~ contextEditorPatchApi ~ simpleSentences", 4813 simpleSentences 4814 ); 4815 */ 4816 // sentence breaking prevent changes end 4817 4818 const res = await fetch(this.context_editor_api, { 4819 method: "POST", 4820 headers: { 4821 "Content-Type": "application/json", 4822 Authorization: `Bearer ${this.dota_token}`, 4823 }, 4824 body: JSON.stringify({ 4825 url: this.document_url, 4826 language_code: this.selected_lang_code, 4827 translations: this.content_editable, 4828 }), 4829 }); 4830 if (res.status == 401) { 4831 this.showErrorMessage(); 4832 if (loader) { 4833 loader.remove(); 4834 } 4835 this.unAuthApiResponse = true; 4836 } 4837 const data = await res.json(); 4838 return data; 4839 } catch (error) { 4840 this.print( 4841 1, 4842 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3851 ~ Devnagri ~ contextEditorPatchApi ~ error", 4843 error 4844 ); 4845 throw new Error("save-translation response-> you are unauthorized"); 4846 } 4847 } 4848 4849 // this will create ui for unauthorized message 4850 showErrorMessage() { 4851 this.uiErrorContextEditor(); 4852 } 4853 // showing unauthorized message 4854 uiErrorContextEditor() { 4855 let element = document.getElementById("devnagri_uiErrorContextEditor"); 4856 if (element) { 4857 element.remove(); 4858 } 4859 let uiErrorEditor = document.createElement("div"); 4860 uiErrorEditor.innerText = "You are unauthorized please use new token"; 4861 uiErrorEditor.classList.add("devnagri_uiErrorEditor"); 4862 uiErrorEditor.id = "devnagri_uiErrorContextEditor"; 4863 let outerMostDiv = document.getElementById("devnagri_outermostdiv"); 4864 outerMostDiv.appendChild(uiErrorEditor); 4865 } 4866 saveChangesUI() { 4867 let element = document.querySelector(".devnagri_unsavedChanges"); 4868 if (element) { 4869 element.remove(); 4870 } 4871 if (!document.getElementById("devnagri_uiErrorContextEditor")) { 4872 let divForUnSavedChange = document.createElement("div"); 4873 divForUnSavedChange.innerText = "Changes Saved"; 4874 divForUnSavedChange.classList.add("devnagri_savedChanges"); 4875 divForUnSavedChange.id = "devnagri_optionElementt"; 4876 let outerMostDiv = document.getElementById("devnagri_outermostdiv"); 4877 outerMostDiv.appendChild(divForUnSavedChange); 4878 // let body = document.getElementsByTagName("body")[0]; 4879 // body.appendChild(divForUnSavedChange); 4880 setTimeout(() => { 4881 let element = document.querySelector(".devnagri_savedChanges"); 4882 if (element) { 4883 element.remove(); 4884 } 4885 }, 1000); 4886 } 4887 } 4888 contentEditt(node) { 4889 this.edit_mode_enabled = true; 4890 //handling the script tag and other unnecesaary text 4891 let blacklistedTags = [ 4892 "IMG", 4893 "VIDEO", 4894 "IFRAME", 4895 "NOSCRIPT", 4896 "STYLE", 4897 "SCRIPT", 4898 ]; 4899 if (node.childNodes && node.childNodes.length > 0) { 4900 if (!blacklistedTags.includes(node.nodeName.toUpperCase())) { 4901 for (let innerNode of node.childNodes) { 4902 this.contentEditt(innerNode); 4903 } 4904 } 4905 } else { 4906 if ( 4907 node.parentElement.getAttribute("id") === "devnagri_optionElementt" || 4908 node.parentElement.getAttribute("class") === "devnagri_optionElement" || 4909 node.parentElement.getAttribute("devnagri_option") === 4910 "devnagri_optionElement" || 4911 node.parentElement.getAttribute("id") === "devnagri_seo_button_id" 4912 ) { 4913 return true; 4914 } else { 4915 switch (node.nodeName) { 4916 case "#text": { 4917 if (node.textContent.trim().length != 0) { 4918 if (node.parentElement.nodeName !== "BODY") { 4919 // english_attr atrribute will contains english text for it's corresponding translated text 4920 node.parentElement.setAttribute("contentEditable", "true"); 4921 } 4922 } 4923 break; 4924 } 4925 default: { 4926 } 4927 } 4928 } 4929 } 4930 } 4931 //this is used for set contenteditable to false so that it will be not in edited mode 4932 remove_contentEditt(node) { 4933 this.edit_mode_enabled = false;
4934 //handling the script tag and other unnecesaary text 4935 let blacklistedTags = [ 4936 "IMG", 4937 "VIDEO", 4938 "IFRAME", 4939 "NOSCRIPT", 4940 "STYLE", 4941 "SCRIPT", 4942 ]; 4943 4944 if (node.childNodes && node.childNodes.length > 0) { 4945 if (!blacklistedTags.includes(node.nodeName.toUpperCase())) { 4946 for (let innerNode of node.childNodes) { 4947 this.remove_contentEditt(innerNode); 4948 } 4949 } 4950 } else { 4951 if ( 4952 node.parentElement.getAttribute("id") === "devnagri_optionElementt" || 4953 node.parentElement.getAttribute("class") === "devnagri_optionElement" || 4954 node.parentElement.getAttribute("devnagri_option") === 4955 "devnagri_optionElement" || 4956 node.parentElement.getAttribute("id") === "devnagri_seo_button_id" 4957 ) { 4958 return true; 4959 } else { 4960 switch (node.nodeName) { 4961 case "#text": { 4962 if (node.textContent.trim().length != 0) { 4963 if (node.parentElement.nodeName !== "BODY") { 4964 node.parentElement.setAttribute("contentEditable", "false"); 4965 } 4966 } 4967 break; 4968 } 4969 4970 default: { 4971 } 4972 } 4973 } 4974 } 4975 } 4976 4977 //handling click event for editing 4978 handler(e) { 4979 if ( 4980 ![ 4981 "devnagri_owner_button Devnagri-tooltip-toggle", 4982 "devnagri_owner_send_button", 4983 "devnagri_owner_cancel_button", 4984 "devnagri_open_button", 4985 "devnagri_container", 4986 "devnagri_optionElement", 4987 "devnagri_seo_cancel", 4988 "devnagri_seo_submit", 4989 "devnagri_seo", 4990 "devnagri_logo", 4991 "devnagri_written_lang", 4992 "devnagri_upArrow", 4993 "devnagri_outermostdivclass", 4994 ].includes(e.target.className) 4995 ) { 4996 e.stopPropagation(); 4997 e.preventDefault(); 4998 e.stopImmediatePropagation(); 4999 } 5000 } 5001 //ui for Devnagri website owner button 5002 async WebOwnerEnableButton() { 5003 let div = document.createElement("div"); 5004 div.setAttribute("style", "float:left"); 5005 let button = document.createElement("div"); 5006 button.classList.add("devnagri_owner_button", "Devnagri-tooltip-toggle"); 5007 button.id = "devnagri_optionElementt"; 5008 button.setAttribute("style", "background-color:white"); 5009 button.setAttribute("data-tooltip", "Edit"); 5010 button.innerHTML = this.edit_button_svg_content; 5011 button.onclick = () => { 5012 this.closeDropdown(); 5013 this.AddDataAttributeDataChangeListioner(); 5014 button.remove(); 5015 this.contentEditt(document.body); 5016 this.webOwner(); 5017 document.addEventListener("click", this.handler, true); 5018 }; 5019 div.appendChild(button); 5020 this.initialdiv.appendChild(div); 5021 let verticalLineDiv = document.createElement("div"); 5022 verticalLineDiv.setAttribute("style", "float:left"); 5023 let vl = document.createElement("div"); 5024 vl.setAttribute("id", "devnagri_vl_logo"); 5025 vl.classList.add("devnagri_vl"); 5026 verticalLineDiv.appendChild(vl); 5027 this.initialdiv.appendChild(verticalLineDiv); 5028 } 5029 5030 async WebOwnerEnableButtonInsert() { 5031 let div = document.createElement("div"); 5032 div.setAttribute("style", "float:left"); 5033 let button = document.createElement("div"); 5034 button.classList.add("devnagri_owner_button", "Devnagri-tooltip-toggle"); 5035 button.id = "devnagri_optionElementt"; 5036 button.setAttribute("style", "background-color:white"); 5037 button.setAttribute("data-tooltip", "Edit"); 5038 const clieckHandler = (button.onclick = () => { 5039 this.closeDropdown(); 5040 this.AddDataAttributeDataChangeListioner(); 5041 button.remove(); 5042 document.getElementById("devnagri_vl_logo").remove(); 5043 this.contentEditt(document.body); 5044 this.webOwner(); 5045 document.addEventListener("click", this.handler, true); 5046 }); 5047 div.appendChild(button); 5048 let verticalLineDiv = document.createElement("div"); 5049 verticalLineDiv.setAttribute("style", "float:left"); 5050 let vl = document.createElement("div"); 5051 vl.setAttribute("id", "devnagri_vl_logo"); 5052 vl.classList.add("devnagri_vl"); 5053 verticalLineDiv.appendChild(vl); 5054 const logoParent = document.querySelector(".devnagri_logo").parentElement; 5055 this.initialdiv.insertBefore(div, logoParent); 5056 this.initialdiv.insertBefore(verticalLineDiv, logoParent); 5057 } 5058 5059 // this function will be used for showing pencil icon 5060 englishSelectShowPencile() { 5061 if (!document.querySelector(".devnagri_owner_button")) { 5062 this.remove_contentEditt(document.body); 5063 } 5064 if ( 5065 document.querySelector(".devnagri_owner_button") && 5066 document.querySelector(".devnagri_owner_button").style.display != "none" 5067 ) { 5068 document.querySelector(".devnagri_owner_button").style.display = "none"; 5069 this.contentEdit; 5070 document.querySelector(".devnagri_vl").style.display = "none"; 5071 } 5072 if (document.getElementById("devnagri_seo_button_id")) { 5073 document.getElementById("devnagri_seo_button_id").style.display = "none"; 5074 document.querySelector(".devnagri_owner_send_button").style.display = 5075 "none"; 5076 document.querySelector(".devnagri_owner_cancel_button").style.display = 5077 "none"; 5078 let verticalLines = document.getElementsByClassName("devnagri_vl"); 5079 for (let i = 0; i < verticalLines.length; i++) { 5080 verticalLines[i].style.display = "none"; 5081 } 5082 } 5083 } 5084 // this function will be used for hiding pencil icon 5085 englishSelectHidePencile() { 5086 if ( 5087 document.querySelector(".devnagri_owner_button") && 5088 document.querySelector(".devnagri_owner_button").style.display == "none" 5089 ) { 5090 document.querySelector(".devnagri_owner_button").style.display = "block"; 5091 document.querySelector(".devnagri_vl").style.display = "block"; 5092 } else if (!document.querySelector(".devnagri_owner_button")) { 5093 if ( 5094 document.getElementById("devnagri_seo_button_id") && 5095 document.getElementById("devnagri_seo_button_id").style.display == 5096 "block" 5097 ) { 5098 document.getElementById("devnagri_seo_button_id").style.display = 5099 "none"; 5100 document.querySelector(".devnagri_owner_send_button").style.display = 5101 "none"; 5102 document.querySelector(".devnagri_owner_cancel_button").style.display = 5103 "none"; 5104 5105 this.remove_contentEditt(document.body); 5106 this.WebOwnerEnableButtonInsert(); 5107 document.querySelector("#devnagri_vl_seo").style.display = "none"; 5108 document.querySelector("#devnagri_vl_logo").style.display = "none"; 5109 } else { 5110 document.getElementById("devnagri_seo_button_id").style.display = 5111 "none"; 5112 document.querySelector(".devnagri_owner_send_button").style.display = 5113 "none"; 5114 document.querySelector(".devnagri_owner_cancel_button").style.display = 5115 "none"; 5116 5117 this.remove_contentEditt(document.body); 5118 this.WebOwnerEnableButtonInsert(); 5119 document.getElementById("devnagri_vl_seo").style.visibility = "hidden"; 5120 document.getElementById("devnagri_vl_seo").parentElement.style.width = 5121 "0"; 5122 5123 document.getElementById("devnagri_vl_logo").style.visibility = "hidden"; 5124 document.getElementById("devnagri_vl_logo").parentElement.style.width = 5125 "0"; 5126 } 5127 5128 let verticalLines = document.getElementsByClassName("devnagri_vl"); 5129 for (let i = 0; i < verticalLines.length; i++) { 5130 verticalLines[i].style.display = "block"; 5131 } 5132 } 5133 }
5134 englishSelectPencile(selected_lang_code) { 5135 if (this.web_owner && selected_lang_code.toLowerCase() == "en") { 5136 // for showing pencil icon 5137 this.englishSelectShowPencile(); 5138 } else if ( 5139 (document.getElementById("devnagri_seo_button_id") && 5140 document.getElementById("devnagri_seo_button_id").style.display == 5141 "none") || 5142 this.web_owner 5143 ) { 5144 // for hiding pencil icon 5145 this.englishSelectHidePencile(); 5146 } 5147 } 5148 // when lang is selected from dropdown then this function will work 5149 async onLangSelection(selected_lang_code) { 5150 if (this.isLiveJs()) { 5151 const old_status = this.subscription_status_active; 5152 5153 this.subscription_status_active = 5154 this.isUrlLangStatusActive(selected_lang_code); 5155 if (!old_status && this.subscription_status_active) { 5156 this.startTraversingNow(); 5157 await this.checkIfTraversingCompleted(); 5158 } 5159 } 5160 5161 if (this.edit_mode_enabled) { 5162 let element = document.querySelector(".devnagri_unsavedChanges"); 5163 if (element) { 5164 element.remove(); 5165 } 5166 this.remove_contentEditt(document.body); 5167 if (selected_lang_code !== this.source_lang_code) { 5168 this.onLangSelection(this.source_lang_code); 5169 } 5170 // this.edit_mode_enabled = false; 5171 } 5172 5173 // for showing and hiding pencil icon 5174 this.englishSelectPencile(selected_lang_code); 5175 this.RemoveDataAttributeDataChangeListioner(); 5176 let element = document.querySelector(".devnagri_unsavedChanges"); 5177 if (element) { 5178 element.remove(); 5179 } 5180 // close the UI dropdown 5181 this.closeDropdown(); 5182 //set the active lanauge CSS on the dropdown option link 5183 this.activeLanguage(selected_lang_code); 5184 5185 // set text direction rtl for urdu 5186 const rtlLangs = ["ur","ar"] 5187 if (rtlLangs.includes(selected_lang_code)) { 5188 console.log("setting text direction rtl for urdu") 5189 document.body.setAttribute("dir", "rtl"); 5190 }else{ 5191 console.log("setting text direction ltr for other langs"); 5192 document.body.setAttribute("dir", "ltr"); 5193 } 5194 5195 var width; 5196 let dotaSelectContainer = document.querySelector(".devnagri_open_button"); 5197 if (dotaSelectContainer) { 5198 width = dotaSelectContainer.offsetWidth; 5199 } 5200 5201 let dropdownContainer = document.getElementById("devnagri_dropdown"); 5202 if (dropdownContainer) { 5203 dropdownContainer.setAttribute("style", `width:${width}px;`); 5204 } 5205 5206 if ( 5207 selected_lang_code === localStorage.getItem("devnagri_source_lang_code") 5208 ) { 5209 this.selected_lang_code = selected_lang_code; 5210 this.default_lang_code = selected_lang_code; 5211 // localStorage.setItem("devnagri_selected_lang_code", selected_lang_code); 5212 // localStorage.setItem("devnagri_default_lang_code", selected_lang_code); 5213 this.translate(selected_lang_code); 5214 } else if ( 5215 (this.default_lang_code = selected_lang_code) 5216 // localStorage.getItem("devnagri_default_lang_code") == selected_lang_code 5217 ) { 5218 this.selected_lang_code = selected_lang_code; 5219 this.default_lang_code = selected_lang_code; 5220 // localStorage.setItem("devnagri_selected_lang_code", selected_lang_code); 5221 // localStorage.setItem("devnagri_default_lang_code", selected_lang_code); 5222 // if ( 5223 // this.status_api_global_data && 5224 // this.status_api_global_data.enable_object_mapping 5225 // ) { 5226 // await this.getObjectUrlsApi(); 5227 // } 5228 this.GetTranslationsApi().then(() => { 5229 this.translate(selected_lang_code); 5230 this.AddDataAttributeDataChangeListioner(); 5231 }); 5232 } else if (selected_lang_code !== this.default_lang_code) { 5233 this.default_lang_code = selected_lang_code; 5234 this.selected_lang_code = selected_lang_code; 5235 // localStorage.setItem("devnagri_selected_lang_code", selected_lang_code); 5236 // localStorage.setItem("devnagri_default_lang_code", selected_lang_code); 5237 // if ( 5238 // this.status_api_global_data && 5239 // this.status_api_global_data.enable_object_mapping 5240 // ) { 5241 // await this.getObjectUrlsApi(); 5242 // } 5243 this.GetTranslationsApi().then(() => { 5244 this.translate(selected_lang_code); 5245 this.AddDataAttributeDataChangeListioner(); 5246 }); 5247 } 5248 } 5249 setEventHandlerOfProxyDropDown() { 5250 this.print(3, "setting click listener to language selection dropdown"); 5251 let dotaSelectContainer = document.querySelector("#Devnagri_open_button"); 5252 let width; 5253 if (dotaSelectContainer && dotaSelectContainer.offsetWidth) { 5254 width = dotaSelectContainer.offsetWidth; 5255 } 5256 let dropdownContainer = document.getElementById("Devnagri_dropdown"); 5257 if (dropdownContainer) { 5258 dropdownContainer.setAttribute("style", `width:${width}px;`); 5259 } 5260 5261 const languageWrapper = document.getElementById( 5262 "Devnagri_written_lang_wrapper" 5263 ); 5264 if (languageWrapper) { 5265 languageWrapper.removeEventListener("click", this.openProxyDropdown); 5266 languageWrapper.addEventListener("click", this.openProxyDropdown); 5267 } 5268 const arrowWrapper = document.getElementById("Devnagri_arrow_up_wrapper"); 5269 if (arrowWrapper) { 5270 arrowWrapper.removeEventListener("click", this.openProxyDropdown); 5271 arrowWrapper.addEventListener("click", this.openProxyDropdown); 5272 } 5273 } 5274 5275 openProxyDropdown() { 5276 let x = document.getElementById("Devnagri_dropdown"); 5277 if (x.style.display === "block") { 5278 x.style.display = "none"; 5279 } else { 5280 x.style.display = "block"; 5281 } 5282 } 5283 5284 async getObjectUrlsApi() { 5285 const langCode = this.selected_lang_code; 5286 5287 const apiUrl = `${this.api_baseurl}/object-mapping?language_code=${langCode}`; 5288 // const res = await fetch(apiUrl, { 5289 // method: "GET", 5290 // headers: { 5291 // Authorization: `Bearer ${this.access_token}`, 5292 // }, 5293 // }); 5294 // if (res.status === 401 || res.status === 403) { 5295 // this.callApiRequest(); 5296 // } 5297 // const responseData = await res.json(); 5298 5299 if(!this.objectMappingapiCounter) 5300 { 5301 this.objectMappingData = await this.callApiRequest(async () => { 5302 const res = await fetch(apiUrl, { 5303 method: "GET", 5304 headers: { 5305 Authorization: `Bearer ${this.access_token}`, 5306 }, 5307 }); 5308 if (res.status === 401 || res.status === 403) { 5309 throw { response: res }; 5310 } 5311 const response = await res.json(); 5312 return response; 5313 }); 5314 ++this.objectMappingapiCounter; 5315 } 5316 5317 let objectsArr = []; 5318 if (this.objectMappingData.data && Array.isArray(this.objectMappingData.data)) { 5319 objectsArr = this.objectMappingData.data; 5320 } 5321 const objectsMap = {}; 5322 const objectsMapLocal = {}; 5323 objectsArr.forEach((object) => { 5324 objectsMap[object.english_url] = object; 5325 objectsMapLocal[object.local_url] = object; 5326 }); 5327 this.subdomain_object_urls_hash_map = objectsMap; 5328 this.print( 5329 3, 5330 "ð ~ file: devnagri-dota-merged-client-dev.js ~ line 3379 ~ Devnagri ~ getObjectUrlsApi ~ this.subdomain_object_urls_hash_map", 5331 this.subdomain_object_urls_hash_map 5332 ); 5333 // this.subdomain_object_urls_hash_map_local = objectsMap; 5334 5335 if ( 5336 this.subdomain_object_urls_hash_map && 5337 typeof this.subdomain_object_urls_hash_map === "object" 5338 ) { 5339 const objectsArr = Object.values(this.subdomain_object_urls_hash_map
5339); 5340 const localObjectUrlsHashMap = {}; 5341 objectsArr.forEach((object) => { 5342 localObjectUrlsHashMap[object.local_url] = object; 5343 }); 5344 this.subdomain_object_urls_hash_map_local = localObjectUrlsHashMap; 5345 } 5346 } 5347 5348 globalCheckIfStringIsLocal(string) { 5349 if( 5350 this.checkIfStringIsHindi(string) || 5351 this.checkIfStringIsPunjabi(string) || 5352 this.checkIfStringIsTamil(string) || 5353 this.checkIfStringIsGujrati(string) || 5354 this.checkIfStringIsKannad(string) || 5355 this.checkIfStringIsBengali(string) || 5356 this.checkIfStringIsHindi(string) || 5357 this.checkIfStringIsTelugu(string) || 5358 this.checkIfStringIsMalyalam(string) || 5359 this.checkIfStringIsAssamese(string) || 5360 this.checkIfStringIsOdia(string) || 5361 this.checkIfStringIsArabic(string) || 5362 this.checkIfStringIsJapanese(string) || 5363 this.checkIfStringIsChinese(string) || 5364 this.checkIfStringIsIndonesian(string) || 5365 this.checkIfStringIsUrdu(string) 5366 ){ 5367 return true; 5368 } 5369 5370 return false; 5371 } 5372}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.