Detect Language of NSString
Thats the result:
- (NSString *)languageForString:(NSString *) text{
if (text.length < 100) {
return (NSString *) CFStringTokenizerCopyBestStringLanguage((CFStringRef)text, CFRangeMake(0, text.length));
} else {
return (NSString *)CFStringTokenizerCopyBestStringLanguage((CFStringRef)text, CFRangeMake(0, 100));
}
}
How to check if NSString language matches NSLocaleLanguageCode
You get a string for both. In Objective-C, NSLinguisticTag
is a synonym for NSString *
. Simply compare the NSLinguisticTag
(really just an NSString
) to the NSString
you obtained from the locale's language code.
But a simpler solution is to use the dominantLanguageForString:
class method of NSLinguisticTagger
to easily get the language of a string as an NSString
. This is much simpler than using one of the tag...
instance methods of NSLinguisticTagger
but it does require iOS 11+/macOS 10.13+.
NSLinguisticTag languageTag = ... // tag from NSLinguisticTagger
NSString *languageCode = ... // language from NSLocale
if ([languageCode isEqualToString:languageTag]) {
}
How to detect the language of NSString
You can't of course.
Read about app internationalization guidelines.
How to detect correctly language user of device objective-c?
If you want the language try
[NSLocale preferredLanguages];
It will return an array of the user's language preference and the most preferred language will be the first in the list.
NSLocale encapsulates a lot more than just the current language. Things like currency identifier and what to use for the decimal separator are just a few. A Spanish speaking user in the northwestern United States may want to see things in Spanish but would probably still expect to see the $ for currency.
With that said I suspect what your really looking for is full fledged localization support in which case there is tons of information out there on how to localize your app. The macro
NSLocalizedString
and its siblings allow you to write language agnostic code (for the most part).
How to detect text (string) language in iOS?
Latest versions (iOS 12+)
Briefly:
You could achieve it by using NLLanguageRecognizer, as:
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
}
Older versions (iOS 11+)
Briefly:
You could achieve it by using NSLinguisticTagger, as:
func detectedLanguage(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
}
Details:
First of all, you should be aware of what are you asking about is mainly relates to the world of Natural language processing (NLP).
Since NLP is more than text language detection, the rest of the answer will not contains specific NLP information.
Obviously, implementing such a functionality is not that easy, especially when starting to care about the details of the process such as splitting into sentences and even into words, after that recognising names and punctuations etc... I bet you would think of "what a painful process! it is not even logical to do it by myself"; Fortunately, iOS does supports NLP (actually, NLP APIs are available for all Apple platforms, not only the iOS) to make what are you aiming for to be easy to be implemented. The core component that you would work with is NSLinguisticTagger
:
Analyze natural language text to tag part of speech and lexical class,
identify names, perform lemmatization, and determine the language and
script.
NSLinguisticTagger
provides a uniform interface to a variety of
natural language processing functionality with support for many
different languages and scripts. You can use this class to segment
natural language text into paragraphs, sentences, or words, and tag
information about those segments, such as part of speech, lexical
class, lemma, script, and language.
As mentioned in the class documentation, the method that you are looking for - under Determining the Dominant Language and Orthography section- is dominantLanguage(for:)
:
Returns the dominant language for the specified string.
.
.
Return Value
The BCP-47 tag identifying the dominant language of the string, or the
tag "und" if a specific language cannot be determined.
You might notice that the NSLinguisticTagger
is exist since back to iOS 5. However, dominantLanguage(for:)
method is only supported for iOS 11 and above, that's because it has been developed on top of the Core ML Framework:
. . .
Core ML is the foundation for domain-specific frameworks and
functionality. Core ML supports Vision for image analysis, Foundation
for natural language processing (for example, theNSLinguisticTagger
class), and GameplayKit for evaluating learned decision trees. Core ML
itself builds on top of low-level primitives like Accelerate and BNNS,
as well as Metal Performance Shaders.
Based on the returned value from calling dominantLanguage(for:)
by passing "The quick brown fox jumps over the lazy dog":
NSLinguisticTagger.dominantLanguage(for: "The quick brown fox jumps over the lazy dog")
would be "en" optional string. However, so far that is not the desired output, the expectation is to get "English" instead! Well, that is exactly what you should get by calling the localizedString(forLanguageCode:)
method from Locale Structure and passing the gotten language code:
Locale.current.localizedString(forIdentifier: "en") // English
Putting all together:
As mentioned in the "Quick Answer" code snippet, the function would be:
func detectedLanguage(_ forString: T) -> String? {
guard let languageCode = NSLinguisticTagger.dominantLanguage(for: String(forString)) else {
return nil
}
let detectedLanguage = Locale.current.localizedString(forIdentifier: languageCode)
return detectedLanguage
}
Output:
It would be as expected:
let englishDetectedLanguage = detectedLanguage(textEN) // => English
let spanishDetectedLanguage = detectedLanguage(textES) // => Spanish
let arabicDetectedLanguage = detectedLanguage(textAR) // => Arabic
let germanDetectedLanguage = detectedLanguage(textDE) // => German
Note That:
There still cases for not getting a language name for a given string, like:
let textUND = "SdsOE"
let undefinedDetectedLanguage = detectedLanguage(textUND) // => Unknown language
Or it could be even nil
:
let rubbish = "000747322"
let rubbishDetectedLanguage = detectedLanguage(rubbish) // => nil
Still find it a not bad result for providing a useful output...
Furthermore:
About NSLinguisticTagger:
Although I will not going to dive deep in NSLinguisticTagger
usage, I would like to note that there are couple of really cool features exist in it more than just simply detecting the language for a given a text; As a pretty simple example: using the lemma when enumerating tags would be so helpful when working with Information retrieval, since you would be able to recognize the word "driving" passing "drive" word.
Official Resources
Apple Video Sessions:
- For more about Natural Language Processing and how
NSLinguisticTagger
works: Natural Language Processing and your Apps.
Also, for getting familiar with the CoreML:
- Introducing Core ML.
- Core ML in depth.
Detect whole word in NSStrings
Use "regular expression" search with the "word boundary pattern" \b
:
NSString *text = @"Here is my string. His isn't a mississippi isthmus. It is...";
NSString *pattern = @"\\bis\\b";
NSRange range = [text rangeOfString:pattern options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
if (range.location != NSNotFound) { ... }
This works also for cases like "Is it?"
or "It is!"
, where the word is not surrounded by spaces.
In Swift 2 this would be
let text = "Here is my string. His isn't a mississippi isthmus. It is..."
let pattern = "\\bis\\b"
if let range = text.rangeOfString(pattern, options: [.RegularExpressionSearch, .CaseInsensitiveSearch]) {
print ("found:", text.substringWithRange(range))
}
Swift 3:
let text = "Here is my string. His isn't a mississippi isthmus. It is..."
let pattern = "\\bis\\b"
if let range = text.range(of: pattern, options: [.regularExpression, .caseInsensitive]) {
print ("found:", text.substring(with: range))
}
Swift 4:
let text = "Here is my string. His isn't a mississippi isthmus. It is..."
let pattern = "\\bis\\b"
if let range = text.range(of: pattern, options: [.regularExpression, .caseInsensitive]) {
print ("found:", text[range])
}
Swift 5 (using the new raw string literals):
let text = "Here is my string. His isn't a mississippi isthmus. It is..."
let pattern = #"\bis\b"#
if let range = text.range(of: pattern, options: [.regularExpression, .caseInsensitive]) {
print ("found:", text[range])
}
How to identify the user's language in iOS?
You can get user's prefered language list by using NSLocal
:
NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0];
if ([language isEqualToString:@"en"]) {
NSLog(@"user's prefered first language is English");
}
Detect language in use by iOS application
I usually reserve a special key in Localizable.strings, such as "HTTPAcceptLanguage", which I set to "en", "fr", etc. Now telling your server the language displayed by the application is as simple as NSLocalizedString(@"HTTPAcceptLanguage", nil).
Related Topics
Autolayout with Hidden Uiviews
iOS 11 Navigation Bar Height Customizing
No Avplayer Delegate? How to Track When Song Finished Playing? Objective C iPhone Development
iOS Background Audio Not Playing
Why Storyboard UI Elements Not Showing on Uiviewcontroller in Xcode 6
Disable Uipageviewcontroller Bounce
Findobjectsinbackgroundwithblock: Gets Data from Parse, But Data Only Exists Inside the Block
Apns (Apple Push Notification Service) Reliability
Receiver (<Viewcontroller>) Has No Segue with Identifier 'Addsegue'
How to Detect When Keyboard Is Shown and Hidden
In iOS, How to Drag Down to Dismiss a Modal
Round Top Corners of a Uibutton in Swift
Uitableview: How to Disable Selection for Some Rows But Not Others
How to Make a Background Image Scale to Screen Size in Swift
How to Post String with Special Character and Thai Language Using Xml Parsing in Objective C
How to Initialize/Instantiate a Custom Uiview Class with a Xib File in Swift