gettext: Special cases

1 
1 4.7 Special Cases of Translatable Strings
1 =========================================
1 
1    The attentive reader might now point out that it is not always
1 possible to mark translatable string with ‘gettext’ or something like
1 this.  Consider the following case:
1 
1      {
1        static const char *messages[] = {
1          "some very meaningful message",
1          "and another one"
1        };
1        const char *string;
1        …
1        string
1          = index > 1 ? "a default message" : messages[index];
1 
1        fputs (string);
1        …
1      }
1 
1    While it is no problem to mark the string ‘"a default message"’ it is
1 not possible to mark the string initializers for ‘messages’.  What is to
1 be done?  We have to fulfill two tasks.  First we have to mark the
1 strings so that the ‘xgettext’ program (⇒xgettext Invocation) can
1 find them, and second we have to translate the string at runtime before
1 printing them.
1 
1    The first task can be fulfilled by creating a new keyword, which
1 names a no-op.  For the second we have to mark all access points to a
1 string from the array.  So one solution can look like this:
1 
1      #define gettext_noop(String) String
1 
1      {
1        static const char *messages[] = {
1          gettext_noop ("some very meaningful message"),
1          gettext_noop ("and another one")
1        };
1        const char *string;
1        …
1        string
1          = index > 1 ? gettext ("a default message") : gettext (messages[index]);
1 
1        fputs (string);
1        …
1      }
1 
1    Please convince yourself that the string which is written by ‘fputs’
1 is translated in any case.  How to get ‘xgettext’ know the additional
1 keyword ‘gettext_noop’ is explained in ⇒xgettext Invocation.
1 
1    The above is of course not the only solution.  You could also come
1 along with the following one:
1 
1      #define gettext_noop(String) String
1 
1      {
1        static const char *messages[] = {
1          gettext_noop ("some very meaningful message"),
1          gettext_noop ("and another one")
1        };
1        const char *string;
1        …
1        string
1          = index > 1 ? gettext_noop ("a default message") : messages[index];
1 
1        fputs (gettext (string));
1        …
1      }
1 
1    But this has a drawback.  The programmer has to take care that he
1 uses ‘gettext_noop’ for the string ‘"a default message"’.  A use of
1 ‘gettext’ could have in rare cases unpredictable results.
1 
1    One advantage is that you need not make control flow analysis to make
1 sure the output is really translated in any case.  But this analysis is
1 generally not very difficult.  If it should be in any situation you can
1 use this second method in this situation.
1