From 6578483036695820d05aa7cf482a38169ad321bf Mon Sep 17 00:00:00 2001 From: Ævar Arnfjörð Bjarmason Date: Tue, 22 Feb 2011 23:41:20 +0000 Subject: i18n: add no-op _() and N_() wrappers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The _ function is for translating strings into the user's chosen language. The N_ macro just marks translatable strings for the xgettext(1) tool without translating them; it is intended for use in contexts where a function call cannot be used. So, for example: fprintf(stderr, _("Expansion of alias '%s' failed; " "'%s' is not a git command\n"), cmd, argv[0]); and const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = { /* ERROR_WOULD_OVERWRITE */ N_("Entry '%s' would be overwritten by merge. Cannot merge."), [...] Define such _ and N_ in a new gettext.h and include it in cache.h, so they can be used everywhere. Each just returns its argument for now. _ is a function rather than a macro like N_ to avoid the temptation to use _("foo") as a string literal (which would be a compile-time error once _(s) expands to an expression for the translation of s). Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- gettext.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 gettext.h (limited to 'gettext.h') diff --git a/gettext.h b/gettext.h new file mode 100644 index 0000000000..6949d736d5 --- /dev/null +++ b/gettext.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2011 Ævar Arnfjörð Bjarmason + * + * This is a skeleton no-op implementation of gettext for Git. + * You can replace it with something that uses libintl.h and wraps + * gettext() to try out the translations. + */ + +#ifndef GETTEXT_H +#define GETTEXT_H + +#ifdef _ +#error "namespace conflict: '_' is pre-defined?" +#endif + +#define FORMAT_PRESERVING(n) __attribute__((format_arg(n))) + +static inline FORMAT_PRESERVING(1) const char *_(const char *msgid) +{ + return msgid; +} + +/* Mark msgid for translation but do not translate it. */ +#define N_(msgid) (msgid) + +#endif -- cgit v1.3 From bb946bba761288e24b3eb621a3782a4fa804f21d Mon Sep 17 00:00:00 2001 From: Ævar Arnfjörð Bjarmason Date: Tue, 22 Feb 2011 23:41:21 +0000 Subject: i18n: add GETTEXT_POISON to simulate unfriendly translator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new GETTEXT_POISON compile-time parameter to make _(msg) always return gibberish. So now you can run make GETTEXT_POISON=YesPlease to get a copy of git that functions correctly (one hopes) but produces output that is in nobody's native language at all. This is a debugging aid for people who are working on the i18n part of the system, to make sure that they are not marking plumbing messages that should never be translated with _(). As new strings get marked for translation, naturally a number of tests will be broken in this mode. Tests that depend on output from Porcelain will need to be marked with the new C_LOCALE_OUTPUT test prerequisite. Newly failing tests that do not depend on output from Porcelain would be bugs due to messages that should not have been marked for translation. Note that the string we're using ("# GETTEXT POISON #") intentionally starts the pound sign. Some of Git's tests such as t3404-rebase-interactive.sh rely on interactive editing with a fake editor, and will needlessly break if the message doesn't start with something the interactive editor considers a comment. A future patch will fix fix the underlying cause of that issue by adding "#" characters to the commit advice automatically. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- Makefile | 7 +++++++ gettext.h | 8 +++++++- t/test-lib.sh | 3 +++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'gettext.h') diff --git a/Makefile b/Makefile index c153f450c5..c348bb7337 100644 --- a/Makefile +++ b/Makefile @@ -216,6 +216,9 @@ all:: # # Define NO_REGEX if you have no or inferior regex support in your C library. # +# Define GETTEXT_POISON if you are debugging the choice of strings marked +# for translation. This will turn all strings that use gettext into gibberish. +# # Define JSMIN to point to JavaScript minifier that functions as # a filter to have gitweb.js minified. # @@ -1370,6 +1373,9 @@ endif ifdef NO_SYMLINK_HEAD BASIC_CFLAGS += -DNO_SYMLINK_HEAD endif +ifdef GETTEXT_POISON + BASIC_CFLAGS += -DGETTEXT_POISON +endif ifdef NO_STRCASESTR COMPAT_CFLAGS += -DNO_STRCASESTR COMPAT_OBJS += compat/strcasestr.o @@ -2089,6 +2095,7 @@ endif ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT @echo GIT_TEST_CMP_USE_COPIED_CONTEXT=YesPlease >>$@ endif + @echo GETTEXT_POISON=\''$(subst ','\'',$(subst ','\'',$(GETTEXT_POISON)))'\' >>$@ ### Detect Tck/Tk interpreter path changes ifndef NO_TCLTK diff --git a/gettext.h b/gettext.h index 6949d736d5..11d82b0a6e 100644 --- a/gettext.h +++ b/gettext.h @@ -15,9 +15,15 @@ #define FORMAT_PRESERVING(n) __attribute__((format_arg(n))) +#ifdef GETTEXT_POISON +#define use_gettext_poison() 1 +#else +#define use_gettext_poison() 0 +#endif + static inline FORMAT_PRESERVING(1) const char *_(const char *msgid) { - return msgid; + return use_gettext_poison() ? "# GETTEXT POISON #" : msgid; } /* Mark msgid for translation but do not translate it. */ diff --git a/t/test-lib.sh b/t/test-lib.sh index 0fdc541a7c..0840e4a5c9 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1079,6 +1079,9 @@ esac test -z "$NO_PERL" && test_set_prereq PERL test -z "$NO_PYTHON" && test_set_prereq PYTHON +# Can we rely on git's output in the C locale? +test -z "$GETTEXT_POISON" && test_set_prereq C_LOCALE_OUTPUT + # test whether the filesystem supports symbolic links ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS rm -f y -- cgit v1.3 From 309552295af4b0f2ddd1af15d919441b1744523a Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Tue, 22 Feb 2011 23:41:22 +0000 Subject: i18n: do not poison translations unless GIT_GETTEXT_POISON envvar is set Tweak the GETTEXT_POISON facility so it is activated at run time instead of compile time. If the GIT_GETTEXT_POISON environment variable is set, _(msg) will result in gibberish as before; but if the GIT_GETTEXT_POISON variable is not set, it will return the message for human-readable output. So the behavior of mistranslated and untranslated git can be compared without rebuilding git in between. For simplicity we always set the GIT_GETTEXT_POISON variable in tests. This does not affect builds without the GETTEXT_POISON compile-time option set, so non-i18n git will not be slowed down. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- Makefile | 5 ++++- gettext.c | 14 ++++++++++++++ gettext.h | 2 +- t/test-lib.sh | 8 +++++++- 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 gettext.c (limited to 'gettext.h') diff --git a/Makefile b/Makefile index c348bb7337..4e9d935828 100644 --- a/Makefile +++ b/Makefile @@ -217,7 +217,9 @@ all:: # Define NO_REGEX if you have no or inferior regex support in your C library. # # Define GETTEXT_POISON if you are debugging the choice of strings marked -# for translation. This will turn all strings that use gettext into gibberish. +# for translation. In a GETTEXT_POISON build, you can turn all strings marked +# for translation into gibberish by setting the GIT_GETTEXT_POISON variable +# (to any value) in your environment. # # Define JSMIN to point to JavaScript minifier that functions as # a filter to have gitweb.js minified. @@ -1374,6 +1376,7 @@ ifdef NO_SYMLINK_HEAD BASIC_CFLAGS += -DNO_SYMLINK_HEAD endif ifdef GETTEXT_POISON + LIB_OBJS += gettext.o BASIC_CFLAGS += -DGETTEXT_POISON endif ifdef NO_STRCASESTR diff --git a/gettext.c b/gettext.c new file mode 100644 index 0000000000..ae5394a496 --- /dev/null +++ b/gettext.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2010 Ævar Arnfjörð Bjarmason + */ + +#include "git-compat-util.h" +#include "gettext.h" + +int use_gettext_poison(void) +{ + static int poison_requested = -1; + if (poison_requested == -1) + poison_requested = getenv("GIT_GETTEXT_POISON") ? 1 : 0; + return poison_requested; +} diff --git a/gettext.h b/gettext.h index 11d82b0a6e..04b5958e2b 100644 --- a/gettext.h +++ b/gettext.h @@ -16,7 +16,7 @@ #define FORMAT_PRESERVING(n) __attribute__((format_arg(n))) #ifdef GETTEXT_POISON -#define use_gettext_poison() 1 +extern int use_gettext_poison(void); #else #define use_gettext_poison() 0 #endif diff --git a/t/test-lib.sh b/t/test-lib.sh index 0840e4a5c9..f4c1e04e4f 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1080,7 +1080,13 @@ test -z "$NO_PERL" && test_set_prereq PERL test -z "$NO_PYTHON" && test_set_prereq PYTHON # Can we rely on git's output in the C locale? -test -z "$GETTEXT_POISON" && test_set_prereq C_LOCALE_OUTPUT +if test -n "$GETTEXT_POISON" +then + GIT_GETTEXT_POISON=YesPlease + export GIT_GETTEXT_POISON +else + test_set_prereq C_LOCALE_OUTPUT +fi # test whether the filesystem supports symbolic links ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS -- cgit v1.3 From 0c9ea33b90f6ed73b9c9151c2cad9ce341d6778b Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Wed, 9 Mar 2011 21:17:58 -0600 Subject: i18n: add stub Q_() wrapper for ngettext The Q_ function translates a string representing some pharse with an alternative plural form and uses the 'count' argument to choose which form to return. Use of Q_ solves the "%d noun(s)" problem in a way that is portable to languages outside the Germanic and Romance families. In English, the semantics of Q_(sing, plur, count) are roughly equivalent to count == 1 ? _(sing) : _(plur) while in other languages there can be more variants (count == 0; more random-looking rules based on the historical pronunciation of the number). Behind the scenes, the singular form is used to look up a family of translations and the plural form is ignored unless no translation is available. Define such a Q_ in gettext.h with the English semantics so C code can start using it to mark phrases with a count for translation. The name "Q_" is taken from subversion and stands for "quantity". Many projects just use ngettext directly without a wrapper analogous to _; we should not do so because git's gettext.h is meant not to conflict with system headers that might include libintl.h. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- gettext.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'gettext.h') diff --git a/gettext.h b/gettext.h index 04b5958e2b..1b253b7e76 100644 --- a/gettext.h +++ b/gettext.h @@ -9,8 +9,8 @@ #ifndef GETTEXT_H #define GETTEXT_H -#ifdef _ -#error "namespace conflict: '_' is pre-defined?" +#if defined(_) || defined(Q_) +#error "namespace conflict: '_' or 'Q_' is pre-defined?" #endif #define FORMAT_PRESERVING(n) __attribute__((format_arg(n))) @@ -26,6 +26,14 @@ static inline FORMAT_PRESERVING(1) const char *_(const char *msgid) return use_gettext_poison() ? "# GETTEXT POISON #" : 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 n == 1 ? msgid : plu; +} + /* Mark msgid for translation but do not translate it. */ #define N_(msgid) (msgid) -- cgit v1.3 From 642f85faab27adec13eced36cd7e7548311f6c87 Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Thu, 7 Apr 2011 19:41:48 +0100 Subject: i18n: avoid parenthesized string as array initializer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The syntax static const char ignore_error[] = ("something"); is invalid C. A parenthesized string is not allowed as an array initializer. Some compilers, for example GCC and MSVC, allow this syntax as an extension, but it is not a portable construct. tcc does not parse it, for example. Remove the parenthesis from the definition of the N_() macro to fix this. Signed-off-by: Ramsay Jones Acked-by: Jonathan Nieder Acked-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- gettext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gettext.h') diff --git a/gettext.h b/gettext.h index 1b253b7e76..24d91824e5 100644 --- a/gettext.h +++ b/gettext.h @@ -35,6 +35,6 @@ const char *Q_(const char *msgid, const char *plu, unsigned long n) } /* Mark msgid for translation but do not translate it. */ -#define N_(msgid) (msgid) +#define N_(msgid) msgid #endif -- cgit v1.3