您的位置:首页 > 移动开发

How to force NSLocalizedString to use a specific language iOS APP内国际化

2016-03-16 00:00 741 查看
http://stackoverflow.com/questions/1669645/how-to-force-nslocalizedstring-to-use-a-specific-language?lq=1

on iPhone
NSLocalizedString
returns
the string in the language of the iPhone. Is it possible to force
NSLocalizedString
to
use a specific language to have the app in a different language than the device ?

ios objective-c cocoa localization internationalization
shareimprove
this question
edited Jan
7 at 9:25





Meet Doshi
939827

asked Nov 3 '09 at 19:33





CodeFlakes
1,33731423

add
a comment


22 Answers

activeoldestvotes

up vote177down
voteaccepted
NSLocalizedString()
(and
variants thereof) access the "AppleLanguages" key in
NSUserDefaults
to
determine what the user's settings for preferred languages are. This returns an array of language codes, with the first one being the one set by the user for their phone, and the subsequent ones used as fallbacks if a resource is not available in the preferred
language. (on the desktop, the user can specify multiple languages with a custom ordering in System Preferences)

You can override the global setting for your own application if you wish by using the setObject:forKey: method to set your own language list. This will take precedence over the globally set value and be returned to any code in your application that is performing
localization. The code for this would look something like:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate


This would make German the preferred language for your application, with English and French as fallbacks. You would want to call this sometime early in your application's startup. You can read more about language/locale preferences here: Internationalization
Programming Topics: Getting the Current Language and Locale

shareimprove
this answer
edited Jan
20 at 6:01





chancyWu
3,91532643

answered Nov 3 '09 at 22:23





Brian Webster
8,88033351

3
This does not work for me, it will use the default language no matter what. – quano Feb
22 '10 at 17:41
2
This didn't work for me, so I used, [[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el",
nil] forKey:@"AppleLanguages"]; – Panagiotis
Korros Mar
8 '10 at 13:32
38
Denniss; It seems to work better if you set the language preference before the
app is launched. I do it in the main() function, before UIApplicationMain() is called. Once it is actually running, it won't change the used language, but just set the preference for the next time. – geon Sep
1 '10 at 21:44
3
You have to set the language before you initialize UIKit and you must specify a complete language+region locale - check
this out for a complete example blog.federicomestrone.com/2010/09/15/…fedmest Apr
21 '11 at 9:16
10
setting AppleLanguages will change a language at runtime if done in main() - true! but... the FIRST TIME the app is
installed, the nsuserdefaults are initialized AFTER UIApplicationMain() is called, which will ignore the previously set AppleLanguages and will require an ugly force-restart of the app to see the desired language.– JohnPayne Sep
9 '13 at 1:02
show 10 more
comments
up vote111down
vote
I usually do this in this way, but you MUST have all localization files in your project.
@implementation Language

static NSBundle *bundle = nil;

+(void)initialize {
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString *current = [[languages objectAtIndex:0] retain];
[self setLanguage:current];

}

/*
example calls:
[Language setLanguage:@"it"];
[Language setLanguage:@"de"];
*/
+(void)setLanguage:(NSString *)l {
NSLog(@"preferredLang: %@", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];
bundle = [[NSBundle bundleWithPath:path] retain];
}

+(NSString *)get:(NSString *)key alter:(NSString *)alternate {
return [bundle localizedStringForKey:key value:alternate table:nil];
}

@end


shareimprove
this answer
answered Nov 17 '09 at 6:11





Mauro Delrio
1,223179

1
+1. This is a really nice trick that I haven't seen anywhere else. By creating a "sub bundle" from one of the localization
folders, you can get the string stuff to work fine as long as you wrap NSLocalizedString with something that detours here. – Ben
Zotto Jun
28 '10 at 15:44
4
Excellent Mauro. I noticed that it can also work for files out of your project. If for some reason (as in my case),
you need to download strings files from network, and store them in your 'Documents' directory (with the folder structure Documents/en.lproj/Localizable.strings, Documents/fr.lproj/Localizable.strings, ...). You can even though make a NSBundle. Just use this
code for path : NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"/Documents/%@.lproj", l, nil]]; – arnaud
del. Feb
6 '12 at 21:13
1
Seems to me that this is the best approach, along with the contribution from Alessandro below. It's not so intrusive
and shouldn't require a restart. – PKCLsoft Feb
29 '12 at 3:37
1
What am I doing wrong? I made a Language class, inheriting NSObject, put this in the implementation, put the method
names in .h, then put [Language setLanguage:@"es"]; in my Change Language Button, code runs(button method gets called, and goes to Language class), but does nothing. I have my localizable.strings (Spanish) set up too. But it seems to be working for a lot of
other people. Please someone dumb it down for me. – KKendall Nov
19 '12 at 23:37
1
@KKendall you call it like this: [Language setLanguage:@"es"]; NSString *stringToUse = [Language get:@"Your Text" alter:nil]; – Mikrasya Sep
28 '13 at 19:08
show 7 more
comments
up vote82down
vote
I had the same problem recently and I didn't want to start and patch my entire NSLocalizedStringnor force the app to restart for the new language to work. I wanted everything to work as-is.

