簡體   English   中英

如何在 iOS 中檢測文本(字符串)語言?

[英]How to detect text (string) language in iOS?

例如,給定以下字符串:

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"

我想檢測他們每個人使用的語言。

讓我們假設實現函數的簽名是:

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

如果未檢測到語言,則返回一個可選字符串。

因此,適當的結果是:

let englishDetectedLanguage = detectedLanguage(textEN) // => English
let spanishDetectedLanguage = detectedLanguage(textES) // => Spanish
let arabicDetectedLanguage = detectedLanguage(textAR) // => Arabic
let germanDetectedLanguage = detectedLanguage(textDE) // => German

有沒有簡單的方法來實現它?

最新版本(iOS 12+)

簡而言之:

您可以通過使用NLlanguageRecognizer來實現它,如下所示:

import NaturalLanguage

func detectedLanguage(for string: String) -> String? {
    let recognizer = NLLanguageRecognizer()
    recognizer.processString(string)
    guard let languageCode = recognizer.dominantLanguage?.rawValue else { return nil }
    let detectedLanguage = Locale.current.localizedString(forIdentifier: languageCode)
    return detectedLanguage
}

舊版本(iOS 11+)

簡而言之:

您可以通過使用NSLinguisticTagger來實現它,如下所示:

func detectedLanguage<T: StringProtocol>(for string: T) -> String? {
    let recognizer = NLLanguageRecognizer()
    recognizer.processString(String(string))
    guard let languageCode = recognizer.dominantLanguage?.rawValue else { return nil }
    let detectedLanguage = Locale.current.localizedString(forIdentifier: languageCode)
    return detectedLanguage
}

細節:

首先,你應該知道你問的是什么主要與 自然語言處理(NLP)世界有關。

由於 NLP 不僅僅是文本語言檢測,因此答案的其余部分將不包含特定的 NLP 信息。

顯然,實現這樣的功能並不是那么容易,尤其是當開始關心過程的細節時,例如拆分成句子甚至拆分成單詞,然后識別名稱和標點符號等......我敢打賭你會想到“什么一個痛苦的過程!我自己做這件事甚至不合邏輯”; 幸運的是,iOS確實支持 NLP(實際上,NLP API 可用於所有 Apple 平台,不僅僅是 iOS),使您的目標易於實現。 您將使用的核心組件是NSLinguisticTagger

分析自然語言文本以標記詞性和詞匯類別、識別名稱、執行詞形還原以及確定語言和腳本。

NSLinguisticTagger為各種自然語言處理功能提供了統一的接口,並支持許多不同的語言和腳本。 您可以使用此類將自然語言文本分割為段落、句子或單詞,並標記有關這些段的信息,例如詞性、詞匯類、引理、腳本和語言。

如類文檔中所述,您正在尋找的方法 - 在確定主導語言和正字法部分下 - 是dominantLanguage(for:)

返回指定字符串的主要語言。

.

.

返回值

BCP-47標簽標識字符串的主要語言,如果無法確定特定語言,則使用標簽“und”。

您可能會注意到NSLinguisticTagger是從 iOS 5 NSLinguisticTagger就存在的。 但是,在 iOS 11 及更高版本上支持dominantLanguage(for:)方法,這是因為它是在Core ML Framework之上開發的:

. . .

Core ML 是特定領域框架和功能的基礎。 Core ML 支持用於圖像分析的 Vision、用於自然語言處理的Foundation (例如NSLinguisticTagger類)和用於評估學習決策樹的 GameplayKit。 Core ML 本身建立在 Accelerate 和 BNNS 等低級原語以及 Metal Performance Shaders 之上。

在此處輸入圖片說明

基於通過傳遞“The quick brown fox jumps over the lazy dog”調用dominantLanguage(for:)的返回值:

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

將是“en”可選字符串。 但是,到目前為止,這不是所需的輸出,而是期望得到“英語”! 好吧,這正是您應該通過從Locale Structure 調用localizedString(forLanguageCode:)方法並傳遞獲得的語言代碼來獲得的:

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

放在一起:

如“快速回答”代碼片段中所述,該函數將是:

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

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

    return detectedLanguage
}

輸出:

它會如預期的那樣:

let englishDetectedLanguage = detectedLanguage(textEN) // => English
let spanishDetectedLanguage = detectedLanguage(textES) // => Spanish
let arabicDetectedLanguage = detectedLanguage(textAR) // => Arabic
let germanDetectedLanguage = detectedLanguage(textDE) // => German

請注意:

仍然存在無法獲取給定字符串的語言名稱的情況,例如:

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

或者它甚至可能nil

let rubbish = "000747322"
let rubbishDetectedLanguage = detectedLanguage(rubbish) // => nil

仍然發現提供有用的輸出是一個不錯的結果......


此外:

關於 NSLinguisticTagger:

雖然我不會深入研究NSLinguisticTagger用法,但我想指出,它存在一些非常酷的功能,而不僅僅是簡單地檢測給定文本的語言; 作為一個非常簡單的例子:在枚舉標簽時使用引理在使用信息檢索時非常有用,因為您將能夠識別“駕駛”這個詞通過“駕駛”這個詞。

官方資源

蘋果視頻會議

此外,為了熟悉 CoreML:

您可以使用 NSLinguisticTagger 的 tagAt 方法。 它支持 iOS 5 及更高版本。

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

我用像hello這樣的短輸入文本嘗試了NSLinguisticTagger ,它總是識別為意大利語。 幸運的是,Apple 最近在 iOS 12 上添加了NLLanguageRecognizer ,而且似乎更准確: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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM