11

I have the following problem with a small iOS 7 project on which I'm testing the localisation capabilities.

  • I have a default project, with one VC, in which I have one button in the middle of the scene
  • in my VC I have an IBOutlet to my button called myButton
  • in the viewDidLoad method of the VC I am setting the buttons's title:


    NSString *title = NSLocalizedString(@"MY_BUTTON", @"My comment for my button");
    [self.myButton setTitle:title forState:UIControlStateNormal];

  • I generated the Localizable.strings file end enabled it for localization for the following languages: Base, Dutch
  • the contents of each file are as follows:

/* My comment for my button */ "MY_BUTTON" = "My [VALUE] Button"; where VALUE = Base, Dutch; so the labels should be My Base Button & My Dutch Button

Problem: If I launch my app using the simulator's language as Dutch, the label is (as expected) "My Dutch Button". If I launch it in English, the label is "My Base Button" (kind of ok…)

However, if I launch it with the phone's language set to French, and I previously had it set to Dutch, the label of the button does not default to Base, and instead displays again "My Dutch Button"

Any thoughts on this?

Thanks

tufyx
  • 163
  • 1
  • 8
  • 1
    Have you set Localizable.strings file for french also ? – Samkit Jain Feb 13 '14 at 13:02
  • on Mac one can set a order for language, maybe the order plays a role as well on iOS and is french, dutch, english due to the order of languages set? – Volker Feb 13 '14 at 13:03
  • No Localizable.strings for French. I want to support only English and Swedish, and for devices with languages other than these two, I want the app to be displayed in Base (which is English) – tufyx Feb 13 '14 at 13:11
  • Sorry… I meant Dutch, not Swedish in my previous comment – tufyx Feb 13 '14 at 13:18
  • Which part is unclear? – tufyx Feb 13 '14 at 13:21
  • 1
    I want to support two languages (Base and Dutch). For every other case (Japanese, Chinese, French, Italian) I want my app to default to Base (which I chose to be English). Right now the app works fine in Base and Dutch, but if I switch to Italian/French/etc. it does not default to Base, but it shows the value of the last language used. Steps: 1. Start app (default language: English) => My Base Button is shown. 2. Change language to Dutch => My Dutch Button is shown 3. Change language to French => My Dutch Button is shown (I would have expected My Base Button to be shown) – tufyx Feb 13 '14 at 13:24
  • possible duplicate of [How do I set the default locale in xcode 5 and ios 7?](http://stackoverflow.com/questions/21167559/how-do-i-set-the-default-locale-in-xcode-5-and-ios-7) – James Frost Feb 13 '14 at 14:01
  • Nice, thanks. So an alternative to actually default to Base would be to implement this manually? (I don't want to go against Apple's HIGs) – tufyx Feb 13 '14 at 14:07

4 Answers4

5

the order of default languages is a user setting on OSX and not editable (AFAIK) on iOS
BUT still adhered to!

the app is passed the array AppleLanguages (or so..) that specifies the languages to try. The NSLocalizedString macro will try load each language in the array in the order they appear UNTIL it finds a working one and then it uses that

compare: How to force NSLocalizedString to use a specific language

Community
  • 1
  • 1
Daij-Djan
  • 49,552
  • 17
  • 113
  • 135
4

I have created the following class, which supports a fallback to a customizable language. In my case I use Base.lproj as file for my default language contents.

StringUtilities.h

@interface StringUtils : NSObject

#define GetLocalizedString(key) [StringUtils getLocalizedString:key comment:nil]
//#define GetLocalizedString(key,comment) [StringUtils getLocalizedString:key comment:comment]


+ (NSString*) getLocalizedString:(NSString*)key comment:(NSString*)comment;

@end

StringUtilities.m

#import "StringUtilities.h"

@implementation StringUtils


//Returns a localized string, with fallback to version of Base
+ (NSString*) getLocalizedString:(NSString*)key comment:(NSString*)comment {
    NSString* localizedString = NSLocalizedString(key, nil);

    //use base language if current language setting on device does not find a proper value
    if([localizedString isEqualToString:key]) {

        NSString * path = [[NSBundle mainBundle] pathForResource:@"Base" ofType:@"lproj"];
        NSBundle * bundle = nil;
        if(path == nil){
            bundle = [NSBundle mainBundle];
        }else{
            bundle = [NSBundle bundleWithPath:path];
        }
        localizedString = [bundle localizedStringForKey:key value:comment table:nil];
    }
    return localizedString;
}

@end

How to use

Import the header file and use the GetLocalizedString macro instead of NSLocalizedString macro.

#import "StringUtilities.h"

NSString* str = GetLocalizedString(@"your.text.key");
Dirk
  • 2,011
  • 1
  • 20
  • 25
0

I have an equivalent in Swift:

public func LS(_ key: String) -> String {
    let value = NSLocalizedString(key, comment: "")
    if value != key || NSLocale.preferredLanguages.first == "en" {
        return value
    }

    // Fall back to en
    guard
        let path = Bundle.main.path(forResource: "en", ofType: "lproj"),
        let bundle = Bundle(path: path)
        else { return value }
    return NSLocalizedString(key, bundle: bundle, comment: "")
}
samwize
  • 25,675
  • 15
  • 141
  • 186
0

Using Dirk's answer here is the Swift equivalent implemented as a computed property in a String extension:

extension String {

var localized: String {

    var localizedString = NSLocalizedString(self, comment: "")

    // If a localized string was found then return it.
    // This check is based on the fact that if no localized string
    // exists then NSLocalized() returns the key itself.
    if self != localizedString {
        return localizedString
    }

    // No localized string exists.  Retrieve the display string
    // from the base strings file.
    var bundleForString: Bundle
    if let path = Bundle.main.path(forResource: "Base", ofType: "lproj"),
        let bundle = Bundle(path: path) {
        bundleForString = bundle
    } else {
        bundleForString = Bundle.main
    }

    localizedString = bundleForString.localizedString(forKey: self, value: self, table: nil)

    return localizedString
}

} 
DCDC
  • 486
  • 5
  • 9