Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE] Add unified Locale class (IETF RFC 5646)
A new locale class is added in order to migrate the code base and the configuration towards real locales in form of RFC 5646 language tag (en-AT) and optional script code ("Hans") and optional country / region based on ISO 3166-1. This unifies handling of locales instead of dealing with "default" or other TYPO3-specific namings in user-land code and configuration. This locale functionality at first serves to handle "label files" (XLF), but will be further extended to also work with the locale to be used in the SiteLanguage object to simplify configuration and Date/Time Formatting based on php-intl. Thus, the first and foremost topic is to allow to create custom "LanguageService" objects out of a defined Locale instead of a string. The locale class contains the actual locale (such as "de-AT" or "en") but also allows to use the backwards-compatibility for the labels internally. It also contains the dependencies, so they do not need to be evaluated in various places and makes the public facing API much easier to understand. Next to the introduction of the Locale object, this patch also adapts various places which touch current LanguageService instantiations to use the Locale. Next Steps: * SiteLanguage.locale should use the object, as Locale uses a \Stringable interface. * Reduce optional settings in Site Language object and editing interface * A new languageService ($GLOBALS[LANG]) could and should be instantiated where it is needed, and not by re-using the same $GLOBALS[LANG] as this is needed This Reduce usages on $GLOBALS[LANG] by building a new LanguageService object based on the Context everywhere. * Ideally deprecate $GLOBALS[LANG] in TYPO3 v12 LTS. Resolves: #99694 Releases: main Change-Id: I9e2464699a2e53f4e3b136e0b66351f9f3aaf71f Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/77558 Tested-by: core-ci <typo3@b13.com> Tested-by: Georg Ringer <georg.ringer@gmail.com> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Georg Ringer <georg.ringer@gmail.com> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
- Loading branch information
1 parent
87a40a0
commit 2412c79
Showing
12 changed files
with
359 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<?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\Core\Localization; | ||
|
||
/** | ||
* A representation of | ||
* language key (based on ISO 639-1 / ISO 639-2) | ||
* - the optional four-letter script code that can follow the language code according to the Unicode ISO 15924 Registry (e.g. HANS in zh_HANS) | ||
* - region / country (based on ISO 3166-1) | ||
* separated with a "-". | ||
* | ||
* This conforms to IETF - RFC 5646 (see https://datatracker.ietf.org/doc/rfc5646/) in a simplified form. | ||
*/ | ||
class Locale implements \Stringable | ||
{ | ||
protected string $locale; | ||
protected string $languageCode; | ||
protected ?string $languageScript = null; | ||
protected ?string $countryCode = null; | ||
|
||
/** | ||
* List of language dependencies for an actual language. This setting is used for local variants of a language | ||
* that depend on their "main" language, like Brazilian Portuguese or Canadian French. | ||
* | ||
* @var array<int, string> | ||
*/ | ||
protected array $dependencies = []; | ||
|
||
public function __construct( | ||
string $locale = 'en', | ||
array $dependencies = [] | ||
) { | ||
$locale = $this->normalize($locale); | ||
if (str_contains($locale, '-')) { | ||
[$this->languageCode, $tail] = explode('-', $locale, 2); | ||
if (str_contains($tail, '-')) { | ||
[$this->languageScript, $this->countryCode] = explode('-', $tail); | ||
} elseif (strlen($tail) === 4) { | ||
$this->languageScript = $tail; | ||
} else { | ||
$this->countryCode = $tail ?: null; | ||
} | ||
$this->languageCode = strtolower($this->languageCode); | ||
$this->languageScript = $this->languageScript ? ucfirst(strtolower($this->languageScript)) : null; | ||
$this->countryCode = $this->countryCode ? strtoupper($this->countryCode) : null; | ||
} else { | ||
$this->languageCode = strtolower($locale); | ||
} | ||
|
||
$this->locale = $this->languageCode . ($this->languageScript ? '-' . $this->languageScript : '') . ($this->countryCode ? '-' . $this->countryCode : ''); | ||
$this->dependencies = array_map(fn ($dep) => $this->normalize($dep), $dependencies); | ||
} | ||
|
||
public function getName(): string | ||
{ | ||
return $this->locale; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getLanguageCode(): string | ||
{ | ||
return $this->languageCode; | ||
} | ||
|
||
public function getLanguageScriptCode(): ?string | ||
{ | ||
return $this->languageScript; | ||
} | ||
|
||
public function getCountryCode(): ?string | ||
{ | ||
return $this->countryCode; | ||
} | ||
|
||
public function getDependencies(): array | ||
{ | ||
return $this->dependencies; | ||
} | ||
|
||
protected function normalize(string $locale): string | ||
{ | ||
if ($locale === 'default') { | ||
return 'en'; | ||
} | ||
if (str_contains($locale, '_')) { | ||
$locale = str_replace('_', '-', $locale); | ||
} | ||
|
||
if (str_contains($locale, '.')) { | ||
[$locale] = explode('.', $locale); | ||
} | ||
return $locale; | ||
} | ||
|
||
public function __toString(): string | ||
{ | ||
return $this->locale; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
...on/Changelog/12.2/Feature-99694-UnifiedLocaleHandlingForTranslationFilesXLF.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
.. include:: /Includes.rst.txt | ||
|
||
.. _feature-99694-1674552209: | ||
|
||
===================================================================== | ||
Feature: #99694 - Unified Locale handling for translation files (XLF) | ||
===================================================================== | ||
|
||
See :issue:`99694` | ||
|
||
Description | ||
=========== | ||
|
||
TYPO3 internally now uses a "locale" format following the IETF RFC 5646 language | ||
tag standard (https://www.rfc-editor.org/rfc/rfc5646.html). | ||
|
||
A locale supported by TYPO3 consists of the following parts (tags and subtags): | ||
* ISO 639-1 / ISO 639-2 compatible Language Key in lower-case (such as "fr" French, or "de" for German) | ||
* optionally the ISO 15924 compatible language script system (4 letter, such as "Hans" as in "zh_Hans") | ||
* optionally the region / country code according to ISO 3166-1 standard in upper camelcase such as "AT" for Austria. | ||
|
||
Examples for a locale string are | ||
* "en" for English | ||
* "pt" for Portuguese | ||
* "da-DK" for Danish as used in Denmark | ||
* "de-CH" for German as used in Switzerland | ||
* "zh-Hans-CN" for Chinese with the simplified script as spoken in China (mainland) | ||
|
||
A new PHP object "Locale" automatically separates each tag and subtag into | ||
these parts. | ||
|
||
The Locale object can now be used to instantiate a new LanguageService object for | ||
translating labels. Previous, TYPO3 used the "default" language key, instead of | ||
the locale "en" to identify the english language. Both are supported, but it is | ||
encouraged to use "en-US" or "en-GB" with the region subtag to identify the chosen | ||
language more precisely. | ||
|
||
|
||
Impact | ||
====== | ||
|
||
Example for using the Locale for creating a "LanguageService" object for translations: | ||
|
||
.. code-block:: php | ||
$languageService = $languageServiceFactory->create(new Locale('de-AT')); | ||
$myTranslatedString = $languageService->sL('LLL:EXT:my_extension/Resources/Private/Language/myfile.xlf:my-label'); | ||
|
||
This is highly recommended, as the wrappers php:`$GLOBALS['LANG']->sL()` and | ||
:php:`$GLOBALS['TSFE']->sL()`will be deprecated in the future. | ||
.. index:: PHP-API, ext:core |
Oops, something went wrong.