My solution was to dynamically change the main bundle's class and load the appropriate bundle there:

Header file
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end


Implementation
#import <objc/runtime.h>

static const char _bundle=0;

@interface BundleEx : NSBundle
@end

@implementation BundleEx
-(NSString*)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
NSBundle* bundle=objc_getAssociatedObject(self, &_bundle);
return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName];
}
@end

@implementation NSBundle (Language)
+(void)setLanguage:(NSString*)language
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
object_setClass([NSBundle mainBundle],[BundleEx class]);
});
objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end


So basically, when your app starts and before you load your first controller, simply call:
[NSBundle setLanguage:@"en"];


When your user changes his preferred language in your setting screen, simply call it again:
[NSBundle setLanguage:@"fr"];


To reset back to system defaults, simply pass nil:
[NSBundle setLanguage:nil];


Enjoy...

shareimprove
this answer
answered Nov 28 '13 at 4:12





Gilad
2,00911835

4
Hi @Wirsing , this works great for me so far. I've even uploaded one app to the store and no complains by Apple. – Gilad Mar
25 '14 at 18:04
4
This is a great solution, I've also referencing this here: medium.com/ios-apprentice/905e4052b9de – James
Tang May
6 '14 at 8:34
1
Hi @JamesTang , Thanks for the reference and your post - I found a lot of useful information there regarding localization. – Gilad May
7 '14 at 3:55
1
@Gilad your method works perfect for dynamic strings (strings that i defined in localizable.strings) but as for storyboard
buttons and labels it only work at main method only. so can you extend your answer to include UI controls localization? i mean how to refresh (without closing) storyboard after i invoke [NSBundle setLanguage:@"??"];? – Jawad
Al Shaikh May
14 '14 at 9:09
1
Thanks for the solution, But its not working with xib views – mohammad
alabid May
14 '14 at 20:31
show 14 more
comments
up vote36down
vote
Do not use on iOS 9. This returns nil for all strings passed through it.

I have found another solution that allows you to update the language strings, w/o restarting the app and compatible with genstrings:

Put this macro in the Prefix.pch:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]


and where ever you need a localized string use:
NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")


To set the language use:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];


Works even with consecutive language hopping like:
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"fr"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"it"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));


shareimprove
this answer
edited Oct
14 '15 at 17:00





Alex Zavatone
1,5881125

answered Oct 28 '11 at 18:40





Tudorizer
2,93742646

1
Does this work with changing strings setup in xibs though? – powerj1984 Oct
30 '12 at 14:28
Nice one! Thank you! – Mikael Nov
28 '13 at 19:21
1
@powerj1984: no, it will change only the strings in your source files. If you want to change the xib languages, you
have to reload the xibs by hand, from the bundle of your selected language. – gklka Jan
23 '14 at 21:57
@gklka I have follow the steps given by Tudozier but my XIB's are not changing the language , as you told reload XIB
by hand , what tis actually mean to reload XIBs ? – Dk
Kumar Feb
22 '14 at 8:55
1
This is horribly broken in iOS 9, returning the null for all strings. – Alex
Zavatone Oct
14 '15 at 16:25
show 5 more
comments
up vote30down
vote
As said earlier, just do:
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];


But to avoid having to restart the app, put the line in the main method of
main.m
,
just before
UIApplicationMain
(...).

shareimprove
this answer
edited May
1 '13 at 5:19





Paras Joshi
15.1k63253

answered Jun 25 '10 at 12:44





Frédéric Feytons
36946

