如何将Word中的智能引号和破折号转换为字符串?

25

我有一个表单和一个文本区域。用户输入一些文本,这些文本被存储在数据库中。

偶尔,用户会从Word中粘贴包含智能引号或破折号的文本。这些字符会出现在数据库中,例如:–, ’, “, â€

我应该调用哪个函数来将智能引号转换为普通引号和破折号转换为普通短横线

我在使用PHP。

更新:非常感谢目前为止所有的回复。Joel网站上有关编码的页面非常有启发性:http://www.joelonsoftware.com/articles/Unicode.html

我的环境方面还有一些注意事项:

MySQL数据库使用UTF-8编码。同样,显示内容的HTML页面也使用UTF-8(更新:)通过明确设置meta content-type。

在这些页面中,智能引号和破折号显示为带有问号的菱形。

解决方法:

再次感谢所有的回复。解决方案有两个:

  1. 确保数据库和HTML文件明确设置为使用UTF-8编码。
  2. 使用htmlspecialchars()而不是htmlentities()
13个回答

15

9

MySQL数据库使用UTF-8编码。同样,显示内容的HTML页面也使用UTF-8。

HTML内容确实可以使用UTF-8,但您是否明确将HTML页面(通过PHP生成)的内容类型(编码)设置为UTF-8呢?尝试返回"text/html;charset=utf-8"Content-Type头或在HTML中添加<meta>标签:

<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>

这样,提交给PHP的数据的内容类型也将是相同的。

我遇到了类似的问题,添加<meta>标签对我有用。


4
似乎真正的问题是您的数据库没有使用与页面相同的字符编码(应该是UTF-8)。在这种情况下,如果任何用户提交非ASCII字符,则可能会在数据库中看到奇怪的字符。仅找到并修复其中几个字符(卷曲引号和em短划线)并不能解决真正的问题。以下是有关将数据库迁移到另一种字符编码的信息(至少适用于MySQL数据库)

2

这是一个非常普遍的问题,PHP对字符集的处理非常差,这并没有帮助到我们。

我们需要通过 iconv 来强制转换文本。

// Convert input data to UTF8, ignore any odd (MS Word..) chars
// that don't translate
$input = iconv("ISO-8859-1","UTF-8//IGNORE",$input);
//IGNORE 标志意味着无法翻译的内容将被丢弃。
如果附加字符串 //IGNORE,则无法在目标字符集中表示的字符将被静默丢弃。

1
这似乎是一个完美的“快速修复”,但可悲的是,它实际上使我的测试用例变得更糟,因为它添加了更多无效字符。 - niczak
6
仅在您知道输入字符集为Latin 1时,将其从Latin 1转换为UTF-8才有意义。但如果输入已经是UTF-8,则通过从Latin 1到UTF-8的“翻译”将其再次翻译会使其更加混乱。 - Mark E. Haase

1
如果您想在Web中转义这些字符并“保留”它们的外观,使您的字符串看起来像这样:“It's nice!”而不是"It's boring"......您可以使用自己的自定义htmlEncode函数来代替PHP的htmlentities()
$trans_tbl = false;

function htmlEncode($text) {

  global $trans_tbl;

  // create translation table once
  if(!$trans_tbl) {
    // start with the default set of conversions and add more.

    $trans_tbl = get_html_translation_table(HTML_ENTITIES); 

    $trans_tbl[chr(130)] = '&sbquo;';    // Single Low-9 Quotation Mark
    $trans_tbl[chr(131)] = '&fnof;';    // Latin Small Letter F With Hook
    $trans_tbl[chr(132)] = '&bdquo;';    // Double Low-9 Quotation Mark
    $trans_tbl[chr(133)] = '&hellip;';    // Horizontal Ellipsis
    $trans_tbl[chr(134)] = '&dagger;';    // Dagger
    $trans_tbl[chr(135)] = '&Dagger;';    // Double Dagger
    $trans_tbl[chr(136)] = '&circ;';    // Modifier Letter Circumflex Accent
    $trans_tbl[chr(137)] = '&permil;';    // Per Mille Sign
    $trans_tbl[chr(138)] = '&Scaron;';    // Latin Capital Letter S With Caron
    $trans_tbl[chr(139)] = '&lsaquo;';    // Single Left-Pointing Angle Quotation Mark
    $trans_tbl[chr(140)] = '&OElig;';    // Latin Capital Ligature OE

    // smart single/ double quotes (from MS)
    $trans_tbl[chr(145)] = '&lsquo;'; 
    $trans_tbl[chr(146)] = '&rsquo;'; 
    $trans_tbl[chr(147)] = '&ldquo;'; 
    $trans_tbl[chr(148)] = '&rdquo;'; 

    $trans_tbl[chr(149)] = '&bull;';    // Bullet
    $trans_tbl[chr(150)] = '&ndash;';    // En Dash
    $trans_tbl[chr(151)] = '&mdash;';    // Em Dash
    $trans_tbl[chr(152)] = '&tilde;';    // Small Tilde
    $trans_tbl[chr(153)] = '&trade;';    // Trade Mark Sign
    $trans_tbl[chr(154)] = '&scaron;';    // Latin Small Letter S With Caron
    $trans_tbl[chr(155)] = '&rsaquo;';    // Single Right-Pointing Angle Quotation Mark
    $trans_tbl[chr(156)] = '&oelig;';    // Latin Small Ligature OE
    $trans_tbl[chr(159)] = '&Yuml;';    // Latin Capital Letter Y With Diaeresis

    ksort($trans_tbl);
  }

  // escape HTML      
  return strtr($text, $trans_tbl); 
}

1
实际上,问题不是发生在PHP中,而是发生在JavaScript中,这是由于从Word复制/粘贴导致的,因此您需要在将文本传递给PHP之前解决JavaScript中的问题,请参见此答案https://dev59.com/I1LTa4cB1Zd3GeqPZlYI#6219023

请添加答案的相关部分。 - Robert
@Robert 他说:“我有一个带有文本区域的表单。用户输入一段文本,该文本将存储在数据库中。”,因此我认为这意味着他使用JavaScript将数据从前端(即浏览器)传递到后端(即PHP)。他还说:“从Word粘贴文本”,“在输入字符串上应调用哪个函数”,这意味着在数据进入MySQL之前,使用该解决方案将避免在数据库中出现那些奇怪的字符。 - Billel Hacaine

1
我们通常会使用标准的字符串替换函数来实现这个功能。尽管在ASCII/Unicode的上下文中,它的性质相当模糊,但它确实有效。只要确保你的php文件以正确的编码格式保存即可。

1
根据我的经验,最好接受智能引号并确保在所有地方使用相同的编码。首先,在您的表单标签中添加以下内容:accept-charset="utf-8"

1

这可能不是最好的解决方案,但我建议测试一下看看PHP看到了什么。假设它看到了“-”(还有几种可能性,比如简单的“”或者“&#8220;”)。然后进行str_replace将所有这些字符替换为正常引号,然后再将答案存入数据库。

更好的解决方案可能涉及使端到端的数据传输全部为UTF-8,正如其他答案中人们正试图帮助您的那样。


1

你必须确保你的数据库连接已经配置好,能够接受和提供UTF-8编码的数据给客户端(否则它会转换成“默认”的编码,通常是Latin1)。

实际上,这意味着运行一个查询 SET NAMES 'utf8';

http://www.phpwact.org/php/i18n/utf-8/mysql

另外,智能引号是Windows-1252字符集的一部分,而不是ISO-8859-1(Latin-1)。这与您的问题不太相关,但只是供您参考。欧元符号也在其中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接