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

时间:2014-04-05 08:48:09

标签: php unicode utf-8 spell-checking hunspell

我正在尝试使用HunSpellChecker类(请参阅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字符串,但我必须检查不同语言的字符串,这些字符有重音字符(必需,segurança等)或非拉丁字母(希腊语,阿拉伯语等)。

在这些情况下的问题是非ASCII字被错误地分段并且发送给Hunspell的“拼写错误”字实际上是子字符串而不是完整字(必需品,seguran)。

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

  

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

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

是否有人处理类似问题,或者有人可以提供任何帮助?

该类包含在文件examples / HunspellBased.php(从http://titirit.users.phpclasses.org/package/5597-PHP-Check-spelling-of-text-and-get-fix-suggestions.html下载的包)中。我试图使用附魔,但我没有设法让它工作。

谢谢! 干杯,曼努埃尔

2 个答案:

答案 0 :(得分:0)

我认为您的问题是HTML实体或字典文件存在问题。

尝试使用从Mozilla add-ons下载的葡萄牙语词典的示例,我只能在使用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文件复制到您的词典文件夹中。

答案 1 :(得分:0)

我认为你可以添加After:

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

添加

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