iOS applications Localization.strings file name change - ios

IOS application provide the support of localization through the Localizable.strings file. If I want to change the file name for some obvious reasons where would I have to put that reference.
Can anyone please help.

How iOS localization works:
As you would already know, iOS provides a nice API for getting localized string as following.
NSString *stringValue = [[NSBundle mainBundle] localizedStringForKey:key
value:#""
table:nil];
And it also provides a macro for quick access as:
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:#"" table:nil]
iOS, by default, looks for strings in Localizable.strings file. However, we can also provide a custom file for iOS to look for strings into. And this is where things get interesting.
To provide a custom file, we can use the API as mentioned above in following manner.
NSString *localizedString = [[NSBundle mainBundle] localizedStringForKey:key
value:#""
table:#"AnotherLocalizableStringsFile"];
The table parameter takes a string argument AnotherLocalizableStringsFile which is the file containing the strings.
Another interesting parameter is the value parameter that takes in a string that should be returned in case no string is found matching the given key.
So following piece of code would return Invalid Key assuming the provided key does not exist in the file.
NSString *stringValue = [[NSBundle mainBundle] localizedStringForKey:#"Wrong_key_passed"
value:#"Invalid Key"
table:#"TargetLocalizable"];
The solution:
By using the combination of these two interesting parameters, we can devise a method to suit our requirements. We will ask iOS to look for strings specific to target in target specific strings file and fall back to Localizablestrings file when it comes to loading generic strings common to all targets.
Here’s how the piece of code looks like.
NSString *stringValue = [[NSBundle mainBundle] localizedStringForKey:#"Key"
value:NSLocalizedString(#"Key", nil)
table:#"TargetLocalizable"];
So, iOS looks for the string first in the given TargetLocalizable.strings file. If it doesn’t find it there, it would search in the base Localizable.strings file.
So all I had to do was to place all the strings common to all targets in Localizable.strings file and put the additional and overridden strings specific to the target in TargetLocalizable.strings file.

The name is 'fixed' - a localizable is named Localizable. you can only decide to not use NSBundle localization and roll your own stuff

Related

Can i define User Defined key at info.plist

Can i defined a user defined key with given name "SomeKey" and can i access with [[NSBundle mainBundle] objectForInfoDictionaryKey:#"SomeKey"]
Of course!
Apple Docs:
Custom Keys
iOS and macOS ignore custom keys you include in an Info.plist file. If
you want to include app-specific configuration information in your
Info.plist file, you can do so freely as long as your key names do not
conflict with the ones Apple uses. When defining custom key names,
prefix them with a unique prefix, such as your app’s bundle ID or your
company’s domain name, to prevent conflicts.
And you can get the value by doing something like this:
Objective-C
[[NSBundle mainBundle].infoDictionary objectForKey:#"SomeKey"];
or
[[NSBundle mainBundle] objectForInfoDictionaryKey:#"SomeKey"];
Swift
Bundle.main.infoDictionary?["SomeKey"]
Reference:
Info Plist Docs
Reserved Keys
We do access the application bundle info.plist like shown below,
Objective-C
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *appDisplayName = [infoDictionary objectForKey:#"CFBundleDisplayName"];
Swift
let appDisplayName = Bundle.main.infoDictionary?["CFBundleDisplayName"]
Similarly, If you have added any custom key-value pair in the info.plist you can surely access it. Just replace the CFBundleDisplayName with your key.
Refere this
Short Answer: Yes.
Read: Custom Keys in Apple Docs

how to change ios APP font in Hindi or tamil

enter image description hereIn iOS, can we change App localization in hindi?
I tried following examples but its only support info.plist values
https://code.tutsplus.com/tutorials/ios-sdk-localization-with-nslocalizedstring--mobile-11603
Yes, we can have any language in app.
You need to have language selection inside the app instead of device's setting language.
Define all keywords in localization bundle.
NSString *selected_lng_code = #"hi"
NSString *path = [[NSBundle mainBundle] pathForResource:selected_lng_code ofType:#"lproj" ];
NSBundle *localizedBundle = [NSBundle bundleWithPath:path];
NSString *translated_word = [localizedBundle localizedStringForKey:#"Hello" value:#"" table:nil];
You have to create on InfoPlist.strings file for localizing Info.plist value. To do so, go to File -> New -> File, choose Strings File under Resource tab of iOS, name it InfoPlist, and create it. Now open that file and add Info.plist values you want to localize like:
"CFBundleDisplayName" = "<app name>". This will be your Base file.
For your desired language, select your localized files and add translated strings.

App localization showing the key instead of the value in iOS

I've been using localization in my app, but for some reason, some of the strings (not all of them) won't translate, I see the key instead the value. I've tried to check if the app finds the localization files by doing this:
NSString *enPath = [[NSBundle mainBundle] pathForResource:#"en" ofType:#"lproj"];
NSString *hePath = [[NSBundle mainBundle] pathForResource:#"he" ofType:#"lproj"];
NSString *ruPath = [[NSBundle mainBundle] pathForResource:#"ru" ofType:#"lproj"];
NSString *esPath = [[NSBundle mainBundle] pathForResource:#"es" ofType:#"lproj"];
NSString *frPath = [[NSBundle mainBundle] pathForResource:#"fr" ofType:#"lproj"];
NSString *arPath = [[NSBundle mainBundle] pathForResource:#"ar" ofType:#"lproj"];
And none of them is nil.
I've checked the name of the localization file and it's Localizable.strings as it should be.
Also checked if the key exists inside the Localizable.strings files and it does.
I've also tried:
Empty Cache
Cleaning all targets
Delete Derived Data folder
Restart
Reset simulator
Convert to UTF-16
Remove all localization files and recreate them.
Also tried to do everything that is in this question.
It's important to say that this is not just a Simulator/Cache problem. It's also showing on devices which download the app. (I have Enterprise account).
What more can I do in order to identify nor fix the problem?
So I found the problem, I guess who translated the Localizable.strings files for me is an asshole. In 4 places in my strings file there was a row as followed:
"KEY" ;= "Value"
This line cause some kind of a crash, but let the compiler to build successfully for some reason. That's why I couldn't find the bug, only when I decided to take the last Key and Value which are not translate and move them to the top of the Localizable.strings file. Then I was able to understand and see that the problem is somewhere in the middle of the file and the top Keys and Values are translated fine.
One thing that you can do catch these kind of errors is to make a copy of the strings file, change the extension to plist and try to open it in Xcode. If there is any problem in the strings file it will show in Xcode since the dictionary will contain only the keys till the point where there is an error. You can then do a Find operation and find the error until you are sure that all strings appear in the plist file. You can then rename the file back to .strings
If you specify table:nil, then NSBundle will try to fetch the localization from the default table (the one in SOMELANG.lproj/Localizable.strings). If you have the localization elsewhere, you should explicitly specify the table using table:#"File" (or use the NSLocalizedStringFromTable() macro in a similar manner:
NSString *value = NSLocalizedStringFromTable(#"key", #"File", nil);
Also,
Double check that the Localizable.strings file is being added to
Targets -> BuildPhases -> Copy Bundle Resources
It hadn't been added automatically for me.

How can I change .plist entries based on my Scheme?

I have some App-Info.plist entries that need to change based on my environment. When I'm doing developmental work, they need to be one set of values, vs QA vs Production.
What would be nice is if I could simply have a script or something that runs based on the Scheme used to do the compilation.
Is this possible?
You can do it by performing some extra steps:
Duplicate [AppName]-Info.plist file by any name. Example: [AppName]-Info-dev.plist or [AppName]-Info-staging.plist etc
Map newly created .plist file in App's Target Settings. Get idea from following screenshot:
At the end, if you want to get some entry from .plist file then you need to get it like: [[[NSBundle mainBundle] infoDictionary] objectForKey:#"baseUrl"]
Project setting will automatically pick correct .plist file and give you required value.
I think msmq's answer is valid, but you should be a little careful about using the main info.plist this way. Doing that suggests that all your versions of info.plist are almost identical, except for a couple of differences. That's a recipe for divergence, and then hard-to-debug issues when you want to add a new URI handler or background mode or any of the other things that might modify info.plist.
Instead, I recommend you take the keys that vary out of the main info.plist. Create another plist (say "Config.plist") to store them. Add a Run Script build phase to copy the correct one over. See the Build Settings Reference for a list of variables you can substitute. An example script might be:
cp ${SOURCE_ROOT}/Resources/Config-${CONFIGURATION}.plist ${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Config.plist
Then you can read the file using something like this (based on Read in the Property List):
NSString *baseURL;
NSString *path = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSDictionary *dict = (NSDictionary *)[NSPropertyListSerialization
propertyListFromData:plistXML
mutabilityOption:NSPropertyListImmutable
format:NULL
errorDescription:&errorDesc];
if (dict != nil) {
baseUrl = dict[#"baseURL"];
} else {
NSAssert(#"Could not read plist: %#", errorDesc); // FIXME: Return error
}
There are other solutions of course. I personally generally use the preprocessor for this kind of problem. In my build configuration, I would set GCC_PREPROCESSOR_DEFINITIONS to include BaseURL=... for each build configuration and then in some header I would have:
#ifndef BaseURL
#define BaseURL #"http://default.example.com"
#endif
The plist way is probably clearer and easier if you have several things to set, especially if they're long or complicated (and definitely if they would need quoting). The preprocessor solution takes less code to process and has fewer failure modes (since the strings are embedded in the binary at compile time rather than read at runtime). But both are good solutions.
You can add a User-Defined-Setting in Xcode>Build-Settings, add its values according to all the schemes listed there. And then simply use that as a variable in Info plist file. That should work just fine.
This way you can avoid creating duplicate plist files, just for the sake of one or two different properties.

iOS - NSLocalizedString is only returning the key string

I'm having some trouble debugging my NSLocalizedString implementation. Should be simple, but whatever I do, the function only returns the KEY string.
I'm using XCode 4.5 and iOS6, so I:
Added a new file called File.strings.
In my project settings I added English and Spanish as language settings.
Clicked "Make Localized" in the file inspector, and made sure that both English and Spanish options were selected, and also that the Target membership to my target was selected.
Added "KEY" = "TestEnglish"; to my english File.strings
Added "KEY" = "TestSpanish"; to my spanish File.strings
Added NSLog(#"Localization: %#\n", NSLocalizedString(#"KEY", nil)); to my .m file.
When I run the app, the value "KEY" is always displayed printed in the NSLog.
To jump into this a bit more, I tried this as well:
NSString *path = [[NSBundle mainBundle] pathForResource:#"en" ofType:#"lproj"];
NSString *str = [[NSBundle bundleWithPath:path] localizedStringForKey:#"KEY" value:#"" table:nil];
NSLog(#"Localization: %#\n", str);
and still the value "KEY" is printed, yet, path is a valid path.
Does anyone have any clue how to debug this? I feel like I've read every SO question/answer out there, but none of the suggestions help.
I realize that NSLocalizedString returns the KEY string when it cannot match a key, but I don't see how I can debug why my app might not be matching the KEY.
I've also deleted/cleaned the app about a dozen times.
If you specify table:nil, then NSBundle will try to fetch the localization from the default table (the one in SOMELANG.lproj/Localizable.strings). If you have the localization elsewhere, you should explicitly specify the table using table:#"File" (or use the NSLocalizedStringFromTable() macro in a similar manner:
NSString *value = NSLocalizedStringFromTable(#"key", #"File", nil);
Rename the InfoPlist.strings file to Localizable.strings (double clic) and then you will get the correct string for that key.
In my case the issue was with the case of the string:
"bla.bla.blabla.BookSlot" whereas the Localizable.strings had it defined as "bla.bla.blabla.Bookslot"
So, double-check that the key string is in the correct case. Better yet, copy-paste.

Resources