在PHP中检测字符串中的语言

时间:2009-09-17 22:06:45

标签: php language-detection

在PHP中,有没有办法检测字符串的语言?假设字符串是UTF-8格式。

17 个答案:

答案 0 :(得分:34)

我使用Text_LanguageDetect pear package得到了一些合理的结果。它使用起来很简单,它有一个适度的52语言数据库。缺点是没有发现东亚语言。

require_once 'Text/LanguageDetect.php';
$l = new Text_LanguageDetect();
$result = $l->detect($text, 4);
if (PEAR::isError($result)) {
    echo $result->getMessage();
} else {
    print_r($result);
}

结果:

Array
(
    [german] => 0.407037037037
    [dutch] => 0.288065843621
    [english] => 0.283333333333
    [danish] => 0.234526748971
)

答案 1 :(得分:17)

您无法从字符类型中检测语言。并且没有万无一失的方法可以做到这一点。

使用任何方法,你只是做了一个有根据的猜测。那里有一些数学相关的articles

答案 2 :(得分:17)

我知道这是一个老帖子,但这是我在找不到任何可行的解决方案之后开发的。

  • 其他建议对我的情况来说太沉重和太麻烦
  • 我在我的网站上支持有限数量的语言(目前两个:'en'和'de' - 但解决方案已推广更多)。
  • 我需要对用户生成的字符串的语言进行合理的猜测,并且我有一个后备(用户的语言设置)。
  • 所以我想要一个最小误报的解决方案 - 但是不要太在意 false negatives

解决方案使用一种语言中最常用的20个单词,计算大海捞针中出现的单词。然后它只比较第一和第二计数语言的计数。如果亚军人数少于获胜者的10%,则获胜者可以全部获胜。

代码 - 欢迎任何有关速度提升的建议!

    function getTextLanguage($text, $default) {
      $supported_languages = array(
          'en',
          'de',
      );
      // German word list
      // from http://wortschatz.uni-leipzig.de/Papers/top100de.txt
      $wordList['de'] = array ('der', 'die', 'und', 'in', 'den', 'von', 
          'zu', 'das', 'mit', 'sich', 'des', 'auf', 'für', 'ist', 'im', 
          'dem', 'nicht', 'ein', 'Die', 'eine');
      // English word list
      // from http://en.wikipedia.org/wiki/Most_common_words_in_English
      $wordList['en'] = array ('the', 'be', 'to', 'of', 'and', 'a', 'in', 
          'that', 'have', 'I', 'it', 'for', 'not', 'on', 'with', 'he', 
          'as', 'you', 'do', 'at');
      // clean out the input string - note we don't have any non-ASCII 
      // characters in the word lists... change this if it is not the 
      // case in your language wordlists!
      $text = preg_replace("/[^A-Za-z]/", ' ', $text);
      // count the occurrences of the most frequent words
      foreach ($supported_languages as $language) {
        $counter[$language]=0;
      }
      for ($i = 0; $i < 20; $i++) {
        foreach ($supported_languages as $language) {
          $counter[$language] = $counter[$language] + 
            // I believe this is way faster than fancy RegEx solutions
            substr_count($text, ' ' .$wordList[$language][$i] . ' ');;
        }
      }
      // get max counter value
      // from http://stackoverflow.com/a/1461363
      $max = max($counter);
      $maxs = array_keys($counter, $max);
      // if there are two winners - fall back to default!
      if (count($maxs) == 1) {
        $winner = $maxs[0];
        $second = 0;
        // get runner-up (second place)
        foreach ($supported_languages as $language) {
          if ($language <> $winner) {
            if ($counter[$language]>$second) {
              $second = $counter[$language];
            }
          }
        }
        // apply arbitrary threshold of 10%
        if (($second / $max) < 0.1) {
          return $winner;
        } 
      }
      return $default;
    }

答案 3 :(得分:15)

