【问题标题】:php iconv translit for removing accents: not working as excepted?用于删除重音的 php iconv translit:不能正常工作?
【发布时间】:2011-02-06 00:14:14
【问题描述】:

考虑一下这个简单的代码:

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

打印出来

 `e

而不仅仅是

 e

你知道我做错了什么吗?


添加 setlocale 后没有任何变化

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

【问题讨论】:

  • 首先,这从根本上来说是一件邪恶且错误的事情。其次,唯一合理的方法是将您的代码渲染为由规范分解形成的 Unicode 规范化形式 D,然后使用 Mark 属性删除这些生成的代码点。当然,它不会“解决”所有问题:Tschüß
  • 忽略tchris,这是这样做的方法,我在实践中使用它。您犯的唯一错误是语言环境“子类”是setlocale(LC_CTYPE, 'en_US.UTF-8'); -> LC_TYPE,而不是_COLLATE。楚斯。
  • 我也遇到了同样的问题 - 当然不是 LC_TYPE... 会产生错误(至少对我而言)。我试过 LC_ALL (这是其他人所说的) - 没有效果。我输入字符串CŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ 并得到CSOEZsoez"YyenuA'A^A~A"AAAECE'E^E"EI'I^I"ID~NO'O^O~O"OOU'U^U"U'Yss@987654330 @e'e^e"ei'i^i"id~no'o^o~o"oou'u^u"u'y"y

标签: php string unicode utf-8 unicode-normalization


【解决方案1】:

我有这个标准函数可以返回没有无效 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"

【讨论】:

  • 我知道我可以在 iconv 音译后做这样的 preg_replace... 我只想知道我的第一篇文章中描述的行为是标准的还是 iconv 可以音译“更好”
  • 抱歉,为什么 preg_replace 中有 2 个反斜杠?不应该只是[^\pL\d]
  • plƒtre francin 字符串中的f 没有被转换怎么办?
【解决方案2】:

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


正如 tchrist 所强调的,并不是所有的 unicode 字符都被认为是可分解的:

从 Unicode 图表中提取:

U0080.pdf

00CF Ï 带有分音符号的拉丁文大写字母 I

≡0049 I 0308¨

注意这个符号 « ≡ » 表示一个可用的分解

00D0 - 拉丁文大写字母 ETH

→ 00F0 ð 拉丁文小写字母 eth

→ 0110 Đ 拉丁文大写字母 d 带笔划

→ 0189Ɖ 拉丁文大写字母非洲 d

没有可用的分解,奇怪的是恕我直言(我们可以将 ASCII 字母 D 视为可接受的等价物)。

U0100.pdf

0110 Đ 带笔划的拉丁文大写字母 D

→ 00D0 Ð 拉丁文大写字母 eth

→ 0111 đ 带笔划的拉丁文小写字母 d

→ 0189Ɖ 拉丁文大写字母非洲 d

更奇怪的是:这个被识别为拉丁大写字母 D(带有笔划),但不能分解!也许更酷的解决方案应该是获取每个字符的 unicode 描述,并将其与每个 ascii 字符的描述进行比较(并相应地替换)。任何人? ;-]

cfhttp://unicode.org/Public/UNIDATA/UnicodeData.txt

【讨论】:

  • 这是唯一对我有用的,在原版 PHP7.2 上。
【解决方案3】:

它发生在我身上,没有 php 的纯 iconv。诀窍是将 LANG 环境值设置为 en_US.UTF-8 (在我的例子中,之前是 hu_HU.UTF-8)。在它按预期工作之后。

【讨论】:

    【解决方案4】:

    好像和php版本有关……


    测试用例 #1

    php -version
    

    PHP 7.0.0RC8 (cli)(构建时间:2015 年 11 月 25 日 12:36:50)(NTS) 版权所有 (c) 1997-2015 PHP 集团 Zend Engine v3.0.0,版权所有 (c) 1998-2015 Zend Technologies 使用 Zend OPcache v7.0.6-dev,版权所有 (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 ) 版权所有 (c) 1997-2016 PHP 集团 Zend Engine v3.0.0,版权所有 (c) 1998-2016 Zend Technologies 使用 Zend OPcache v7.0.8-1~dotdeb+8.1,版权所有 (c) 1999-2016,由 Zend Technologies 提供

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

    【讨论】:

      【解决方案5】:

      在进行音译时,您必须确保您的 LC_COLLATE 设置正确,否则将使用默认的 POSIX。

      http://uk3.php.net/manual/en/function.setlocale.php

      【讨论】:

      • 使用 setlocale 的结果与以前相同,(见第一篇文章)
      【解决方案6】:

      我很想说“没什么”,尽管这有点超出我的专业知识。 PHP 的 iconv() 是臭名昭著的,许多变通方法的灵感,包括

      • 拖放到系统的图标v 实用程序(Unix 和 Linux)
      • 制作查找表
      • 替换所有重音字符 使用 ASCII 等价物作为一种 预处理阶段
      • 设置 LC_COLLATE(这不会 似乎对每个人都有效)
      • 使用 htmlentities() 代替 iconv()

      阅读 iconv() documentation 的 cmets 以获得更多灵感。 (或表示同情。太接近了。)

      【讨论】:

        【解决方案7】:

        似乎处理此问题的标准方法是使用“删除重音”功能,您可以在 flourish 之类的库或 Wordpress 之类的 CMS 中找到该功能。 Iconv 似乎无法翻译口音(这是正确的),因为这对于 URL slug 以外的任何东西都不是一个好主意。

        【讨论】:

          猜你喜欢
          • 2011-04-02
          • 2014-04-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多