Транслит php iconv для удаления акцентов: не работает как исключение?

рассмотрим этот простой код:

echo iconv('UTF-8', 'ASCII//TRANSLIT', 'è');

он печатает

 `e

вместо того, чтобы просто

 e

вы знаете, что я делаю неправильно?


ничего не изменилось после добавления setlocale

setlocale(LC_COLLATE, 'en_US.utf8');
echo iconv('UTF-8', 'ASCII//TRANSLIT', 'è');

person dynamic    schedule 06.02.2011    source источник
comment
Во-первых, это в корне зло и неправильное желание. Во-вторых, единственный разумный подход — преобразовать ваш код в форму нормализации Unicode D, сформированную путем канонической декомпозиции, а затем удалить эти полученные кодовые точки с помощью свойства Mark. Конечно, все это не исправит: Tschüß   -  person tchrist    schedule 06.02.2011
comment
Не обращайте внимания на Криса, это НАСТОЯЩИЙ способ сделать это, я использую его на практике. Единственная ошибка, которую вы допустили, заключается в том, что подкласс локали — setlocale(LC_CTYPE, 'en_US.UTF-8'); -> LC_TYPE, а не _COLLATE. Чусс.   -  person Michał Leon    schedule 19.12.2013
comment
У меня та же проблема - это, конечно, не LC_TYPE..., который генерирует ошибку (по крайней мере, для меня). Я пробовал LC_ALL (так все говорят) - безрезультатно. Я ввожу строку CŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ и получаю CSOEZsoez"YyenuA'A^A~AAAAECE'E^E"EI'I^IID~NO'O^O~O"OOU'U^UU'Yssa'a^a~a"aaaece'e^eei'i^i"id~no'o^o~ooou'u^u"u'y"y   -  person Scott    schedule 16.10.2015


Ответы (7)


У меня есть эта стандартная функция для возврата допустимых строк URL без недопустимых символов URL. Магия, кажется, заключается в строке после комментария //удалить нежелательные символы.

Это взято из документации фреймворка Symfony: http://www.symfony-project.org/jobeet/1_4/Doctrine/en/08, который, в свою очередь, взят из http://php.vrana.cz/vytvoreni-pratelskeho-url.php но я не говорю по-чешски ;-)

function slugify($text)
{
  // replace non letter or digits by -
  $text = preg_replace('#[^\\pL\d]+#u', '-', $text);

  // trim
  $text = trim($text, '-');

  // transliterate
  if (function_exists('iconv'))
  {
    $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
  }

  // lowercase
  $text = strtolower($text);

  // remove unwanted characters
  $text = preg_replace('#[^-\w]+#', '', $text);

  if (empty($text))
  {
    return 'n-a';
  }

  return $text;
}

echo slugify('é'); // --> "e"
person Hidde    schedule 06.02.2011
comment
Я знаю, что мог бы сделать preg_replace таким образом после транслитерации с помощью iconv ... Я только хотел знать, является ли поведение, описанное в моем первом посте, стандартным или iconv может лучше транслитерировать - person dynamic; 06.02.2011
comment
Извините, но почему в preg_replace 2 обратных слэша? не должно быть просто [^\pL\d] ? - person dynamic; 06.02.2012
comment
Как насчет строки plƒtre francin, где f не преобразуется? - person NullPointer; 16.07.2013

cf @tchrist, с расширением INTL php

http://fr2.php.net/manual/en/book.intl.php

preg_replace('/\pM*/u','',normalizer_normalize( $mystring, Normalizer::FORM_D));

eéèêëiîïoöôuùûüaâäÅ Ἥ ŐǟǠ ǺƶƈƉųŪŧȬƀ␢ĦŁȽŦ ƀǖ становится

eeeeeiiiooouuuuaaaA Η OaA AƶƈƉuUŧOƀ␢ĦŁȽŦ ƀu


Как подчеркивает Крист, не все символы Юникода считаются разложимыми:

выдержка из диаграмм Unicode:

U0080.pdf

00CF Ï ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА I С ДИЭРЕЗИСОМ

≡ 0049 I 0308 ¨

NB этот символ «≡» указывает на доступное разложение

00D0 Ð ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА ETH

→ 00F0 ð латинская строчная буква eth

→ 0110 Đ латинская заглавная буква d со штрихом

→ 0189 Ɖ латинская заглавная буква африканская d

декомпозиция недоступна, ИМХО, как ни странно (мы могли бы рассматривать букву D ASCII как приемлемый эквивалент).

U0100.pdf

0110 Đ ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА D С Штрихом

→ 00D0 ì латинская заглавная буква eth

→ 0111 đ латинская строчная буква d со штрихом

→ 0189 Ɖ латинская заглавная буква африканская d

еще более странно: этот идентифицируется как ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА D (со штрихом), но не разлагается как таковой! Возможно, более крутое решение должно заключаться в том, чтобы получить описание юникода для каждого символа и сравнить его с описанием каждого символа ascii (и соответственно заменить). Кто угодно? ;-]

cf http://unicode.org/Public/UNIDATA/UnicodeData.txt

person eleg    schedule 08.08.2012
comment
Это единственный, который работал у меня на ванильном PHP7.2. - person dearsina; 27.06.2019

У меня это происходит с чистым iconv без php. Хитрость заключалась в том, чтобы установить значение среды LANG в en_US.UTF-8 (в моем случае раньше было hu_HU.UTF-8). После того, как он работал, как ожидалось.

person Stone    schedule 01.07.2013

При выполнении транслитерации вы должны убедиться, что ваш LC_COLLATE установлен правильно, иначе будет использоваться POSIX по умолчанию.

Посмотрите на http://uk3.php.net/manual/en/function.setlocale.php

person Michael Parkin    schedule 06.02.2011
comment
тот же результат, что и раньше с setlocale (см. первый пост) - person dynamic; 06.02.2011

У меня возникает соблазн сказать «ничего», хотя это немного выходит за рамки моей компетенции. PHP iconv() печально известен и является источником вдохновения для многих обходных путей, включая

  • переход к системной утилите iconv (Unix и Linux)
  • создание таблицы поиска
  • замена всех акцентированных символов эквивалентом ASCII в качестве этапа предварительной обработки
  • установка LC_COLLATE (которая, кажется, не работает для всех)
  • используйте htmlentities() вместо iconv()

Прочтите комментарии к документации по iconv(), чтобы получить больше вдохновения. (Или сочувствие. Слишком близко, чтобы позвонить.)

person Mike Sherrill 'Cat Recall'    schedule 06.02.2011

Кажется, что стандартный способ справиться с этим — использовать функцию «удаления акцентов», которую вы можете найти в таких библиотеках, как flourish или в CMS. например Wordpress. Iconv, кажется, не может переводить акценты (и это правильно), поскольку это не очень хорошая идея для чего-либо, кроме слагов URL.

person Xeoncross    schedule 28.10.2011

Кажется, это зависит от версии php...


Тестовый пример №1

php -version

PHP 7.0.0RC8 (cli) (построено: 25 ноября 2015 г., 12:36:50) (NTS) Copyright (c) 1997-2015 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998 -2015 Zend Technologies с Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, Zend Technologies

php -r "var_dump(iconv('UTF-8', 'ASCII//TRANSLIT', 'è'));"

string(2) "`e"

Тестовый пример № 2

php -version

PHP 7.0.8-1~dotdeb+8.1 (cli) ( NTS ) Copyright (c) 1997–2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998–2016 Zend Technologies with Zend OPcache v7.0.8-1~dotdeb+8.1, Copyright (c) 1999-2016, Zend Technologies

php -r "var_dump(iconv('UTF-8', 'ASCII//TRANSLIT', 'è'));"

string(1) "e"
person fred727    schedule 01.08.2016