char *obj, *color; ... /* make choices */ ... printf("%s %s\n", color, obj);The printf() call produces this:
white houseEven once we make sure that obj and color are localized strings, we are not quite finished. If our locale is Spanish, the printf() yields:
blanca casaThat is incorrect grammar; in Spanish, it should be:
casa blancaThe solution to this problem is variably ordered referencing of printf() arguments. The syntax of printf() format strings has been expanded to deal with this.
The original definition of printf() is that each conversion specification %T (where T represents any of the printf() conversion characters) is implicitly matched to an argument value by position. In order to deal with variably ordered strings, printf() allows an argument position index D to appear in the conversion specification following the %, so that where a format string contains %T , it can now contain %D$T. The value D, set off by a currency symbol ($), selects the argument from the argument list to be used. This means you can write
printf("2nd parameter is %2$s; the 1st is %1$s", p1, p2)The second parameter is printed first, with the first parameter printed second. For example:
char *store = "Macy's"; char *obj = "a cup"; printf("At %1$s, I bought %2$s.\n", store, obj); printf("I bought %2$s at %1$s.\n", store, obj);This code displays
At Macy's, I bought a cup. I bought a cup at Macy's.In English, we are able to come up with strings suitable for either word order; in some other language, we might not be so lucky. Nor can we predict which order such languages might prefer. So the developer has no way of knowing how to create traditional printf() format strings suitable for all languages.
Developers should therefore use message catalogs for their printf() format strings that take linguistic parameters, and allow localizers to localize the format strings as well as text strings. This means that the localizer has much greater ability to create intelligible text. An internationalized version of the above code appears in Example 6-4.
Example 6-4 : Internationalized Code
/* internationalized (XPG/4) version */ char *form = catgets(msgd, set, formNum, "At %1$s, I bought %2$s.\n"); char *store = catgets(msgd, set, storeNum, "Macy's"); char *obj = catgets(msgd, set, objNum, "a cup"); printf(form, store, obj);The unlocalized (default) version would produce
At Macy's, I bought a cup.A localized version might produce
Compré una tasa en Macy's.In practice, variably ordered format strings are found only in message catalogs and not in default strings. The default string usually simply uses the parameters in the order they're given, without the new variable-order format strings.