I have to create a software that must work on several *nix platforms (Linux, AIX, ...).
I need to handle internationalization and my translation strings are in the following form:
"Hi %1, you are %2." // English
"Vous êtes %2, bonjour %1 !" // French
Here %1
stand for the name, and %2
for another word. I may change the format, that's not an issue.
I tried to use printf()
but you cannot specify the order of the parameters, you just specify their types.
"Hi %s, you are %s"
"Vous êtes %s, bonjour %s !"
Now there is no way to know which parameter to use for replacement of %s
: printf()
just uses the first one, then the next.
Is there any alternative to printf()
that deals with this ?
Note: gettext()
is not an option.
puts() The function puts() is used to print the string on the output stream with the additional new line character '\n'. It moves the cursor to the next line. Implementation of puts() is easier than printf().
In the big picture, printf is not compatible with C++ streams. C++ streams allow you to easily convert your console output to a file. (Although you can do similar with fprintf ).
Hey printf() is a built in function in C which is bundled in header file stdio. h(STANDARD INPUT OUTPUT). It is used to print something on console screen. But as you asked for print(), according to me there is no such function in C language, it must be in other programming or web language.
Definition. printf is a C function to print a formatted string to the standard output stream, which is the computer screen. In contrast, “puts” is a C library function that writes a string to stdout or standard output. Thus, this is the fundamental difference between printf and puts.
If you are looking for some alternatives, you might consider {fmt} too. The GNU C++ compiler g++ checks printf arguments at compile-time. If you specify -Wall on the command line, it issues a warning if it detects a mismatch. So if you are using this compiler, you can use printf without worrying.
Check out the full Printify review if you'd like to learn more. Spocket is an interesting alternative to Printful. Unlike other solutions that act like a design system and marketplace in one, Spocket is an app that integrates with WooCommerce and Shopify stores.
Depending on the compiler you use, printf will be type safe in practice because many compilers can parse and check your format strings. My recommendation is to ignore iostreams; they're a mess.
printf is just as safe as snprintf. The snprintf function is provided to guard against the buffer overrun errors that sprintf (not printf) is vulnerable to. @Chipster: did you read my comment?
I don't mean to be the bearer of bad tidings but what you're proposing is actually a bad idea. I work for a company that take i18n very seriously and we've discovered (painfully) that you cannot just slot words into sentences like that, since they often make no sense.
What we do is to simply disconnect the error text from the variable bits altogether, so as to avoid these problems. For, example, we'll generate an error:
XYZ-E-1002 Frobozz not configured for multiple zorkmids (F22, 7).
And then, in the description of the error, you state simply that the two values in the parentheses at the end were the Frobozz identifier and the number of zorkmids you tried to inflict on it.
This leaves i18n translation as an incredibly easy task since you have, at translation time, all of the language elements you need without worrying whether the variable bits should be singular or plural, masculine or feminine, first, second, or third declension (whatever the heck that actually means).
The translation team simply has to convert "Frobozz not configured for multiple zorkmids"
and that's a lot easier.
For those who would like to see a concrete example, I have something back from our translation bods (with enough stuff changed to protect the guilty).
At some point, someone submitted the following:
The {name} {object} is invalid
where {name}
was the name of a object (customers, orders, etc) and {object}
was the object type itself (table, file, document, stored procedure, etc).
Simple enough for English, the primary (probably only) language of the developers, but they struck a problem when translating to German/Swiss-German.
While the "customers document" translated correctly (in a positional sense) to Kundendokument
, the fact that the format string had a space between the two words was an issue. That was basically because the developers were trying to get the sentence to sound more natural but, unfortunately, only more natural based on their limited experience.
A bigger problem was with the "customers stored procedure" which became gespeichertes Verfahren der Kunden
, literally "stored procedure of the customers". While the German customers may have put up with a space in Kunden dokument
, there is no way to impose gespeichertes Verfahren der Kunden
onto {name} {object}
successfully.
Now you may say that a cleverer format string would have fixed this but there are several reasons why that would be incorrect:
{possible-pre-adjectives} {possible-pre-owner} {object} {possible-post-adjectives} {possible-post-owner} {possible-postowner-adjectives}
. That is the job of the translation teams since they understand the nuances.Note that introducing the disconnect sidesteps this issue nicely:
The object specified by <parameter 1>, of type <parameter 2>, is invalid. Parameter 1 = {name}. Parameter 2 = {object}. Der sache nannte <parameter 1>, dessen art <parameter 2> ist, ist falsch. Parameter 1 = {name}. Parameter 2 = {object}.
That last translation was one of mine, please don't use it to impugn the quality of our translators. No doubt more fluent German speakers will get a good laugh out of it.
POSIX printf()
supports positional arguments.
printf("Hi %1$s, you are %2$s.", name, status);
printf("Vous êtes %2$s, bonjour %1$s !", name, status);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With