Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

ArtOfWarfare

macrumors G3
Original poster
Nov 26, 2007
9,557
6,058
I've written a category on NSString that includes this:

Code:
// From what I can tell, NSString's default localizedStringWithFormat: method
// doesn't actually do a lookup on Localizable.strings. So I wrote this which
// does the lookup and then does everything the default one does.

+ (NSString *)fullyLocalizedStringWithFormat:(NSString *)format, ...
{
    NSString *lookup = NSLocalizedString(format, @"");
    NSString *fullyLocalized;

    va_list arguments;
    va_start(arguments, format);

    NSLogv(lookup, arguments);
    fullyLocalized = [NSString localizedStringWithFormat:lookup, arguments];

    va_end(arguments);
    return fullyLocalized;
}

If I invoke it with:

Code:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateStyle = NSDateFormatterShortStyle;
dateFormatter.timeStyle = NSDateFormatterNoStyle;
dateFormatter.locale = [NSLocale currentLocale];
[NSString fullyLocalizedStringWithFormat:@"Replaced %@", [dateFormatter stringFromDate:[NSDate date]]];

And I have this in Localizable.strings:
Code:
"Replaced %@" = "Batteries were Last Full: %@";

Then NSLogv will (today in the US) properly print out
"Batteries were Last Full: 4/30/13"

But on the very next line, localizedStringWithFormat: crashes my program with EXC_BAD_ACCESS

If I replaced localizedStringWithFormat: with stringWithFormat:, it crashes just the same.

It also crashes if I replace it with:

Code:
fullyLocalized = [[NSString alloc] initWithFormat:lookup arguments:arguments];
Suggestions?

Edit: I found one thing that doesn't crash so far:

Code:
+ (NSString *)fullyLocalizedStringWithFormat:(NSString *)format, ...
{
    NSString *lookup = NSLocalizedString(format, @"");
    NSString *fullyLocalized;
    va_list arguments;
    va_start(arguments, format);
    //NSLogv(lookup, arguments);
    fullyLocalized = [[NSString alloc] initWithFormat:lookup arguments:arguments];
    va_end(arguments);
    return fullyLocalized;
}

NSLogv can't be there or it doesn't work. I still can't make it localize the arguments at the same time, though (IE, use [localizedStringWithFormat:lookup, arguments]; ).

Exit 2x: This appears to work, but the documentation confuses me a little so I'm not sure if it's actually working the way I want it to or if it just looks like it is for my local:

Code:
+ (NSString *)fullyLocalizedStringWithFormat:(NSString *)format, ...
{
    NSString *lookup = NSLocalizedString(format, @"");
    NSString *fullyLocalized;
    va_list arguments;
    va_start(arguments, format);
    fullyLocalized = [[NSString alloc] initWithFormat:lookup
                                               locale:nil
                                            arguments:arguments];
    va_end(arguments);
    return [fullyLocalized autorelease];
}

The documentation for initWithFormat:locale:arguments: says, pertaining to locale:
If this value is nil, uses the canonical locale.

Is the canonical locale what I want?

Afterwards it says:
To use a dictionary containing the current user's locale, you can use [[NSUserDefaults standardUserDefaults] dictionaryRepresentation].

The current user's locale is exactly what I want, but I'm really confused how exactly the method they provide would do anything like that... standardUserDefaults doesn't contain anything about the current user's locale (as far as I know), so it makes no sense to me and sounds like a typo.

Edit 3x: I've decided to use

Code:
+ (NSString *)fullyLocalizedStringWithFormat:(NSString *)format, ...
{
    NSString *lookup = NSLocalizedString(format, @"");
    NSString *fullyLocalized;
    va_list arguments;
    va_start(arguments, format);
    fullyLocalized = [[NSString alloc] initWithFormat:lookup
                                               locale:[NSLocale currentLocale]
                                            arguments:arguments];
    va_end(arguments);
    return [fullyLocalized autorelease];
}

It appears to work, it doesn't confuse me, and it seems to make sense.
 
Last edited:

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
You can't use a va_list twice in two calls as you did in your very first method; the first called function will modify it, and then the second one won't work. You need to use a sequence va_start / use it / va_end, va_start, use it again, va_end.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.