Unable to use localizable strings - ios

I am trying to follow all instructions I have found in previous questions in term of localizing the application.
I Have succeeded in localizing storybaord when strings were generated. Now I am trying to prepare .strings file in order to use them in my swift files.
what I did:
new -> file -> strings file
Create localization of at least 2 languages on the previously created .strings file
I have put values in (polish)
"HELLO_WORLD" = "Dzień dobry!";
and in (english)
"HELLO_WORLD" = "Hello world!";
I have created string extension as follows:
extension String {
var localized: String {
return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
}
}
I am trying to show the value like:
`helloworldLabel.text = "HELLO_WORLD".localized
but everything I gets is the same result. In hello world label I see "HELLO_WORLD"
can anyone give me a hint what Am I doing wrong?

Related

How can I localise my multiple string in swift?

When I do as below, I can write all string expressions in different languages. But it doesn't happen when I make a multi line String. Please help me on how to Integrate this?
Modal
Unit(unit: "Unit 1".localized(),
category: [Category(category: "Personal Pronouns".localized()])
controller
extension String {
func localized() -> String {
return NSLocalizedString(self,
tableName: "Localizable",
bundle: .main,
value: self,
comment: self)
}
}
localizable.string
"Unit 1" = "Unité 1";
"Personal Pronouns" = "Pronoms personnel";
The multi line string I want to do will be like this but how ?
let text = """
We want to change the World
but not everywhere or everything
only on people
"""
https://github.com/ysrtirak/Make-localise
here there is my example
I could not translate the text in """ """
I haven't tried it, but according to this SO answer you can put multi-line strings directly into your localizable.strings file:
localizable.strings:
"multiLine" = "We want to change the World
but not everywhere or everything
only on people";
And in your swift code:
print("multiLine".localized())
I just tried a test application, and the following localizable.strings file worked perfectly:
/*
Localizable.strings
MultiLine
Created by Duncan Champney on 8/13/21.
*/
"foo" = "This
is
a
multi-line
string";
With that localizable.strings file, this code:
print(NSLocalizedString("foo", value: "foo", comment: "comment"))
prints the output:
This
is
a
multi-line
string
Just as you would expect it to.
Edit:
Try downloading this sample app from Github. It is a working example of using multi-line strings in a localizable.strings file.
Edit #2:
You have an extra newline at the beginning and end of the English in your French localizable.strings. Change it as follows:
/*
Localizable.strings
Make localise
Created by Yasir Tırak on 15.08.2021.
*/
"I know how to localise that . thats not problem" = "Je sais comment localiser ça. ce n'est pas un problème";
"This is my text
But i cant localise it
hey
how are you" = "C'est mon texte
Mais je ne peux pas le localiser
Hé
Comment ça va";
That works.
To figure out what was going on, I broke your code into steps and logged the results:
let text = """
This is my text
But i cant localise it
hey
how are you
"""
print("text = '\(text)'")
let localizedText = text.localized()
textLabel.text = localizedText
That outputs:
text = 'This is my text
But i cant localise it
hey
how are you'
Note how there are no newlines before the first single quote and none after the last single quote.

Return a string if localized string not found

I would like to know how could I return a default string value if localized string of key is not found. here is my function to return the localized String.
func localizedStr(key: String) {
return NSLocalizedString(key, comment: "")
}
I would like to return default string e.g. "foo" if the key is not found in localization file.
TL;DR
Use the full
NSLocalizedString(key: "key", value:"English string", comment: "")
If key is not found in your translated file, value is returned
Long version
Don't wrap NSLocalizedString in a function - while there's less code, you're losing valuable information for the localisation process.
you won't be able to use Xcode export an Xliff file for translation - only string literal keys in NSLocalizedString are included
Use a value: parameter with the English (or your base language) string. This is used when no translation is found, and means you don't need to have a base Localizable.strings file.
The comment: appears in the xliff file, and is useful for translators. Use this to give information about the context of the string being translated.
You could give it default value like this, using NSLocalizedString(key, comment: "") would return an Empty String if the Key was not found so checking on it like this should do the trick.
func localizedStr(key: String) {
if NSLocalizedString(key, comment: "") == key {
return "foo"
}
return NSLocalizedString(key, comment: "")

How to compare Localized string with the string from the database?

I have a to compare a string with the string from the db.
var variableFromDB = "test"
if "test" == variableFromDB{
print("Success")
}
It works fine in the English Language. I don't know how to compare it in the arabic language. Is the need to check in arabic language also. Please tell me know to check it.
In general it's a bad idea for your code to make decisions based on display strings. That goes double for display strings.
If your primary audience is Arabic-speaking, you could make your development language Arabic and then localize for other languages as needed.
In any case, I would suggest using a set of fixed strings as keys, and then calling NSLocalizedString(_:tableName:bundle:value:comment:) or one of it's variants to fetch a display string. Example:
Put this code somewhere central so the keys can be shared:
let screen1Prompt = "screen1Prompt"
Then when you need a localized string for display:
let prompt = NSLocalizedString(screen1Prompt)
Where the actual prompt string might be "Please select the date for your payment." in English, Arabic, etc.
Then if you need to match something in your database, look it up using the unlocalized key, not the localized display string.
That way if you later change the display string, your code still works.
var language: String
UserDefaults.standard.set("AE", forKey: "Apple") // manually set language
UserDefaults.standard.synchronize()
self.language = UserDefaults.standard.object(forKey: "Apple")as! String
// self.language = Locale.current.languageCode // your device language
extension String {
func stringlocalized(lang:String) ->String {
let path = Bundle.main.path(forResource: lang, ofType: "lproj")
let bundle = Bundle(path: path!)
return NSLocalizedString(self, tableName: nil, bundle: bundle!, value: "", comment: "")
}}
// Check You Localization string from your current language
let str = “ test”.localized(lang: self.language! )
if str ==variableFromDB
{ // Your logic here
}

iOS Base localization was not used for missing key

Let's say I have this 2 strings files in my project:
Localizable.strings (Base)
"hello_key" = "Hello";
"bye_key" = "Goodbye";
and
Localizable.strings (Chinese Traditional)
"hello_key" = "您好";
And I use the following code to localize the "hello" string
NSLocalizedString("hello_key", comment: "")
It works fine for "hello_key", but if I use "bye_key" in my iPhone with phone language set to Tradition Chinese, I get "bye_key" as the localized string.
In another word, the Base localization was not used. Is it possible to show the Base English "GoodBye" in this case?
Thanks.
This is the case of unsupported phrase, because your did not translate completely for Traditional Chinese.
Apple will not fallback to the base language, but simply return the key. This is just how it behaves. I wrote more about it in my blog.
You have to write a custom NSLocalizedString like this (the example uses en as the fallback language):
public func LS(_ key: String) -> String {
let value = NSLocalizedString(key, comment: "")
if value != key || NSLocale.preferredLanguages.first == "en" {
return value
}
// Fall back to en
guard
let path = Bundle.main.path(forResource: "en", ofType: "lproj"),
let bundle = Bundle(path: path)
else { return value }
return NSLocalizedString(key, bundle: bundle, comment: "")
}

Override a base localizable.strings file

Is there a way to have one base localizable.strings file for multiple targets within a project, and also have a second localizable.string file for each target that will override and append individual values to the base file?
EDIT
I want my app to have two .strings files - Localizable.string and Override.strings. If a string, Title.Welcome, is not found in OverrideLocalizable.strings then I would like the app to search Localizable.strings for Title.Welcome. Essentially, specifying Localizable as the fallback, but using OverrideLocalizable.strings by default.
Here is the solution I found:
NSString *PSILocalizedString(NSString *key, NSString *comment)
{
return NSLocalizedStringWithDefaultValue(key,
#"OverrideLocalizable",
[NSBundle mainBundle],
NSLocalizedString(key, nil),
comment);
}
What this will do is search a file called OverrideLocalizable.strings for the key. If the value for key is not found in OverrideLocalizable.strings, it will search localizable.strings for key. NSLocalizedString(key, nil) by default will search localizable.strings
Pretty simple and elegant solution
For Swift 4 users that come across this issue...
func localizedString(
for key: String, tableName: String = "OverrideLocalizable",
bundle: Bundle = .main, comment: String = ""
) -> String {
let defaultValue = NSLocalizedString(key, comment: comment)
return NSLocalizedString(
key, tableName: tableName, bundle: bundle,
value: defaultValue, comment: comment
)
}

Resources