Skip to content

Commit

Permalink
[FEATURE] Use site configuration in v:page.languageMenu on TYPO3 9/10 (
Browse files Browse the repository at this point in the history
…#1723)

* [FEATURE] Use site configuration for language menu

TYPO3 9 includes a new way to configure the languages available on a
site as part of the newly implemented "site" configuration. Among other
things, there is now no special treatment of the default language any
more as far as the configuration is concerned.

vhs, until now, still relied on querying the sys_language table to
gather the languages to display. This is now replaced by querying the
site configuration on supported TYPO3 versions. Although the label
override arguments are still supported on the view helper, they should
now not be necessary any more, since labels to display in the frontend
can be directly specified in the site configuration.

* [FEATURE] Use IconFactory for displaying flags in language menu

The flag selection for languages in the site configuration of the TYPO3
backend is not directly based on ISO language codes like the
sys_language table was, but instead uses TYPO3 icon identifiers.
To be more compatible with what the backend uses, vhs can also use the
IconFactory to render the flags. This is, however, only performed if the
user has not otherwise specified a path to flags.

Co-authored-by: Claus Due <claus@namelesscoder.net>
  • Loading branch information
yol and NamelessCoder committed Apr 21, 2022
1 parent 69a1335 commit ca9bbe4
Showing 1 changed file with 140 additions and 45 deletions.
185 changes: 140 additions & 45 deletions Classes/ViewHelpers/Page/LanguageMenuViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\LanguageAspect;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Site\Site;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
Expand Down Expand Up @@ -46,6 +50,11 @@ class LanguageMenuViewHelper extends AbstractTagBasedViewHelper
*/
protected $cObj;

/**
* @var \TYPO3\CMS\Core\Site\Site|\TYPO3\CMS\Core\Site\Entity\Site
*/
protected $site;

/**
* Initialize
* @return void
Expand All @@ -68,8 +77,8 @@ public function initializeArguments()
false,
'li'
);
$this->registerArgument('defaultIsoFlag', 'string', 'ISO code of the default flag', false, 'gb');
$this->registerArgument('defaultLanguageLabel', 'string', 'Label for the default language', false, 'English');
$this->registerArgument('defaultIsoFlag', 'string', 'ISO code of the default flag', false);
$this->registerArgument('defaultLanguageLabel', 'string', 'Label for the default language', false);
$this->registerArgument('order', 'mixed', 'Orders the languageIds after this list', false, '');
$this->registerArgument('labelOverwrite', 'mixed', 'Overrides language labels');
$this->registerArgument(
Expand Down Expand Up @@ -126,6 +135,10 @@ public function render()
$this->tagName = $this->arguments['tagName'];
$this->tag->setTagName($this->tagName);

if (class_exists(SiteFinder::class)) {
$this->site = $this->getSite();
$this->defaultLangUid = $this->site->getDefaultLanguage()->getLanguageId();
}
$this->languageMenu = $this->parseLanguageMenu();
$this->renderingContext->getVariableProvider()->add($this->arguments['as'], $this->languageMenu);
$content = $this->renderChildren();
Expand Down Expand Up @@ -190,12 +203,13 @@ protected function getLanguageMenu()
}

/**
* Returns the flag source
* Returns the flag source given the language ISO code
*
* @param string $iso
* @param string $label
* @return string
*/
protected function getLanguageFlagSrc($iso)
protected function getLanguageFlag($iso, $label)
{
if ('' !== $this->arguments['flagPath']) {
$path = trim($this->arguments['flagPath']);
Expand All @@ -204,7 +218,25 @@ protected function getLanguageFlagSrc($iso)
}

$imgType = trim($this->arguments['flagImageType']);
return $path . strtoupper($iso) . '.' . $imgType;
$conf = [
'file' => $path . strtoupper($iso) . '.' . $imgType,
'altText' => $label,
'titleText' => $label
];
return $this->cObj->render($this->cObj->getContentObject('IMAGE'), $conf);
}

/**
* Returns the flag source given a TYPO3 icon identifier
*
* @param string $iso
* @return string
*/
protected function getLanguageFlagByIdentifier($identifier)
{
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$icon = $iconFactory->getIcon($identifier, Icon::SIZE_SMALL);
return $icon->render();
}

/**
Expand All @@ -215,7 +247,7 @@ protected function getLanguageFlagSrc($iso)
*/
protected function getLayout(array $language)
{
$flagImage = false !== stripos($this->arguments['layout'], 'flag') ? $this->getFlagImage($language) : '';
$flagImage = false !== stripos($this->arguments['layout'], 'flag') ? $language['flagCode'] : '';
$label = $language['label'];
switch ($this->arguments['layout']) {
case 'flag':
Expand All @@ -241,22 +273,6 @@ protected function getLayout(array $language)
return $html;
}

/**
* Render the flag image for autorenderer
*
* @param array $language
* @return string
*/
protected function getFlagImage(array $language)
{
$conf = [
'file' => $language['flagSrc'],
'altText' => $language['label'],
'titleText' => $language['label']
];
return $this->cObj->render($this->cObj->getContentObject('IMAGE'), $conf);
}

/**
* Sets all parameter for langMenu
*
Expand All @@ -269,34 +285,23 @@ protected function parseLanguageMenu()
if (!empty($labelOverwrite)) {
$labelOverwrite = GeneralUtility::trimExplode(',', $this->arguments['labelOverwrite']);
}

$languageMenu = [];
// first gather languages into this array so we can reorder it later
$tempArray = [];

$tempArray[0] = [
'label' => $this->arguments['defaultLanguageLabel'],
'flag' => $this->arguments['defaultIsoFlag']
];

$select = 'uid,title,flag';
$from = 'sys_language';
$limitLanguages = static::arrayFromArrayOrTraversableOrCSVStatic($this->arguments['languages'] ?? []);
$limitLanguages = array_filter($limitLanguages);

if (!empty($limitLanguages)) {
$sysLanguage = $GLOBALS['TSFE']->cObj->getRecords($from, ['selectFields' => $select, 'pidInList' => 'root', 'uidInList' => implode(',', $limitLanguages)]);
if (!class_exists(SiteFinder::class)) {
// TYPO3 < 9 legacy
$tempArray = $this->getLanguagesFromSysLanguage($limitLanguages);
} else {
$sysLanguage = $GLOBALS['TSFE']->cObj->getRecords($from, ['selectFields' => $select, 'pidInList' => 'root']);
}

foreach ($sysLanguage as $value) {
$tempArray[$value['uid']] = [
'label' => $value['title'],
'flag' => $value['flag'],
];
// site configuration is available since TYPO3 9 and offers a consolidated and more
// detailed view of the language configuration, so it is preferred
$tempArray = $this->getLanguagesFromSiteConfiguration($limitLanguages);
}

// reorders languageMenu
// reorder languageMenu
$languageMenu = [];
if (false === empty($order)) {
foreach ($order as $value) {
if (isset($tempArray[$value])) {
Expand All @@ -316,6 +321,7 @@ protected function parseLanguageMenu()
}
}

// get the languages actually available on this page
$languageUids = $this->getSystemLanguageUids();

if (class_exists(LanguageAspect::class)) {
Expand All @@ -334,7 +340,16 @@ protected function parseLanguageMenu()
$languageMenu[$key]['current'] = $current;
$languageMenu[$key]['inactive'] = $inactive;
$languageMenu[$key]['url'] = $url;
$languageMenu[$key]['flagSrc'] = $this->getLanguageFlagSrc($value['flag']);
$languageMenu[$key]['flagSrc'] = $this->getLanguageFlag($value['flag'] ?? $value['iso'], $value['label']);
// if the user has set a flag path, always use that over the TYPO3 icon factory so the user
// has the option to use custom flag images based on the ISO code of the language.
// if the user has not set a flag path, prefer the TYPO3 icon factory when an icon
// identifier is available (i.e., when using the site-based language lookup) .
if (isset($value['flagIdentifier']) && empty($this->arguments['flagPath'])) {
$languageMenu[$key]['flagCode'] = $this->getLanguageFlagByIdentifier($value['flagIdentifier']);
} else {
$languageMenu[$key]['flagCode'] = $this->getLanguageFlag($value['flag'] ?? $value['iso'], $value['label']);
}
if (true === (boolean) $this->arguments['hideNotTranslated'] && true === (boolean) $inactive) {
unset($languageMenu[$key]);
}
Expand All @@ -343,6 +358,75 @@ protected function parseLanguageMenu()
return $languageMenu;
}

/**
* Get the list of languages from the sys_language table
*
* @param array $limitLanguages
* @return array
*/
protected function getLanguagesFromSysLanguage(array $limitLanguages)
{
// add default language
$result[0] = [
'label' => $this->arguments['defaultLanguageLabel'] ?? 'English',
'flag' => $this->arguments['defaultIsoFlag'] ?? 'gb'
];

$select = 'uid,title,flag';
$from = 'sys_language';

if (!empty($limitLanguages)) {
$sysLanguage = $GLOBALS['TSFE']->cObj->getRecords($from, ['selectFields' => $select, 'pidInList' => 'root', 'uidInList' => implode(',', $limitLanguages)]);
} else {
$sysLanguage = $GLOBALS['TSFE']->cObj->getRecords($from, ['selectFields' => $select, 'pidInList' => 'root']);
}

foreach ($sysLanguage as $value) {
$result[$value['uid']] = [
'label' => $value['title'],
'flag' => $value['flag'],
];
}

return $result;
}

/**
* Get the list of languages from the site configuration
*
* @param array $limitLanguages
* @return array
*/
protected function getLanguagesFromSiteConfiguration(array $limitLanguages)
{
$siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
$site = $siteFinder->getSiteByPageId($this->getPageUid());
// get only languages set as visible in frontend
$languages = $site->getLanguages();
$defaultLanguage = $site->getDefaultLanguage();

$result = [];
foreach ($languages as $language) {
if (!empty($limitLanguages) && !in_array($language->getLanguageId(), $limitLanguages)) {
continue;
}
$label = $language->getNavigationTitle();
$flag = $language->getFlagIdentifier();
if ($language->getLanguageId() == $defaultLanguage->getLanguageId()) {
// override label/flag of default language if given
$label = $this->arguments['defaultLanguageLabel'] ?? $label;
$flag = $this->arguments['defaultIsoFlag'] ?? $flag;
}
$result[$language->getLanguageId()] = [
'label' => $label,
'iso' => $language->getTwoLetterIsoCode(),
'flagIdentifier' => $flag
];
}

return $result;
}

/**
* Get link of language menu entry
*
Expand Down Expand Up @@ -385,7 +469,18 @@ protected function getPageUid()
}

/**
* Fetches system languages depending on the TYPO3 version.
* Find the site corresponding to the page that the menu is being rendered for
*
* @return Site|\TYPO3\CMS\Core\Site\Entity\Site
*/
protected function getSite()
{
$siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
return $siteFinder->getSiteByPageId($this->getPageUid());
}

/**
* Fetches system languages available on the page depending on the TYPO3 version.
*
* @return int[]
* @see https://docs.typo3.org/typo3cms/extensions/core/Changelog/9.0/Important-82445-MigratePagesLanguageOverlayIntoPages.html
Expand Down

0 comments on commit ca9bbe4

Please sign in to comment.