iOS - change language for user via buttons -
im making interactive children's story uses custom graphics , narrations.
i have graphics in both english , spanish.
i dont have non-custom buttons, no text fields, not single "standard" apple app ui element anywhere. custom png file.
im looking method allow user change english spanish or vice-versa.
i created custom english , spanish button already, highlight when pressed.
the app (from ive read need restarted) , app present spanish pages (and spanish text embedded in png). spanish narration ensue.
at point user can elect hit english language button, , return english if desired.
tabtale's "mermaid princess" app extremely well, , far more need, example of im after. click button, change region, app restarts, , custom text , narrations result region youve selected.
i have 2 regions (languages) need simpler.
but how in world pull off ?
cheers !
ok, harder had expected…
basically exchanging nsbundle's method invoked nslocalizedstring(…)
using category on nsbundle , technique called isa-swizzeling
nsbundle+language.h
#import <foundation/foundation.h> @interface nsbundle (language) +(void)setlanguage:(nsstring*)language; @end
nsbundle+language.m
#import "nsbundle+language.h" #import <objc/runtime.h> static const char associatedlanguagebundle=0; @interface privatebundle : nsbundle @end @implementation privatebundle -(nsstring*)localizedstringforkey:(nsstring *)key value:(nsstring *)value table:(nsstring *)tablename { nsbundle* bundle=objc_getassociatedobject(self, &associatedlanguagebundle); 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],[privatebundle class]); }); objc_setassociatedobject([nsbundle mainbundle], &associatedlanguagebundle, language ? [nsbundle bundlewithpath:[[nsbundle mainbundle] pathforresource:language oftype:@"lproj"]] : nil, objc_association_retain_nonatomic); } @end
the appdelegate listen language_will_change
notifications, set language , broadcast notification language_did_change
appdelegate.m
#import "appdelegate.h" #import "nsbundle+language.h" @interface appdelegate () @end @implementation appdelegate - (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions { [[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(languagewillchange:) name:@"language_will_change" object:nil]; nsstring *targetlang = [[nsuserdefaults standarduserdefaults] objectforkey:@"selectedlanguage"]; [nsbundle setlanguage:targetlang?:@"en"]; return yes; } -(void)languagewillchange:(nsnotification *) noti { nsstring *targetlang = [noti object]; [[nsuserdefaults standarduserdefaults] setobject:targetlang forkey:@"selectedlanguage"]; [nsbundle setlanguage:targetlang]; [[nsnotificationcenter defaultcenter] postnotificationname:@"language_did_change" object:targetlang]; } @end
a baseviewcontroller post language_will_change
, listen language_did_change
baseviewcontroller.h
#import <uikit/uikit.h> @interface baseviewcontroller : uiviewcontroller -(void) languagedidchange; - (ibaction)switchlanguage:(id)sender; @end
baseviewcontroller.m
#import "baseviewcontroller.h" @interface baseviewcontroller () @property (weak, nonatomic) iboutlet uibutton *englishbutton; @property (weak, nonatomic) iboutlet uibutton *spanishbutton; @end @implementation baseviewcontroller - (void)viewdidload { [super viewdidload]; [[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(languagedidchangenotification:) name:@"language_did_change" object:nil]; } - (ibaction)switchlanguage:(id)sender { nsstring *localstring; if (self.englishbutton == sender) { localstring = @"en"; } else if(self.spanishbutton == sender){ localstring = @"es"; } if (localstring) { [[nsnotificationcenter defaultcenter] postnotificationname:@"language_will_change" object:localstring]; } } -(void)languagedidchangenotification:(nsnotification *)notification { [self languagedidchange]; } -(void)languagedidchange { } @end
now view controller subclasses baseviewcontroller
can implement languagedidchange
call nslocalizedstring
.
viewcontroller.m
#import "viewcontroller.h" @interface viewcontroller () @property (weak, nonatomic) iboutlet uilabel *label; @property (weak, nonatomic) iboutlet uiimageview *imageview; @end @implementation viewcontroller - (void)viewdidload { [super viewdidload]; [self languagedidchange]; } -(void)languagedidchange { self.label.text = nslocalizedstring(@"hello world", nil); self.imageview.image = [uiimage imagenamed:nslocalizedstring(@"image.png", nil)]; } @end
ad see, localising image name, added images en_image.png
, es_image.png
images asset bundle , map them in localizable strings
"image.png" = "en_image.png";
and
"image.png" = "es_image.png";
result
you'll find example code here: https://github.com/vikingosegundo/immidiatelanguagechange
Comments
Post a Comment