web-dev-qa-db-fra.com

Détecter la langue de la chaîne PHP

En PHP, existe-t-il un moyen de détecter la langue d'une chaîne? Supposons que la chaîne soit au format UTF-8.

29
Beier

Vous ne pouvez pas détecter la langue à partir du type de caractère. Et il n'y a pas de moyen infaillible de le faire.

Avec n'importe quelle méthode, vous ne faites qu'une supposition éclairée. Il y a des maths liés articles disponibles

17
Ólafur Waage

J'ai utilisé le package Text_LanguageDetect pear avec des résultats raisonnables. Il est extrêmement simple à utiliser et dispose d’une base de données modeste en 52 langues. L'inconvénient est que les langues d'Asie orientale ne sont pas détectées.

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);
}

résulte en:

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

Je sais que ceci est un ancien post, mais voici ce que j’ai développé après ne pas avoir trouvé de solution viable.

  • les autres suggestions sont trop lourdes et trop lourdes pour ma situation
  • Je supporte un nombre limité de langues sur mon site web (pour le moment deux: 'en' et 'de' - mais la solution est généralisée pour davantage) 
  • J'ai besoin d'une conjecture plausible sur la langue d'une chaîne générée par l'utilisateur, et j'ai un repli (le paramètre de langue de l'utilisateur). 
  • Donc, je veux une solution avec un minimum de faux positifs - mais je me moque bien de faux négatifs.

La solution utilise les 20 mots les plus courants d'une langue et compte les occurrences de ceux dans la botte de foin. Ensuite, il se contente de comparer les comptes de la première et de la deuxième langue les plus dénombrées. Si le nombre de finalistes est inférieur à 10% du gagnant, le gagnant remporte tout.

Code - Toutes les suggestions d'amélioration de la vitesse sont plus que bienvenues!

    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;
    }
17
Swiss Mister

Vous pouvez le faire entièrement côté client avec API de langage AJAX de Google (maintenant disparu).

Avec l'API de langue AJAX, vous pouvez traduire et détecter la langue de blocs de texte dans une page Web à l'aide de Javascript. En outre, vous pouvez activer la translittération sur n’importe quel champ de texte ou zone de texte de votre page Web. Par exemple, si vous traduisiez en hindi, cette API permettra aux utilisateurs d’épeler phonétiquement les mots hindi en anglais et de les faire apparaître dans le script hindi.

Vous pouvez détecter automatiquement le langage d'une chaîne

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 + "";
  }
});

Et traduisez toute chaîne écrite dans l’un des langues supportées (également disparu)

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

Alors que l'API Google Translate se ferme en tant que service gratuit, vous pouvez essayer cette alternative gratuite, qui remplace l'API Google Translate:

http://detectlanguage.com

7
Laurynas

J'ai essayé la bibliothèque Text_LanguageDetect et les résultats que j'ai obtenus n'étaient pas très bons (par exemple, le texte "test" était identifié en estonien et non en anglais).

Je peux vous recommander d’utiliser l’API Yandex Translate , qui est GRATUIT pour 1 million de caractères pendant 24 heures et jusqu’à 10 millions de caractères par mois . Il prend en charge (selon la documentation) plus de 60 langues.

<?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>";
?>
4
Muzikant

vous pouvez utiliser l'API du service Lnag ID http://langid.net/identify-language-from-api.html

3
Akim Kelar

Text_LanguageDetect Le paquet de poires a donné des résultats catastrophiques: "les appartements de luxe au centre-ville" est détecté comme étant portugais ...

Google API est toujours la meilleure solution, ils accordent 300 $ de crédit gratuit et vous avertissent avant de vous faire payer quoi que ce soit.

Ci-dessous se trouve une fonction très simple qui utilise file_get_contents pour télécharger le langage détecté par l’API, évitant ainsi le téléchargement ou l’installation de bibliothèques, etc.

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"];
 }

Exécuter: 

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

Vous pouvez obtenir votre clé API Google Translate ici: https://console.cloud.google.com/apis/library/translate.googleapis.com/

Ceci est un exemple simple pour les phrases courtes pour vous aider à aller. Pour les applications plus complexes, vous voudrez limiter votre clé API et utiliser la bibliothèque de toute évidence.

2
Robert Sinclair

Vous pouvez probablement utiliser l'API Google Translate pour détecter la langue et le traduire si nécessaire.

2
strager

Vous pouvez voir comment détecter la langue d’une chaîne dans php en utilisant le package Text_LanguageDetect Pear ou en le téléchargeant pour l’utiliser séparément, comme une bibliothèque php classique.

2
adiian

