Как обрабатывать диакритические знаки (акценты) при переписывании «красивых URL» - PullRequest
19 голосов
/ 21 января 2009

Я переписываю URL, чтобы включить заголовок сгенерированных пользователем блогов.

Я делаю это как для удобства чтения URL, так и для целей SEO.

 http://www.example.com/gallery/280-Gorges_du_Todra/

Первое целое число - это идентификатор, остальное для нас, людей (но не имеет значения для запроса ресурса).

Теперь люди могут писать заголовки, содержащие любой символ UTF-8, но большинство из них не допускаются в URL. Моя аудитория, как правило, говорит по-английски, но, поскольку они путешествуют, им нравится включать такие имена, как

 Aït Ben Haddou

Как правильно перевести это для отображения в URL, используя PHP на Linux.

Пока я видел несколько решений:

  1. просто удалите все недопустимые символы, замените пробелы это имеет странные результаты:
    'Aït Ben Haddou' → /gallery/280-At_Ben_Haddou/
    Не очень полезно.

  2. просто удалите все недопустимые символы, замените пробелы, оставьте charcode (stackoverflow.com), скорее всего из-за используемого 'regex-hammer'
    это дает странные результаты: 'tést tést' → /questions/0000/t233st-t233st

  3. перевести на «ближайший эквивалент»
    'Aït Ben Haddou' → /gallery/280-Ait_Ben_Haddou/
    Но это идет не так для немецкого языка; например, 'ü' должно транслитерироваться 'ue'.

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

Другая проблема с третьим вариантом: как найти все возможные символы, которые можно преобразовать в 7-битный эквивалент?

Так что вопрос:

  1. что, на ваш взгляд, является наиболее желательным результатом. (в пределах технических ограничений)

  2. Как технически это решить. (достичь желаемого результата) с помощью PHP.

Ответы [ 6 ]

16 голосов
/ 21 января 2009

В конечном счете, вам придется отказаться от идеи «правильно» для этой проблемы. Перевод строки, независимо от того, как вы это делаете, разрушает точность во имя совместимости и читабельности. Все три варианта одинаково совместимы, но № 1 и № 2 страдают с точки зрения читабельности. Так что просто бегите с этим и выбирайте то, что выглядит лучше всего - вариант № 3.

Да, переводы неверны для немецкого языка, но если вы не начнете требовать от своих пользователей указывать, на каком языке их названия (и ограничивать их только одним), вы не решите эту проблему без гораздо больших усилий, это стоит (Например, прогон каждого слова в названии через словари для каждого известного языка и перевод диакритических знаков этого слова в соответствии с правилами его языка будет работать , но это излишне.)

В качестве альтернативы, если немецкий язык важнее других языков, сделайте перевод всегда , используйте версию на немецком языке, если она существует: äae, ëe, ïi, öoe, üue.

Edit:

О, а что касается фактического метода, я бы перевел особые случаи, если они есть, через str_replace, затем использовал бы iconv для остальных:

$text = str_replace(array("ä", "ö", "ü", "ß"), array("ae", "oe", "ue", "ss"), $text);
$text = iconv('UTF-8', 'US-ASCII//TRANSLIT', $text);
3 голосов
/ 21 января 2009

Для меня третья наиболее читаема.

Вы можете использовать небольшой словарь, например ï -> i и ü -> ue, чтобы указать, как вы хотите переводить различные charcaters.

1 голос
/ 24 января 2010

Хорошая тема, у меня была такая же проблема некоторое время назад.
Вот как я это исправил:

function title2url($string=null){
 // return if empty
 if(empty($string)) return false;

 // replace spaces by "-"
 // convert accents to html entities
 $string=htmlentities(utf8_decode(str_replace(' ', '-', $string)));

 // remove the accent from the letter
 $string=preg_replace(array('@&([a-zA-Z]){1,2}(acute|grave|circ|tilde|uml|ring|elig|zlig|slash|cedil|strok|lig){1};@', '@&[euro]{1};@'), array('${1}', 'E'), $string);

 // now, everything but alphanumeric and -_ can be removed
 // aso remove double dashes
 $string=preg_replace(array('@[^a-zA-Z0-9\-_]@', '@[\-]{2,}@'), array('', '-'), html_entity_decode($string));
}

Вот как работает моя функция:

  1. Преобразовать его в HTML-сущности
  2. Раздели акценты
  3. Удалить все оставшиеся странные символы
1 голос
/ 21 января 2009

Как примечание, на SO ничего не имеет значения после ID - это ссылка на эту страницу:

Как обрабатывать диакритические знаки (акценты) при переписывании «красивых URL»

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

0 голосов
/ 24 ноября 2014

Это хорошая функция:

function friendlyURL($string) {
    setlocale(LC_CTYPE, 'en_US.UTF8');
    $string = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $string);
    $string = str_replace(' ', '-', $string);
    $string = preg_replace('/\\s+/', '-', $string);
    $string = strtolower($string);
    return $string;
}
0 голосов
/ 21 января 2009

Теперь люди могут писать заголовки, содержащие любой символ UTF-8, но большинство из них не допускаются в URL.

Наоборот, большинство разрешено. Посмотрите, например, URL-адреса Википедии - такие вещи, как http://en.wikipedia.org/wiki/Café (он же http://en.wikipedia.org/wiki/Caf%C3%A9), отображаются красиво - даже если маркер StackOverflow не выбирает их правильно: -)

Хитрость заключается в надежном их чтении в любой среде хостинга; Есть проблемы с CGI и серверами Windows, в частности с IIS, например.

...