Nat! bio photo


Senior Mull.

Twitter RSS


Localizing library code, the right way ?

Lets say I have a method that needs to emit a localized string:

- (NSString *) errorMessage
   return( NSLocalizedString( @"system failure", @"your system has failed somehow"));

I would put "system failure" = "Das System ist kaputt"; in a unicode file de.lproj/Localizable.stringsand it will just work. Maybe.

What does the app say ?

If you are an app and link against the library, you put Localizable.strings into your Resources folder and it works.

What does the framework say ?

When you put the strings file into the Resources folder of the framework, it doesn't work, because NSLocalizedString uses [NSBundle mainBundle] to locate the translation table.

You will have to use NSLocalizedStringWithDefaultValue with your framework bundle as the search bundle. You get the framework bundle by calling something like [NSBundle bundleWithIdentifier:@""].

It's tempting to use [NSBundle bundleWithClass:[self class]] throughout, but this will fail in categories.

Unfortunately this ties the code to being in a framework (with that particular identifier).

A somewhat better solution

A generally better solution is to use the mainBundle as a fallback, if the lookup in the framework fails. This also allows an app to supplement new languages, if they do not exist in the framework.

NSString   *_MulleLocalizedFrameworkString( NSString *key, NSString * framework)
   NSBundle   *bundle;
   bundle = [NSBundle bundleWithIdentifier:framework];
   return( [bundle localizedStringForKey:key

NSString   *MulleLocalizedFrameworkString( NSString *key, NSString *comment, NSString *framework)
   NSBundle   *bundle;
   NSString   *s;

   s = _MulleLocalizedFrameworkString( key, framework);

   if( ! s)
      bundle = [NSBundle mainBundle];
      s      = [bundle localizedStringForKey:key
   return( s ? s : key);

It may become a little unwieldy to always specify the framework identifier, but that can be fixed with another small function, that you would specify in a private header of each Framework:

static inline NSString   *MyFrameworkLocalizedString( NSString *a, NSString *b)
    return( MulleLocalizedFrameworkString( a, b, ""));


Adapt mulle-genstrings to use user-supplied localization function names.

Post a comment

All comments are held for moderation; basic HTML formatting accepted.

E-mail: (not published)