TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Extbase\Utility;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Core\Localization\LanguageServiceFactory;
|
||||
use TYPO3\CMS\Core\Localization\Locale;
|
||||
use TYPO3\CMS\Core\Localization\Locales;
|
||||
use TYPO3\CMS\Core\Localization\TranslationDomainMapper;
|
||||
use TYPO3\CMS\Core\Localization\TranslationDomainResolver;
|
||||
use TYPO3\CMS\Core\TypoScript\FrontendTypoScript;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Mvc\Request;
|
||||
|
||||
/**
|
||||
* Localization helper which should be used to fetch localized labels.
|
||||
*/
|
||||
class LocalizationUtility
|
||||
{
|
||||
/**
|
||||
* Returns the localized label of the LOCAL_LANG key, $key.
|
||||
*
|
||||
* @param string $key The key from the LOCAL_LANG array for which to return the value.
|
||||
* @param string|null $extensionName The name of the extension or domain name (such as "myextension.messages")
|
||||
* @param array|null $arguments The arguments for the label. For sprintf-style labels (e.g., "Downloaded %d times"),
|
||||
* use positional arguments [42]. For ICU MessageFormat labels
|
||||
* (e.g., "{count, plural, one {# file} other {# files}}"), use named arguments ['count' => 42].
|
||||
* @param Locale|string|null $languageKey The language key or null for using the current language from the system
|
||||
* @return string|null The value from LOCAL_LANG or null if no translation was found.
|
||||
*/
|
||||
public static function translate(string $key, ?string $extensionName = null, ?array $arguments = null, Locale|string|null $languageKey = null, ?ServerRequestInterface $request = null): ?string
|
||||
{
|
||||
if ($key === '') {
|
||||
// Early return guard: returns null if the key was empty, because the key may be a dynamic value
|
||||
// (from for example Fluid). Returning null allows null coalescing to a default value when that happens.
|
||||
return null;
|
||||
}
|
||||
|
||||
$languageFilePath = null;
|
||||
if (str_starts_with($key, 'LLL:EXT:')) {
|
||||
$keyParts = explode(':', $key);
|
||||
unset($keyParts[0]);
|
||||
$key = array_pop($keyParts);
|
||||
$languageFilePath = implode(':', $keyParts);
|
||||
} elseif ($extensionName) {
|
||||
if (str_contains($extensionName, '.')) {
|
||||
// We assume this is a valid domain now
|
||||
$languageFilePath = $extensionName;
|
||||
$extensionName = self::getExtensionNameFromDomain($languageFilePath);
|
||||
} else {
|
||||
$languageFilePath = GeneralUtility::camelCaseToLowerCaseUnderscored($extensionName) . '.messages';
|
||||
}
|
||||
} elseif (str_contains($key, ':')) {
|
||||
[$languageFilePath, $key, $extensionName] = self::extractLanguageInfoFromDomainString($key);
|
||||
}
|
||||
if ($languageFilePath === null || $key === '') {
|
||||
throw new \InvalidArgumentException(
|
||||
'Parameter $extensionName cannot be empty if a fully-qualified key is not specified.',
|
||||
1498144052
|
||||
);
|
||||
}
|
||||
$request = $request ?? $GLOBALS['TYPO3_REQUEST'] ?? null;
|
||||
$locale = self::getLocale($languageKey, $request);
|
||||
$languageService = GeneralUtility::makeInstance(LanguageServiceFactory::class)->create($locale);
|
||||
if (!empty($extensionName) && $request instanceof ServerRequestInterface) {
|
||||
$typoScript = $request->getAttribute('frontend.typoscript');
|
||||
if ($typoScript instanceof FrontendTypoScript) {
|
||||
// Loads local-language values by looking for a "locallang.xlf" file in the plugin resources directory and if found includes it.
|
||||
// Locallang values set in the TypoScript property "_LOCAL_LANG" are merged onto the values found in the "locallang.xlf" file.
|
||||
$overrideLabels = $languageService->loadTypoScriptLabelsFromExtension($extensionName, $typoScript, self::getPluginName($request));
|
||||
if ($overrideLabels !== []) {
|
||||
$languageService->overrideLabels($languageFilePath, $overrideLabels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return $languageService->translate($key, $languageFilePath, $arguments ?? []);
|
||||
} catch (\ValueError $e) {
|
||||
return sprintf('Error: could not translate key "%s" with value "%s" and %d argument(s)!', $key, $e->getMessage(), count($arguments));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the currently active locale.
|
||||
* Using the Locales factory, as it handles dependencies (e.g. "de-AT" falls back to "de").
|
||||
*/
|
||||
protected static function getLocale(Locale|string|null $localeOrLanguageKey, ?ServerRequestInterface $request): Locale
|
||||
{
|
||||
if ($localeOrLanguageKey instanceof Locale) {
|
||||
return $localeOrLanguageKey;
|
||||
}
|
||||
$localeFactory = GeneralUtility::makeInstance(Locales::class);
|
||||
if (is_string($localeOrLanguageKey)) {
|
||||
return $localeFactory->createLocale($localeOrLanguageKey);
|
||||
}
|
||||
return $localeFactory->createLocaleFromRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow plugin.tx_myextension._LOCAL_LANG and plugin.tx_myextension_myplugin._LOCAL_LANG
|
||||
*/
|
||||
protected static function getPluginName(?ServerRequestInterface $request): string
|
||||
{
|
||||
if ($request instanceof Request) {
|
||||
return strtolower($request->getPluginName());
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private static function getExtensionNameFromDomain(string $possibleDomain): ?string
|
||||
{
|
||||
[$extensionName, $filePart] = explode('.', $possibleDomain, 2);
|
||||
if ($filePart !== 'messages') {
|
||||
return null;
|
||||
}
|
||||
return $extensionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<?string>
|
||||
*/
|
||||
private static function extractLanguageInfoFromDomainString(string $key): array
|
||||
{
|
||||
$languageFilePath = null;
|
||||
$extensionName = null;
|
||||
|
||||
if (str_starts_with($key, 'LLL:')) {
|
||||
$key = substr($key, 4);
|
||||
}
|
||||
|
||||
[$possibleDomain, $possibleId] = explode(':', $key, 2);
|
||||
$domainMapper = GeneralUtility::makeInstance(TranslationDomainMapper::class);
|
||||
$domainResolver = GeneralUtility::makeInstance(TranslationDomainResolver::class);
|
||||
if ($domainResolver->isValidDomainName($possibleDomain) && $domainMapper->mapDomainToFileName($possibleDomain) !== $possibleDomain) {
|
||||
$languageFilePath = $possibleDomain;
|
||||
$key = trim($possibleId);
|
||||
$extensionName = self::getExtensionNameFromDomain($languageFilePath);
|
||||
}
|
||||
return [
|
||||
$languageFilePath,
|
||||
$key,
|
||||
$extensionName,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user