1
+1 great suggestion! – Dave
DeLong Jun
25 '10 at 21:20
2
Very helpful answer! P.S. May sound obvious to non-beginners, but you should insert that line after
NSAutoreleasePool
* pool ..
or a few autoreleased objects will leak. – pt2ph8 Jul
18 '11 at 16:52
1
IMPORTANT: This won't work if you call
[[NSBundle
mainBundle] URLForResource:withExtension:]
before. – Kof Jul
30 '13 at 8:31
Worked Great for me.. +1... – Mitesh
Khatri Sep
5 '14 at 9:20
1
What about if using Swift, then there is no main.m? – turingtested Nov
24 '15 at 18:22
add
a comment
up vote30down
vote
The trick to use specific language by selecting it from the app is to force the
NSLocalizedString
to
use specific bundle depending on the selected language ,

here is the post i have written for this learning advance localization
in ios apps

and here is the code of one sample app advance localization in ios apps

shareimprove
this answer
edited Jun
19 '13 at 13:26





NANNAV
3,30731739

answered May 1 '11 at 17:33





object2.0
743911

1
This is excellent. I wish I could give you more upvotes! – Luke May
13 '11 at 3:01
It works on iOS7 as well, I have to switch from Brian's solution to this as it seems like iOS overrides the languages
option again thus I stuck with the first-time setting of language. Your solution works like a charm! – haxpor Dec
28 '13 at 12:59
add
a comment
up vote11down
vote
I like best Mauro Delrio's method. I also have added the following in my Project_Prefix.pch
#import "Language.h"
#define MyLocalizedString(key, alt) [Language get:key alter:alt]


So if you ever want to use the standard method (that uses NSLocalizedString) you can make a quick syntax substitution in all files.

shareimprove
this answer
answered Jan 27 '11 at 12:38





AlessandroDN
14518

1
I also like his method and I add a method to load png images: +(UIImage )imageNamed:(NSString
*)imageFileName{ NSString fullPath = [bundle pathForResource:imageFileName ofType:@"png"]; UIImage* imageObj = [[UIImage alloc] initWithContentsOfFile:fullPath]; return [imageObj autorelease]; } – Jagie Jul
11 '11 at 13:04
add
a comment
up vote9down
vote
As Brian Webster mentions, the language needs to be set "sometime early in your application's startup". I thought
applicationDidFinishLaunching:
of
the
AppDelegate
should
be a suitable place to do it, since it's where I do all other initialization.

But as William Denniss mentions, that seems to have an effect only after the app is restarted, which is kind of useless.

It seems to work fine if I put the code in the main function, though:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// Force language to Swedish.
[[NSUserDefaults standardUserDefaults]
setObject:[NSArray arrayWithObject:@"sv"]
forKey:@"AppleLanguages"];

int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}


I'd appreciate any comments on this.

shareimprove
this answer
edited May
1 '13 at 5:20





Paras Joshi
15.1k63253

answered Sep 1 '10 at 22:04





geon
3,0351827

in my implementation it's a user-settable thing – so I just pop up a dialog telling them they'll need to restart :) – William
Denniss Sep
4 '10 at 1:41
It Works, almost for all - except for the localized Default.png image. – Lukasz Nov
30 '10 at 7:40
1
If you're letting users set a language and then telling them to restart the app, just remember that the NSUserDefaults
might not be saved if they restart too quickly. Most users aren't this fast, but when you're testing the app you might be too fast and see inconsistent behavior as a result. It took me a couple hours to realize why my language switch was sometimes working
and sometimes not! – arlomedia Jan
4 '13 at 7:21
1
That's not an issue, just use
[[NSUserDefaults
standardUserDefaults] synchronize];
after calling
setObject:forKey:
einsteinx2 Feb
1 '13 at 1:38
add
a comment
up vote7down
vote
I came up with a solution that allows you to use
NSLocalizedString
.
I create a category of
NSBundle
call
NSBundle+RunTimeLanguage
.
The interface is like this.
// NSBundle+RunTimeLanguage.h
#import <Foundation/Foundation.h>
@interface NSBundle (RunTimeLanguage)
#define NSLocalizedString(key, comment) [[NSBundle mainBundle] runTimeLocalizedStringForKey:(key) value:@"" table:nil]
- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName;
@end


The implementation is like this.
// NSBundle+RunTimeLanguage.m
#import "NSBundle+RunTimeLanguage.h"
#import "AppDelegate.h"

@implementation NSBundle (RunTimeLanguage)

- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSString *path= [[NSBundle mainBundle] pathForResource:[appDelegate languageCode] ofType:@"lproj"];
NSBundle *languageBundle = [NSBundle bundleWithPath:path];
NSString *localizedString=[languageBundle localizedStringForKey:key value:key table:nil];
return localizedString;
}
@end