Une approche peut consister à diviser la chaîne d'entrée en mots, puis à rechercher ces mots dans un dictionnaire anglais pour voir combien d'entre eux sont présents. Cette approche a quelques limitations:

  • les noms propres peuvent ne pas être bien traités
  • les fautes d'orthographe peuvent perturber vos recherches
  • des abréviations comme "lol" ou "b4" ne seront pas nécessairement dans le dictionnaire
1
Greg Hewgill

Je prendrais des documents de différentes langues et les référencerais avec Unicode. Vous pouvez ensuite utiliser un raisonnement bayésien pour déterminer la langue à l'aide des seuls caractères Unicode utilisés. Cela séparerait le français de l'anglais ou du russe.

Je ne sais pas exactement quoi d'autre pourrait être fait, sauf de rechercher les mots dans les dictionnaires linguistiques pour déterminer la langue (en utilisant une approche probabiliste similaire).

1
MathGladiator

Soumettez peut-être la chaîne à ce devineur de langue: 

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

1
Andy

essayez d'utiliser ascii encode . J'utilise ce code pour déterminer les langues en ru dans mon projet de bot social

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;  
1
Master-Bunny

Vous pouvez implémenter un module d'Apache Tika avec Java, insérer les résultats dans un fichier txt, une base de données, etc., puis lire le fichier, db, tout ce dont vous avez besoin avec php . pouvez utiliser l'API de Google, mais gardez à l'esprit que vos appels seront limités et que vous ne pourrez envoyer qu'un nombre limité de caractères à l'API. Au moment de la rédaction de cet article, j'avais terminé de tester la version 1 (qui s'avérait moins précise) et la version 2 du laboratoire (après avoir lu qu'il y avait une limite de 100 000 caractères par jour) de l'API.

0
Osvaldo Mercado

J'ai eu de bons résultats avec https://github.com/patrickschur/language-detection et je l'utilise en production:

  • Il utilise des ngrammes dans les langues pour détecter la langue la plus probable (plus votre chaîne est longue/plus il y a de mots, plus elle est précise), ce qui semble être une méthode éprouvée.
  • 110 langues sont prises en charge, mais vous pouvez également limiter le nombre de langues à celles qui vous intéressent.
  • Le formateur et le détecteur de langue peuvent facilement être améliorés/personnalisés. Il utilise la Déclaration universelle des droits de l'homme dans chacune des langues comme base pour détecter une langue. Toutefois, si vous connaissez le type de phrases que vous rencontrez, vous pouvez facilement étendre ou remplacer les textes utilisés dans chaque langue et obtenir rapidement de meilleurs résultats. "Former" cette bibliothèque pour devenir meilleure est facile.
  • Je suggérerais d'augmenter setMaxNgrams (je l'ai défini sur 9000) dans le formateur et de l'exécuter une fois, puis d'utiliser également ce paramètre dans la classe de détecteur de langue. Changer le nombre de ngrams n'est pas très intuitif (j'ai dû regarder dans le code pour savoir comment ça marche), ce qui est un inconvénient, et la valeur par défaut (310) est toujours trop basse à mon avis. Plus de programmes améliorent les devinettes.
  • Comme la bibliothèque est très petite, il était relativement facile de comprendre ce qui se passe et comment la modifier.

Mon utilisation: J'analyse les courriels d'un système de gestion de la relation client pour savoir dans quelle langue un e-mail a été écrit. Par conséquent, l'envoi du texte à un service tiers n'était pas une option. Bien que la Déclaration universelle des droits de l'homme ne soit probablement pas la meilleure base pour classer le langage des courriers électroniques (les courriers électroniques comportant souvent des formules telles que les salutations, qui ne font pas partie de la Déclaration des droits de l'homme), il identifie le langage correct dans 99% cas, s'il y a au moins 5 mots.

Update: j'ai réussi à améliorer la reconnaissance de la langue dans les e-mails à 100% en utilisant la bibliothèque de détection de langue avec les méthodes suivantes:

  • Ajoutez des phrases courantes aux exemples de langues (pertinents), tels que "Salutations", "Meilleures salutations", "Sincèrement". Ces expressions ne sont pas utilisées dans la Déclaration universelle des droits de l'homme. Les phrases couramment utilisées aident beaucoup à la reconnaissance de la langue, en particulier les formules employant souvent mes humains ("Bonjour", "Bonne journée") si vous analysez la communication humaine.
  • Définissez la longueur maximale de ngrammes sur 4 (au lieu de 3 par défaut).
  • Gardez les maxNgrams à 9000 comme auparavant.

Cela rend la bibliothèque un peu plus lente, donc je suggérerais de les utiliser de manière asynchrone si possible et de mesurer les performances. Dans mon cas, c'est plus qu'assez rapide et beaucoup plus précis.

0
iquito