I want to make my app in two language.I have tried lots of localization code but it doesn't work. please help me i am not using storyboard . i have more than 15 xib files.
when i have made in single language i take a constant file and describes all label and button text.
but after some time i have two make app in two language .In my app i have option to select language by user.
my infoPlist.strings code given below
for turkish lang
"TT_TEXT" = "merhaba";
for English lang
"TT_TEXT" = "hello";
and at calling point i write
[self setTitleOnNavBar:NSLocalizedString(#"TT_TEXT", nil)];
it treats TT_TEXT as string.
Try with this code -
NSString *bundle_path = [[NSBundle mainBundle] pathForResource:#"Localizable" ofType:#"strings"inDirectory:nil forLocalization:#"en"];
NSBundle *localized_bundle = [[NSBundle alloc] initWithPath:[bundle_path stringByDeletingLastPathComponent]];
NSString *str = NSLocalizedStringFromTableInBundle(#"TT_TEXT",nil,localized_bundle, nil);
[self setTitleOnNavBar:str];
write your language country code in place of #"en" and use it.
Related
I am developing an app in which an user can change language at any time. I have done this in a demo app. It is working fine. But there is an issue with it, that is for localisation app I have to do following 2 tasks.
Step 1: I have to create IB outlet for every object (i.e in every class ==> buttons, labels, textFields, TextViews).
Step 2 : I have to set language for every objects for example : [myButton setTitle:[Language get:#"Language Test" alter:nil] forState:UIControlStateNormal];
OR myLabel.text=LocalizedString(#"Forgot Passoword");
I have a project which has many screens, around 60 screens (in storyboard). Unfortunately in this project there is no IB outlet for all objects. Strings are set in via storyboard. Now I have to make support this app in another language also (current language english )name Arabic language.
Conclusion : If I do above 2 steps (create IB outlet for every objects
, then write code in .m file for every object). It will take very much
time. Is there any other better options please ? I want do not want
create IB outlet and coding in .m file. Any suggestion will be great!!
What I have done till now :
Follow these tuttorials :
(1). How to force NSLocalizedString to use a specific language
and sample projects :
(1). https://github.com/tonisalae/TSLanguageManager
(2). https://github.com/object2dot0/Advance-Localization-in-ios-apps
My code :
example calls:
[Language setLanguage:#"it"];
OR
[Language setLanguage:#"de"];
+(void)initialize {
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:#"AppleLanguages"];
NSString *current = [languages objectAtIndex:0];
[self setLanguage:current];
}
+(void)setLanguage:(NSString *)l {
NSLog(#"\n\n\t ***** Hint Lang. selected by user: %# ****\n\n", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:#"lproj" ];
bundle = [NSBundle bundleWithPath:path];
}
+(NSString *)get:(NSString *)key alter:(NSString *)alternate {
return [bundle localizedStringForKey:key value:alternate table:nil];
}
You can achieve this using User Defined Runtime Attribute. Follow this link for detail.
I know how to make a phone call, but I'm trying to call certain people depending on which table view cell is selected. I viewed this question but with no success. In my viewDidLoad method, I created a NSDictionary for the phone numbers:
NSString *path = [[NSBundle mainBundle] pathForResource:#"State" ofType:#"plist"];
// Load the file content and read the data into arrays
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
stateNum = [dict objectForKey:#"Phone"];
I then sent the number that was selected to my detail view controller in the prepareForSegue method:
destViewController.phoneName = [stateNum objectAtIndex:indexPath.row];
I created an IBAction method and successfully linked it to the button in my storyboard:
-(IBAction)phone
{
[[UIApplication sharedApplication]
openURL: [NSURL URLWithString:plistNum]];
}
plistNum is defined in my viewDidLoad method of the detail view controller as:
plistNum = [NSString stringWithFormat:#"tel:%#",stateName];
The app compiles and runs, but when I click the button nothing happens. It worked when I had tel:12345678901 in URLWithString but not now. If anyone has any suggestions I would be happy to listen. I am very, very new to this so if you could explain your answer I would appreciate it. Thanks.
Edit: #rmaddy helped me find my dumb mistake. I had used stateName in the plistNum String instead of phoneName. There were no messages on the console, the string I had created was just not a phone number. Also, I don't have a viewWillAppear method. Will creating this make the program smoother?
I have recently released my first app to the App Store and still have a very long way to go with iOS development.
I'm looking to introduce themes into my app as an update so the user can select from 4-5 different themes.
I've got a tab bar controller and have set the 5th tab to be the "Settings" tab which contains a Table View with cells. The first cell contains the text "Themes" where the user can select it, be taken to a new Table view/Collection View to select the themes.
So I searched online and came across this incredible answer on doing just this:
How to create Multiple Themes/Skins for iphone apps?
Because I'm still new to development, I'm in need of assistance to take this forward.
To start off with, I have two themes:
1) DefaultTheme (Newiphonebackground.png)
2) PurplePinkTheme (Purplepinknew.png)
Following the instructions, I have created one plist for the Default theme and one plist for the PurplePink theme.
In the ThemeManager class that I created, I have:
- (id)init
{
if ((self = [super init]))
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *themeName = [defaults objectForKey:#"theme"] ?: #"DefaultTheme";
NSString *path = [[NSBundle mainBundle] pathForResource:themeName ofType:#"plist"];
self.styles = [NSDictionary dictionaryWithContentsOfFile:path];
}
return self;
}
+ (ThemeManager *)sharedManager
{
static ThemeManager *sharedManager = nil;
if (sharedManager == nil)
{
sharedManager = [[ThemeManager alloc] init];
}
return sharedManager;
}
In my table view, where the theme will get applied (it's going to get applied to every screen in the app but this is just to start off with where I'm testing with one scene in the app), in the viewDidLoad, I put:
NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:#"DefaultTheme"];
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
self.tableView.backgroundView = backgroundImageView;
That does nothing different because it applies the default theme. However if in the ThemeManager, I change the plist to be:
NSString *themeName = [defaults objectForKey:#"theme"] ?: #"PurplePinkTheme";
and in the viewDidLoad of the separate Table View, I set the code to be:
NSString *imageName = [styles objectForKey:#"PurplePinkTheme"];
Then upon loading my application, my PurplePinkTheme loads.
So far so good, but I don't think I've done anything substantial here.
I am confused from this point on. I am looking to start off with changing just the background images from the in-app settings and once I have that done, I'll look to change the custom navigation bars, etc.
So my questions are:
1) Why do I create one plist per theme?
2) How exactly do I link multiple plists in the ThemeManager class?
3) How do I link all of the themes up to the settings Theme cells allowing the user to choose?
I'm sorry this is vague, but I really need to understand how exactly I can carry on here. For example, I just don't get how to have multiple plists in the ThemeManager and how to move forward from here.
To recap, I, for now just want the ability to have multiple plist files with the different backgrounds, and for the user to go the settings tab in my app, click on the "Themes" cell and be able to select a different theme for the app without restarting the app.
I know the tutorial does carry on with explanations on that, but I'm just not quite sure I understand it all.
Any guidance on this would be massively appreciated.
Many thanks,
Your question is super long so I must confess I did not read the whole thing. That said I spent a lot of time with themes and the best solution I have found is to create an object that handles formatting. This is how I think you can implement it:
Create a formatter object extending NSObject
Have a property for each changeable piece of the theme:
for example if the background changes images you can have a UIImage in there called background. If the font color changes you have a UIFont property in there.
create a shared instance of your formater by adding:
+(Formater *) sharedInstance; //add to .h
+ (Formater *) sharedInstance //add to .m
{
if (!_sharedInstance)
{
_sharedInstance = [[Formater alloc] init];
}
}
Now in your view controller all you need to do is create a reference to your shared item and use that to style your view controller. (remember to make the changes in viewWillAppear not or it will not change after the setting is changed.
Voila!
I have 2 languages in my app, English and Dutch, the point is i want the language to change dynamically, lets say on a button click.
Is there a way to do this without having to write NSLocalizedString(#"key",#"comment") in code ?? i.e: using only storyboard, and somehow make the storyboard refresh it self on button click or something.
Any help will be very much appreciated.
Use Singleton to Call you Local String.
first to set the language type By you Button;
- (void)setLanguageType:(LanguageType)languageType {
if (_languageType != languageType) {
_languageType = languageType;
[self setBundleForName:bundleForType(languageType)];
//POST notification if necessary
}
}
- (void)setBundleForName:(NSString* )name {
NSString* path = [[ NSBundle mainBundle ] pathForResource:name ofType:#"lproj"];
_bundle = [NSBundle bundleWithPath:path];
}
and then,
Get the string by localizedString.
[[__class sharedInstance] localizedStringForKey:__key];
- (NSString* )localizedStringForKey:(NSString* )key {
return [_bundle localizedStringForKey:key value:nil table:nil];
}
If you need more help,give me a message.
if you want to create a Custom localization system. Let's try this http://aggressive-mediocrity.blogspot.in/2010/03/custom-localization-system-for-your.html
I ended up using the LocalizationSystem classes in this link to load the languages i needed when i needed them, i had to bind all the text via code, i'm afraid there's no way around this unfortunately, if you want your language change to be in-app and realtime !!
Thanks all for your help.
I want to create an iPhone application with English and Arabic language. I checked the Internationalization document for language switcher, however to take that into effect I have to manually go and change the iPhone setting. I don't want to do that. So what I am planning is on home screen I will have two button as English and Arabic. If user click Arabic, I will have arabic text and if user select English, app will be in english.
Any idea/ suggestion how to get this done?
Note: I don't want to manually go and change the language.
Edit 1
As per #Jano, I have done below.
Created new project. Added Arabic in Localization. Now I have two storyboard and two InfoPlist.strings file.
Added Localization.h and .m file as shown in answer.
Directory structure is MyProject-ar.lproj & MyProject-en.lproj
Content of Plist are "myButton01" = "Back"; & "myButton01" = "ظهر";
First View Controller have two button as English and Arabic. Called action on those button.
- (IBAction)pressedEnglish:(id)sender {
[Localization sharedInstance].fallbackLanguage = #"ar";
[Localization sharedInstance].preferredLanguage = #"en";
NSLog(#"pressed english");
}
- (IBAction)pressedArabic:(id)sender {
[Localization sharedInstance].fallbackLanguage = #"en";
[Localization sharedInstance].preferredLanguage = #"ar";
NSLog(#"pressed arabic");
}
In second view controller, I added one button and gave name as myButton. Now in viewDidLoad, I have
[self.myButton setTitle:localize(#"myButton01") forState:UIControlStateNormal];
I hope this should be working, however when I run the project, I see button as myButton01
Any reason why this is happening?
Edit 2
I got Edit 1 problem. I renamed InfoPlist.strings to Localizable.strings and it worked. But but but, I am still getting Arabic text irrespective of whatever button I press.
When finding reason, I found that it was because of below statement that we have in Localization.m
static Localization *shared = nil;
dispatch_once(&pred, ^{
shared = [[Localization alloc] init];
shared.fallbackLanguage = #"en";
shared.preferredLanguage = #"ar";
The problem is at last two lines. As we have set Arabic as preferredLanguage, I am always seeing the arabic text.
What changes will I need to do so that I can have it as changeable as per button pressed.
You want to set the language of the app from the app UI ignoring the user preference on the device. This is unusual, but here you go...
First write all your language strings on a directory structure like this:
i18n/en.lproj/Localizable.strings
i18n/ar.lproj/Localizable.strings
Create an additional directory with the corresponding two letter code for each additional language supported.
If the files are recognized as i18n resources, they will be presented like this:
Files will have a key=value with the following format:
"button.back" = "ظهر";
In your code, replace any localizable string with the key. Example:
[self.stateBtn setTitle:localize(#"button.back") forState:UIControlStateNormal];
Usually you would use NSLocalizedString(#"key",#"fallback") but since you want to ignore iPhone settings, I wrote a localize(#"key") macro above that will have the following implementation:
Localization.h
#ifndef localize
#define localize(key) [[Localization sharedInstance] localizedStringForKey:key]
#endif
#interface Localization : NSObject
#property (nonatomic, retain) NSBundle* fallbackBundle;
#property (nonatomic, retain) NSBundle* preferredBundle;
#property (nonatomic, copy) NSString* fallbackLanguage;
#property (nonatomic, copy) NSString* preferredLanguage;
-(NSString*) localizedStringForKey:(NSString*)key;
-(NSString*) pathForFilename:(NSString*)filename type:(NSString*)type;
+(Localization*)sharedInstance;
#end
Localization.m
#import "Localization.h"
#implementation Localization
+(Localization *)sharedInstance
{
static dispatch_once_t pred;
static Localization *shared = nil;
dispatch_once(&pred, ^{
shared = [[Localization alloc] init];
[shared setPreferred:#"en" fallback:#"ar"];
});
return shared;
}
-(void) setPreferred:(NSString*)preferred fallback:(NSString*)fallback
{
self.fallbackLanguage = fallback;
self.preferredLanguage = preferred;
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"Localizable" ofType:#"strings" inDirectory:nil forLocalization:self.fallbackLanguage];
self.fallbackBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
bundlePath = [[NSBundle mainBundle] pathForResource:#"Localizable" ofType:#"strings" inDirectory:nil forLocalization:self.preferredLanguage];
self.preferredBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
}
-(NSString*) pathForFilename:(NSString*)filename type:(NSString*)type
{
NSString *path = [self.preferredBundle pathForResource:filename ofType:type inDirectory:nil forLocalization:self.preferredLanguage];
if (!path) path = [self.fallbackBundle pathForResource:filename ofType:type inDirectory:nil forLocalization:self.fallbackLanguage];
if (!path) NSLog(#"Missing file: %#.%#", filename, type);
return path;
}
-(NSString*) localizedStringForKey:(NSString*)key
{
NSString* result = nil;
if (_preferredBundle!=nil) {
result = [_preferredBundle localizedStringForKey:key value:nil table:nil];
}
if (result == nil) {
result = [_fallbackBundle localizedStringForKey:key value:nil table:nil];
}
if (result == nil) {
result = key;
}
return result;
}
#end
This will use lookup the key strings in the arabic file, and if the key is missing, it will look in the arabic file. If you want it the other way, do the following from your button handlers:
[[Localization sharedInstance] setPreferred:#"ar" fallback:#"en"];
Sample project at Github.
If localisation doesn't work
If localisation doesn't work, use the plutil command line tool to verify the format of the file. It should output: Localizable.strings: OK. Example:
$ plutil -lint Localizable.strings
Localizable.strings: OK
This format is described in Internationalization Programming Topics > Localizing String Resources. You can optionally add // single-line or /* multi-line */ comments. For non latin languages it’s recommended to encode Localized.strings in UTF-16. You can convert between encodings in the inspector pane of XCode.
If it still doesn't work, check that you are copying the Localizable.strings file in the Copy files phase of your target. Note that when you add Localizable.strings files there, sometimes they appear in red, keep doing it until a file appears in black, then delete the red ones (hacky I know, blame Xcode).