您可以使用 Google's AJAX Language API 完成客户端(现已解散)。

  

使用AJAX语言API,您只需使用Javascript即可在网页中翻译和检测文本块的语言。此外,您可以在网页中的任何文本字段或文本区域上启用音译。例如,如果您是音译到印地语,此API将允许用户使用英语在语音上拼写出印地语单词并将其显示在印地语脚本中。

您可以自动检测字符串的语言

var text = "¿Dónde está el baño?";
google.language.detect(text, function(result) {
  if (!result.error) {
    var language = 'unknown';
    for (l in google.language.Languages) {
      if (google.language.Languages[l] == result.language) {
        language = l;
        break;
      }
    }
    var container = document.getElementById("detection");
    container.innerHTML = text + " is: " + language + "";
  }
});

并翻译用 supported languages (也已废弃)中的任何一个字符串

google.language.translate("Hello world", "en", "es", function(result) {
  if (!result.error) {
    var container = document.getElementById("translation");
    container.innerHTML = result.translation;
  }
});

答案 4 :(得分:7)

由于谷歌翻译API将作为免费服务关闭,您可以尝试这种免费替代方案,它取代谷歌翻译API:

http://detectlanguage.com

答案 5 :(得分:4)

我尝试了Text_LanguageDetect库,我得到的结果不是很好(例如,文本“test”被识别为爱沙尼亚语而非英语)。

我建议您尝试Yandex Translate API 免费,每小时播放100万个字符,每月最多1000万个字符。 它支持(根据文档)超过60种语言。

<?php
function identifyLanguage($text)
{
    $baseUrl = "https://translate.yandex.net/api/v1.5/tr.json/detect?key=YOUR_API_KEY";
    $url = $baseUrl . "&text=" . urlencode($text);

    $ch = curl_init($url);

    curl_setopt($ch, CURLOPT_CAINFO, YOUR_CERT_PEM_FILE_LOCATION);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    $output = curl_exec($ch);
    if ($output)
    {
        $outputJson = json_decode($output);
        if ($outputJson->code == 200)
        {
            if (strlen($outputJson->lang) > 0)
            {
                return $outputJson->lang;
            }
        }
    }

    return "unknown";
}

function translateText($text, $targetLang)
{
    $baseUrl = "https://translate.yandex.net/api/v1.5/tr.json/translate?key=YOUR_API_KEY";
    $url = $baseUrl . "&text=" . urlencode($text) . "&lang=" . urlencode($targetLang);

    $ch = curl_init($url);

    curl_setopt($ch, CURLOPT_CAINFO, YOUR_CERT_PEM_FILE_LOCATION);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    $output = curl_exec($ch);
    if ($output)
    {
        $outputJson = json_decode($output);
        if ($outputJson->code == 200)
        {
            if (count($outputJson->text) > 0 && strlen($outputJson->text[0]) > 0)
            {
                return $outputJson->text[0];
            }
        }
    }

    return $text;
}

header("content-type: text/html; charset=UTF-8");

echo identifyLanguage("エクスペリエンス");
echo "<br>";
echo translateText("エクスペリエンス", "en");
echo "<br>";
echo translateText("エクスペリエンス", "es");
echo "<br>";
echo translateText("エクスペリエンス", "zh");
echo "<br>";
echo translateText("エクスペリエンス", "he");
echo "<br>";
echo translateText("エクスペリエンス", "ja");
echo "<br>";
?>

答案 6 :(得分:2)

您可以使用Google Translate API检测语言,并在必要时翻译。

答案 7 :(得分:2)

Text_LanguageDetect梨包产生了可怕的结果:“市中心的豪华公寓”被检测为葡萄牙语......

Google API仍然是最好的解决方案,他们会向您收取300美元的免费赠送金额并在向您收取任何费用之前发出警告

下面是一个超级简单的函数,它使用file_get_contents来下载API检测到的lang,因此无需下载或安装库等。

