web-dev-qa-db-fra.com

Comment détecter le langage texte (chaîne de caractères) dans iOS?

Par exemple, étant donné les chaînes suivantes:

let textEN = "The quick brown fox jumps over the lazy dog"
let textES = "El zorro marrón rápido salta sobre el perro perezoso"
let textAR = "الثعلب البني السريع يقفز فوق الكلب الكسول"
let textDE = "Der schnelle braune Fuchs springt über den faulen Hund"

Je veux détecter la langue utilisée dans chacune des chaînes déclarées.

Supposons que la signature de la fonction implémentée est:

func detectedLangauge<T: StringProtocol>(_ forString: T) -> String?

retourne un Facultatif chaîne en cas d'absence de langue détectée.

le résultat approprié serait donc:

let englishDetectedLangauge = detectedLangauge(textEN) // => English
let spanishDetectedLangauge = detectedLangauge(textES) // => Spanish
let arabicDetectedLangauge = detectedLangauge(textAR) // => Arabic
let germanDetectedLangauge = detectedLangauge(textDE) // => German

Y a-t-il une approche facile pour y parvenir?

8
Ahmad F

Réponse rapide:

Depuis iOS 11+, vous pouvez le réaliser en utilisant NSLinguisticTagger . Implémentation de la fonction souhaitée comme ceci:

func detectedLangauge<T: StringProtocol>(_ forString: T) -> String? {
    guard let languageCode = NSLinguisticTagger.dominantLanguage(for: String(forString)) else {
        return nil
    }

    let detectedLangauge = Locale.current.localizedString(forIdentifier: languageCode)

    return detectedLangauge
}

devrait atteindre ce que vous demandez.



Réponse décrite:

Tout d’abord, vous devez savoir que le contenu de votre question concerne principalement le monde de Traitement du langage naturel.

Puisque la PNL est plus que la détection de la langue du texte, le reste de la réponse ne contiendra aucune information spécifique de la PNL.

De toute évidence, la mise en oeuvre d’une telle fonctionnalité n’est pas facile, en particulier lorsque l’on commence à s’intéresser aux détails du processus, tels que la scission en phrases et même en mots, après la reconnaissance des noms et des signes de ponctuation, etc. Je parie que vous penseriez à un processus douloureux! il n’est même pas logique de le faire tout seul "; Heureusement, iOS fait prend en charge la PNL (en fait, les API de la PNL sont disponibles pour toutes les plates-formes Apple, et pas seulement pour iOS) pour faciliter la mise en œuvre de vos objectifs. Le composant principal que vous utiliseriez est NSLinguisticTagger :

Analysez le texte en langage naturel pour baliser une partie de la parole et de la classe lexicale, Identifie des noms, effectue une lemmatisation, détermine le langage et le script .

NSLinguisticTagger fournit une interface uniforme à une variété de fonctionnalités de traitement du langage naturel, avec prise en charge de nombreux langages et scripts différents. Vous pouvez utiliser cette classe pour segmenter Du texte en langage naturel en paragraphes, phrases ou mots, et baliser des informations sur ces segments, telles que partie du discours, classe lexicale, lemme. , script et langue.

Comme indiqué dans la documentation de classe, la méthode que vous recherchez - sous Détermination de la langue dominante et de l'orthographe} section - est dominantLanguage(for:) :

Renvoie la langue dominante pour la chaîne spécifiée.

.

.

Valeur de retour

La balise BCP-47 identifiant la langue dominante de la chaîne, ou la balise "Und" si une langue spécifique ne peut pas être déterminée.

Vous remarquerez peut-être que la NSLinguisticTagger existe depuis le retour à iOS 5. Cependant, la méthode dominantLanguage(for:) est seulement prise en charge pour iOS 11 et versions ultérieures, car elle a été développée au-dessus de Core ML Cadre :

. . .

La ML de base est la base des frameworks spécifiques à un domaine et de la fonctionnalité . La ML de base prend en charge Vision pour l’analyse d’images, Fondation pour le traitement du langage naturel (par exemple, la NSLinguisticTagger classe) , et GameplayKit pour évaluer les arbres de décision appris. Le noyau ML Lui-même s’appuie sur les primitives de bas niveau telles que Accelerate et BNNS, Ainsi que sur les Metal Performance Shaders.

 enter image description here

