重写“漂亮的 URL”时如何处理变音符号(口音)

Posted

技术标签:

【中文标题】重写“漂亮的 URL”时如何处理变音符号(口音)【英文标题】:How to handle diacritics (accents) when rewriting 'pretty URLs' 【发布时间】:2010-10-02 17:35:57 【问题描述】:

我重写 URL 以包含用户生成的旅游博客的标题。

我这样做是为了 URL 的可读性和 SEO 目的。

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

第一个整数是id,其余的都是给我们人类的(但与请求资源无关)。

现在人们可以编写包含任何 UTF-8 字符的标题,但大多数都不允许在 URL 中。 我的听众一般说英语,但由于他们旅行,他们喜欢包括像

这样的名字 阿伊特·本·哈杜

在 linux 上使用 php 在 URL 中显示的正确翻译方法是什么。

到目前为止,我已经看到了几种解决方案:

    只去掉所有不允许的字符,替换空格 这有奇怪的结果:'Aït Ben Haddou' → /gallery/280-At_Ben_Haddou/ 不是很有帮助。

    只是去掉所有不允许的字符,替换空格,留下字符代码 (***.com) 很可能是因为使用了“正则表达式锤子” 这会产生奇怪的结果: 'tést tést' → /questions/0000/t233st-t233st

    翻译成“最接近的等价物”'Aït Ben Haddou' → /gallery/280-Ait_Ben_Haddou/ 但这对德语来说是错误的。例如'ü'应该音译'ue'。

对我来说,作为一个荷兰人,第三个结果“看起来”最好。 但是我很确定(1)很多人会有不同的意见,(2)在德国的例子中这是完全错误的。

第 3 个选项的另一个问题是:如何找到所有可以转换为 7 位等效字符的可能字符?

所以问题是:

    在您看来,最理想的结果是什么。 (在技术范围内)

    如何从技术上解决它。 (达到预期的结果)用 PHP。

【问题讨论】:

“ü”实际上会写成“ue”。 “oe”是“ö”。 :) IDNA 我知道国际化域名,但它们并没有解决该资源路径的问题,它们的可读性也不是很好 【参考方案1】:

最终,对于这个问题,您将不得不放弃“正确”的想法。无论您如何翻译字符串,都会以兼容性和可读性的名义破坏准确性。所有三个选项都同样兼容,但#1和#2在可读性方面受到影响。因此,只需运行它并选择看起来最好的东西 - 选项 #3。

是的,德语的翻译是错误的,但是除非您开始要求您的用户指定他们的标题所用的语言(并将它们限制为只有一种),否则您不会不费吹灰之力就解决这个问题这是值得的。 (例如,通过字典为每种已知语言运行标题中的每个单词并根据其语言规则翻译该单词的变音符号会工作,但这是过度的。)

或者,如果德语比其他语言更受关注,让您的翻译始终使用德语版本(如果存在):äaeëeïi, öoe, üue.

编辑:

哦,至于实际的方法,我会通过str_replace翻译特殊情况,然后使用iconv进行其余的:

$text = str_replace(array("ä", "ö", "ü", "ß"), array("ae", "oe", "ue", "ss"), $text);
$text = iconv('UTF-8', 'US-ASCII//TRANSLIT', $text);

【讨论】:

一个很好的近似值是指定观众的语言。如果您要为德国读者翻译“Müller”,请使用setlocale(LC_CTYPE, 'de_DE.UTF8'); iconv(...);,它提供“Mueller”,对于美国读者使用setlocale(LC_CTYPE, 'en_US.UTF8'); iconv(...);,它提供“Muller”。【参考方案2】:

对我来说,第三个是最易读的。

你可以使用一个小字典,例如ï -> iü -> ue 指定您希望如何翻译各种字符。

【讨论】:

问题是,法语和德语的翻译不同,更不用说土耳其语或越南语了。 也许使用不同的字典(如果你知道它是哪种语言),或者总是使用最简单的字典,例如ü -> u.【参考方案3】:

作为一个有趣的附注,在 ID 之后似乎没有什么真正重要 - 这是此页面的链接:

How to handle diacritics (accents) when rewriting 'pretty URLs'

显然,这样做的动机是允许在不中断链接的情况下更改标题,您可能也需要考虑该功能。

【讨论】:

我在项目中使用了类似的技术,除非提供的“slug”不匹配,我会自动 301 到正确的“slug”(例如 /questions/465990/why-does -this-link-go-to-the-same-place 将重定向到 /questions/465990/how-to-handle-diacritics-accents-when-rewriting-pretty-urls )。我认为从 SEO 和一般网络标准的角度来看,这通常是可取的:理想情况下,一个资源应该可以从一个或最多几个 URL 访问——而不是 SO 目前允许的数百万个。【参考方案4】:

不错的话题,我前段时间也遇到过同样的问题。 这是我修复它的方法:

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));

这是我的函数的工作原理:

    将其转换为 html 实体 去掉重音 删除所有剩余的奇怪字符

【讨论】:

你可以使用 htmlentities(str_replace(' ', '-', $string), ENT_QUOTES, "UTF-8"));【参考方案5】:

现在人们可以编写包含任何 UTF-8 字符的标题,但大多数都不允许在 URL 中。

相反,大多数都是允许的。参见例如 Wikipedia 的 URL - 像 http://en.wikipedia.org/wiki/Café(又名 http://en.wikipedia.org/wiki/Caf%C3%A9)这样的东西显示得很好 - 即使 *** 的荧光笔没有正确选择它们:-)

诀窍是在任何托管环境中可靠地读取它们; CGI 和 Windows 服务器(尤其是 IIS)存在问题。

【讨论】:

当然,支持是参差不齐的,以至于您的回答甚至提供了一个示例,说明您通常不想这样做的原因——SO 的 URL 识别器在您的 Café 示例中截断了“é”。 我的浏览器 (Safari) 会自动为我执行此操作。我在地址字段中输入的每个 URL 都以 UTF-8 格式发送。 我必须让它与世界各地网吧中的古老计算机兼容。但也许我应该说:老学校的 URL :)【参考方案6】:

这是一个很好的功能:

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;

【讨论】:

以上是关于重写“漂亮的 URL”时如何处理变音符号(口音)的主要内容,如果未能解决你的问题,请参考以下文章

Ruby 超级不敏感的正则表达式将学校名称与口音和其他变音符号匹配

应用关闭时如何处理 UNNotificationAction?

执行 Flux.map() 时如何处理错误

C - 如何避免变音符号/重音敏感问题

调试时如何处理 ClassNotLoadedException?

使用 QNetworkAccessManager 时如何处理代理