cakephp / localized

I18n and L10n related CakePHP code
Other
214 stars 179 forks source link

Add localized slugging #210

Open dereuromark opened 3 years ago

dereuromark commented 3 years ago

I propose

src/Inflector/LocalizedInflector.php src/Inflector/InflectorDe.php

etc as e.g. normal inflection (default cake core) of Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove is invalid for German for example. Refs https://stackoverflow.com/questions/50412085/how-to-make-textslug-convert-german-umlauts-properly

Here one would expect de-ASCII; Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove. We cannot hardcode this into bootstrap however for a multi-language site, as this will kill the others, e.g. Turkish Söğütlü wouldn't be Sogutlu anymore, but Soeguetlue.

So for this we should add localized ones per language - and invoke that based on that language then inside the business logic. Is there a better way to avoid too many classes? Maybe with some simple config instead?

ravage84 commented 3 years ago

:+1: but I would really try to avoid having a class for each locale. Let's try it with a simple config, first.

dereuromark commented 3 years ago

This is the custom file so far that works

<?php

namespace App\Inflector;

use Cake\Utility\Text;

class LocalizedInflector
{
    /**
     * We can move this later into config.
     *
     * @var string[]
     */
    protected static $slugMap = [
        'de' => 'de-ASCII; Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove',
    ];

    /**
     * We can move this later into config.
     *
     * @var string[]
     */
    protected static $normalizeMap = [
        'de' => 'de-ASCII; Any-Latin; Latin-ASCII',
    ];

    /**
     * Transliterate only (removal of accents, but not replacing of e.g. -).
     *
     * @param string $string
     * @param string $code ISO 2 code lowercase
     * @param array $options
     *
     * @return string
     */
    public static function normalize(string $string, string $code, array $options = []): string
    {
        if (isset(static::$normalizeMap[$code])) {
            $options['transliteratorId'] = static::$normalizeMap[$code];
        }

        return Text::transliterate($string, $options['transliteratorId'] ?? null);
    }

    /**
     * Slug using specific language version where possible.
     *
     * @param string $string
     * @param string $code ISO 2 code lowercase
     * @param array $options
     *
     * @return string
     */
    public static function slug(string $string, string $code, array $options = []): string
    {
        if (isset(static::$slugMap[$code])) {
            $options['transliteratorId'] = static::$slugMap[$code];
        }

        return Text::slug($string, $options);
    }

}

We might want to make it non static and allow Configure::read() to merge in any custom project ones. Then this should be fine as is.