views:

2124

answers:

4

I'm trying to find a manageable way to translate every visible string in an iPhone application. The official apple documentation says to use .strings files for programmatic strings, while using the built in "add localized file" option in xcode to localize nib files.

The problem i see with this is that if the UI needs to change after localization happens, then we would need to update the nibs for each language individually which is less than optimal. Is there a simpler way to perhaps tie strings displayed in nib files to relevant values in a .strings file? or would i have to programmatically have to set those strings for each ui element (which is slightly better but still annoying)?

+1  A: 

I think you want to read about the command line tool: ibtool. It should simplify what you're looking to do.

Lyndsey Ferguson
While it does help with the translation process itself, it still results in having a separate nib file at the end which is what i'm hoping to avoid. thanks for the pointer though.
Kevlar
I haven't used it before as we don't localize in-house. I was under the impression that you could use it to 'extract' files to something that you can localize and then re-insert into the nib file. The nib file certainly helps with the GUI though..
Lyndsey Ferguson
ibtool should be able to reintegrate strings back into main nib files that are changed, in order to spit out new nib files that have both the new strings and the new nib changes. See "Performing Incremental Localization Updates" in http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/IB_UserGuide/LocalizingNibFiles/LocalizingNibFiles.html#//apple_ref/doc/uid/TP40005344-CH13
mahboudz
A: 

Perhaps you should update every string manually. Let's say you have an array, or an xml file, of strings in different languages, when the user changes the language just get the translated string from the array and then change it to the UI.

Marco

Marco
+2  A: 

The best you can do is recursively loop through each view and then set the text on them:

static void translateView(NSBundle *bundle, UIView *view)
{
    id idView = view;
    if ([idView respondsToSelector:@selector(text)] && [view respondsToSelector:@selector(setText:)])
        [idView setText:[bundle localizedStringForKey:[idView text] value:nil table:nil]];
    if ([idView respondsToSelector:@selector(title)] && [view respondsToSelector:@selector(setTitle:)])
        [idView setTitle:[bundle localizedStringForKey:[idView title] value:nil table:nil]];
    if ([idView respondsToSelector:@selector(placeholder)] && [view respondsToSelector:@selector(setPlaceholder:)])
        [idView setPlaceholder:[bundle localizedStringForKey:[idView placeholder] value:nil table:nil]];
    if ([idView respondsToSelector:@selector(prompt)] && [view respondsToSelector:@selector(setPrompt:)])
        [idView setPrompt:[bundle localizedStringForKey:[idView prompt] value:nil table:nil]];
    if ([idView respondsToSelector:@selector(titleForState:)] && [view respondsToSelector:@selector(setTitle:forState:)])
        [idView setTitle:[bundle localizedStringForKey:[idView titleForState:UIControlStateNormal] value:nil table:nil] forState:UIControlStateNormal];
    if ([idView isKindOfClass:[UITabBar class]] || [idView isKindOfClass:[UIToolbar class]])
        for (UIBarItem *item in [idView items])
            [item setTitle:[bundle localizedStringForKey:[item title] value:nil table:nil]];
    for (UIView *subview in [view subviews])
        translateView(bundle, subview);
}

Warning: You may of have to check other sets of selectors to catch everything. This is not a best-practice, but it seems like much less work

rpetrich
Interesting approach; I'll try it out when our app progresses more.
Kevlar
I try this and get a stack overflow (ie a infinite loop)
mamcx
Sorry, there's a typo in the last line. It should be translateView(bundle, subview); instead of translateView(bundle, view); of course
rpetrich
+5  A: 

Apple's built-in command line program ibtool lets you do this. You can dump the strings from a XIB, localize them, then create a new XIB based on the existing XIB but using the localized strings. So you can always have a base set of XIBs and recreate them all whenever the localized strings change. More info here: http://www.bdunagan.com/2009/03/15/ibtool-localization-made-easy/.

bdunagan