I followed this Tutorial to use resources in my ios static library.
Now, I can use images, xib files, plist files... into my static library but I can't use localized resources..
In my bundle resources I can see all (for example) images into correct folders (es: english image into en.lproj folder)
But .. when I load the image, I see always the english image also when my language device is different from english.
I have same problem about localized strings: always I see only english localized strings.
* EDIT **
I could not find a better solution for this problem ..
I was in a hurry to fix this so I duvuto apply this method to solve the problem with the localized images:
+ (NSString*) getLocalizedPathImageWithImageName:(NSString*) aImageName
{
NSString *currentDeviceLanguage = [[NSLocale preferredLanguages] objectAtIndex:0];
NSString *resourceBundlePath = [[NSBundle mainBundle] pathForResource:BUNDLE_RESOURCESNAME ofType:#"bundle"];
NSString *completeLocalizedImageName = [aImageName stringByAppendingFormat:#"_%#",currentDeviceLanguage];
NSString *imagePath = [[NSBundle bundleWithPath:resourceBundlePath] pathForResource:completeLocalizedImageName ofType:USERBUTTON_PNG_FILEEXTENSION];
if (imagePath == nil) {
completeLocalizedImageName = [aImageName stringByAppendingFormat:#"_%#",DEFAULT_LANGUAGE];
imagePath = [[NSBundle bundleWithPath:resourceBundlePath] pathForResource:completeLocalizedImageName ofType:USERBUTTON_PNG_FILEEXTENSION];
}
return imagePath;
}
a better solution is welcome
Related
This is likely not limited to iOS Universal Frameworks but all xxx.framework files. However I can't seem to find documentation on how to get the current version and build of a framework within the client application. Within an app you'd use something like:
NSString *name = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleDisplayName"];
NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleShortVersionString"];
That would give you the current information stored in the Info.plist for the app. But how to we find that information for a framework. And in my case, specifically an embedded framework.
Here's a solution that does work with Universal Frameworks. Just replace SomeFrameworkClass with a class from the desired framework.
if let sdkVersion = Bundle(for: SomeFrameworkClass.self).infoDictionary?["CFBundleShortVersionString"] {
// sdkVersion is available here
}
I have found that Apple's new Cocoa Touch frameworks supported in Xcode 6, offer an easy answer to this problem. In the default header file created for you, something like Framework.h, you'll see two constants declared for you. These are defined later presumably at runtime by internal framework logic. But I have confirmed they're pulled from the plist for the framework.
//! Project version number for LocalSearch.
FOUNDATION_EXPORT double FrameworkVersionNumber;
//! Project version string for LocalSearch.
FOUNDATION_EXPORT const unsigned char FrameworkVersionString[];
Let's say Foo is a class from the given framework, you can use something like :
NSDictionary *infoDictionary = [[NSBundle bundleForClass: [Foo class]] infoDictionary];
NSString *name = [infoDictionary valueForKey:(__bridge NSString*)kCFBundleNameKey];
NSString *version = [infoDictionary valueForKey:(__bridge NSString*)kCFBundleVersionKey];
NSLog(#"%# version %#", name, version);
In Swift :
// `Foo` is a type defined in the framework
if let infos = Bundle(for: Foo.self).infoDictionary,
let name = infos[kCFBundleNameKey as String],
let version = infos[kCFBundleVersionKey as String] {
print("Using \(name) version \(version)")
if let shortVersion = infos["CFBundleShortVersionString"] as? String {
print("Short version : " + shortVersion)
}
}
Note : For some reason, "CFBundleShortVersionString" is not defined in a constant, cf Is there a constant defined for CFBundleShortVersionString in iOS/MacOS framework
This is for who may want to have a function on your framework that returns or print on the console it's version with build number. Just make sure you are using the class you are sharing on your Framework.h when declaring the *infoDictionary. In my example I'm using a class named cloud
+(NSString *)frameWorkVersion {
NSDictionary *infoDictionary = [[NSBundle bundleForClass: [cloud class]] infoDictionary];
NSString *version = [infoDictionary objectForKey:#"CFBundleShortVersionString"];
NSString *build = [infoDictionary objectForKey:(NSString *)kCFBundleVersionKey];
NSString *fVersion = [NSString stringWithFormat:#"%#.%#",version,build];
NSLog(#"Framework Version %#",fVersion);
return fVersion; }
Let say I already put everything on Localizable.strings for several language. As for now I use NSLocalizedString and it return the text based on [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"] setting. Now I need to get specific string for each language.
Let say I want to put it on select language setting and show it when user press Submit button. So it will show a dialog with a message "Select this language?" on respective language that user select.
You can get any translation from any language file by loading it manually:
- (NSString *)localizedString:(NSString *)string forCountry:(NSString *)countryCode {
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"Localizable" ofType:#"strings" inDirectory:nil forLocalization:countryCode];
NSBundle *dataBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
return NSLocalizedStringFromTableInBundle(string, #"Localizable", dataBundle, nil); }
Does this help?
How can I read a localised plist as dictionary? This felt promising …
if let path = NSBundle.mainBundle().pathForResource("LocalizedDictionary", ofType: "plist", inDirectory: ???, forLocalization: "en") {
localizedDictionary = NSDictionary(contentsOfFile: path)
return localizedDictionary
}
But I apparently I had issues getting right path for the inDirectory parameter. Is this the right approach?
How do I get the localised version of a plist file as Dictionary?
Note: I am not using NSLocalizedString as I had issues without switching languages while the app is running.
Here's something that should help.
Create a NSDictionary class extension like this.
It can be tweaked and adapted to your needs ( to load 'strings' dictionaries for exemple, or passing the locale in a parameter… )
#implementation NSDictionary (NSDictionary_Extras)
+(NSDictionary*)dictionaryWithName:(NSString*)name
{
NSDictionary *dict = NULL;
NSURL *dictURL = [[NSBundle mainBundle] URLForResource:name withExtension:#"plist"];
if (dictURL) {
dict = [NSDictionary dictionaryWithContentsOfURL:dictURL];
}
return dict;
}
+(NSDictionary*)localizedDictionaryWithName:(NSString*)name
{
NSDictionary *localizedDict = NULL;
NSString *localizationName = [[NSLocale preferredLanguages] objectAtIndex:0];
NSURL *localizedDictURL = [[NSBundle mainBundle] URLForResource:name withExtension:#"plist" subdirectory:[NSString stringWithFormat:#"%#.lproj",localizationName]];
// If resource doe not exist, we try at root ( resource must have a 'base' localization, or not being localized )
if (!localizedDictURL) {
localizedDictURL = [[NSBundle mainBundle] URLForResource:name withExtension:#"plist"];
}
if (localizedDictURL) {
localizedDict = [NSDictionary dictionaryWithContentsOfURL:localizedDictURL];
}
return localizedDict;
}
#end
Then you simply load a plist using :
NSDictionary* myDict = [NSDictionary dictionaryWithName:#"myDict"]
Or a localized plist with
NSDictionary* myDict = [NSDictionary localizedDictionaryWithName:#"myDict"].
I import this extra in all my projects.
You don't need to change any code.
xCode's resource localisation is neat and can frequently be completely transparent to you. You just ask the main bundle for resource urls as normal and load from them. NSBundle performs any mapping required to give you localised resources.
There's a tutorial here that got me going. It's a little out of date, but none of the significant details have changed.
I have created a custom plist named as test.plist in Supporting Files folder. In that i stored App product name and App version number.
Now, how could i get product name from test.plist for PRODUCT NAME in Build Settings in Target.
I can get values from user defined build settings. But i don't want that.
Note: I need to store product name in test.plist only. And others can access the value from this file.
Thanks in Advance..
you can read the values from the plist in main bundle, put below code in viewDidLoad , method, Please note that all files in main bundle are read only if you want to write any data to plist then you have to copy it to app's document directory
NSString *bundle = [[NSBundle mainBundle] pathForResource:#”test” ofType:#”plist”];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:bundle];
NSString *productName = [dict objectForKey:#"ProductName"];
NSString * appVersion = [dict objectForKey:#"AppVersion"];
Another way is to read app properties
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleDisplayName"];
NSString appVersion = [NSString stringWithFormat:#"Version %# (%#)", [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"], kRevisionNumber];
Hope it helps!
I have made an ios app that is localized to two languages (english and danish, english being default).
I have made a Localizable.strings with two subfiles, en and da.
Everything should be made correctly, and i see the english texts load fine from the strings file. But the danish ones do not.
I have tried to check the preferred language via below code and it is danish.
[[NSLocale preferredLanguages] objectAtIndex:0];
I have tried clean + delete and rebuild with no luck.
I know that the Localizable.strings file is working since it is getting the english texts. and i know that it is seeing the danish localization via the above line of code.
What am i missing?
Just to add a couple of examples:
from the EN:
"YesButton" = "Done";
"NoButton" = "Not yet!";
"NextButton" = "Next";
"BackButton" = "Back";
"EditButton" = "Edit";
"DoneButton" = "Done";
and the DANISH:
"YesButton" = "Færdig";
"NoButton" = "Ikke endnu!";
"NextButton" = "Næste";
"BackButton" = "Tilbage";
"EditButton" = "Redigér";
"DoneButton" = "Færdig";
and the code for getting the text would be:
[yesButton setTitle:NSLocalizedString(#"YesButton", nil) forState:UIControlStateNormal];
which is returning "Done" even when preferredLang is da (danish)!
Hope somebody has an idea? :)
Thanks in advance.
EDIT:::
Something was wrong with the actual DANISH-DENMARK localization. i dont know if apple updated it or what they did but it went from being called "Danish-Denmark" to just "Danish".
After making a whole new Danish localization and deleting the old one it worked! crazy stuff. keeps you scratching your head!
I had similar thing happened to me before. All I did to fix the problem was to change the string encoding from:
encoding:NSASCIIStringEncoding
to
encoding:NSUTF8StringEncoding
~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.
Now assume the problem is not string encoding. You can also work around it and do something like:
NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0];
NSString yesButtonStr=#"";
NSString noButtonStr=#"";
NSString nextButtonStr=#"";
if([#"en" caseInsensitiveCompare:language] == NSOrderedSame )
{
yesButtonStr = #"Done";
noButtonStr= #"Not yet!";
nextButtonStr = #"Next";
//...
}
else if if([#"da" caseInsensitiveCompare:language] == NSOrderedSame )
{
yesButtonStr = #"Færdig";
noButtonStr = #"Ikke endnu!";
nextButtonStr = #"Næste";
//...
}
Then:
[yesButton setTitle:NSLocalizedString(yesButtonStr, nil) forState:UIControlStateNormal];
Try this,
NSString *translatedString = [self languageSelectedStringForKey:#"YesButton"]; // Give your key here
-(NSString*) languageSelectedStringForKey:(NSString*) key
{
NSString *path;
path = [[NSBundle mainBundle] pathForResource:#"en" ofType:#"lproj"]; // give your language type in pathForResource, i.e. "en" for english, "da" for Danish
NSBundle* languageBundle = [NSBundle bundleWithPath:path];
NSString* str=[languageBundle localizedStringForKey:key value:#"" table:nil];
return str;
}
Hope this helps, Thanks. Happy coding
There was something wrong with the actual danish localization.
When i started making the localization it was called "Danish-Denmark". After an update of ios and/or xcode, it is now only "Danish".
So had to make a whole new localization.
Thank you apple...... NOT!