[BUGFIX] Manage Language Packs: Render empty column if language pack is downloaded 37/61837/5
authorAndreas Fernandez <a.fernandez@scripting-base.de>
Thu, 26 Sep 2019 08:06:22 +0000 (10:06 +0200)
committerRichard Haeser <richard@maxserv.com>
Mon, 30 Sep 2019 12:24:00 +0000 (14:24 +0200)
If a language pack is available for an extension, the matrix now renders
an empty column to fix wrong positioning of the actual download buttons.

Resolves: #89283
Releases: master, 9.5
Change-Id: I100a0c8f4a4db3ed03f86e2fb71c95ec9448b3bb
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61837
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Frank Nägler <frank.naegler@typo3.org>
Tested-by: Richard Haeser <richard@maxserv.com>
Reviewed-by: Frank Nägler <frank.naegler@typo3.org>
Reviewed-by: Richard Haeser <richard@maxserv.com>
Build/Sources/TypeScript/install/Resources/Public/TypeScript/Module/Maintenance/LanguagePacks.ts
typo3/sysext/install/Resources/Public/JavaScript/Module/Maintenance/LanguagePacks.js

index 63cc3c2..6119410 100644 (file)
@@ -18,6 +18,7 @@ import Router = require('../../Router');
 import FlashMessage = require('../../Renderable/FlashMessage');
 import ProgressBar = require('../../Renderable/ProgressBar');
 import InfoBox = require('../../Renderable/InfoBox');