function guess_lang($str) {

    $str = str_replace(" ", "%20", $str);

    $content = file_get_contents("https://translation.googleapis.com/language/translate/v2/detect?key=YOUR_API_KEY&q=".$str);

    $lang = (json_decode($content, true));

    if(isset($lang))
        return $lang["data"]["detections"][0][0]["language"];
 }

执行:

echo guess_lang("luxury apartments downtown montreal"); // returns "en"

您可以在此处获取Google翻译API密钥:https://console.cloud.google.com/apis/library/translate.googleapis.com/

这是一个简短的短语例子,可以帮助您前进。对于更复杂的应用程序,您需要限制API密钥并明显使用库。

答案 8 :(得分:2)

您可以使用how to detect language for a string in php Pear Package查看Text_LanguageDetect或下载以像常规php库一样单独使用。

答案 9 :(得分:1)

一种方法可能是将输入字符串分解为单词,然后在英语字典中查找这些单词以查看其中有多少单词存在。这种方法有一些限制:

  • 专有名词可能无法妥善处理
  • 拼写错误可能会破坏您的查找
  • 缩写词如“lol”或“b4”不一定在词典中

答案 10 :(得分:1)

我在https://github.com/patrickschur/language-detection上取得了不错的成绩,并将其用于生产中:

  • 它使用语言中的ngram来检测最可能的语言(字符串越长/单词越多,它将越准确)。
  • 支持110种语言,但是您也可以将语言的数量限制为仅对您感兴趣的语言。
  • 培训师和语言检测器可以轻松进行改进/定制。它使用每种语言的《世界人权宣言》作为检测语言的基础,但是,如果您知道遇到的句子类型,则可以轻松地扩展或替换每种语言中使用的文本,并快速获得更好的结果。 “培训”这个库以变得更好很容易。
  • 我建议在Trainer中增加setMaxNgrams(我将其设置为9000)并运行一次,然后在“语言检测器”类中使用该设置。更改ngrams数有点不直观(我必须仔细检查代码以了解其工作原理),这是一个缺点,我认为默认值(310)总是太低。更多的ngram使猜测变得更好。
  • 由于库很小,因此相对容易理解正在发生的事情以及如何对其进行调整。

我的用法:我正在分析CRM系统的电子邮件,以了解电子邮件所用的语言,因此无法将文本发送给第三方服务。尽管《世界人权宣言》可能不是对电子邮件语言进行分类的最佳依据(因为电子邮件通常包含诸如问候语之类的公式化部分,但并非《人权宣言》的一部分),但它却以99%的的情况下,如果其中至少有5个单词。

更新:使用以下方法使用语言检测库时,我设法将电子邮件中的语言识别率提高到基本上100%:

  • 向(相关)语言示例中添加其他常用短语,例如“问候”,“最诚挚的问候”,“真诚的”。 《世界人权宣言》未使用此类表达。常用短语在很大程度上有助于语言识别,尤其是在分析人际交往时经常使用的人类习惯用语(“ Hello”,“祝您今天愉快”)。
  • 将最大ngram长度设置为4(而不是默认值3)。
  • 将maxNgrams保持在9000。

这些确实会使库变慢一些,因此我建议尽可能以异步方式使用它们并评估性能。就我而言,它不仅足够快而且更准确。

答案 11 :(得分:1)

尝试使用ascii编码。 我使用该代码来确定社交机器人项目中的语言

