Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

285
Views
How to split string as English and non English using Swift 4?

I have a string which contains English and Arabic together. I am using an API, that is why I cannot set an indicator in it.

What I want to get is: the Arabic and English split into tow parts. Here is a sample String:

"بِاسْمِكَ رَبِّي وَضَعْتُ جَنْبِي، وَبِكَ أَرْفَعُهُ، فَإِنْ أَمْسَكْتَ نَفْسِي فَارْحَمْهَا، وَإِنْ أَرْسَلْتَهَا فَاحْفَظْهَا، بِمَا تَحْفَظُ بِهِ عِبَادَكَ الصَّالِحِينَ.Bismika rabbee wadaAAtu janbee wabika arfaAAuh, fa-in amsakta nafsee farhamha, wa-in arsaltaha fahfathha bima tahfathu bihi AAibadakas-saliheen. In Your name my Lord, I lie down and in Your name I rise, so if You should take my soul then have mercy upon it, and if You should return my soul then protect it in the manner You do so with Your righteous servants.",

I cannot find how to split it into 2 parts that I get Arabic and English into two different parts.

What I want:

so there can be any language, my problem is to only take out English or Arabic language and show them in respective fields.

How can I achieve it?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

You can use a Natural Language Tagger, which would work even if both scripts are intermingled:

import NaturalLanguage

let str = "¿como? بداية start وسط middle начать средний конец نهاية end. 從中間開始. "

let tagger = NLTagger(tagSchemes: [.script])

tagger.string = str

var index = str.startIndex
var dictionary = [String: String]()
var lastScript = "other"


while index < str.endIndex {
    let res = tagger.tag(at: index, unit: .word, scheme: .script)
    let range = res.1

    let script = res.0?.rawValue

    switch script {
    case .some(let s):
        lastScript = s
        dictionary[s, default: ""] += dictionary["other", default: ""] + str[range]
        dictionary.removeValue(forKey: "other")
    default:
        dictionary[lastScript, default: ""] += str[range]
    }

    index = range.upperBound
}

print(dictionary)

and print the result if you'd like:

for entry in dictionary {
    print(entry.key, ":", entry.value)
}

yielding :

Hant : 從中間開始. 
Cyrl : начать средний конец 
Arab : بداية وسط نهاية 
Latn : ¿como? start middle end.

This is still not perfect since the language tagger only checks to which script the most number of letters in a word belong to. For example, in the string you're working with, the tagger would consider الصَّالِحِينَ.Bismika as one word. To overcome this, we could use two pointers and traverse the original string and check the script of words individually. Words are defined as contiguous letters:

let str = "بِاسْمِكَ رَبِّي وَضَعْتُ جَنْبِي، وَبِكَ أَرْفَعُهُ، فَإِنْ أَمْسَكْتَ نَفْسِي فَارْحَمْهَا، وَإِنْ أَرْسَلْتَهَا فَاحْفَظْهَا، بِمَا تَحْفَظُ بِهِ عِبَادَكَ الصَّالِحِينَ.Bismika rabbee wadaAAtu janbee wabika arfaAAuh, fa-in amsakta nafsee farhamha, wa-in arsaltaha fahfathha bima tahfathu bihi AAibadakas-saliheen. In Your name my Lord, I lie down and in Your name I rise, so if You should take my soul then have mercy upon it, and if You should return my soul then protect it in the manner You do so with Your righteous servants."

let tagger = NLTagger(tagSchemes: [.script])
var i = str.startIndex
var dictionary = [String: String]()
var lastScript = "glyphs"

while i < str.endIndex {
    var j = i
    while j < str.endIndex,
        CharacterSet.letters.inverted.isSuperset(of: CharacterSet(charactersIn: String(str[j]))) {
        j = str.index(after: j)
    }
    if i != j { dictionary[lastScript, default: ""] += str[i..<j] }
    if j < str.endIndex { i = j } else { break }

    while j < str.endIndex,
        CharacterSet.letters.isSuperset(of: CharacterSet(charactersIn: String(str[j]))) {
        j = str.index(after: j)
    }

    let tempo = String(str[i..<j])
    tagger.string = tempo
    let res = tagger.tag(at: tempo.startIndex, unit: .word, scheme: .script)

    if let s = res.0?.rawValue {
        lastScript = s
        dictionary[s, default: ""] += dictionary["glyphs", default: ""] + tempo
        dictionary.removeValue(forKey: "glyphs")
    }
    else { dictionary["other", default: ""] += tempo }

    i = j
}
over 4 years ago · Santiago Trujillo Report

0

You can use the NaturalLanguageTagger as answered by @ielyamani but the only limitation is that it is iOS 12+

If you are trying to do this on earlier iOS versions, you can take a look at NSCharacterSet

You can create your own characterset to check whether a string has english characters and numbers

extension String {

     func containsLatinCharacters() -> Bool {

        var charSet = NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
        charSet = charSet.invertedSet

        let range = (self as NSString).rangeOfCharacterFromSet(charSet)

        if range.location != NSNotFound {
            return false
        }

        return true
    }
}

Another option is to use the charactersets already available:

let nonLatinString = string.trimmingCharacters(in: .alphanumerics)//symbols will still get through
let latinString = string.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)//symbols and non-latin characters wont get through

With these you can get the strings you want quite easily. But if these are not good enough, you can look to create your own characterset, use union, intersect etc to filter out the wanted and the unwanted characters.

over 4 years ago · Santiago Trujillo Report

0

Step 1: You have to split whole string into an array by "." as I can see there are "." between sentence.

Step 2: Pass each sentence to determine its language and append into different string.

Final Code

//add in your viewController

enum Language : String {
case arabic = "ar"
case english = "en"
}

override func viewDidLoad() {
    super.viewDidLoad()
    //make array of string
    let kalmaArray = "بِاسْمِكَ رَبِّي وَضَعْتُ جَنْبِي، وَبِكَ أَرْفَعُهُ، فَإِنْ أَمْسَكْتَ نَفْسِي فَارْحَمْهَا، وَإِنْ أَرْسَلْتَهَا فَاحْفَظْهَا، بِمَا تَحْفَظُ بِهِ عِبَادَكَ الصَّالِحِينَ.Bismika rabbee wadaAAtu janbee wabika arfaAAuh, fa-in amsakta nafsee farhamha, wa-in arsaltaha fahfathha bima tahfathu bihi AAibadakas-saliheen. In Your name my Lord, I lie down and in Your name I rise, so if You should take my soul then have mercy upon it, and if You should return my soul then protect it in the manner You do so with Your righteous servants.".components(separatedBy: ".")

    splitInLanguages(kalmaArray: kalmaArray)

}



private func splitInLanguages(kalmaArray: [String]){
    var englishText = ""
    var arabicText = ""

    for kalma in kalmaArray {

        if kalma.count > 0 {

            if let language = NSLinguisticTagger.dominantLanguage(for: kalma) {
                switch language {
                case Language.arabic.rawValue:
                    arabicText.append(kalma)
                    arabicText.append(".")
                    break
                default: // English
                    englishText.append(kalma)
                    englishText.append(".")
                    break
                }
            } else {
                print("Unknown language")
            }
        }
    }

    debugPrint("Arabic: ", arabicText)
    debugPrint("English: ", englishText)
}

I hope it will help you to split the string in two language. Let me know if you are still having any issue.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!