Skip to content

Commit

Permalink
Replace iconv with ICU Transliterator
Browse files Browse the repository at this point in the history
  • Loading branch information
ElForastero committed Dec 5, 2018
1 parent f34b764 commit a556232
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 18 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
"require": {
"php": ">=7.1",
"ext-iconv": "*",
"ext-intl": "*",
"illuminate/support": "~5"
},
"require-dev": {
Expand Down
20 changes: 12 additions & 8 deletions src/Map.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
<?php
/**
* Created by PhpStorm.
* User: elforastero
* Date: 12/3/18
* Time: 10:08 PM
*/

namespace ElForastero\Transliterate;
declare(strict_types=1);

namespace ElForastero\Transliterate;

class Map
/**
* Class Map.
* @author Eugene Dzhumak <[email protected]>
* @version 2.0.0
*/
abstract class Map
{
public const LANG_RU = 'ru';
public const LANG_UK = 'uk';

public const DEFAULT = 'common';
public const GOST_7_79_2000 = 'GOST_7.79.2000';
}
34 changes: 33 additions & 1 deletion src/Transliterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace ElForastero\Transliterate;

use \Transliterator as IntlTransliterator;

/**
* Feel free to change it.
* Either by pull request or forking.
Expand All @@ -25,6 +27,12 @@ class Transliterator
*/
private $map;

public function __construct(string $lang = null, string $map = null)
{
$this->lang = $lang;
$this->map = $map;
}

/**
* @param string $lang
* @return Transliterator
Expand Down Expand Up @@ -60,12 +68,36 @@ public function make(string $text): string
$transliterated = str_replace(array_keys($map), array_values($map), $text);

if (config('transliterate.remove_accents', false) === true) {
$transliterated = iconv('UTF-8', 'ASCII//IGNORE//TRANSLIT', $transliterated);
$transliterator = IntlTransliterator::create('Any-Latin; Latin-ASCII');
$transliterated = $transliterator->transliterate($transliterated);
}

return self::applyTransformers($transliterated);
}

/**
* Create a slug by converting and removing all non-ascii characters.
*
* @param string $text
* @return string
*/
public function slugify(string $text): string
{
$map = $this->getMap();
$text = str_replace(array_keys($map), array_values($map), trim($text));

$transliterator = IntlTransliterator::create('Any-Latin; Latin-ASCII; Lower()');

$text = $transliterator->transliterate($text);
$text = str_replace('&', 'and', $text);

return preg_replace(
['/[^\w\s]/', '/\s+/'],
['', '-'],
$text
);
}

/**
* Get map array according to config file.
*
Expand Down
7 changes: 2 additions & 5 deletions src/config/transliterate.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,8 @@
| Remove accents
|--------------------------------------------------------------------------
|
| Try to remove accents from letters already transliterated text.
| This feature uses iconv function, which may doesn't work properly depending
| on the installed libiconv realization.
|
| See http://php.net/manual/ru/intro.iconv.php
| Remove accents from letters using ICU rules.
| E.g. À, Ä, Â, etc. all become A.
|
*/
'remove_accents' => true,
Expand Down
15 changes: 12 additions & 3 deletions tests/TransliterationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace ElForastero\Transliterate\Tests;

use ElForastero\Transliterate\Transliterator;
use ElForastero\Transliterate\Map;

class TransliterationTest extends TestCase
{
Expand All @@ -24,21 +25,29 @@ public function testMake()
$commonResult = 'abvgdeyozhziyklmnoprstufhcchshshhieyuyaABVGDEYoZhZIYKLMNOPRSTUFHCChShShhIEYuYa';
$gost2000Result = 'abvgdeyozhzijklmnoprstufxcchshshh``y\'`e`yuyaABVGDEYoZhZIJKLMNOPRSTUFXCChShShh``Y\'`E`YuYa';

$transliterator = (new Transliterator)->from('ru')->useMap('common');
$transliterator = new Transliterator(Map::LANG_RU, Map::DEFAULT);

$this->assertEquals($commonResult, $transliterator->make($this->initialString));
$this->assertEquals($gost2000Result, $transliterator->useMap('GOST_7.79.2000')->make($this->initialString));
}

public function testSlugify()
{
$initialString = ' Съешь еще этих мягких французских булок, да выпей чаю! & 123';
$expectedString = 'sesh-eshhe-etih-myagkih-francuzskih-bulok-da-vipey-chayu-and-123';

$this->assertEquals($expectedString, (new Transliterator)->slugify($initialString));
}

public function testCustomMap()
{
$transliterator = (new Transliterator)->from('ru')->useMap('test');
$transliterator = (new Transliterator(Map::LANG_RU, 'test'));
$this->assertEquals(str_repeat('a', 66), $transliterator->make($this->initialString));
}

public function testMakeWithInvalidMapName()
{
$this->expectException(\InvalidArgumentException::class);
(new Transliterator)->useMap('non-existent')->make('Test');
(new Transliterator(Map::LANG_RU, 'non-existent'))->make('Test');
}
}

0 comments on commit a556232

Please sign in to comment.