From: Johannes Schindelin <johannes.schindelin@xxxxxx> Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> --- gettext.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- gettext.h | 5 +++-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/gettext.c b/gettext.c index 35d2c1218db..7e8966d8326 100644 --- a/gettext.c +++ b/gettext.c @@ -68,11 +68,72 @@ const char *get_preferred_languages(void) int use_gettext_poison(void) { static int poison_requested = -1; - if (poison_requested == -1) - poison_requested = git_env_bool("GIT_TEST_GETTEXT_POISON", 0); + if (poison_requested == -1) { + const char *v = getenv("GIT_TEST_GETTEXT_POISON"); + if (v && !strcmp(v, "rot13")) + poison_requested = 2; + else + poison_requested = + git_env_bool("GIT_TEST_GETTEXT_POISON", 0); + } return poison_requested; } +static inline char do_rot13(char c) +{ + if (c >= 'a' && c <= 'm') + return c + 'n' - 'a'; + if (c >= 'n' && c <= 'z') + return c + 'a' - 'n'; + if (c >= 'A' && c <= 'M') + return c + 'N' - 'A'; + if (c >= 'N' && c <= 'Z') + return c + 'A' - 'N'; + return c; +} + +const char *gettext_maybe_rot13(const char *msgid) +{ + static struct strbuf round_robin[4] = { + STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT + }; + static int current; + struct strbuf *buf; + + if (use_gettext_poison() != 2) + return "# GETTEXT POISON #"; + + buf = &round_robin[current++]; + if (current >= ARRAY_SIZE(round_robin)) + current = 0; + + strbuf_reset(buf); + while (*msgid) { + const char *p = strchrnul(msgid, '%'), *spec; + + while (*p && p[1] == '%') + p = strchrnul(p + 2, '%'); + + if (p != msgid) { + strbuf_addstr(buf, "<rot13>"); + while (p != msgid) + strbuf_addch(buf, do_rot13(*(msgid++))); + strbuf_addstr(buf, "</rot13>"); + } + + if (!*p) + break; + + spec = strpbrk(p + 1, "diouxXeEfFgGaAcsCSpnm%"); + if (!spec) + BUG("Unrecognized format string: %s", p); + strbuf_add(buf, p, spec + 1 - p); + msgid = spec + 1; + } + + return buf->buf; +} + #ifndef NO_GETTEXT static int test_vsnprintf(const char *fmt, ...) { diff --git a/gettext.h b/gettext.h index bee52eb1134..298adda7e15 100644 --- a/gettext.h +++ b/gettext.h @@ -29,6 +29,7 @@ #define FORMAT_PRESERVING(n) __attribute__((format_arg(n))) int use_gettext_poison(void); +const char *gettext_maybe_rot13(const char *msgid); #ifndef NO_GETTEXT void git_setup_gettext(void); @@ -48,14 +49,14 @@ static inline FORMAT_PRESERVING(1) const char *_(const char *msgid) { if (!*msgid) return ""; - return use_gettext_poison() ? "# GETTEXT POISON #" : gettext(msgid); + return use_gettext_poison() ? gettext_maybe_rot13(msgid) : gettext(msgid); } static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2) const char *Q_(const char *msgid, const char *plu, unsigned long n) { if (use_gettext_poison()) - return "# GETTEXT POISON #"; + return gettext_maybe_rot13(n < 2 ? msgid : plu); return ngettext(msgid, plu, n); } -- gitgitgadget