NSLocalizedString only retrieves the key, not the value in Localizable.strings (IOS) - ios

I've made a strings file named "Localizable.strings" and added two languages to it, like so:
"CONNECTIONERROR" = "Check that you have a working internet connection.";
"CONNECTIONERRORTITLE" = "Network error";
I have also converted the files to Unicode UTF-8
However, when I create a UIAlertView like this:
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(#"CONNECTIONERRORITLE",nil)
message:NSLocalizedString(#"CONNECTIONERROR",nil)
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
the alert view only shows the key text, not the value. It works if I, for example, set a UITextviews text to NSLocalizedString(#"CONNECTIONERROR",nil), but the alert view only displays the key. Anyone know what's wrong?

In my case it was because I had mistakenly named the file "Localization.strings" and hadn't noticed (it has to be named Localizable.strings). As explained previously the symptom is because the compiler cannot find the string. Otherwise the cause could be any number of things but usually it's a missing semi colon or quotation mark. These are hard to find when you're doing a lot of localizations at once. The lesson learned is to start building your localization file early on in your development process and build it as you go, so that they are easier to spot.

Same problem, solved using the filename: Localizable.strings

Change your .strings file name to Localizable.strings, it worked for me.

Double check that the Localizable.strings file is being added to
Targets -> BuildPhases -> Copy Bundle Resources
It hadn't been added automatically for me.
Edit 2021: with XCode 12 the Localizable.strings have to be added to
Targets -> Build Phases -> Compile resources

I have been searching the solution for 5 hours, I tried everything I could to make my app localization working.
The problem was that one of the Pods of my project had a Localizable.strings file (actually it was Parse pod that had not renamed it). Therefore my Localizable.strings file was not recognized by my app.
I fixed the issue by changing the name of the file to "MyappnameLocalizable.strings" and using NSLocalizedString this way:
NSLocalizedString("key", tableName: "MyappnameLocalizable", comment: "comment")

Tested the app on an actual device and it worked

I was having problems with this on the iOS Simulator. I ended up deleting the Localization.strings file in the simulator directory
( /Users/(me)/Library/Application Support/iPhone
Simulator/5.0/Applications/(etc)/(project)/(application.app)
cd to there and delete all copies of Localization.strings found there.
For some reason the usual rubber chicken voodoo of build clean, quit iOS Simulator, quit XCode, etc wasn't working, but this did. At least for me, today.

This is happening when the runtime can't find the specified key, for whatever reason. In your case, it's most likely due to a typo: CONNECTIONERRORITLE is missing a T for TITLE. Also pay attention to any warnings/error when compiling regarding the Localizable.strings file: if there are unbalanced " or missing ; the file cannot be compiled/read correctly.

Change the name of the file to Localizable.strings, make sure the target in the file inspector is set.
To avoid syntax errors right click on Localizable.strings file->open as->ASCII property list
Also, cleaning the project and building again helped in my case.

NSLocalizedString usage means you need the EXACT case and spelling of your key in order to get the content from it. You'll notice that this one says
NSLocalizedString(#"CONNECTIONERRORITLE",nil)
when it should be
NSLocalizedString(#"CONNECTIONERRORTITLE",nil)
If you look at the last part of the first one, it says 'ITLE', not 'TITLE'

Rename the InfoPlist.strings file to Localizable.strings (double clic) and then you will get the correct string for that key.

If you wrote double semicolons at the end of a line, NSLocalization does not working.
You should check Localizable.strings file if there is ';;'

When you are developing an SDK. You need some extra operation.
1) create Localizable.strings as usual in YourLocalizeDemoSDK.
2) create the same Localizable.strings in YourLocalizeDemo.
3) find your Bundle Path of YourLocalizeDemoSDK.
Swift4:
// if you use NSLocalizeString in NSObject, you can use it like this
let value = NSLocalizedString("key", tableName: nil, bundle: Bundle(for: type(of: self)), value: "", comment: "")
Bundle(for: type(of: self)) helps you to find the bundle in YourLocalizeDemoSDK. If you use Bundle.main instead, you will get a wrong value(in fact it will be the same string with the key).
But if you want to use the String extension mentioned by dr OX. You need to do some more. The origin extension looks like this.
extension String {
var localized: String {
return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
}
}
As we know, we are developing an SDK, Bundle.main will get the bundle of YourLocalizeDemo's bundle. That's not what we want. We need the bundle in YourLocalizeDemoSDK. This is a trick to find it quickly.
Run the code below in a NSObject instance in YourLocalizeDemoSDK. And you will get the URL of YourLocalizeDemoSDK.
let bundleURLOfSDK = Bundle(for: type(of: self)).bundleURL
let mainBundleURL = Bundle.main.bundleURL
Print both of the two url, you will find that we can build bundleURLofSDK base on mainBundleURL. In this case, it will be:
let bundle = Bundle(url: Bundle.main.bundleURL.appendingPathComponent("Frameworks").appendingPathComponent("YourLocalizeDemoSDK.framework")) ?? Bundle.main
And the String extension will be:
extension String {
var localized: String {
let bundle = Bundle(url: Bundle.main.bundleURL.appendingPathComponent("Frameworks").appendingPathComponent("YourLocalizeDemoSDK.framework")) ?? Bundle.main
return NSLocalizedString(self, tableName: nil, bundle: bundle, value: "", comment: "")
}
}
Hope it helps.

To find out if the Localizable.strings file is being found, check the content of your .app build and you can also do this in code:
//en is for English for example so specify yours here
NSString *path = [[NSBundle mainBundle] pathForResource:#"en" ofType:#"lproj"];
If path is NULL, it means file not found.

If you have any extra semicolon in your strings file, it doesnt localise.

I faced a similar problem, suddenly my localizable strings didn't work at all. Then I used file-compare with the old .strings copy, and at-last I found I have accidentally deleted a key in it.
So Definitely if the format is wrong Xcode will not read the strings for you.
This is the format it expects "Key" = "Value";

Because I stumbled upon this when looking for the answer to a similar problem, I'm leaving my solution here:
If your key has "\u2028" in it instead of "\n", it will always return just the key and not the value. Seems to be a bug with localization.

We were dealing with an issue in which some keys were not getting their values despite all of them existing in Localizable.strings.
Turns out that the developer who built the file added two semi-colons at one line, and that caused the parsing of this file to be quite erratic.
After I found the two semi-colons one next to the other and got rid of one of them, the app wouldn't compile anymore. At this point I was able to find some lines that didn't have semi-colons. After fixing those and the app compiled, all my strings worked fine.
So having two semi-colons in the same line caused the file to compile despite it missing semi-colons in other lines.
It looks like Apple's parser for .strings file is very primitive.
Unfortunately, the plist linter was useless in our case. To find and fix the issue, I copied and pasted the entire contents of our Localizable.strings file (which is over 2000 lines long), and started copying it back in 20 line chunks and compiling each time. It was the only way to find an issue that the linter would not catch.

Put an ; at end of the lines in the Localizable.strings files.

Resetting the simulator settings worked for me.
iOS Simulator > Reset Content and Settings...

In my case, I tried clean project and delete derived data still not work. I remove several line breaks in the strings file and then Xcode find the strings again.

None of the suggested solutions worked for me, but I did solve the issue by deleting the .app file in Products

I had the issue when one language was working properly and other language worked half of the time and other time I was getting the key, instead of localized version of that key.
Problem in my case was that after manually merging version control conflict, there was extra line of '>>>>>' left, project didn't complain (not like when you miss the semicolon, it complains) and was building properly, so every key before that '>>>>>' was being translated and every key after, not.
If more simpler solutions fails, you might have to go through every line and look for extra characters (not only '>>>>>', other extra characters too), or if you are using the version control get older, stable version of Localizable.strings file and manually go through changes and add later commits.

The first line of the localization file must contain a mapping, otherwise the SDK won't read the file.

Be sure to not put '#' in front of your key or value like so:
#"key" = #"value";
It should be just:
"key" = "value";
The '#' only goes in front of the key when accessing it:
NSWebLocalizedString(#"key", #"label for coder");

I had everything working when suddenly localization just stopped translating strings. This means the file is somehow unreadable to Xcode.
This had happened to me because I had pasted a bad character in the Localized.strings file. When I deleted the few lines with the offending character (a non unicode character? bad quote signs? Couldn't tell) everything went back to normal.
To find the offending lines I made a breakpoint, and manually translated the strings in my file in the debugger, until I hit the first one that won't translate.

Did you tried cleaning and rebuilding the project?

For xcode 9.2 removing "Localizable.strings" files from the simulators for the project using console solved it for me. Here is the commands for the lazy ones like me ;)
Do not forget to replace YOUR_APP_NAME_HERE with your project name
Shell script:
cd
cd Library/Developer/CoreSimulator/Devices/
find . -name "Localizable.strings" | grep "YOUR_APP_NAME_HERE.app" | xargs rm
If you are experiencing the problem with Unit Tests it will work in simulator ;)

Swift 4:
If you use more than one bundle such as you use it in an external framework:
var currentBundle = Bundle.main
NSLocalizedString("CONNECTIONERRORITLE", tableName: nil, bundle: currentBundle, value: "", comment: "")

I resolved it using this approach.
The localize file was created with the name main.Strings. Then, I open the main.Strings files (for each language added) and I renamed them manually with the name localize.strings and add them one by one to my project, also I deleted the main.strings.
The second thing to evaluate is: check . your file, all the keys have to end with ; and be sure all the quotes are properly opened and closed.
And you can use in swift 4 :
myButon.setTitle(NSLocalizedString("forgotpassword.key", comment: ""), for: UIControlState.normal)

Related

Xcode 10, could not decode input file using specific encoding

I am working on an iOS app. It is working fine in Xcode 9.4.1, but when I build it in Xcode 10 it gives me following error:
I tried the solution given in the following post by changing the encoding, but it didn't work. I tried it by both Reinterpret and Convert
still the same error:
It's working fine on Xcode 9.4.1
Find your Localizable.strings in a Terminal and execute:
$ iconv -f UTF-16LE -t UTF-8 Localizable.strings > LocalizableNew.strings
Then check LocalizableNews.string
and if there is no errors just replace files
$ mv LocalizableNew.strings Localizable.strings
I have similar error once i open my project in Xcode 10.4 and open it agian in Xcode 10.1.
I solved it by selecting my all Localizable.strings file and change there text encoding to UTF-16(In my case error was related to UTF-16 you can change it to UTF-8)
So changing the text encoding to UTF-16 or UTF-8 will works.
It sounds like the file is corrupted, probably with parts of it encoded in UTF-8 and parts of it encoded in 8859-5. From its name, I would suspect this is a Cyrillic localization (perhaps Russian), and the file was probably edited using an editor that didn't correctly maintain encoding or use UTF-8 (the most common cause of that is editing on Windows).
You'll need to open the file, probably in an external editor that can handle random encodings like vim or Sublime Text, and fix any corruption. Exactly how to do that depends on the nature of the corruption.
You need to set correct Text Encoding in the File Inspector. The default is UTF-8.
If you want to fix the problem without UI, you need to look for the XCode project definition (generally YOURPROJECT.xcodeproj/project.pbxproj), then find the reference to the file causing an issue.
You should find something like this (from Adium, in this case)
D182F1B611DFF23700E33AE2 /* sk */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/schema.strings; sourceTree = "<group>"; };
fileEncoding = 10 is UTF-16; 4 is UTF-8, which is currently the default, so you can either set it to that value explicitely, or simply remove the fileEncoding bit altogether.
I got this error message when I forgot to put semicolons at the end of the line to separate the individual translations.

NSLocalizedString always returns capitalized text

Ive run into an issue where NSLocalizedString is always returning strings capitalized regardless of its input. localization was working
and Im assuming I did something that caused this but I cannot seem
to figure out exactly what changed.
Here's my code:
func localize(_ str: String) -> String {
print("str in: \(str)")
return NSLocalizedString(str, comment: "")
}
I call it like this:
let txt = self.localize("Question")
print("txt = \(txt)")
Output:
str in: Question
txt = QUESTION
Things Ive tried:
Ive grep'd all of my .strings files and confirmed there is no
'QUESTION' in there.
Removed app from Simulator and re-run app
Changed incoming string to something that doesn't exist in any file such as 'randomxxyxxy'
Ive tried searching for quite a while on this issue and wasn't able to find anything that was like this problem.
Any help is appreciated,
Thank you
When your app is trying to localize a string but cannot find the translated text for it then it will show it in capitals. This is done to show you that the capitalized text is not localized. You can disable the capitalization of those cases by disabling the option: Show not-localized strings
This is how you do that:
Edit the scheme
Select the “Run” action and click the “Options” tab
Uncheck the “Show non-localized strings” option
In your case I think that your strings' localization is not working and so they are capitalized because that setting is activated.

Localizable.strings - The data couldn’t be read because it isn’t in the correct format

If I copy something from textedit or web and paste it to localizable file it shows this compilation error. If I type those in localizable file it does not show any error. I am assuring you that I using the correct format and ';' in the file.
"New" = "New";
"In Progress" = "In Progress";
"Waiting" = "Waiting";
"Closed" = "Closed";
Use plutil from the Terminal:
you have to run it for each version of the localizable file. E.g
cd into your project root
cd eb.lproj - you can replace this with
any localisation you are working with.
plutil -lint Localizable.strings
When you run step 3, you will either be shown an error, telling you what is wrong with your file. Or you will be told the file is OK
Note that plutil output is bad, it seems it always says "Unexpected character at line 1" but above that output, it prints other stuff like missing semicolon on line 121, and that is the real error
For me, it was missing semi-colons. If you use a tool to generate .strings file, make sure there are no un-escaped quotes that may 'eat' the delimiting semi-colons.
pl < Localizable.strings
is better than plutil -lint Localizable.strings
Log will show something like this
2019-08-14 16:39:34.066 pl[21007:428513] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 427. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.
2019-08-14 16:39:34.068 pl[21007:428513] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line 427. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug.
2019-08-14 16:39:34.071 pl[21007:428513] *** Exception parsing ASCII property list: NSParseErrorException Error Domain=NSCocoaErrorDomain Code=3840 "Unexpected character / at line 1" UserInfo={NSDebugDescription=Unexpected character / at line 1, kCFPropertyListOldStyleParsingError=Error Domain=NSCocoaErrorDomain Code=3840 "Missing ';' on line 427" UserInfo={NSDebugDescription=Missing ';' on line 427}}
Fastest way to detect the line with the issued string is to :
right click the strings file and
then Open as/ASCII property list.
Xcode will immediately tell you in what line there's an error.
I know this question was asked long ago but my scenario and solution is little bit different.
Today I faced same issue but when I tried to check the issue using
plutil -lint Localizable.strings
I got OK status which means everything is fine, then I tried to find issue using
pl < Localizable.strings
But again I got file text printed with no error mentioned, then I tried a trick and it worked for me.
Right click on the Localizable.strings file
Then select option Open As option
Then select option ASCII Property List
That's it, XCode shows me the issue with line number and the issue was I had this DéjàVerified text as key on specified line, this helps me to identify and solve the issue, I hope it will save someone's time.
Cheers!
There can be multiple reasons for this:
Semicolon is missing at the end.
Multiple semicolons at the end.
" within the message which should be escaped by \".
Extra character after semicolon.
Invalid white space in the file.
Other invalid characters in the file.
Merge conflict characters in the file!
<<<<<<< HEAD, ======= and >>>>>>>.
Please note that plutil -lint Localizable.strings returned OK for point-2 & 7!
In my case, I was missing "=" between a string pair. Even plutil did not help me to spot the error line. I manually checked each string pair. :/
Your syntax seems to be fine, the only thing that I can see can "break" your file and cause this error is the quote character. Make sure to use the reqular one " and not in any other form like ″ for example.
Also make sure the strings file name is always Localizable.strings
I Had the same issue and i resolved it by commenting or removed unused strings in my Localizable.String file :)
I once had a similar error and it turned out that there was an URL in the middle of the file, like this:
// Some Comment 1
"Some key 1" = "Some value 1";
http://...whatever...
// Some Comment 2
"Some key 2" = "Some value 2";
When calling plutil -lint on that file the output was:
Unexpected character / at line 1
Well, the first character indeed was / as the file started with a comment but the problem resolved after removing the URL; or turning it into a comment which it actually should have been. Note that the URL was nowhere near the beginning of the strings file, it was about in the middle of a 6000 lines string file. I was only able to find it by browsing through commit history and always look at the changes.
if missing ";" at end of the all lines in Localizable.string file, this error can occur.
eg :-
"header_text" = "Current Language";
"change_language" = "Change Language";
"header_text" = "වත්මන් භාෂාව";
"change_language" = "භාෂාව වෙනස් කරන්න";
This may be because the translation file format is wrong.
You can download a mac software called Localizable.
This is the download link: https://apps.apple.com/cn/app/localizable-%E7%BF%BB%E8%AF%91%E6%96%87%E4%BB%B6%E5%B7%A5%E5%85%B7/id1268616588?mt=12,
you only need to drag Localizable.strings to the software and it will It is useful to tell you which line in the file may have a problem. It saved me a lot of time. Now I share it with you.
I hope it will be helpful to you.
It seems your info.plist is not in correct form . check it properly. I also had the same issue . I resolved it by modifying my info.plist.
I just had this experience:
external translator doing the work inside Visual Code or other text editors
Files not working and getting an error like this one: ( testing with plutil -lint )
Localizable.strings: Unexpected character " at line 1
CardRatingView.strings: Unexpected character / at line 2
I just created a new file within XCode and copy pasted all the file content and suddenly everything was working properly.
I guess something can go wrong / corrupting the file itself while working with other text editors.
If showing something like Unexpected character " at line 1, and it is the first string like "app_name"="Any Name"
Check that the file is UTF16
I ran into this issue, all my formatting was correct. Checking for illegal characters using plutil -lint Localizable.strings and using ruby libraries like "utf8_utils" also didn't work at finding the illegal characters. BUT when I pasted the Localizable.strings contents into the Terminal app while running irb, it did show me the weird characters.
"PercentComplete" = "%d procent gennemført";
Pasted into irb:
"PercentComplete"\U+FFC2\U+FFA0= "%d procent gennemf\U+FFC3\U+FFB8rt";
Then all I had to do was a regex replace to fix those weird white space characters: \U+FFC2\U+FFA0
Thanks to the plutil suggestion I understood that to make it work you have to delete also any \ or * as are not read as comments and, important, add a ; to the end of the file. Xcode 11.5.
If pl and plutil show no problems, check the file's encoding. I had a similar problem twice and in my case it was due to incorrect encoding, though I have no idea how it has been changed (I literally added a single line in the middle of the file in X-Code). Converting from UTF-16LE to UTF-16BE in some editor (I used Android Studio) fixed the problem.
For me I had an NSLocalizedString in my code that contained a string interpolation e.g. NSLocalizedString("\(product.price ?? "")per_month"). When I exported localisations this got added to my strings file, which was then in the wrong format. It threw me off because my strings file in Xcode looked fine, but actually the file gets updated as part of the export localisations process, and errors were creeping in there.
If anyone things they might be having the same issue try calling genstrings separately and seeing if the newly generated file is in the correct format. Make sure you save your strings first as this will overwrite your strings file : find ./ -name "*.swift" -print0 | xargs -0 genstrings -SwiftUI -o en.lproj
This tool can help solve this problem, just select your localizable.strings file, it will help you find out which line format is wrong, it can save a lot of time
https://localizable.appdevtool.io/
In my case, I had one line with using ” instead of " and that breaks the file. My code editor did not detect this difference.
I was having the similar issue where i didn't escape the string value with backslash \ for one of my string's value.
Before:
"INVALID_NUMBER" = "It seems you're entering invalid number. Number should starts with "0" or "7"";
Updated:
"INVALID_NUMBER" = "It seems you're entering invalid number. Number should starts with \"0\" or \"7\"";
Backslashes are required when you want to display the quotation marks "
Please, have a quick look at here for How to include Quotation mark in strings
It seems like SVN is having some issue with this file. As it consider it to be a binary file. It is inserting a lot of non printable characters between each characters. I still couldn't find a proper solution. Just changing the Localizable.string files from production PC for avoiding any issue with it.
Update: Updating the SVN client (smartSVN) to the latest version solved the issue. It seems one of my colleague was using a older version. When he commited the change to localizable file it caused the error.

NSLocalizedString is it really working?

I misunderstand NSLocalizedString.
I have a project with French and English .strings files.
In project target - Localizations I have 6 files in French and English.
In english.strings file:
"hello" = "world";
In french.strings file:
"hello" = "salut";
When I write a simple line of code to change label text:
exerciseDescription.text = NSLocalizedString(#"hello", #"no comment");
Output is: hello
I changed in iOS simulator : settings - general - international - language - French/English - Done
And output is again: hello
I thought it should be world or salut...
You're using it in correct way but not added properly,
Localized filename should always be named Localizable.strings, and that file is within the particular language folder, for English, en.lproj and for French fr.lproj like wise.
You are using it right, but as #Hemang mentioned you should change your filename to Localizable.strings as this is the default.
Furthermore I would like to suggest cleaning the build folder, and removing the application from the simulator. That helped for me in one case.

iOS Localization: Extract strings

I find this tool genstrings, but it fails on line: NSLocalizedString(key,comment);
-(NSString*)toLocalizableString:(NSString*)key
withComment:(NSString*)comment{
NSString* stringResult = nil;
if (key){
stringResult = NSLocalizedString(key, comment);
}
NSLog(#"(*) key: <%#> (&) value: <%#> (*)",key,comment);
return stringResult;
}
Also, steps of localization:
Find all strings and wrap them with NSLocalizedStringFromTable
Extract strings with genstrings
Put localizable files and find translations
well done!
I stuck at first step.
How find all strings, that are needed to have translations?
Or i'm wrong?
Thanks for explanation!
I use Ltools to help with this. It's a two step process:
Search for #" in your code, and wrap the appropriate strings in L()
Run L.sh as part of your build process
This will make sure that every string that needs translating has a translation.
This is not exactly what you are searching for, but for me it doesn't make sense to translate all strings, e.g. you likely do not want to translate strings (#"") from an NSPredicate.
If you moved all relevant strings to NSLocalizableString / NSLocalizableStringFromTable, then I can recommend Linguan. You just pass in your XCode project and you are ready to start translating.

Resources