Than just add import
NSBundle+RunTimeLanguage.h
into
the files that use
NSLocalizedString
.

As you can see I store my languageCode in a property of
AppDelegate
.
This could be stored anywhere you'd like.

This only thing I don't like about it is a Warning that
NSLocalizedString
marco
redefined. Perhaps someone could help me fix this part.

shareimprove
this answer
edited Apr
30 '14 at 19:14





Ugo
1,92821622

answered Apr 30 '14 at 18:53





qman64
11113

1
Add
#undef
NSLocalizedString
just before
#define
to
disable the warning – beryllium May
3 '14 at 19:02
Thanks beryllium!!! – qman64 Aug
19 '14 at 21:55
Does this work on localization for xib file ? I have .xib file and .strings to translate UIs name in particular language.
I tried and it does not work with XIB but I am not sure if I have done things correctly – Kong
Hantrakool Mar
1 '15 at 18:18
Kong sorry for the delayed response. This works where ever you use NSLocalizedString. So it will not work directly in
an XIB. You would need IBOutlets to the strings in the XIB and then would have to programmatically set the string values in code. – qman64 Oct
12 '15 at 23:29
add
a comment
up vote5down
vote
NSLocalizedString()
reads
the value for the key
AppleLanguages
from
the standard user defaults (
[NSUserDefaults
standardUserDefaults]
). It uses that value to choose an appropriate localization among all existing localizations at runtime. When Apple builds the user defaults dictionary at app launch, they look up the preferred language(s) key in the system preferences
and copy the value from there. This also explains for example why changing the language settings in OS X has no effect on running apps, only on apps started thereafter. Once copied, the value is not updated just because the settings change. That's why iOS
restarts all apps if you change then language.

However, all values of the user defaults dictionary can be overwritten by command line arguments. See
NSUserDefaults
documentation
on the
NSArgumentDomain
.
This even includes those values that are loaded from the app preferences (.plist) file. This is really good to know if you want to change a value just once for testing.

So if you want to change the language just for testing, you probably don't want to alter your code (if you forget to remove this code later on ...), instead tell Xcode to start your app with a command line parameters (e.g. use Spanish localization):



No need to touch your code at all. Just create different schemes for different languages and you can quickly start the app once in one language and once in another one by just switching the scheme.

shareimprove
this answer
answered Sep 10 '14 at 10:28





Mecki
52.4k21108150

add
a comment
up vote4down
vote
In file .pch to define:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")


shareimprove
this answer
edited Jun
19 '13 at 13:26





NANNAV
3,30731739

answered Mar 13 '13 at 15:19





MrPiliffo
411

How do I get rid of the warning 'ovverride...'? – Idan
Moshe Feb
19 '14 at 13:33
Simple solution does everything I need. Was able to use this as a guide to solve my problem. If pathForResource returns
nil because I don't have a localization file then I use pathForResource:@"Base" since nothing else I have tried pulls strings from the base localization. Thank you. – GRW Sep
19 '14 at 5:44
add
a comment
up vote4down
vote


In a nutshell :


Localize your application

It's the first thing you have to do is to localise your app with at least two languages (english and french in this example).


Override NSLocalizedString

In your code, instead of using
NSLocalizedString(key,
comment)
, use a macro
MYLocalizedString(key,
comment)
defined like this :
#define
MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];


This
MYLocalizationSystem
singleton
will :

Set langage by setting the right localized NSBundle user asks for
Returns the localized NSString according to this previously set language


Set user language

When user changed application language in french, call
[[MYLocalizationSystem
sharedInstance] setLanguage:@"fr"];

- (void)setLanguage:(NSString *)lang
{
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj"];
if (!path)
{
_bundle = [NSBundle mainBundle];
NSLog(@"Warning: No lproj for %@, system default set instead !", lang);
return;
}

_bundle = [NSBundle bundleWithPath:path];
}


In this example this method set localized bundle to fr.lproj


Return localized string

Once you've set the localized bundle, you'll be able to get the right localised string from him with this method :
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value
{
// bundle was initialized with [NSBundle mainBundle] as default and modified in setLanguage method
return [self.bundle localizedStringForKey:key value:value table:nil];
}


Hope this will help you.

You'll find more details in this article from NSWinery.io

shareimprove
this answer
edited Apr
23 '15 at 10:49

answered Apr 22 '15 at 18:31





user3465357
412

