feature #39699 [String] Made AsciiSlugger fallback to parent locale's symbolsMap (jontjs)
This PR was merged into the 5.3-dev branch.
Discussion
----------
[String] Made AsciiSlugger fallback to parent locale's symbolsMap
| Q | A
| ------------- | ---
| Branch? | 5.x
| Bug fix? | no
| New feature? | yes
| Deprecations? | no
| Tickets | Fix #39178
| License | MIT
| Doc PR | symfony/symfony-docs#14776
The Slugger already performed a fallback from (e.g.) 'en_GB' to (e.g.) 'en' for the transliterator, this PR adds similar behaviour for the symbols map.
Commits
-------
916a8cfe7e
[String] Make AsciiSlugger fallback to parent locale's symbolsMap
This commit is contained in:
commit
e60721014b
@ -1,6 +1,11 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
5.3
|
||||||
|
---
|
||||||
|
|
||||||
|
* Made `AsciiSlugger` fallback to parent locale's symbolsMap
|
||||||
|
|
||||||
5.2.0
|
5.2.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -111,6 +111,8 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->symbolsMap instanceof \Closure) {
|
if ($this->symbolsMap instanceof \Closure) {
|
||||||
|
// If the symbols map is passed as a closure, there is no need to fallback to the parent locale
|
||||||
|
// as the closure can just provide substitutions for all locales of interest.
|
||||||
$symbolsMap = $this->symbolsMap;
|
$symbolsMap = $this->symbolsMap;
|
||||||
array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) {
|
array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) {
|
||||||
return $symbolsMap($s, $locale);
|
return $symbolsMap($s, $locale);
|
||||||
@ -119,9 +121,20 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
|
|||||||
|
|
||||||
$unicodeString = (new UnicodeString($string))->ascii($transliterator);
|
$unicodeString = (new UnicodeString($string))->ascii($transliterator);
|
||||||
|
|
||||||
if (\is_array($this->symbolsMap) && isset($this->symbolsMap[$locale])) {
|
if (\is_array($this->symbolsMap)) {
|
||||||
foreach ($this->symbolsMap[$locale] as $char => $replace) {
|
$map = null;
|
||||||
$unicodeString = $unicodeString->replace($char, ' '.$replace.' ');
|
if (isset($this->symbolsMap[$locale])) {
|
||||||
|
$map = $this->symbolsMap[$locale];
|
||||||
|
} else {
|
||||||
|
$parent = self::getParentLocale($locale);
|
||||||
|
if ($parent && isset($this->symbolsMap[$parent])) {
|
||||||
|
$map = $this->symbolsMap[$parent];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($map) {
|
||||||
|
foreach ($map as $char => $replace) {
|
||||||
|
$unicodeString = $unicodeString->replace($char, ' '.$replace.' ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,17 +156,28 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Locale not supported and no parent, fallback to any-latin
|
// Locale not supported and no parent, fallback to any-latin
|
||||||
if (false === $str = strrchr($locale, '_')) {
|
if (!$parent = self::getParentLocale($locale)) {
|
||||||
return $this->transliterators[$locale] = null;
|
return $this->transliterators[$locale] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales
|
// Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales
|
||||||
$parent = substr($locale, 0, -\strlen($str));
|
|
||||||
|
|
||||||
if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) {
|
if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) {
|
||||||
$transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
|
$transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null;
|
return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getParentLocale(?string $locale): ?string
|
||||||
|
{
|
||||||
|
if (!$locale) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (false === $str = strrchr($locale, '_')) {
|
||||||
|
// no parent locale
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr($locale, 0, -\strlen($str));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,37 @@ class SluggerTest extends TestCase
|
|||||||
$this->assertSame('yo_y_tu_a_esta_direccion_slug_en_senal_test_es', $slug);
|
$this->assertSame('yo_y_tu_a_esta_direccion_slug_en_senal_test_es', $slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSlugCharReplacementLocaleConstructWithoutSymbolsMap()
|
||||||
|
{
|
||||||
|
$slugger = new AsciiSlugger('en');
|
||||||
|
$slug = (string) $slugger->slug('you & me with this address slug@test.uk', '_');
|
||||||
|
|
||||||
|
$this->assertSame('you_and_me_with_this_address_slug_at_test_uk', $slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSlugCharReplacementParentLocaleConstructWithoutSymbolsMap()
|
||||||
|
{
|
||||||
|
$slugger = new AsciiSlugger('en_GB');
|
||||||
|
$slug = (string) $slugger->slug('you & me with this address slug@test.uk', '_');
|
||||||
|
|
||||||
|
$this->assertSame('you_and_me_with_this_address_slug_at_test_uk', $slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSlugCharReplacementParentLocaleConstruct()
|
||||||
|
{
|
||||||
|
$slugger = new AsciiSlugger('fr_FR', ['fr' => ['&' => 'et', '@' => 'chez']]);
|
||||||
|
$slug = (string) $slugger->slug('toi & moi avec cette adresse slug@test.fr', '_');
|
||||||
|
|
||||||
|
$this->assertSame('toi_et_moi_avec_cette_adresse_slug_chez_test_fr', $slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSlugCharReplacementParentLocaleMethod()
|
||||||
|
{
|
||||||
|
$slugger = new AsciiSlugger(null, ['es' => ['&' => 'y', '@' => 'en senal']]);
|
||||||
|
$slug = (string) $slugger->slug('yo & tu a esta dirección slug@test.es', '_', 'es_ES');
|
||||||
|
$this->assertSame('yo_y_tu_a_esta_direccion_slug_en_senal_test_es', $slug);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSlugClosure()
|
public function testSlugClosure()
|
||||||
{
|
{
|
||||||
$slugger = new AsciiSlugger(null, function ($s, $locale) {
|
$slugger = new AsciiSlugger(null, function ($s, $locale) {
|
||||||
|
Reference in New Issue
Block a user