Skip to content

Commit

Permalink
Breaking changes: Languages are used for Domain Models and must be ma…
Browse files Browse the repository at this point in the history
…pped in TypoScript

- A mapping for each used language must be defined in `plugin.tx_rest.settings.languages`
- System language is respected for Extbase Domain Models
  • Loading branch information
cundd committed Aug 22, 2019
1 parent 94780af commit 6848078
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 51 deletions.
10 changes: 10 additions & 0 deletions Classes/Bootstrap/Language/Exception/InvalidLanguageException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace Cundd\Rest\Bootstrap\Language\Exception;

use RuntimeException;

class InvalidLanguageException extends RuntimeException
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);

namespace Cundd\Rest\Bootstrap\Language\Exception;

class MissingLanguageCodeException extends InvalidLanguageException
{
}
56 changes: 56 additions & 0 deletions Classes/Bootstrap/Language/LanguageInformation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
declare(strict_types=1);

namespace Cundd\Rest\Bootstrap\Language;

use Cundd\Rest\Bootstrap\Language\Exception\MissingLanguageCodeException;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;

class LanguageInformation
{
/**
* @var int
*/
private $uid;

/**
* @var string
*/
private $code;

/**
* LanguageInformation constructor.
*
* @param int $uid
* @param string $code
*/
public function __construct(int $uid, ?string $code)
{
$this->uid = $uid;
if (!$code) {
throw new MissingLanguageCodeException('Two Letter ISO Code must be given');
}
$this->code = $code;
}

public static function fromSiteLanguage(SiteLanguage $siteLanguage): self
{
return new static($siteLanguage->getLanguageId(), $siteLanguage->getTwoLetterIsoCode());
}

/**
* @return int
*/
public function getUid(): int
{
return $this->uid;
}

/**
* @return string
*/
public function getCode(): string
{
return $this->code;
}
}
117 changes: 75 additions & 42 deletions Classes/Bootstrap/LanguageBootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Cundd\Rest\Bootstrap;

use Cundd\Rest\Bootstrap\Language\LanguageInformation;
use Cundd\Rest\Exception\InvalidLanguageException;
use Cundd\Rest\ObjectManagerInterface;
use Psr\Http\Message\ServerRequestInterface;
Expand All @@ -29,6 +30,20 @@ public function __construct(ObjectManagerInterface $objectManager)
$this->objectManager = $objectManager;
}

/**
* Initialize language object
*
* @param ServerRequestInterface $request
*/
public function initializeLanguageObject(ServerRequestInterface $request)
{
if (!isset($GLOBALS['LANG']) || !is_object($GLOBALS['LANG'])) {
/** @var LanguageService $GLOBALS ['LANG'] */
$GLOBALS['LANG'] = GeneralUtility::makeInstance(LanguageService::class);
$GLOBALS['LANG']->init($this->getRequestedPrimaryLanguageCode($request));
}
}

