【问题标题】:How to detect text (string) language in iOS?如何在 iOS 中检测文本(字符串)语言?
【发布时间】:2018-06-02 02:40:18
【问题描述】:

例如,给定以下字符串:

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 swift nslinguistictagger


    【解决方案1】:

    最新版本(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
    }
    

    详情:

    首先,你应该知道你问的主要是与Natural language processing (NLP)的世界有关。

    由于NLP不仅仅是文本语言检测,剩下的答案将不包含具体的NLP信息。

    显然,实现这样的功能并不容易,尤其是在开始关心过程的细节时,例如拆分成句子甚至单词,然后识别名称和标点符号等...我敢打赌您会认为“多么痛苦的过程!一个人做这件事甚至不合逻辑”;幸运的是,iOS确实支持 NLP(实际上,NLP API 可用于所有 Apple 平台,而不仅仅是 iOS),以使您的目标易于实现。您将使用的核心组件是NSLinguisticTagger

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

    NSLinguisticTagger 为各种 自然语言处理功能,支持许多 不同的语言和脚本。您可以使用此类进行细分 自然语言文本成段落、句子或单词,并标记 有关这些片段的信息,例如词性、词汇 类、引理、脚本和语言。

    如课程文档中所述,您正在寻找的方法 - 在 Determining the Dominant Language and Orthography 部分 - 是 dominantLanguage(for:):

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

    .

    .

    返回值

    BCP-47 标识字符串的主要语言的标签,或者 如果无法确定特定语言,请标记“und”。

    您可能会注意到 NSLinguisticTagger 自 iOS 5 以来就存在。但是,dominantLanguage(for:) 方法支持 iOS 11 及更高版本,这是因为它是在Core ML Framework:

    。 . .

    Core ML 是特定领域框架和 功能。 Core ML 支持 Vision 进行图像分析,Foundation 用于自然语言处理(例如,NSLinguisticTagger class),以及用于评估学习决策树的 GameplayKit。核心机器学习 它本身建立在 Accelerate 和 BNNS 等低级原语之上, 以及金属性能着色器。

    基于调用 dominantLanguage(for:) 的返回值,通过“The quick brown fox jumps over the lazy dog”:

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

    将是“en”可选字符串。但是,到目前为止,这不是所需的输出,而是期望得到“英语”!嗯,这正是你应该通过从Locale 结构调用localizedString(forLanguageCode:) 方法并传递获取的语言代码来得到的:

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

    综合起来:

    如“快速回答”代码 sn-p 中所述,函数为:

    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 的用法,但我想指出,它还有一些非常酷的功能,而不仅仅是简单地检测给定文本的语言;作为一个非常简单的示例:在使用Information retrieval 时,在枚举标签时使用引理 非常有帮助,因为您将能够识别“驾驶”这个词经过“驱动”一词。

    官方资源

    Apple 视频会话

    另外,为了熟悉 CoreML:

    【讨论】:

    • 我想你没有找到可以在服务器上运行的版本?
    • @Burf2000 不。您应该尝试找到一种处理 NLP 的方法,该方法与您的服务器使用的编程语言/框架有关。
    • 对不起,我应该澄清一下,我的意思是运行在 Linux 上的 Swift Server,因为我相信这个框架还没有开源
    • @AhmadF 一句话!它无法检测到文本(字符串)语言,因此它对我不起作用。你能测试一下吗? detectLanguage(for: "Islam")
    • @NazmulHasan 我将通过添加另一种不同的方法来更新我的答案。但是请记住,Islam 将被识别为“土耳其语”。
    【解决方案2】:

    你可以使用 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
    

    【讨论】:

      【解决方案3】:

      我尝试了NSLinguisticTaggerhello 之类的短输入文本,它总是识别为意大利语。 幸运的是,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)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-23
        • 2011-03-16
        • 2011-12-26
        • 1970-01-01
        相关资源
        最近更新 更多