使用 HunSpellChecker 类对 UTF-8 文本进行拼写检查


Spell checking UTF-8 text with HunSpellChecker class

我正在尝试使用HunSpellChecker类(见 https://web.archive.org/web/20130311163032/http://www.phpkode.com/source/s/php-spell-checker/php-spell-checker/HunSpellChecker.class.php)和hunspell拼写引擎对字符串进行拼写检查。相关函数复制如下:

public function checkSpelling ($text, $locale, $suggestions = true) {
     
    $text = trim($text);
     
    if ($this->textIsHtml == true) {
        $text = strtr($text, "'n", ' ');
    } elseif ($text == "") {
        $this->spellingWarnings[] = array(self::SPELLING_WARNING__TEXT_EMPTY=>"Text empty");
        return false;
    }
     
    $descspec = array(
                      0=>array('pipe', 'r'),
                      1=>array('pipe', 'w'),
                      2=>array('pipe', 'w')
                );
     
    $pipes = array();
    $cmd  = $this->hunspellPath;
    $cmd .= ($this->textIsHtml) ? " -H ":"";
    $cmd .= " -d ".dirname(__FILE__)."/dictionaries/hunspell/".$locale;
     
    $process = proc_open($cmd, $descspec, $pipes);
     
    if (!is_resource($process)) {
        $this->spellingError[] = array(self::SPELLING_ERROR__INTERNAL_ERROR=>"Hunspell process could not be created.");
        return false;
    }
     
    fwrite($pipes[0], $text);
    fclose($pipes[0]);
     
    $out = '';
    while (!feof($pipes[1])) {
        $out .= fread($pipes[1], 4096);
    }
    fclose($pipes[1]);
     
    // check for errors
    $err = '';
    while (!feof($pipes[2])) {
        $err .= fread($pipes[2], 4096);
    }
    if ($err != '') {
        $this->spellingError[] = array(self::SPELLING_ERROR__INTERNAL_ERROR=>"Spell checking error: ".$err);
        fclose($pipes[2]);
        return false;
    }
    fclose($pipes[2]);
     
    proc_close($process);
     
    if (strlen($out) === 0) {
        $this->spellingError[] = array(self::SPELLING_WARNING__EMPTY_RESULT=>"Empty result");
        return false;
    }
     
    return $this->parseHunspellOutput(explode("'n", $out), $locale, $suggestions);
}

它适用于 ASCII 字符串,但我必须检查不同语言的字符串,这些字符串具有重音字符(necessário、segurança 等)或非拉丁字母(希腊语、阿拉伯语等)。

在这些情况下,问题在于非ASCII单词被错误地分割,并且发送到Hunspell的"拼写错误"单词实际上是一个子字符串而不是完整的单词(必要,seguran)。

我试图跟踪问题发生的位置,我认为当字符串转换为资源(或之后的某个地方)时,它必须在上面链接的类的第 072 行中。072行包含:

fwrite($pipes[0], $text);

该课程没有评论,所以我不太确定那里发生了什么。

有没有人处理过类似的问题,或者有人可以提供任何帮助吗?

该类包含在文件示例/HunspellBased.php(从 http://titirit.users.phpclasses.org/package/5597-PHP-Check-spelling-of-text-and-get-fix-suggestions.html 下载的包)中。我尝试使用Enchant,但我根本无法让它工作。

谢谢!干杯,曼努埃尔

我认为您的问题要么是 HTML 实体,要么是字典文件的问题。

使用从 Mozilla 附加组件下载的葡萄牙语词典尝试您的示例,我只能在使用 HTML 编码实体时重现您的问题。 segurança很好,但segurança如你所说被分割。

我不认为这是班级的问题。该类所做的只是将文本通过管道传输到命令行程序。您可以通过直接使用该程序来消除 PHP 类的问题,如下所示:

根据上面的代码将工作目录更改为拥有字典的位置,php-spell-checker/dictionaries/hunspell。准备一个包含要测试的重音单词的文本文件,然后执行以下操作:

hunspell -l -d pt-PT test.text

或对于 HTML:

hunspell -l -d pt-PT -H test.html

其中pt_PT表示葡萄牙语词典文件对的名称,即pt-PT.affpt–PT.dic

输出意味着无错误。如果您仅在使用 HTML 实体时收到诸如"必要"之类的部分词,那么这就是您的问题。如果不是,那么要么是其他类型的字符串编码问题,要么是您正在使用的字典的问题。

我怀疑这是 hunspell 的 HTML 解析器的一个限制 - 它忽略了 HTML 标签和其他标点符号实体,但不会包含和解码中间有实体的单词。

解决此问题的唯一方法(假设 HTML 是您的问题)是在将 HTML 发送到拼写检查之前进行自己的预处理。PHP 的 html_entity_decode 将转换ç -> ç因此您可以尝试在每个字符串上调用它。理想情况下,尽管您会解析HTML DOM并仅提取文本节点。

如果 HTML 不是您的问题,请检查字符串是否有效 UTF-8。

如果失败,请尝试另一个字典文件。我从Mozilla抓取的那个在纯文本下工作得很好。只需将.xpi文件重命名为.gzip,使用您拥有的任何解压缩软件将其展开,然后将.dic.aff文件复制到字典文件夹中。

我想你可以在之后添加:

$cmd  = $this->hunspellPath;
$cmd .= ($this->textIsHtml) ? " -H ":"";
$cmd .= " -d ".dirname(__FILE__)."/dictionaries/hunspell/".$locale;

$cmd .= " -i UTF-8";