如何检测iOS中的文本(string)语言?

例如,给出以下string:

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" 

我想在每个声明的string中检测使用的语言。

假设实现函数的签名是:

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

在没有检测到语言的情况下返回可选string。

因此适当的结果是:

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

有一个简单的方法来实现它?

快速回答:

由于iOS 11+,你可以通过使用NSLinguisticTagger来实现它。 像这样实现所需的function:

 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 } 

应该达到你要求的。


形容答案:

首先,你应该知道你在问什么主要涉及到自然语言处理(NLP)的世界。

由于NLP不仅仅是文本语言检测,其余的答案将不包含特定的NLP信息。

显然,实现这样的function并不是那么容易,特别是当开始关心过程的细节时,例如分解成句子甚至是文字,在识别名字和标点等之后……我敢打赌你会想到“什么一个痛苦的过程!我自己做这件事甚至是不合逻辑的。 幸运的是,iOS 确实支持NLP(实际上,NLP API可用于所有的苹果平台,不仅仅是iOS),使您能够轻松实现目标。 你将使用的核心组件是NSLinguisticTagger

分析自然语言文本来标记词类和词汇类,识别名称,执行词形化,并确定语言和脚本。

NSLinguisticTagger为各种自然语言处理function提供了一个统一的接口,支持许多不同的语言和脚本。 您可以使用这个类将自然语言文本分割成段落,句子或单词,并标记关于这些分段的信息,如词性,词法类,引理,脚本和语言。

正如在类文档中提到的,您正在寻找的方法 – 在决定主导语言和正字法部分 – 是dominantLanguage(for:) 地位的语言 dominantLanguage(for:)

返回指定string的主要语言。

返回值

识别string的主要语言的BCP-47标签,或者如果特定语言不能被确定,则标签“und”。

您可能会注意到,自从回到iOS 5以来, NSLinguisticTagger已经存在。但是, 在iOS 11及更高版本中支持dominantLanguage(for:)方法,这是因为它是在Core ML Framework之上开发的:

。 。 。

核心ML是领域特定框架和function的基础。 Core ML支持用于图像分析的Vision, 自然语言处理基础(例如NSLinguisticTagger 类)和用于评估学习决策树的GameplayKit。 核心ML本身build立在像Accelerate和BNNS这样的低级基元之上,以及金属性能着色器。

在这里输入图像说明

根据调用dominantLanguage(for:)的返回值,通过传递“快速棕色狐狸跳过懒狗”:

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

将是“en”可选string。 然而,到目前为止,这不是所需的输出,例外是取而代之的是“英语”! 那么,这正是你应该通过从语言环境结构中调用localizedString(forLanguageCode:)方法并传递获得的语言代码来获得的:

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

放在一起:

正如在“快速回答”代码片段中提到的,该function将是:

 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 } 

输出:

这将如预期的那样:

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

注意:

还有一些情况是没有为给定的string获取语言名称,如:

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

或者甚至可以是nil

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

仍然发现它提供了一个有用的输出一个不错的结果…

此外:

关于NSLinguisticTagger:

尽pipe我不打算深入研究NSLinguisticTagger用法,但是我想指出的是,其中存在一些非常酷的function,而不仅仅是检测给定文本的语言; 作为一个非常简单的例子 :枚举标签时使用引理在使用信息检索时非常有用,因为您将能够识别传递“驱动”字的“驱动”一词。

官方资源

苹果video会议

  • 有关自然语言处理和NSLinguisticTagger如何工作的更多信息: 自然语言处理和您的应用程序 。

另外,为了熟悉CoreML:

  • 介绍核心ML 。
  • 核心ML深入 。