Преобразование символов Unicode в эквивалентные символы ASCII

Мне нужно «сгладить» ряд строк Unicode для целей индексации и поиска. Например, мне нужно преобразовать GötheФ€ в ASCII. Последние два символа не имеют близких представлений в ASCII, поэтому их можно полностью отбросить. Итак, что я ожидаю от

echo iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", "GötheФ€");

равно Gothe, но вместо этого выводит Gothe?EUR.

В дополнение к буквам я также хотел бы, чтобы все разнообразие цифр и знаков препинания Unicode, таких как точки, запятые, тире, косые черты и т. д., было заменено их ближайшими аналогами ASCII, что уже делает функция ASCII//TRANSLIT//IGNORE в iconv, но не без создания некоторого мусора для символов Unicode, для которых он не может найти замену ASCII. Я бы хотел, чтобы такие персонажи полностью игнорировались.

Как получить ожидаемый результат? Есть ли лучший способ, возможно, с использованием библиотеки intl?


person Desmond Hume    schedule 11.02.2013    source источник
comment
Возможный обман, удаление диакритических знаков из Unicode: stackoverflow.com/questions/3542717/   -  person Eric Leschinski    schedule 11.02.2013
comment
@EricLeschinski Не только диактрические знаки. Например, есть как минимум 4 символа Юникода для правой косой черты (002F, 0338, 2044, 2215), я хочу, чтобы все они стали 002F.   -  person Desmond Hume    schedule 11.02.2013
comment
Интересно, зачем кому-то нужен ASCII в 2013 году? Используйте UTF-8..   -  person Pavel Radzivilovsky    schedule 12.02.2013


Ответы (1)


Вы выбрали трудную задачу. Лучше попросить пользователя, вводящего символы Unicode, самостоятельно транслитерировать ASCII. Делая это для них, вы расстроите их только тогда, когда они не согласятся с вашей транслитерацией.

Все, что вы делаете, скорее всего, будет раздражать и оскорблять людей, которые придают большое значение диакритическим знакам: http://en.wikipedia.org/wiki/Diacritic

Какую бы стратегию транслитерации вы ни использовали, всем не угодишь, так как разные люди приписывают разным символам разные значения. Транслитерация, которая нравится одному человеку, приведет в ярость другого. Вы не сделаете всех счастливыми, если не позволите всем использовать любые символы в Unicode.

Но жизнь неприятна и обидна, так что поехали:

Этот PHP-код:

function toASCII( $str )
{
    return strtr(utf8_decode($str),
        utf8_decode(
        'ŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ'),
        'SOZsozYYuAAAAAAACEEEEIIIIDNOOOOOOUUUUYsaaaaaaaceeeeiiiionoooooouuuuyy');
}

Приведенная выше функция PHP заменяет каждый символ Unicode в первом параметре utf8_decode и заменяет его соответствующим символом во втором параметре utf8_decode.

Например, Unicode À транслитерируется в ASCII A, а å преобразуется в a. Вам нужно указать это для каждого отдельного символа Unicode, который, по вашему мнению, транслитерируется в символ ASCII. Для остальных удалите их или пропустите через другой алгоритм транслитерации.

Есть еще 95 221 символ, на которые вам придется обратить внимание, и которые могут транслитерироваться в ASCII. Это становится экзистенциальной игрой «Когда A больше не A?». А как насчет клингонских персонажей и знаков дорожной карты, похожих на букву А? Персонаж рыбы выглядит как a. Кто скажет, что есть что?

Это много работы, но если вы очищаете ввод в базу данных, вы должны создать белый список персонажей и заблокировать других варваров, удерживая их у рва, это единственный надежный способ.

person Eric Leschinski    schedule 11.02.2013
comment
Лучшая часть? Строка для перевода начинается с SOZ. - person Quentin Skousen; 14.09.2018