+import SecurityUtility = require('TYPO3/CMS/Core/SecurityUtility');
 import Severity = require('../../Renderable/Severity');
 
 /**
@@ -402,6 +403,7 @@ class LanguagePacks extends AbstractInteractableModule {
   }
 
   private extensionMatrixHtml(data: any): any {
+    const securityUtility = new SecurityUtility();
     const packMissesIcon: string = this.findInModal(this.selectorExtensionPackMissesIcon).html();
     const updateIcon: string = this.findInModal(this.selectorLanguageUpdateIcon).html();
     let tooltip: string = '';
@@ -461,22 +463,22 @@ class LanguagePacks extends AbstractInteractableModule {
         $('<td>').text(extension.key),
       );
       extension.packs.forEach((pack: any): void => {
+        const $column = $('<td>');
+        $tr.append($column);
         if (pack.exists !== true) {
           if (pack.lastUpdate !== null) {
-            tooltip = 'No language pack available when tried at ' + pack.lastUpdate + '. Click to re-try.';
+            tooltip = 'No language pack available for ' + pack.iso + ' when tried at ' + pack.lastUpdate + '. Click to re-try.';
           } else {
             tooltip = 'Language pack not downloaded. Click to download';
           }
-          $tr.append(
-            $('<td>').append(
-              $('<a>', {
-                'class': 'btn btn-default t3js-languagePacks-update',
-                'data-extension': extension.key,
-                'data-iso': pack.iso,
-                'data-toggle': 'tooltip',
-                'title': tooltip,
-              }).append(packMissesIcon),
-            ),
+          $column.append(
+            $('<a>', {
+              'class': 'btn btn-default t3js-languagePacks-update',
+              'data-extension': extension.key,
+              'data-iso': pack.iso,
+              'data-toggle': 'tooltip',
+              'title': securityUtility.encodeHtml(tooltip),
+            }).append(packMissesIcon),
           );
         }
       });
index 917d80d..96d70ad 100644 (file)
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-define(["require","exports","../AbstractInteractableModule","jquery","../../Router","../../Renderable/FlashMessage","../../Renderable/ProgressBar","../../Renderable/InfoBox","../../Renderable/Severity","bootstrap"],function(t,a,e,s,n,i,o,d,l){"use strict";return new class extends e.AbstractInteractableModule{constructor(){super(...arguments),this.selectorOutputContainer=".t3js-languagePacks-output",this.selectorContentContainer=".t3js-languagePacks-mainContent",this.selectorActivateLanguage=".t3js-languagePacks-activateLanguage",this.selectorActivateLanguageIcon="#t3js-languagePacks-activate-icon",this.selectorAddLanguageToggle=".t3js-languagePacks-addLanguage-toggle",this.selectorLanguageInactive=".t3js-languagePacks-inactive",this.selectorDeactivateLanguage=".t3js-languagePacks-deactivateLanguage",this.selectorDeactivateLanguageIcon="#t3js-languagePacks-deactivate-icon",this.selectorUpdate=".t3js-languagePacks-update",this.selectorLanguageUpdateIcon="#t3js-languagePacks-languageUpdate-icon",this.selectorExtensionPackMissesIcon="#t3js-languagePacks-extensionPack-misses-icon",this.selectorNotifications=".t3js-languagePacks-notifications",this.activeLanguages=[],this.activeExtensions=[],this.packsUpdateDetails={toHandle:0,handled:0,updated:0,new:0,failed:0},this.notifications=[]}initialize(t){this.currentModal=t,this.getData(),t.on("click",this.selectorAddLanguageToggle,()=>{t.find(this.selectorContentContainer+" "+this.selectorLanguageInactive).toggle()}),t.on("click",this.selectorActivateLanguage,t=>{const a=s(t.target).closest(this.selectorActivateLanguage).data("iso");t.preventDefault(),this.activateLanguage(a)}),t.on("click",this.selectorDeactivateLanguage,t=>{const a=s(t.target).closest(this.selectorDeactivateLanguage).data("iso");t.preventDefault(),this.deactivateLanguage(a)}),t.on("click",this.selectorUpdate,t=>{const a=s(t.target).closest(this.selectorUpdate).data("iso"),e=s(t.target).closest(this.selectorUpdate).data("extension");t.preventDefault(),this.updatePacks(a,e)})}getData(){const t=this.getModalBody();s.ajax({url:n.getUrl("languagePacksGetData"),cache:!1,success:a=>{if(!0===a.success){this.activeLanguages=a.activeLanguages,this.activeExtensions=a.activeExtensions,t.empty().append(a.html);const e=t.parent().find(this.selectorContentContainer);e.empty(),e.append(this.languageMatrixHtml(a)),e.append(this.extensionMatrixHtml(a)),s('[data-toggle="tooltip"]').tooltip({container:e})}else{const t=d.render(l.error,"Something went wrong","");this.addNotification(t)}this.renderNotifications()},error:a=>{n.handleAjaxError(a,t)}})}activateLanguage(t){const a=this.getModalBody(),e=this.findInModal(this.selectorOutputContainer),c=o.render(l.loading,"Loading...","");e.empty().append(c),s.ajax({url:n.getUrl(),method:"POST",context:this,data:{install:{action:"languagePacksActivateLanguage",token:this.getModuleContent().data("language-packs-activate-language-token"),iso:t}},cache:!1,beforeSend:()=>{this.getNotificationBox().empty()},success:t=>{if(e.empty(),!0===t.success&&Array.isArray(t.status))t.status.forEach(t=>{const a=d.render(t.severity,t.title,t.message);this.addNotification(a)});else{const t=i.render(l.error,"Something went wrong","");this.addNotification(t)}this.getData()},error:t=>{n.handleAjaxError(t,a)}})}deactivateLanguage(t){const a=this.getModalBody(),e=this.findInModal(this.selectorOutputContainer),c=o.render(l.loading,"Loading...","");e.empty().append(c),s.ajax({url:n.getUrl(),method:"POST",context:this,data:{install:{action:"languagePacksDeactivateLanguage",token:this.getModuleContent().data("language-packs-deactivate-language-token"),iso:t}},cache:!1,beforeSend:()=>{this.getNotificationBox().empty()},success:t=>{if(e.empty(),!0===t.success&&Array.isArray(t.status))t.status.forEach(t=>{const a=d.render(t.severity,t.title,t.message);this.addNotification(a)});else{const t=i.render(l.error,"Something went wrong","");this.addNotification(t)}this.getData()},error:t=>{n.handleAjaxError(t,a)}})}updatePacks(t,a){const e=this.findInModal(this.selectorOutputContainer),i=this.findInModal(this.selectorContentContainer),o=void 0===t?this.activeLanguages:[t];let d=!0,l=this.activeExtensions;void 0!==a&&(l=[a],d=!1),this.packsUpdateDetails={toHandle:o.length*l.length,handled:0,updated:0,new:0,failed:0},e.empty().append(s("<div>",{class:"progress"}).append(s("<div>",{class:"progress-bar progress-bar-info",role:"progressbar","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100,style:"width: 0;"}).append(s("<span>",{class:"text-nowrap"}).text("0 of "+this.packsUpdateDetails.toHandle+" language packs updated")))),i.empty(),o.forEach(t=>{l.forEach(a=>{s.ajax({url:n.getUrl(),method:"POST",context:this,data:{install:{action:"languagePacksUpdatePack",token:this.getModuleContent().data("language-packs-update-pack-token"),iso:t,extension:a}},cache:!1,beforeSend:()=>{this.getNotificationBox().empty()},success:t=>{!0===t.success?(this.packsUpdateDetails.handled++,"new"===t.packResult?this.packsUpdateDetails.new++:"update"===t.packResult?this.packsUpdateDetails.updated++:this.packsUpdateDetails.failed++,this.packUpdateDone(d,o)):(this.packsUpdateDetails.handled++,this.packsUpdateDetails.failed++,this.packUpdateDone(d,o))},error:()=>{this.packsUpdateDetails.handled++,this.packsUpdateDetails.failed++,this.packUpdateDone(d,o)}})})})}packUpdateDone(t,a){const e=this.getModalBody(),o=this.findInModal(this.selectorOutputContainer);if(this.packsUpdateDetails.handled===this.packsUpdateDetails.toHandle){const o=d.render(l.ok,"Language packs updated",this.packsUpdateDetails.new+" new language packs downloaded, "+this.packsUpdateDetails.updated+" language packs updated, "+this.packsUpdateDetails.failed+" language packs not available");this.addNotification(o),!0===t?s.ajax({url:n.getUrl(),method:"POST",context:this,data:{install:{action:"languagePacksUpdateIsoTimes",token:this.getModuleContent().data("language-packs-update-iso-times-token"),isos:a}},cache:!1,success:t=>{if(!0===t.success)this.getData();else{const t=i.render(l.error,"Something went wrong","");this.addNotification(t)}},error:t=>{n.handleAjaxError(t,e)}}):this.getData()}else{const t=this.packsUpdateDetails.handled/this.packsUpdateDetails.toHandle*100;o.find(".progress-bar").css("width",t+"%").attr("aria-valuenow",t).find("span").text(this.packsUpdateDetails.handled+" of "+this.packsUpdateDetails.toHandle+" language packs updated")}}languageMatrixHtml(t){const a=this.findInModal(this.selectorActivateLanguageIcon).html(),e=this.findInModal(this.selectorDeactivateLanguageIcon).html(),n=this.findInModal(this.selectorLanguageUpdateIcon).html(),i=s("<div>"),o=s("<tbody>");return t.languages.forEach(t=>{const i=t.active,d=s("<tr>");i?o.append(d.append(s("<td>").text(" "+t.name).prepend(s("<div />",{class:"btn-group"}).append(s("<a>",{class:"btn btn-default t3js-languagePacks-deactivateLanguage","data-iso":t.iso,"data-toggle":"tooltip",title:"Deactivate"}).append(e),s("<a>",{class:"btn btn-default t3js-languagePacks-update","data-iso":t.iso,"data-toggle":"tooltip",title:"Download language packs"}).append(n))))):o.append(d.addClass("t3-languagePacks-inactive t3js-languagePacks-inactive").css({display:"none"}).append(s("<td>").text(" "+t.name).prepend(s("<div />",{class:"btn-group"}).append(s("<a>",{class:"btn btn-default t3js-languagePacks-activateLanguage","data-iso":t.iso,"data-toggle":"tooltip",title:"Activate"}).append(a))))),d.append(s("<td>").text(t.iso),s("<td>").text(t.dependencies.join(", ")),s("<td>").text(null===t.lastUpdate?"":t.lastUpdate)),o.append(d)}),i.append(s("<h3>").text("Active languages"),s("<table>",{class:"table table-striped table-bordered"}).append(s("<thead>").append(s("<tr>").append(s("<th>").append(s("<div />",{class:"btn-group"}).append(s("<button>",{class:"btn btn-default t3js-languagePacks-addLanguage-toggle",type:"button"}).append(s("<span>").append(a)," Add language"),s("<button>",{class:"btn btn-default t3js-languagePacks-update",type:"button"}).append(s("<span>").append(n)," Update all"))),s("<th>").text("Locale"),s("<th>").text("Dependencies"),s("<th>").text("Last update"))),o)),i.html()}extensionMatrixHtml(t){const a=this.findInModal(this.selectorExtensionPackMissesIcon).html(),e=this.findInModal(this.selectorLanguageUpdateIcon).html();let n,i="",o=!0,c=0;const p=s("<div>"),g=s("<tr>");g.append(s("<th>").text("Extension"),s("<th>").text("Key")),t.activeLanguages.forEach(t=>{g.append(s("<th>").append(s("<a>",{class:"btn btn-default t3js-languagePacks-update","data-iso":t,"data-toggle":"tooltip",title:"Download and update all language packs"}).append(s("<span>").append(e)," "+t)))});const r=s("<tbody>");return t.extensions.forEach(t=>{if(o=!0,t.packs.forEach(t=>{!1===t.exists&&(o=!1)}),!0===o)return;c++,n=""!==t.icon?s("<span>").append(s("<img>",{style:"max-height: 16px; max-width: 16px;",src:"../"+t.icon,alt:t.title}),s("<span>").text(" "+t.title)):s("<span>").text(t.title);const e=s("<tr>");e.append(s("<td>").html(n.html()),s("<td>").text(t.key)),t.packs.forEach(n=>{!0!==n.exists&&(i=null!==n.lastUpdate?"No language pack available when tried at "+n.lastUpdate+". Click to re-try.":"Language pack not downloaded. Click to download",e.append(s("<td>").append(s("<a>",{class:"btn btn-default t3js-languagePacks-update","data-extension":t.key,"data-iso":n.iso,"data-toggle":"tooltip",title:i}).append(a))))}),r.append(e)}),p.append(s("<h3>").text("Translation status"),s("<table>",{class:"table table-striped table-bordered"}).append(s("<thead>").append(g),r)),0===c?d.render(l.ok,"Language packs have been found for every installed extension.","To download the latest changes, use the refresh button in the list above."):p.html()}getNotificationBox(){return this.findInModal(this.selectorNotifications)}addNotification(t){this.notifications.push(t)}renderNotifications(){const t=this.getNotificationBox();for(let a of this.notifications)t.append(a);this.notifications=[]}}});
\ No newline at end of file
+define(["require","exports","../AbstractInteractableModule","jquery","../../Router","../../Renderable/FlashMessage","../../Renderable/ProgressBar","../../Renderable/InfoBox","TYPO3/CMS/Core/SecurityUtility","../../Renderable/Severity","bootstrap"],function(t,a,e,s,n,i,o,d,l,c){"use strict";return new class extends e.AbstractInteractableModule{constructor(){super(...arguments),this.selectorOutputContainer=".t3js-languagePacks-output",this.selectorContentContainer=".t3js-languagePacks-mainContent",this.selectorActivateLanguage=".t3js-languagePacks-activateLanguage",this.selectorActivateLanguageIcon="#t3js-languagePacks-activate-icon",this.selectorAddLanguageToggle=".t3js-languagePacks-addLanguage-toggle",this.selectorLanguageInactive=".t3js-languagePacks-inactive",this.selectorDeactivateLanguage=".t3js-languagePacks-deactivateLanguage",this.selectorDeactivateLanguageIcon="#t3js-languagePacks-deactivate-icon",this.selectorUpdate=".t3js-languagePacks-update",this.selectorLanguageUpdateIcon="#t3js-languagePacks-languageUpdate-icon",this.selectorExtensionPackMissesIcon="#t3js-languagePacks-extensionPack-misses-icon",this.selectorNotifications=".t3js-languagePacks-notifications",this.activeLanguages=[],this.activeExtensions=[],this.packsUpdateDetails={toHandle:0,handled:0,updated:0,new:0,failed:0},this.notifications=[]}initialize(t){this.currentModal=t,this.getData(),t.on("click",this.selectorAddLanguageToggle,()=>{t.find(this.selectorContentContainer+" "+this.selectorLanguageInactive).toggle()}),t.on("click",this.selectorActivateLanguage,t=>{const a=s(t.target).closest(this.selectorActivateLanguage).data("iso");t.preventDefault(),this.activateLanguage(a)}),t.on("click",this.selectorDeactivateLanguage,t=>{const a=s(t.target).closest(this.selectorDeactivateLanguage).data("iso");t.preventDefault(),this.deactivateLanguage(a)}),t.on("click",this.selectorUpdate,t=>{const a=s(t.target).closest(this.selectorUpdate).data("iso"),e=s(t.target).closest(this.selectorUpdate).data("extension");t.preventDefault(),this.updatePacks(a,e)})}getData(){const t=this.getModalBody();s.ajax({url:n.getUrl("languagePacksGetData"),cache:!1,success:a=>{if(!0===a.success){this.activeLanguages=a.activeLanguages,this.activeExtensions=a.activeExtensions,t.empty().append(a.html);const e=t.parent().find(this.selectorContentContainer);e.empty(),e.append(this.languageMatrixHtml(a)),e.append(this.extensionMatrixHtml(a)),s('[data-toggle="tooltip"]').tooltip({container:e})}else{const t=d.render(c.error,"Something went wrong","");this.addNotification(t)}this.renderNotifications()},error:a=>{n.handleAjaxError(a,t)}})}activateLanguage(t){const a=this.getModalBody(),e=this.findInModal(this.selectorOutputContainer),l=o.render(c.loading,"Loading...","");e.empty().append(l),s.ajax({url:n.getUrl(),method:"POST",context:this,data:{install:{action:"languagePacksActivateLanguage",token:this.getModuleContent().data("language-packs-activate-language-token"),iso:t}},cache:!1,beforeSend:()=>{this.getNotificationBox().empty()},success:t=>{if(e.empty(),!0===t.success&&Array.isArray(t.status))t.status.forEach(t=>{const a=d.render(t.severity,t.title,t.message);this.addNotification(a)});else{const t=i.render(c.error,"Something went wrong","");this.addNotification(t)}this.getData()},error:t=>{n.handleAjaxError(t,a)}})}deactivateLanguage(t){const a=this.getModalBody(),e=this.findInModal(this.selectorOutputContainer),l=o.render(c.loading,"Loading...","");e.empty().append(l),s.ajax({url:n.getUrl(),method:"POST",context:this,data:{install:{action:"languagePacksDeactivateLanguage",token:this.getModuleContent().data("language-packs-deactivate-language-token"),iso:t}},cache:!1,beforeSend:()=>{this.getNotificationBox().empty()},success:t=>{if(e.empty(),!0===t.success&&Array.isArray(t.status))t.status.forEach(t=>{const a=d.render(t.severity,t.title,t.message);this.addNotification(a)});else{const t=i.render(c.error,"Something went wrong","");this.addNotification(t)}this.getData()},error:t=>{n.handleAjaxError(t,a)}})}updatePacks(t,a){const e=this.findInModal(this.selectorOutputContainer),i=this.findInModal(this.selectorContentContainer),o=void 0===t?this.activeLanguages:[t];let d=!0,l=this.activeExtensions;void 0!==a&&(l=[a],d=!1),this.packsUpdateDetails={toHandle:o.length*l.length,handled:0,updated:0,new:0,failed:0},e.empty().append(s("<div>",{class:"progress"}).append(s("<div>",{class:"progress-bar progress-bar-info",role:"progressbar","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100,style:"width: 0;"}).append(s("<span>",{class:"text-nowrap"}).text("0 of "+this.packsUpdateDetails.toHandle+" language packs updated")))),i.empty(),o.forEach(t=>{l.forEach(a=>{s.ajax({url:n.getUrl(),method:"POST",context:this,data:{install:{action:"languagePacksUpdatePack",token:this.getModuleContent().data("language-packs-update-pack-token"),iso:t,extension:a}},cache:!1,beforeSend:()=>{this.getNotificationBox().empty()},success:t=>{!0===t.success?(this.packsUpdateDetails.handled++,"new"===t.packResult?this.packsUpdateDetails.new++:"update"===t.packResult?this.packsUpdateDetails.updated++:this.packsUpdateDetails.failed++,this.packUpdateDone(d,o)):(this.packsUpdateDetails.handled++,this.packsUpdateDetails.failed++,this.packUpdateDone(d,o))},error:()=>{this.packsUpdateDetails.handled++,this.packsUpdateDetails.failed++,this.packUpdateDone(d,o)}})})})}packUpdateDone(t,a){const e=this.getModalBody(),o=this.findInModal(this.selectorOutputContainer);if(this.packsUpdateDetails.handled===this.packsUpdateDetails.toHandle){const o=d.render(c.ok,"Language packs updated",this.packsUpdateDetails.new+" new language packs downloaded, "+this.packsUpdateDetails.updated+" language packs updated, "+this.packsUpdateDetails.failed+" language packs not available");this.addNotification(o),!0===t?s.ajax({url:n.getUrl(),method:"POST",context:this,data:{install:{action:"languagePacksUpdateIsoTimes",token:this.getModuleContent().data("language-packs-update-iso-times-token"),isos:a}},cache:!1,success:t=>{if(!0===t.success)this.getData();else{const t=i.render(c.error,"Something went wrong","");this.addNotification(t)}},error:t=>{n.handleAjaxError(t,e)}}):this.getData()}else{const t=this.packsUpdateDetails.handled/this.packsUpdateDetails.toHandle*100;o.find(".progress-bar").css("width",t+"%").attr("aria-valuenow",t).find("span").text(this.packsUpdateDetails.handled+" of "+this.packsUpdateDetails.toHandle+" language packs updated")}}languageMatrixHtml(t){const a=this.findInModal(this.selectorActivateLanguageIcon).html(),e=this.findInModal(this.selectorDeactivateLanguageIcon).html(),n=this.findInModal(this.selectorLanguageUpdateIcon).html(),i=s("<div>"),o=s("<tbody>");return t.languages.forEach(t=>{const i=t.active,d=s("<tr>");i?o.append(d.append(s("<td>").text(" "+t.name).prepend(s("<div />",{class:"btn-group"}).append(s("<a>",{class:"btn btn-default t3js-languagePacks-deactivateLanguage","data-iso":t.iso,"data-toggle":"tooltip",title:"Deactivate"}).append(e),s("<a>",{class:"btn btn-default t3js-languagePacks-update","data-iso":t.iso,"data-toggle":"tooltip",title:"Download language packs"}).append(n))))):o.append(d.addClass("t3-languagePacks-inactive t3js-languagePacks-inactive").css({display:"none"}).append(s("<td>").text(" "+t.name).prepend(s("<div />",{class:"btn-group"}).append(s("<a>",{class:"btn btn-default t3js-languagePacks-activateLanguage","data-iso":t.iso,"data-toggle":"tooltip",title:"Activate"}).append(a))))),d.append(s("<td>").text(t.iso),s("<td>").text(t.dependencies.join(", ")),s("<td>").text(null===t.lastUpdate?"":t.lastUpdate)),o.append(d)}),i.append(s("<h3>").text("Active languages"),s("<table>",{class:"table table-striped table-bordered"}).append(s("<thead>").append(s("<tr>").append(s("<th>").append(s("<div />",{class:"btn-group"}).append(s("<button>",{class:"btn btn-default t3js-languagePacks-addLanguage-toggle",type:"button"}).append(s("<span>").append(a)," Add language"),s("<button>",{class:"btn btn-default t3js-languagePacks-update",type:"button"}).append(s("<span>").append(n)," Update all"))),s("<th>").text("Locale"),s("<th>").text("Dependencies"),s("<th>").text("Last update"))),o)),i.html()}extensionMatrixHtml(t){const a=new l,e=this.findInModal(this.selectorExtensionPackMissesIcon).html(),n=this.findInModal(this.selectorLanguageUpdateIcon).html();let i,o="",p=!0,g=0;const r=s("<div>"),h=s("<tr>");h.append(s("<th>").text("Extension"),s("<th>").text("Key")),t.activeLanguages.forEach(t=>{h.append(s("<th>").append(s("<a>",{class:"btn btn-default t3js-languagePacks-update","data-iso":t,"data-toggle":"tooltip",title:"Download and update all language packs"}).append(s("<span>").append(n)," "+t)))});const u=s("<tbody>");return t.extensions.forEach(t=>{if(p=!0,t.packs.forEach(t=>{!1===t.exists&&(p=!1)}),!0===p)return;g++,i=""!==t.icon?s("<span>").append(s("<img>",{style:"max-height: 16px; max-width: 16px;",src:"../"+t.icon,alt:t.title}),s("<span>").text(" "+t.title)):s("<span>").text(t.title);const n=s("<tr>");n.append(s("<td>").html(i.html()),s("<td>").text(t.key)),t.packs.forEach(i=>{const d=s("<td>");n.append(d),!0!==i.exists&&(o=null!==i.lastUpdate?"No language pack available for "+i.iso+" when tried at "+i.lastUpdate+". Click to re-try.":"Language pack not downloaded. Click to download",d.append(s("<a>",{class:"btn btn-default t3js-languagePacks-update","data-extension":t.key,"data-iso":i.iso,"data-toggle":"tooltip",title:a.encodeHtml(o)}).append(e)))}),u.append(n)}),r.append(s("<h3>").text("Translation status"),s("<table>",{class:"table table-striped table-bordered"}).append(s("<thead>").append(h),u)),0===g?d.render(c.ok,"Language packs have been found for every installed extension.","To download the latest changes, use the refresh button in the list above."):r.html()}getNotificationBox(){return this.findInModal(this.selectorNotifications)}addNotification(t){this.notifications.push(t)}renderNotifications(){const t=this.getNotificationBox();for(let a of this.notifications)t.append(a);this.notifications=[]}}});
\ No newline at end of file