We ask that you not just link to a solution in your answer; the link might stop working some day. While you don't have
to remove the link from your answer, we do ask that you edit your answer to include a summary of the relevant section of the linked article. – Oblivious
Sage Apr
22 '15 at 18:51
add
a comment
up vote3down
vote
You could build a sub-bundle with the set of localized strings that you want to do this with, and then use
NSLocalizedStringFromTableInBundle()
to
load them. (I'm assuming that this is content separate from the normal UI localization you might be doing on the app.)

shareimprove
this answer
answered Nov 3 '09 at 19:51





Sixten Otto
12.2k33455

add
a comment
up vote3down
vote
Maybe you should complement with this (on .pch file after #import ):
extern NSBundle* bundle; // Declared on Language.m

#ifdef NSLocalizedString
#undef NSLocalizedString
// Delete this line to avoid warning
#warning "Undefining NSLocalizedString"
#endif

#define NSLocalizedString(key, comment) \
[bundle localizedStringForKey:(key) value:@"" table:nil]


shareimprove
this answer
answered Aug 4 '11 at 15:22





D33pN16h7
1,755918

/Users/pwang/Desktop/Myshinesvn/Myshine/viewController/OrientationReadyPagesView‌​.m:193:31: Use of undeclared identifier
'bundle' – pengwang Mar
12 '13 at 4:08
add
a comment
up vote2down
vote
for my case i have two localized file , ja and en

and i would like to force it to en if the preferred language in the system neither en or ja

i'm going to edit the main.m file

i 'll check whether the first preferred is en or ja , if not then i 'll change the second preferred language to en.
int main(int argc, char *argv[])
{

[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];

NSString *lang = [[NSLocale preferredLanguages] objectAtIndex:0];

if (![lang isEqualToString:@"en"]  &&  ![lang isEqualToString:@"ja"]){

NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[NSLocale preferredLanguages]];
[array replaceObjectAtIndex:1 withObject:@"en"];

[[NSUserDefaults standardUserDefaults] setObject:array forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];

}

@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

}

}


shareimprove
this answer
answered Apr 2 '14 at 8:40





chings228
1,3471518

Thanks @chings228 it is usefull for me, but this not change the default launch image (splash) for the app I have diferents
splashs for each language. do you know how to apply for this?? – JERC Jun
4 '14 at 18:13
i think the splash runs before the main program start to run , so i don't know how to override it , may be plist can
help but it may work for next time the app opens – chings228 Jun
5 '14 at 1:12
add
a comment
up vote2down
vote
swift version

NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages") NSUserDefaults.standardUserDefaults().synchronize()

shareimprove
this answer
answered Dec 28 '14 at 13:04





daaniaal
1138

add
a comment
up vote1down
vote
This function will try to get localized string for current language and if it's not found it will get it using english language.
- (NSString*)L:(NSString*)key
{
static NSString* valueNotFound = @"VALUE_NOT_FOUND";
static NSBundle* enBundle = nil;

NSString* pl = [NSLocale preferredLanguages][0];
NSString* bp = [[NSBundle mainBundle] pathForResource:pl ofType:@"lproj"];
NSBundle* b = [NSBundle bundleWithPath:bp];

NSString* s = [b localizedStringForKey:key value:valueNotFound table:nil];
if ( [s isEqualToString:valueNotFound] ) {
if ( !enBundle ) {
bp = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
enBundle = [NSBundle bundleWithPath:bp];
}
s = [enBundle localizedStringForKey:key value:key table:nil];
}

return s;
}


shareimprove
this answer
answered Jun 17 '13 at 8:41





Cherpak Evgeny
891719

add
a comment
up vote1down
vote
You can do something like this:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];

NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];

NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):


shareimprove
this answer
answered Nov 17 '14 at 20:59





JERC
6302923

add
a comment
up vote0down
vote
whatever you all do, the best way is to take the short_name for the specified language, i.e.: fr, en, nl, de, it, etc... and assign the same to a global value.

make a picker view to pop up like a drop down menu (combination of a button on click of which a picker view appears from below with a list of languages) and select the language you desire. let the short name be stored internally. make a .h + .m file named LocalisedString.

Set the global value of short_name to be equal to the obtained value in LocalisedString.m When the required language is selected assign the NSBundlePath to create project sub-directories for the needed language. for eg, nl.proj, en.proj.

When the particular proj folder is selected call the localised string for the respective language and change the language dynamically.

no rules broken.

shareimprove
this answer
answered Aug 12 '11 at 11:17





Abhijeet
3428

