Commit 3ebc7ba9 authored by Benni Mack's avatar Benni Mack Committed by Andreas Wolf
Browse files

[TASK] Move moduleLabels to ModuleLoader

Already translated module labels were previously resolved
and stored within $GLOBALS[LANG]. Several checks
and calls were then made to ModuleLoader and $LANG.

All information about the module, as well as all labels
are now stored within ModuleLoader, a addLabelsForModule()
method and a getLabelsForModule() method are placed within
that method, where labels are stored (but not resolved
to the language yet). The language service then is only used
when outputting the labels in various places.

The method $LANG->addModuleLabels() and the public
property $LANG->moduleLabels were deprecated.

Resolves: #72340
Releases: master
Change-Id: I82f01e7641b1395d81895d246ef22f11206d927d
Reviewed-on: https://review.typo3.org/46702

Reviewed-by: Nicole Cordes's avatarNicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes's avatarNicole Cordes <typo3@cordes.co>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Andreas Wolf's avatarAndreas Wolf <andreas.wolf@typo3.org>
Tested-by: Andreas Wolf's avatarAndreas Wolf <andreas.wolf@typo3.org>
parent ca0d46cb
......@@ -117,12 +117,13 @@ class ModulesController extends ActionController
$loadedModules->load($GLOBALS['TBE_MODULES']);
$mainModulesData = array();
foreach ($loadedModules->modules as $moduleName => $moduleInfo) {
$mainModuleData = array();
$moduleKey = $moduleName . '_tab';
$mainModuleData['name'] = $moduleName;
$mainModuleData['label'] = $this->languageService->moduleLabels['tabs'][$moduleKey];
$moduleLabels = $loadedModules->getLabelsForModule($moduleName);
$mainModuleData = [
'name' => $moduleName,
'label' => $moduleLabels['title']
];
if (is_array($moduleInfo['sub']) && !empty($moduleInfo['sub'])) {
$mainModuleData['subModules'] = $this->getSubModuleData($moduleName, $moduleInfo['sub']);
$mainModuleData['subModules'] = $this->getSubModuleData($loadedModules, $moduleName);
}
$mainModulesData[] = $mainModuleData;
}
......@@ -132,22 +133,22 @@ class ModulesController extends ActionController
/**
* Create array with data of all subModules of a specific main module
*
* @param ModuleLoader $loadedModules the module loader instance
* @param string $moduleName Name of the main module
* @param array $subModulesInfo Sub module information
* @return array
*/
protected function getSubModuleData($moduleName, array $subModulesInfo = array())
protected function getSubModuleData(ModuleLoader $loadedModules, $moduleName)
{
$subModulesData = array();
foreach ($subModulesInfo as $subModuleName => $subModuleInfo) {
$subModuleKey = $moduleName . '_' . $subModuleName . '_tab';
foreach ($loadedModules->modules[$moduleName]['sub'] as $subModuleName => $subModuleInfo) {
$moduleLabels = $loadedModules->getLabelsForModule($moduleName . '_' . $subModuleName);
$subModuleData = array();
$subModuleData['name'] = $subModuleName;
$subModuleData['icon'] = $subModuleInfo['icon'];
$subModuleData['iconIdentifier'] = $subModuleInfo['iconIdentifier'];
$subModuleData['label'] = $this->languageService->moduleLabels['tabs'][$subModuleKey];
$subModuleData['shortDescription'] = $this->languageService->moduleLabels['labels'][$subModuleKey . 'label'];
$subModuleData['longDescription'] = $this->languageService->moduleLabels['labels'][$subModuleKey . 'descr'];
$subModuleData['label'] = $moduleLabels['title'];
$subModuleData['shortDescription'] = $moduleLabels['shortdescription'];
$subModuleData['longDescription'] = $moduleLabels['description'];
$subModulesData[] = $subModuleData;
}
return $subModulesData;
......
......@@ -18,7 +18,9 @@
<f:for each="{modules}" as="mainModule">
<f:if condition="{mainModule.subModules}">
<h2>{mainModule.label}</h2>
<f:if condition="{mainModule.label}">
<h2>{f:translate(key: mainModule.label)}</h2>
</f:if>
<div class="container-fuid">
<div class="row">
<f:for each="{mainModule.subModules}" as="subModule" iteration="subModuleIterator">
......@@ -27,10 +29,10 @@
<a
href="#"
onclick="top.goToModule('{mainModule.name}_{subModule.name}'); return false;"
title="{subModule.shortDescription}"
title="{f:if(condition: subModule.shortDescription, then: '{f:translate(key: subModule.shortDescription)}')}"
class="pull-left"
>
<span class="typo3-app-icon media-object" title="{subModule.label}">
<span class="typo3-app-icon media-object" title="{f:if(condition: subModule.label, then: '{f:translate(key: subModule.label)}')}">
<span>
<span>
<core:icon identifier="{subModule.iconIdentifier}" size="default" />
......@@ -40,19 +42,23 @@
</a>
<div class="media-body">
<strong>
<a
href="#"
onclick="top.goToModule('{mainModule.name}_{subModule.name}'); return false;"
title="{subModule.shortDescription}"
>{subModule.label}</a>
</strong><br>
<f:if condition="{subModule.label}">
<strong>
<a
href="#"
onclick="top.goToModule('{mainModule.name}_{subModule.name}'); return false;"
title="{f:if(condition: subModule.shortDescription, then: '{f:translate(key: subModule.shortDescription)}')}"
>{f:translate(key: subModule.label)}</a>
</strong><br>
</f:if>
<f:if condition="{subModule.shortDescription}">
<small class="text-muted">{subModule.shortDescription}</small><br>
<small class="text-muted"><f:translate key="{subModule.shortDescription}" /></small><br>
</f:if>
{subModule.longDescription -> f:format.raw()}
<f:if condition="{subModule.longDescription}">
{f:translate(key: subModule.longDescription) -> f:format.raw()}
</f:if>
</div>
</div>
</div>
......
......@@ -286,9 +286,8 @@ class ShortcutToolbarItem implements ToolbarItemInterface
// Check for module access
$moduleName = $row['M_module_name'] ?: $row['module_name'];
if (!isset($this->getLanguageService()->moduleLabels['labels'][$moduleName . '_tablabel'])) {
// Nice hack to check if the user has access to this module
// - otherwise the translation label would not have been loaded :-)
// Check if the user has access to this module
if (!is_array($this->moduleLoader->checkMod($moduleName))) {
continue;
}
if (!$backendUser->isAdmin()) {
......@@ -658,12 +657,9 @@ class ShortcutToolbarItem implements ToolbarItemInterface
*/
protected function addShortcut($url, $shortcutName, $module)
{
// Shorts
$db = $this->getDatabaseConnection();
$lS = $this->getLanguageService();
if ($shortcutName === 'Shortcut' && !empty($lS->moduleLabels['labels'][$module . '_tablabel'])) {
$shortcutName = $lS->moduleLabels['labels'][$module . '_tablabel'];
$moduleLabels = $this->moduleLoader->getLabelsForModule($module);
if ($shortcutName === 'Shortcut' && !empty($moduleLabels['shortdescription'])) {
$shortcutName = $this->getLanguageService()->sL($moduleLabels['shortdescription']);
}
$motherModule = GeneralUtility::_POST('motherModName');
......@@ -675,14 +671,13 @@ class ShortcutToolbarItem implements ToolbarItemInterface
'sorting' => $GLOBALS['EXEC_TIME']
];
$db->exec_INSERTquery('sys_be_shortcuts', $fieldValues);
$this->getDatabaseConnection()->exec_INSERTquery('sys_be_shortcuts', $fieldValues);
$shortcutCreated = 'failed';
if ($db->sql_affected_rows() === 1) {
$shortcutCreated = 'success';
if ($this->getDatabaseConnection()->sql_affected_rows() === 1) {
return 'success';
} else {
return 'failed';
}
return $shortcutCreated;
}
/**
......@@ -881,10 +876,12 @@ class ShortcutToolbarItem implements ToolbarItemInterface
if (substr($moduleName, 0, 5) == 'xMOD_') {
$title = substr($moduleName, 5);
} else {
$splitModuleName = explode('_', $moduleName);
$title = $languageService->moduleLabels['tabs'][$splitModuleName[0] . '_tab'];
if (count($splitModuleName) > 1) {
$title .= '>' . $languageService->moduleLabels['tabs'][$moduleName . '_tab'];
list($mainModule, $subModule) = explode('_', $moduleName);
$mainModuleLabels = $this->moduleLoader->getLabelsForModule($mainModule);
$title = $languageService->sL($mainModuleLabels['title']);
if (!empty($subModule)) {
$subModuleLabels = $this->moduleLoader->getLabelsForModule($moduleName);
$title .= '>' . $languageService->sL($subModuleLabels['title']);
}
}
if ($parentModuleName) {
......
......@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Backend\Domain\Repository\Module;
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Backend\Module\ModuleLoader;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
......@@ -165,7 +166,7 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface
$entry->setLink($module['path']);
}
if (!empty($module['description']) && is_string($module['description'])) {
$entry->setDescription($module['description']);
$entry->setDescription($this->getLanguageService()->sL($module['description']));
}
if (!empty($module['icon'])) {
$entry->setIcon($module['icon']);
......@@ -234,7 +235,8 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface
public function getRawModuleMenuData()
{
// Loads the backend modules available for the logged in user.
$moduleLoader = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleLoader::class);
/** @var ModuleLoader $moduleLoader */
$moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
$moduleLoader->observeWorkspaces = true;
$moduleLoader->load($GLOBALS['TBE_MODULES']);
$loadedModules = $moduleLoader->modules;
......@@ -250,25 +252,26 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface
$moduleLink = $moduleData['script'];
}
$moduleLink = GeneralUtility::resolveBackPath($moduleLink);
$moduleLabels = $moduleLoader->getLabelsForModule($moduleName);
$moduleKey = 'modmenu_' . $moduleName;
$modules[$moduleKey] = array(
'name' => $moduleName,
'title' => $GLOBALS['LANG']->moduleLabels['tabs'][$moduleName . '_tab'],
'title' => $moduleLabels['title'],
'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName) . ');',
'icon' => $this->getModuleIcon($moduleKey, $moduleData),
'link' => $moduleLink,
'description' => $GLOBALS['LANG']->moduleLabels['labels'][$moduleKey . 'label']
'description' => $moduleLabels['shortdescription']
);
if (!is_array($moduleData['sub']) && $moduleData['script'] !== $dummyScript) {
// Work around for modules with own main entry, but being self the only submodule
$modules[$moduleKey]['subitems'][$moduleKey] = array(
'name' => $moduleName,
'title' => $GLOBALS['LANG']->moduleLabels['tabs'][$moduleName . '_tab'],
'title' => $moduleLabels['title'],
'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName) . ');',
'icon' => $this->getModuleIcon($moduleKey, $moduleData),
'link' => $moduleLink,
'originalLink' => $moduleLink,
'description' => $GLOBALS['LANG']->moduleLabels['labels'][$moduleKey . 'label'],
'description' => $moduleLabels['shortdescription'],
'navigationFrameScript' => null,
'navigationFrameScriptParam' => null,
'navigationComponentId' => null
......@@ -280,13 +283,14 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface
} else {
$submoduleLink = BackendUtility::getModuleUrl($submoduleData['name']);
}
$submoduleKey = $moduleName . '_' . $submoduleName . '_tab';
$submoduleDescription = $GLOBALS['LANG']->moduleLabels['labels'][$submoduleKey . 'label'];
$submoduleKey = $moduleName . '_' . $submoduleName;
$submoduleLabels = $moduleLoader->getLabelsForModule($submoduleKey);
$submoduleDescription = $submoduleLabels['shortdescription'];
$originalLink = $submoduleLink;
$navigationFrameScript = $submoduleData['navFrameScript'];
$modules[$moduleKey]['subitems'][$submoduleKey] = array(
'name' => $moduleName . '_' . $submoduleName,
'title' => $GLOBALS['LANG']->moduleLabels['tabs'][$submoduleKey],
'title' => $submoduleLabels['title'],
'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName . '_' . $submoduleName) . ');',
'icon' => $this->getModuleIcon($moduleKey, $submoduleData),
'link' => $submoduleLink,
......@@ -351,8 +355,8 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface
$iconIdentifier = !(empty($moduleData['iconIdentifier']))
? $moduleData['iconIdentifier']
: 'module-icon-' . $moduleKey;
$iconRegisty = GeneralUtility::makeInstance(IconRegistry::class);
if ($iconRegisty->isRegistered($iconIdentifier)) {
$iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
if ($iconRegistry->isRegistered($iconIdentifier)) {
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
return $iconFactory->getIcon($iconIdentifier)->render();
} else {
......
......@@ -304,34 +304,36 @@ abstract class AbstractItemProvider
}
break;
case ($special === 'modListGroup' || $special === 'modListUser'):
/** @var ModuleLoader $loadModules */
$loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
$loadModules->load($GLOBALS['TBE_MODULES']);
$modList = $special === 'modListUser' ? $loadModules->modListUser : $loadModules->modListGroup;
if (is_array($modList)) {
foreach ($modList as $theMod) {
$moduleLabels = $loadModules->getLabelsForModule($theMod);
list($mainModule, $subModule) = explode('_', $theMod, 2);
// Icon:
if (strpos($theMod, '_') !== false) {
list($mainModule, $subModule) = explode('_', $theMod, 2);
if (!empty($subModule)) {
$icon = $loadModules->modules[$mainModule]['sub'][$subModule]['iconIdentifier'];
} else {
$icon = $loadModules->modules[$theMod]['iconIdentifier'];
}
// Add help text
$helpText = [
'title' => $languageService->moduleLabels['labels'][$theMod . '_tablabel'],
'description' => $languageService->moduleLabels['labels'][$theMod . '_tabdescr']
'title' => $languageService->sL($moduleLabels['shortdescription']),
'description' => $languageService->sL($moduleLabels['description'])
];
$label = '';
// Add label for main module:
$pp = explode('_', $theMod);
if (count($pp) > 1) {
$label .= $languageService->moduleLabels['tabs'][$pp[0] . '_tab'] . '>';
// Add label for main module if this is a submodule
if (!empty($subModule)) {
$mainModuleLabels = $loadModules->getLabelsForModule($mainModule);
$label .= $languageService->sL($mainModuleLabels['title']) . '>';
}
// Add modules own label now:
$label .= $languageService->moduleLabels['tabs'][$theMod . '_tab'];
// Add modules own label now
$label .= $languageService->sL($moduleLabels['title']);
// Item configuration:
// Item configuration
$items[] = [$label, $theMod, $icon, $helpText];
}
}
......
......@@ -74,6 +74,12 @@ class ModuleLoader
*/
protected $navigationComponents = array();
/**
* Labels for the modules
* @var array
*/
protected $moduleLabels = [];
/**
* Init.
* The outcome of the load() function will be a $this->modules array populated with the backend module structure available to the BE_USER
......@@ -145,6 +151,7 @@ class ModuleLoader
if ($this->checkModAccess($name, $MCONF) !== true) {
return false;
}
$this->addLabelsForModule($name, $MCONF['labels']);
return $MCONF;
}
}
......@@ -166,23 +173,7 @@ class ModuleLoader
$finalModuleConfiguration = $setupInformation['configuration'];
$finalModuleConfiguration['name'] = $name;
// Language processing. This will add module labels and image reference to the internal ->moduleLabels array of the LANG object.
$lang = $this->getLanguageService();
if (is_object($lang)) {
$defaultLabels = $setupInformation['labels']['default'];
// If LOCAL_LANG references are used for labels of the module:
if ($defaultLabels['ll_ref']) {
// Now the 'default' key is loaded with the CURRENT language - not the english translation...
$defaultLabels['labels']['tablabel'] = $lang->sL($defaultLabels['ll_ref'] . ':mlang_labels_tablabel');
$defaultLabels['labels']['tabdescr'] = $lang->sL($defaultLabels['ll_ref'] . ':mlang_labels_tabdescr');
$defaultLabels['tabs']['tab'] = $lang->sL($defaultLabels['ll_ref'] . ':mlang_tabs_tab');
$lang->addModuleLabels($defaultLabels, $name . '_');
} else {
// ... otherwise use the old way:
$lang->addModuleLabels($defaultLabels, $name . '_');
$lang->addModuleLabels($setupInformation['labels'][$lang->lang], $name . '_');
}
}
$this->addLabelsForModule($name, $setupInformation['labels']);
// Default script setup
if ($setupInformation['configuration']['script'] === '_DISPATCH' || isset($setupInformation['configuration']['routeTarget'])) {
......@@ -362,6 +353,69 @@ class ModuleLoader
return preg_replace('/[^a-z0-9]/i', '', $str);
}
/**
* Registers labels for a module in a unified way.
*
* Legacy info: This was previously named
* - labels->tablabel (now called "shortdescription")
* - labels->tabdescr (now called "description")
* - tabs->tab (now called "title")
*
* The LLL information is stored, not the actual translated string.
*
* @param string $moduleName the name of the module
* @param string|array $labels the information about the three labels
*/
public function addLabelsForModule($moduleName, $labels)
{
// If LOCAL_LANG references are used for labels of the module:
if (is_string($labels)) {
// Extbase-based modules
$this->moduleLabels[$moduleName] = [
'shortdescription' => $labels . ':mlang_labels_tablabel',
'description' => $labels . ':mlang_labels_tabdescr',
'title' => $labels . ':mlang_tabs_tab',
];
} elseif (isset($labels['title'])) {
// New way, where all labels can be LLL references
$this->moduleLabels[$moduleName] = $labels;
} elseif (isset($labels['ll_ref'])) {
// Classic, non-extbase module labels
$this->addLabelsForModule($moduleName, $labels['ll_ref']);
} else {
// Very old obsolete approach, don't use anymore, use one of the ways above.
if (is_object($this->getLanguageService())) {
$language = $this->getLanguageService()->lang;
} else {
$language = 'default';
}
if (isset($labels[$language]['ll_ref'])) {
$this->addLabelsForModule($moduleName, $labels[$language]['ll_ref']);
} elseif (isset($labels['default']['ll_ref'])) {
$this->addLabelsForModule($moduleName, $labels['default']['ll_ref']);
} else {
$this->moduleLabels[$moduleName] = [
'shortdescription' => isset($labels[$language]['labels']['tablabel']) ? $labels[$language]['labels']['tablabel'] : $labels['default']['labels']['tablabel'],
'description' => isset($labels[$language]['labels']['tabdescr']) ? $labels[$language]['labels']['tabdescr'] : $labels['default']['labels']['tabdescr'],
'title' => isset($labels[$language]['tabs']['tab']) ? $labels[$language]['tabs']['tab'] : $labels['default']['tabs']['tab'],
];
}
}
}
/**
* Returns the labels for the given module
*
* @param string $moduleName
* @return array
*/
public function getLabelsForModule($moduleName)
{
return isset($this->moduleLabels[$moduleName]) ? $this->moduleLabels[$moduleName] : array();
}
/**
* @return LanguageService
*/
......
......@@ -1058,15 +1058,6 @@ class TcaSelectItemsTest extends UnitTestCase
$languageService = $this->prophesize(LanguageService::class);
$GLOBALS['LANG'] = $languageService->reveal();
$languageService->sL(Argument::cetera())->willReturnArgument(0);
$languageService->moduleLabels = [
'labels' => [
'aModule_tablabel' => 'aModuleTabLabel',
'aModule_tabdescr' => 'aModuleTabDescription',
],
'tabs' => [
'aModule_tab' => 'aModuleLabel',
]
];
/** @var ModuleLoader|ObjectProphecy $moduleLoaderProphecy */
$moduleLoaderProphecy = $this->prophesize(ModuleLoader::class);
......@@ -1080,6 +1071,11 @@ class TcaSelectItemsTest extends UnitTestCase
'iconIdentifier' => 'empty-empty'
]
];
$moduleLoaderProphecy->getLabelsForModule('aModule')->shouldBeCalled()->willReturn([
'shortdescription' => 'aModuleTabLabel',
'description' => 'aModuleTabDescription',
'title' => 'aModuleLabel'
]);
$expectedItems = [
0 => [
......
<?php
namespace TYPO3\CMS\Backend\Tests\Unit\Module;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Backend\Module\ModuleLoader;
use TYPO3\CMS\Core\Tests\UnitTestCase;
/**
* Test case
*/
class ModuleLoaderTest extends UnitTestCase
{
protected function setUp()
{
$GLOBALS['LANG'] = new \stdClass();
$GLOBALS['LANG']->lang = 'it';
}
/**
* @return array
*/
public function addModuleLabelsDataProvider()
{
return [
'extbase only with string' => [
'extbasemodule',
'EXT:myext/Resources/Private/Language/modules.xlf',
[
'shortdescription' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_labels_tablabel',
'description' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_labels_tabdescr',
'title' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_tabs_tab',
],
],
'array with LLLs and proper names' => [
'singlereferences',
[
'shortdescription' => 'EXT:myext/Resources/Private/Language/modules.xlf:myshortdescription',
'description' => 'EXT:myext/Resources/Private/Language/modules.xlf:mydescription',
'title' => 'EXT:myext/Resources/Private/Language/modules.xlf:mytitle',
],
[
'shortdescription' => 'EXT:myext/Resources/Private/Language/modules.xlf:myshortdescription',
'description' => 'EXT:myext/Resources/Private/Language/modules.xlf:mydescription',
'title' => 'EXT:myext/Resources/Private/Language/modules.xlf:mytitle',
],
],
'XLF reference inside [ll_ref] - classic' => [
'classicmodule',
[
'll_ref' => 'EXT:myext/Resources/Private/Language/modules.xlf',
],
[
'shortdescription' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_labels_tablabel',
'description' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_labels_tabdescr',
'title' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_tabs_tab',
],
],
'XLF reference inside [default][ll_ref] - classic with default' => [
'classicmodule',
[
'default' => [
'll_ref' => 'EXT:myext/Resources/Private/Language/modules.xlf',
],
],
[
'shortdescription' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_labels_tablabel',
'description' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_labels_tabdescr',
'title' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_tabs_tab',
],
],
'XLF reference inside [it][ll_ref] - classic with italian' => [
'classicmodule',
[
'it' => [
'll_ref' => 'EXT:myext/Resources/Private/Language/modules.xlf',
],
],
[
'shortdescription' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_labels_tablabel',
'description' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_labels_tabdescr',
'title' => 'EXT:myext/Resources/Private/Language/modules.xlf:mlang_tabs_tab',
],
],
'classic inline labels' => [
'classic_inline_labels',
[
'default' => [
'labels' => [
'tablabel' => 'My short description!',
'tabdescr' => 'My description!',
],
'tabs' => [
'tab' => 'My title',
],
],
],
[
'shortdescription' => 'My short description!',
'description' => 'My description!',
'title' => 'My title',
],
],
'classic inline labels in italian completely' => [
'classic_italian_labels',
[