I'm trying to use NSLocalizedStringFromTable but with no results. I've got created Profile.strings file, clicked localized, in project settings I add Polish and English languages, so my file has 2 "files" inside and I typed the same strings with other values but when I switch languages and restart app there is still one localization used (Polish).
Profile.strings in Xcode:
Profile.strings
Profile.strings (Polish)
Profile.strings (English)
Polish:
"fullName.placeholder" = "Imie i nazwisko";
"emailAddress.placeholder" = "Adres email";
"phoneNumber.placeholder" = "Numer telefonu";
English:
"fullName.placeholder" = "Full name";
"emailAddress.placeholder" = "Email address";
"phoneNumber.placeholder" = "Phone number";
To get value I call:
NSLocalizedStringFromTable(#"fullName.placeholder", #"Profile", #"");
Any time I call this I've got value from Profile.strings (Polish)
What I'm doing wrong?
try to Reset Content and Settings of simulator it will work (:
Maybe you're not changing the language correctly. Try doing it in code. Like this:
- (void) setLanguage:(NSString*) l{
for (NSString *language1 in [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"]) {
NSBundle *bundle1 = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language1 ofType:#"lproj"]];
NSLog(#"%#: %#", language1, NSLocalizedStringFromTableInBundle(#"left", #"Localizable", bundle1, nil));
}
NSBundle *bundle1 = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:l ofType:#"lproj"]];
/*
if ([l isEqualToString:#"en"]) {
bundle1 = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:#"English" ofType:#"lproj"]];
}
*/
if (bundle1 == nil)
//in case the language does not exists
[self resetLocalization];
else
bundle = bundle1;
NSMutableArray *langs = [NSMutableArray arrayWithArray: [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"]];
[langs removeObject:l];
NSMutableArray *newLangs = [NSMutableArray arrayWithObject:l];
[newLangs addObjectsFromArray:langs];
[[NSUserDefaults standardUserDefaults] setObject: newLangs forKey:#"AppleLanguages"];
}
And then you can do
[self setLanguage:#"en"];
Related
I build a Macro for NSLocalizedString like this in my Prefix.pch:
#undef NSLocalizedString
#define NSLocalizedString(key,_comment) [[LocalizedText sharedInstance] localizedStringFor:key]
My LocalizedText class looks like this:
+ (LocalizedText *)sharedInstance {
#synchronized(self)
{
if (_singletonInstance == nil)
_singletonInstance = [[LocalizedText alloc] init];
}
return _singletonInstance;
}
- (NSString *) localizedStringFor:(NSString*) key
{
NSUserDefaults *deviceLanguage = [NSUserDefaults standardUserDefaults];
NSString *currentLanguage = [deviceLanguage objectForKey:#"deviceLanguage"];
NSString *path;
if([currentLanguage isEqual: #"en"])
path = [[NSBundle mainBundle] pathForResource:#"en" ofType:#"lproj"];
else if([currentLanguage isEqual: #"de"])
path = [[NSBundle mainBundle] pathForResource:#"de" ofType:#"lproj"];
else if([currentLanguage isEqual: #"it"])
path = [[NSBundle mainBundle] pathForResource:#"it" ofType:#"lproj"];
NSBundle* languageBundle = [NSBundle bundleWithPath:path];
NSString* str=[languageBundle localizedStringForKey:key value:#"" table:nil];
return str;
}
So for example, when i change my NSUserDefaults to #"en", i expect that every NSLocalizedString gives me the correct english translation, but it never changes and is always the default language. Whats wrong with my code?
Before debugging your Macro, I would set up a test as follows:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *currentLanguage = [defaults objectForKey:#"deviceLanguage"];
NSString *key = #"SomeKeyFromYourLocalizedFile";
NSString *localized = [[LocalizedText sharedInstance] localizedStringFor:key];
NSLog(#"%#: %#", currentLanguage, localized);
[defaults setObject:#"de" forKey:#"deviceLanguage"];
[defaults synchronize];
NSString *localized = [[LocalizedText sharedInstance] localizedStringFor:key];
NSLog(#"%#: %#", currentLanguage, localized);
[defaults setObject:#"it" forKey:#"deviceLanguage"];
[defaults synchronize];
NSString *localized = [[LocalizedText sharedInstance] localizedStringFor:key];
NSLog(#"%#: %#", currentLanguage, localized);
And see the output of that. Your bug is probably somewhere in there.
I expect:
en: English localized
de: German localized
it: Italian localized
After that, you would simply use your macro (which looks like it will work just like that). I tried:
#ifdef NSLocalizedString
#undef NSLocalizedString
#endif
#define NSLocalizedString(key, comment) NSLog(#"Output %#, %#", key, comment)
NSLocalizedString(#"First", #"Second");
Which results in:
2017-01-12 14:31:31.501 App[49000:50650596] Output First, Second
This question already has answers here:
Change Language in the app programmatically in iOS
(3 answers)
Closed 6 years ago.
In my iOS app I need an option to change language. Can we change it without changing the language in the device settings
You can use following code to set the language
- (void) setLanguage:(NSString*) lang {
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:#"lproj"];
if (path == nil) {
myBundle = [NSBundle mainBundle];
} else {
myBundle = [NSBundle bundleWithPath:path];
}
if (myBundle == nil) {
myBundle = [NSBundle mainBundle];
}
}
And after that you can get the localizations with
- (NSString*) localizedStringForKey:(NSString*) key {
return [myBundle localizedStringForKey:key value:#"" table:nil];
}
For example store different static json/plist and etc in your app with different languages strings and when you switch option parse this and set to labels.
i am not sure but try this code once using NSUserDefaults
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray* languages = [userDefaults objectForKey:#"AppleLanguages"];
[languages insertObject:#"de" atIndex:0]; // ISO639-1
[[NSUserDefaults standardUserDefaults] synchronize];
I have an app settings file which displays the version number for our app. The idea is to update the Root.plist on compile so that we don't have to update two places rather than one. We update theBuild settings version and would like those settings to update the Root.plist on compile.
This code extracts the information for the build settings, how do I update the Root.plist file?
NSString *appBuildNo = [[NSBundle mainBundle]objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
NSString *appBuildVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"];
NSString *appBuildStr = [NSString stringWithFormat:#"%# Build %#", appBuildNo, appBuildVersion];
NSURL * settingsURL = [[NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:#"Settings" withExtension:#"bundle"]]
URLForResource:#"Root" withExtension:#"plist"];
NSDictionary * settingsDict = [NSDictionary dictionaryWithContentsOfURL:settingsURL];
NSArray * settingsArr = [settingsDict objectForKey:#"PreferenceSpecifiers"];
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
for( NSDictionary * setting in settingsArr ){
NSString * key = [setting objectForKey:#"DefaultValue"];
[defaults setValue:appBuildStr forKey:key];
[defaults synchronize];
break;
}
The idea is that defaults updates Root.plist but it is not working. Any help would be appreciated
Droppy was very helpful in helping me to fix this. After setting up my Settings Bundle and the Root.plist file, I added the following code to my AppDelegate and called it from the didFinishLaunchingWithOptions.
- (void)updateVersionInfo
{
//This method updates the Root settings to display current Version and Build No in Settings Bundle
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *appVersionNumber = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
NSString *appBuildNo = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
NSString *versionNumberInSettings = [NSString stringWithFormat:#"%# Build %#", appBuildNo, appVersionNumber];
[defaults setObject:versionNumberInSettings forKey:#"version"];
}
This code then adds the contents of the Version in the info.plist file to my Settings Bundle.
I have a project divided in layers, and the bottom one is included in the top one as a static lib.
The thing is that I need to localize a string in the static lib, using the translations present in my app (upper layer).
Is this possible somehow?
The way I managed to do this is loading the strings from a bundle instead of using NSLocalizedString:
+ (NSString *)getTranslationFromAppBundleForString:(NSString *)originalText {
NSString * lang = [[NSLocale preferredLanguages] objectAtIndex:0];
NSString * bundlePath = [[NSBundle mainBundle] pathForResource:lang ofType:#"lproj"];
NSBundle * bundle = [NSBundle bundleWithPath:bundlePath];
return [bundle localizedStringForKey:originalText value:originalText table:nil];
}
You can create an LanguageAgent in your static library, add a bundle ressource in that library. Then use a function like this to get localizedString. In my application, I separate language by different table (see picture below for a table named 'Dictionaire'. You can have more than 1 table in your languages bundle.
-(NSString*) myLocalizedStringForKey:(NSString*) key ofTable:(NSString*)tableName {
//I save selected language in my NSUserDefaults.
NSString *selectedLanguage = [[NSUserDefaults standardUserDefaults] stringForKey:#"DefaultLanguage"];
if (selectedLanguage == nil) {
[[NSUserDefaults standardUserDefaults] setValue:#"en" forKey:#"DefaultLanguage"];
[[NSUserDefaults standardUserDefaults] synchronize];
selectedLanguage = [[NSUserDefaults standardUserDefaults] stringForKey:#"DefaultLanguage"];
}
NSString *langBundleNew = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingFormat:#"/langs/Languages.bundle/%#.lproj/",selectedLanguage]; //use your path to the Languages.bundle here.
if ([[NSFileManager defaultManager] fileExistsAtPath:langBundleNew]) {
NSBundle *aBundle = (NSBundle*)[self.dictLangueBundle objectForKey:selectedLanguage];
NSString* str=[aBundle localizedStringForKey:key value:#"[string not defined]" table:tableName];
return str;
} else {
return #"[]";
}
}
My language bundle is similar like this: ('Dictionaire' = name of the table)
Here is a sample of content in my Dictionnaire.strings for 'en.lproj':
So when I click "View User Record" button I want to display whatever value of Score and Live of a view controller and store it in a plist as an array. And then those values from the plist will be displayed into the table view
try this for adding value in plist file .
NSString* plistPath = nil;
NSFileManager* manager = [NSFileManager defaultManager];
if (plistPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:#"Contents/Info.plist"])
{
if ([manager isWritableFileAtPath:plistPath])
{
NSMutableDictionary* infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
[infoDict setObject:[NSNumber numberWithBool:hidden] forKey:#"LSUIElement"];
[infoDict writeToFile:plistPath atomically:NO];
[manager changeFileAttributes:[NSDictionary dictionaryWithObject:[NSDate date] forKey:NSFileModificationDate] atPath: [[NSBundle mainBundle] bundlePath]];
}
}
And This is for Get Value from plist file.
NSBundle* mainBundle = [NSBundle mainBundle];
// Reads the value of the custom key I added to the Info.plist
NSString *value = [mainBundle objectForInfoDictionaryKey:#"key"];
//Log the value
NSLog(#"Value = %#", value);
// Get the value for the "Bundle version" from the Info.plist
[mainBundle objectForInfoDictionaryKey:#"CFBundleVersion"];
// Get the bundle identifier
[mainBundle bundleIdentifier];
i hope this code is useful for you.