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
|
||||
=========
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
* Made `AsciiSlugger` fallback to parent locale's symbolsMap
|
||||
|
||||
5.2.0
|
||||
-----
|
||||
|
||||
|
@ -111,6 +111,8 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
|
||||
}
|
||||
|
||||
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;
|
||||
array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) {
|
||||
return $symbolsMap($s, $locale);
|
||||
@ -119,11 +121,22 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
|
||||
|
||||
$unicodeString = (new UnicodeString($string))->ascii($transliterator);
|
||||
|
||||
if (\is_array($this->symbolsMap) && isset($this->symbolsMap[$locale])) {
|
||||
foreach ($this->symbolsMap[$locale] as $char => $replace) {
|
||||
if (\is_array($this->symbolsMap)) {
|
||||
$map = null;
|
||||
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.' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $unicodeString
|
||||
->replaceMatches('/[^A-Za-z0-9]++/', $separator)
|
||||
@ -143,17 +156,28 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
$transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
$slugger = new AsciiSlugger(null, function ($s, $locale) {
|
||||
|
Reference in New Issue
Block a user