/**
* Initialize the language settings
*
Expand All @@ -40,30 +55,36 @@ public function initializeFrontendController(
TypoScriptFrontendController $frontendController,
ServerRequestInterface $request
) {
$this->detectAndSetRequestedLanguage($frontendController, $request);
$requestedLanguage = $this->detectRequestedLanguage($frontendController, $request);

$this->setRequestedLanguage($frontendController, $requestedLanguage);

return $frontendController;
}

/**
* Configure the system to use the requested language
* Detect the requested language
*
* @param TypoScriptFrontendController $frontendController
* @param ServerRequestInterface $request
* @return LanguageInformation
*/
private function detectAndSetRequestedLanguage(
private function detectRequestedLanguage(
TypoScriptFrontendController $frontendController,
ServerRequestInterface $request
) {
): ?LanguageInformation {
$requestedLanguageUid = $this->getRequestedLanguageUid($frontendController, $request);
if (!class_exists(SiteMatcher::class)) {
$this->setRequestedLanguage(
$frontendController,
$requestedLanguageUid,
null
);

return;
// TYPO3 v8
if (!class_exists(SiteMatcher::class)) {
if ($requestedLanguageUid) {
return new LanguageInformation(
$requestedLanguageUid,
$this->getLanguageCodeForId($frontendController, $requestedLanguageUid)
);
} else {
return null;
}
}

// support new TYPO3 v9.2 Site Handling until middleware concept is implemented
Expand All @@ -89,17 +110,14 @@ private function detectAndSetRequestedLanguage(

// Set language if defined
if ($language && $language->getLanguageId() !== null) {
$this->setRequestedLanguage(
$frontendController,
$language->getLanguageId(),
$language->getTwoLetterIsoCode()
);
} else {
$this->setRequestedLanguage(
$frontendController,
return LanguageInformation::fromSiteLanguage($language);
} elseif ($requestedLanguageUid) {
return new LanguageInformation(
$requestedLanguageUid,
$this->getRequestedPrimaryLanguageCode($patchedRequest)
$this->getLanguageCodeForId($frontendController, $requestedLanguageUid)
);
} else {
return null;
}
}

Expand Down Expand Up @@ -171,6 +189,8 @@ private function getRequestedLanguageUid(
}

/**
* Look up the TypoScript configuration for the language UID for the given language code
*
* @param TypoScriptFrontendController $frontendController
* @param string $languageCode
* @return int
Expand All @@ -193,6 +213,31 @@ private function getLanguageIdForCode(TypoScriptFrontendController $frontendCont
}
}

/**
* Look up the TypoScript configuration for the language code matching the given language UID
*
* Reverse lookup for `getLanguageIdForCode()`
*
* @param TypoScriptFrontendController $frontendController
* @param int $languageUid
* @return string|null
*/
private function getLanguageCodeForId(TypoScriptFrontendController $frontendController, int $languageUid): ?string
{
$languages = $this->readConfigurationFromTyposcript(
'plugin.tx_rest.settings.languages',
$frontendController
);

foreach ($languages as $code => $uid) {
if (is_numeric($uid) && (int)$uid === $languageUid) {
return $code;
}
}

return null;
}

/**
* Retrieve the TypoScript configuration for the given key path
*
Expand Down Expand Up @@ -235,7 +280,7 @@ private function getRequestedPrimaryLanguageCode(ServerRequestInterface $request

if (class_exists('Locale')) {
/** @noinspection PhpComposerExtensionStubsInspection PhpFullyQualifiedNameUsageInspection */
return \Locale::getPrimaryLanguage(\Locale::acceptFromHttp($headerValue));
return \Locale::getPrimaryLanguage((string)\Locale::acceptFromHttp($headerValue));
}

if (preg_match('/^[a-z]{2}/', $headerValue, $matches)) {
Expand All @@ -247,35 +292,23 @@ private function getRequestedPrimaryLanguageCode(ServerRequestInterface $request

/**
* @param TypoScriptFrontendController $frontendController
* @param int|null $requestedLanguageUid
* @param string|null $requestedLanguageCode
* @param LanguageInformation|null $languageInformation
*/
private function setRequestedLanguage(
TypoScriptFrontendController $frontendController,
?int $requestedLanguageUid,
?string $requestedLanguageCode
?LanguageInformation $languageInformation
): void {
if (null !== $requestedLanguageUid) {
$frontendController->config['config']['sys_language_uid'] = $requestedLanguageUid;
if (null !== $languageInformation) {
$frontendController->config['config']['sys_language_uid'] = $languageInformation->getUid();
// Add LinkVars and language to work with correct localized labels
$frontendController->config['config']['linkVars'] = 'L(int)';
$frontendController->config['config']['language'] = $requestedLanguageCode;
$frontendController->config['config']['language'] = $languageInformation->getCode();
}

$frontendController->settingLocale();
}

/**
* Initialize language object
*
* @param ServerRequestInterface $request
*/
public function initializeLanguageObject(ServerRequestInterface $request)
{
if (!isset($GLOBALS['LANG']) || !is_object($GLOBALS['LANG'])) {
/** @var LanguageService $GLOBALS ['LANG'] */
$GLOBALS['LANG'] = GeneralUtility::makeInstance(LanguageService::class);
$GLOBALS['LANG']->init($this->getRequestedPrimaryLanguageCode($request));
// Invoke the internal method to initialize the language system
if (is_callable([$frontendController, 'settingLanguage'])) {
$frontendController->settingLanguage();
}
$frontendController->settingLocale();
}
}
22 changes: 13 additions & 9 deletions Documentation/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,17 @@ Internationalization and localization

The extension supports different types to handle localized requests.

- Since version `3.6.0` TYPO3's site handling is supported
- Specify the `L` `GET`-parameter
- Specify a `Accept-Language` header and define a mapping from the header value to the sys-language UID in TypoScript
```typo3_typoscript
plugin.tx_rest.settings {
languages {
de-DE = 1
}
All languages must be registered in the language map:

```typo3_typoscript
plugin.tx_rest.settings {
languages {
en = 0
de = 1
}
```
}
```

- Since version `3.6.0` TYPO3's site handling is supported
- Specify the `GET`-parameter `L` with the language UID
- Specify a `Accept-Language` header

0 comments on commit 6848078

Please sign in to comment.