Есть ли хорошее решение, которое делает эту транслитерацию в хорошей манере?
Я пробовал использовать iconv()
, но очень раздражает, и он не ведет себя так, как можно было бы ожидать.
- Использование
//TRANSLIT
попытается заменить то, что может, оставив все неконвертируемым как "?" - Использование
//IGNORE
не останется "?" в тексте, но также не транслитерирует, а также будет подниматьE_NOTICE
, когда будет найден неконвертируемый char, поэтому вам нужно использовать iconv с подавлением ошибок @ - Использование
//IGNORE//TRANSLIT
(как предлагают некоторые люди в форуме PHP) на самом деле такое же, как//IGNORE
(пробовал сам по php версии 5.3.2 и 5.3.13) - Также использование
//TRANSLIT//IGNORE
аналогично//TRANSLIT
Он также использует текущие настройки языка для транслитерации.
ПРЕДУПРЕЖДЕНИЕ - много текста и кода следует!
Вот несколько примеров:
$text = 'Regular ascii text + čćžšđ + äöüß + éĕěėëȩ + æø€ + $ + ¶ + @';
echo '<br />original: ' . $text;
echo '<br />regular: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text);
//> regular: Regular ascii text + ????? + ???ss + ?????? + ae?EUR + $ + ? + @
setlocale(LC_ALL, 'en_GB');
echo '<br />en_GB: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text);
//> en_GB: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @
setlocale(LC_ALL, 'en_GB.UTF8'); // will this work?
echo '<br />en_GB.UTF8: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text);
//> en_GB.UTF8: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @
Хорошо, это конвертировало č ć š ä ö ü ß é ĕ ě é ë ȩ и æ, но почему бы не đ и ø?
// now specific locales
setlocale(LC_ALL, 'hr_Hr'); // this should fix croatian đ, right?
echo '<br />hr_Hr: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text);
// wrong > hr_Hr: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @
setlocale(LC_ALL, 'sv_SE'); // so this will fix swedish ø?
echo '<br />sv_SE: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text);
// will not > sv_SE: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @
//this is interesting
setlocale(LC_ALL, 'de_DE');
echo '<br />de_DE: ' . iconv("UTF-8", "ASCII//TRANSLIT", $text);
//> de_DE: Regular ascii text + cczs? + aeoeuess + eeeeee + ae?EUR + $ + ? + @
// actually this is what any german would expect since ä ö ü really is same as ae oe ue
Давайте попробуем с помощью //IGNORE
:
echo '<br />ignore: ' . iconv("UTF-8", "ASCII//IGNORE", $text);
//> ignore: Regular ascii text + + + + + $ + + @
//+ E_NOTICE: "Notice: iconv(): Detected an illegal character in input string in /var/www/test.server.web/index.php on line 49"
// with translit?
echo '<br />ignore/translit: ' . iconv("UTF-8", "ASCII//IGNORE//TRANSLIT", $text);
//same as ignore only> ignore/translit: Regular ascii text + + + + + $ + + @
//+ E_NOTICE: "Notice: iconv(): Detected an illegal character in input string in /var/www/test.server.web/index.php on line 54"
// translit/ignore?
echo '<br />translit/ignore: ' . iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", $text);
//same as translit only> translit/ignore: Regular ascii text + cczs? + aouss + eeeeee + ae?EUR + $ + ? + @
Используя решение этого парня также не работает как нужно: Regular ascii text + YYYYY + aous + eYYYeY + aoY + $ + � + @
Даже используя класс PECL intl Normalizer (который не всегда доступен, даже если у вас есть PHP > 5.3.0, поскольку пакет ICU intl может быть недоступен для PHP, то есть на определенных серверах хостинга) создает неправильный результат:
echo '<br />normalize: ' .preg_replace('/\p{Mn}/u', '', Normalizer::normalize($text, Normalizer::FORM_KD));
//>normalize: Regular ascii text + cczsđ + aouß + eeeeee + æø€ + $ + ¶ + @
Итак, есть ли другой способ сделать это правильно или единственное, что нужно сделать, это сделать preg_replace()
или str_replace()
и самостоятельно определить транслитерационные таблицы?
//добавление: Я нашел в дискуссиях ZF wiki с 2008 года о предложение для Zend_Filter_Transliterate, но проект был удален, поскольку на некоторых языках невозможно преобразовать (т.е. китайский), но все же для любого языкового ИМО на латинском и кириллическом языках эта опция должна существовать.