Project

General

Profile

Bug #102911

Updated by RVVN no-lastname-given 4 months ago

In Maintenance module, when opening the modal to manage language packs, the following Javascript error occurs : 

 <pre><code class="javascript"> 
 LanguagePacks.js?bust=1706035863:13 Uncaught (in promise) TypeError: t.activeLanguages.forEach is not a function 
     at g.extensionMatrixHtml (LanguagePacks.js?bust=1706035863:13:9297) 
     at LanguagePacks.js?bust=1706035863:13:2610 
 extensionMatrixHtml @ LanguagePacks.js?bust=1706035863:13 
 (anonymous) @ LanguagePacks.js?bust=1706035863:13 
 </code></pre> 

 It's because `t.activeLanguages` it not an array but a JSON object. 
 As a result, the list of language packs for extensions does not appear in the modal window. 

 h2. Explanation : 

 The XHR call to @/typo3/install.php?install[controller]=maintenance&install[context]=backend&install[action]=languagePacksGetData@ returns this kind of JSON data : 

 <pre><code class="javascript"> 
 { 
     "success": true, 
     "languages": [ 
         [...], 
         { 
             "iso": "fr", 
             "name": "French", 
             "active": true, 
             "lastUpdate": "23-01-24 18:51", 
             "dependencies": [] 
         }, 
         [...] 
     ], 
     "extensions": [ 
         { 
             "key": "adminpanel", 
             "title": "TYPO3 Admin Panel", 
             "icon": "/typo3/sysext/adminpanel/Resources/Public/Icons/Extension.png", 
             "packs": [ 
                 { 
                     "iso": "fr", 
                     "exists": true, 
                     "lastUpdate": null 
                 } 
             ] 
         }, 
         [...] 
     ], 
     "activeLanguages": { 
         "19": "fr" 
     }, 
     "activeExtensions": [ 
         "adminpanel", 
         "backend", 
         "belog", 
         [...], 
         "t3editor", 
         "tstemplate" 
     ], 
     "html": "..." 
 } 
 </code></pre> 



 The @LanguagePackService->getActiveLanguages()@ function returns an array which is a trimmed version of @$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['lang']['availableLanguages']@ (all empty values are removed). 
 Thus the indexes are not a continous numeric sequence. 

 But according to the official documentation (https://www.php.net/manual/en/function.json-encode.php#refsect1-function.json-encode-notes) : 

 ??When encoding an array, if the keys are not a continuous numeric sequence starting from 0, all keys are encoded as strings, and specified explicitly for each key-value pair.?? 

 Examples taken from this documentation : 

 <pre><code class="php"> 
 Sequential array 
 array(4) { 
   [0]=> 
   string(3) "foo" 
   [1]=> 
   string(3) "bar" 
   [2]=> 
   string(3) "baz" 
   [3]=> 
   string(5) "blong" 
 } 
 string(27) "["foo","bar","baz","blong"]" 

 Non-sequential array 
 array(4) { 
   [1]=> 
   string(3) "foo" 
   [2]=> 
   string(3) "bar" 
   [3]=> 
   string(3) "baz" 
   [4]=> 
   string(5) "blong" 
 } 
 string(43) "{"1":"foo","2":"bar","3":"baz","4":"blong"}" 

 Sequential array with one key unset 
 array(3) { 
   [0]=> 
   string(3) "foo" 
   [2]=> 
   string(3) "baz" 
   [3]=> 
   string(5) "blong" 
 } 
 string(33) "{"0":"foo","2":"baz","3":"blong"}" 
 </code></pre> 



 h2. Workaround / Fix :  

 At this point, it seems we only need ISO values, so a potential workaround/fix may be to apply @array_values@ @array_value@ to the active languages in the JSON response of @MaintenanceController->languagePacksGetDataAction()@ : 

 <pre><code class="php"> 
 public function languagePacksGetDataAction(ServerRequestInterface $request): ResponseInterface 
     { 
         [...] 
        
         return new JsonResponse([ 
             'success' => true, 
             'languages' => $languagePackService->getLanguageDetails(), 
             'extensions' => $extensions, 
             'activeLanguages' => array_values($languagePackService->getActiveLanguages()), // HERE 
             'activeExtensions' => array_column($extensions, 'key'), 
             'html' => $view->render(), 
         ]); 
     } 
 </code></pre> 

Back