add
a comment
up vote0down
vote
I wanted to add support for a language that isn't officially supported by iOS (not listed in Language section under system settings). By following the Apple's
Internationalization Tutorial and few hints here by Brian Webster and geon, I came up with this piece of code (put it in main.m):
int main(int argc, char * argv[]) {
@autoreleasepool {
// Grab regional settings locale, for Slovenian this is either sl_SI or en_SI
NSLocale *locale = [NSLocale currentLocale];
NSString *ll = [locale localeIdentifier]; // sl_SI

// Grab the first part of language identifier
NSArray *comp = [ll componentsSeparatedByString:@"_"];
NSString *ll1 = @"en";
if (comp.count > 0) {
ll1 = comp[0]; // sl, en, ...
}
// Check if we already saved language (user can manually change it inside app for example)
if (![[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"]) {
//   Slovenian (Slovenia),            Slovenia
if ([ll isEqualToString:@"sl_SI"] || [ll isEqualToString:@"en_SI"]) {
ll1 = @"sl-SI"; // This is the part of localized path for Slovenian language that Xcode generates
}
// Add more unsupported languages here...

[[NSUserDefaults standardUserDefaults] setObject:ll1 forKey:@"SelectedLanguage"]; // Save language
}
else {
// Restore language as we have previously saved it
ll1 = [[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"];
}
// Overwrite NSLocalizedString and StoryBoard language preference
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:ll1, @"en", @"fr", nil] forKey:@"AppleLanguages"];
// Make sure settings are stored to disk
[[NSUserDefaults standardUserDefaults] synchronize];

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}


This works well for both Storyboard and NSLocalizedString code. The code assumes that user will have an option to manually change language inside app later on.

Of course, don't forget to add proper Storyboard translations and Localizable.strings translations (see link to Apple page above for how to do that).

shareimprove
this answer
answered Oct 9 '13 at 19:23





frin
2,83511415

add
a comment
up vote0down
vote
Here is a decent solution for this problem, and it does not require application restart.

https://github.com/cmaftuleac/BundleLocalization

This implementation works by tweaking inside NSBundle. The idea is that you override the method localizedStringForKey on the instance of NSBundle object, and then call this method on a different bundle with a different language. Simple and elegant fully compatible
with all types of resources.

shareimprove
this answer
answered Apr 16 '15 at 19:24





Corneliu Maftuleac
836

add
a comment
up vote0down
vote
Based on Tudorizer's answer to change language without leaving or restarting the application.

Instead of a macro, use a class for accessing the preferred language in order to check if a specific language code is present.

Below is a class used to obtain the current language bundle that is working for iOS 9:
@implementation OSLocalization

+ (NSBundle *)currentLanguageBundle
{
// Default language incase an unsupported language is found
NSString *language = @"en";

if ([NSLocale preferredLanguages].count) {
// Check first object to be of type "en","es" etc
// Codes seen by my eyes: "en-US","en","es-US","es" etc

NSString *letterCode = [[NSLocale preferredLanguages] objectAtIndex:0];

if ([letterCode rangeOfString:@"en"].location != NSNotFound) {
// English
language = @"en";
} else if ([letterCode rangeOfString:@"es"].location != NSNotFound) {
// Spanish
language = @"es";
} else if ([letterCode rangeOfString:@"fr"].location != NSNotFound) {
// French
language = @"fr";
} // Add more if needed
}

return [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]];
}

/// Check if preferred language is English
+ (BOOL)isCurrentLanguageEnglish
{
if (![NSLocale preferredLanguages].count) {
// Just incase check for no items in array
return YES;
}

if ([[[NSLocale preferredLanguages] objectAtIndex:0] rangeOfString:@"en"].location == NSNotFound) {
// No letter code for english found
return NO;
} else {
// Tis English
return YES;
}
}

/*  Swap language between English & Spanish
*  Could send a string argument to directly pass the new language
*/
+ (void)changeCurrentLanguage
{
if ([self isCurrentLanguageEnglish]) {
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
} else {
[[NSUserDefaults standardUserDefaults] setObject:@[@"en"] forKey:@"AppleLanguages"];
}
}
@end


Use the class above to reference a string file / image / video / etc:
// Access a localized image
[[OSLocalization currentLanguageBundle] pathForResource:@"my_image_name.png" ofType:nil]
// Access  a localized string from Localizable.strings file
NSLocalizedStringFromTableInBundle(@"StringKey", nil, [OSLocalization currentLanguageBundle], @"comment")


Change language in-line like below or update the "changeCurrentLanguage" method in the class above to take a string parameter referencing the new language.
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: