Next: , Previous: c-format Flag, Up: Sources


4.7 Special Cases of Translatable Strings

The attentive reader might now point out that it is not always possible to mark translatable string with gettext or something like this. Consider the following case:

     {
       static const char *messages[] = {
         "some very meaningful message",
         "and another one"
       };
       const char *string;
       ...
       string
         = index > 1 ? "a default message" : messages[index];
     
       fputs (string);
       ...
     }

While it is no problem to mark the string "a default message" it is not possible to mark the string initializers for messages. What is to be done? We have to fulfill two tasks. First we have to mark the strings so that the xgettext program (see xgettext Invocation) can find them, and second we have to translate the string at runtime before printing them.

The first task can be fulfilled by creating a new keyword, which names a no-op. For the second we have to mark all access points to a string from the array. So one solution can look like this:

     #define gettext_noop(String) String
     
     {
       static const char *messages[] = {
         gettext_noop ("some very meaningful message"),
         gettext_noop ("and another one")
       };
       const char *string;
       ...
       string
         = index > 1 ? gettext ("a default message") : gettext (messages[index]);
     
       fputs (string);
       ...
     }

Please convince yourself that the string which is written by fputs is translated in any case. How to get xgettext know the additional keyword gettext_noop is explained in xgettext Invocation.

The above is of course not the only solution. You could also come along with the following one:

     #define gettext_noop(String) String
     
     {
       static const char *messages[] = {
         gettext_noop ("some very meaningful message",
         gettext_noop ("and another one")
       };
       const char *string;
       ...
       string
         = index > 1 ? gettext_noop ("a default message") : messages[index];
     
       fputs (gettext (string));
       ...
     }

But this has a drawback. The programmer has to take care that he uses gettext_noop for the string "a default message". A use of gettext could have in rare cases unpredictable results.

One advantage is that you need not make control flow analysis to make sure the output is really translated in any case. But this analysis is generally not very difficult. If it should be in any situation you can use this second method in this situation.