function language($string) {
        $ru = array("208","209","208176","208177","208178","208179","208180","208181","209145","208182","208183","208184","208185","208186","208187","208188","208189","208190","208191","209128","209129","209130","209131","209132","209133","209134","209135","209136","209137","209138","209139","209140","209141","209142","209143");
        $en = array("97","98","99","100","101","102","103","104","105","106","107","108","109","110","111","112","113","114","115","116","117","118","119","120","121","122");
        $htmlcharacters = array("<", ">", "&amp;", "&lt;", "&gt;", "&");
        $string = str_replace($htmlcharacters, "", $string);
        //Strip out the slashes
        $string = stripslashes($string);
        $badthings = array("=", "#", "~", "!", "?", ".", ",", "<", ">", "/", ";", ":", '"', "'", "[", "]", "{", "}", "@", "$", "%", "^", "&", "*", "(", ")", "-", "_", "+", "|", "`");
        $string = str_replace($badthings, "", $string);
        $string = mb_strtolower($string);
        $msgarray = explode(" ", $string);
        $words = count($msgarray);
        $letters = str_split($msgarray[0]);
        $letters = ToAscii($letters[0]);
        $brackets = array("[",",","]");
        $letters = str_replace($brackets,  "", $letters);
        if (in_array($letters, $ru)) {
            $result = 'Русский' ; //russian
        } elseif (in_array($letters, $en)) {
            $result = 'Английский'; //english
        } else {
            $result = 'ошибка' . $letters; //error
        }} return $result;  

答案 12 :(得分:1)

我会从各种语言中获取文档并根据Unicode引用它们。然后,您可以使用一些贝叶斯推理来确定所使用的unicode字符所使用的语言。这将使法语与英语或俄语分离。

我不确定除了查找语言词典中的单词以确定语言之外还能做些什么(使用类似的概率方法)。

答案 13 :(得分:1)

也许将字符串提交给这个语言guesser:

http://www.xrce.xerox.com/competencies/content-analysis/tools/guesser

答案 14 :(得分:0)

您可以使用Java实现Apache Tika模块,将结果插入到txt文件,数据库等中,然后从文件db中读取,无论使用php。 如果您没有那么多内容,可以使用Google的API,但请记住,您的通话将受到限制,并且您只能向API发送有限数量的字符。在撰写本文时,我已经完成了测试版本1(结果证明不是那么准确)和实验室版本2(我读完之后,我每天都有100,000个字符上限)。

答案 15 :(得分:0)

瑞士先生的回答中法语和西班牙语的附加字词:

    // Franch word list
    // from https://1000mostcommonwords.com/1000-most-common-french-words/
    $wordList['fr'] = array ('comme', 'que',  'était',  'pour',  'sur',  'sont',  'avec',
                             'être',  'à',  'un',  'ce',  'par',  'mais',  'que',  'est',
                             'il',  'eu',  'la', 'et', 'dans');

    // Spanish word list
    // from https://spanishforyourjob.com/commonwords/
    $wordList['es'] = array ('que', 'no', 'a', 'la', 'el', 'es', 'y',
                             'en', 'lo', 'un', 'por', 'qué', 'si', 'una',
                             'los', 'con', 'para', 'está', 'eso', 'las');

答案 16 :(得分:0)

我的回答是针对具体情况的。 这是我写的用于查找字符串是否使用特定语言的内容,但有一个条件 - 不同的语言具有不同的字母表。 在我的情况下,单词可以是 3 种语言 - 英语、保加利亚语和希腊语(每种都有不同的字母表)。我需要查找文本是否为保加利亚语,以便稍后将其翻译为希腊语。

class Language {
        protected $bgSymbols = array(
            'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ъ', 'ь', 'ч', 'щ', 'ш', 'ю', 'я',
            'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ъ', 'Ь', 'Ч', 'Щ', 'Ш', 'Ю', 'Я'
        );
        
        public function checkIfForTranslate($string) {
            $result = false;
            $stringArray = array();
            preg_match_all('/./u', $string, $matches);
            if(isset($matches[0])) {
                $stringArray = $matches[0];
            }
            foreach($this->bgSymbols as $symbol) {
                $found = array_search($symbol, $stringArray);
                if($found !== false) {
                    $result = true;
                    break;
                }
            }
            return $result;
        }
    }

希望这能帮助和我有类似情况的人。