繁体   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