D'après la valeur renvoyée par l'appel dominantLanguage(for:) en passant "Le renard brun rapide saute par-dessus le chien paresseux":

NSLinguisticTagger.dominantLanguage(for: "The quick brown fox jumps over the lazy dog")

serait "en" chaîne optionnelle. Cependant, jusqu'à présent, ce n'est pas la sortie souhaitée, l'attente est d'obtenir "Anglais" à la place! Eh bien, c'est exactement ce que vous devriez obtenir en appelant le localizedString(forLanguageCode:) method from Locale Structure et en passant le code de langue obtenu:

Locale.current.localizedString(forIdentifier: "en") // English

Mettre tout cela ensemble:

Comme indiqué dans l'extrait de code "Réponse rapide", la fonction serait:

func detectedLangauge<T: StringProtocol>(_ forString: T) -> String? {
    guard let languageCode = NSLinguisticTagger.dominantLanguage(for: String(forString)) else {
        return nil
    }

    let detectedLangauge = Locale.current.localizedString(forIdentifier: languageCode)

    return detectedLangauge
}

Sortie:

Ce serait comme prévu:

let englishDetectedLangauge = detectedLangauge(textEN) // => English
let spanishDetectedLangauge = detectedLangauge(textES) // => Spanish
let arabicDetectedLangauge = detectedLangauge(textAR) // => Arabic
let germanDetectedLangauge = detectedLangauge(textDE) // => German

Notez que:

Il y a encore des cas pour ne pas avoir un nom de langue pour une chaîne donnée, comme:

let textUND = "SdsOE"
let undefinedDetectedLanguage = detectedLangauge(textUND) // => Unknown language

Ou cela pourrait même être nil:

let rabish = "000747322"
let rabishDetectedLanguage = detectedLangauge(rabish) // => nil

Vous trouvez toujours un résultat pas mal pour avoir fourni une sortie utile ...


En outre:

À propos de NSLinguisticTagger:

Bien que je ne vais pas plonger profondément dans l'utilisation de NSLinguisticTagger, je voudrais noter qu'il contient quelques fonctionnalités vraiment intéressantes, qui ne se limitent pas à la simple détection de la langue d'un texte donné; Comme un simple exemple : utiliser le lemme lors de l'énumération des balises serait très utile lorsque vous travaillerez avec Récupération de l'information , car vous seriez capable de reconnaître le mot "moteur" en passant "lecteur" Word.

Ressources officielles

Sessions vidéo Apple :

De plus, pour vous familiariser avec le CoreML:

14
Ahmad F

Vous pouvez utiliser la méthode tagAt de NSLinguisticTagger. Il supporte iOS 5 et versions ultérieures.

func detectLanguage<T: StringProtocol>(for text: T) -> String? {
    let tagger = NSLinguisticTagger.init(tagSchemes: [.language], options: 0)
    tagger.string = String(text)

    guard let languageCode = tagger.tag(at: 0, scheme: .language, tokenRange: nil, sentenceRange: nil) else { return nil }
    return Locale.current.localizedString(forIdentifier: languageCode)
}

detectLanguage(for: "The quick brown fox jumps over the lazy dog")              // English
detectLanguage(for: "El zorro marrón rápido salta sobre el perro perezoso")     // Spanish
detectLanguage(for: "الثعلب البني السريع يقفز فوق الكلب الكسول")                // Arabic
detectLanguage(for: "Der schnelle braune Fuchs springt über den faulen Hund")   // German
2
Max Lebedev

J'ai essayé NSLinguisticTagger avec un texte court comme hello, il reconnaît toujours l'italien. Heureusement, Apple a récemment ajouté NLLanguageRecognizer disponible sur iOS 12, et semble plus précis: D 

import NaturalLanguage

if #available(iOS 12.0, *) {
    let languageRecognizer = NLLanguageRecognizer()
    languageRecognizer.processString(text)
    let code = languageRecognizer.dominantLanguage!.rawValue
    let language = Locale.current.localizedString(forIdentifier: code)
}
0
Tai Le