All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle
@ 2012-04-23 12:30 Nguyễn Thái Ngọc Duy
  2012-04-23 12:30 ` [PATCH 01/10] Makefile: feed all header files to xgettext Nguyễn Thái Ngọc Duy
                   ` (12 more replies)
  0 siblings, 13 replies; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

Compared to v1 [1], parseopt patch is taken out. I attempted to
convert all struct option, and it turned into a huge series [2]. Not
sure how to submit that series yet.

Apart from that, Makefile is updated to make sure xgettext scan all
files, including header files. fprintf_ln() now uses fputc (so do a
few other places). About 4 more sentences in plural forms are detected
and converted to Q_().

[1] http://thread.gmane.org/gmane.comp.version-control.git/195623
[2] https://github.com/pclouds/git/tree/parseopt-i18n

Jonathan Nieder (1):
  i18n: mark relative dates for translation

Nguyễn Thái Ngọc Duy (9):
  Makefile: feed all header files to xgettext
  Add three convenient format printing functions with \n automatically
    appended
  i18n: help: mark strings for translation
  i18n: make warn_dangling_symref() automatically append \n
  i18n: remote: mark strings for translation
  i18n: apply: mark strings for translation
  i18n: apply: update say_patch_name to give translators complete
    sentence
  i18n: index-pack: mark strings for translation
  i18n: bundle: mark strings for translation

 Makefile             |   49 +++++++----
 builtin/apply.c      |  206 ++++++++++++++++++++++++---------------------
 builtin/fetch.c      |    4 +-
 builtin/help.c       |   48 +++++-----
 builtin/index-pack.c |  125 +++++++++++++++-------------
 builtin/remote.c     |  227 +++++++++++++++++++++++++++-----------------------
 bundle.c             |   38 +++++----
 cache.h              |    6 +-
 date.c               |   95 ++++++++++++---------
 generate-cmdlist.sh  |    2 +-
 git.c                |    2 +-
 help.c               |   32 +++++---
 refs.c               |    1 +
 strbuf.c             |   33 +++++++
 strbuf.h             |    7 ++
 test-date.c          |    7 +-
 16 files changed, 504 insertions(+), 378 deletions(-)

-- 
1.7.8.36.g69ee2

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH 01/10] Makefile: feed all header files to xgettext
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-23 12:30 ` [PATCH 02/10] Add three convenient format printing functions with \n automatically appended Nguyễn Thái Ngọc Duy
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

Translation markers may be present in header files too. Make sure we
don't miss any.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Makefile |   48 +++++++++++++++++++++++++++++++-----------------
 1 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/Makefile b/Makefile
index be1957a..dab7362 100644
--- a/Makefile
+++ b/Makefile
@@ -386,6 +386,7 @@ XDIFF_OBJS =
 VCSSVN_H =
 VCSSVN_OBJS =
 VCSSVN_TEST_OBJS =
+MISC_H =
 EXTRA_CPPFLAGS =
 LIB_H =
 LIB_OBJS =
@@ -543,6 +544,35 @@ LIB_FILE=libgit.a
 XDIFF_LIB=xdiff/lib.a
 VCSSVN_LIB=vcs-svn/lib.a
 
+XDIFF_H += xdiff/xinclude.h
+XDIFF_H += xdiff/xmacros.h
+XDIFF_H += xdiff/xdiff.h
+XDIFF_H += xdiff/xtypes.h
+XDIFF_H += xdiff/xutils.h
+XDIFF_H += xdiff/xprepare.h
+XDIFF_H += xdiff/xdiffi.h
+XDIFF_H += xdiff/xemit.h
+
+VCSSVN_H += vcs-svn/line_buffer.h
+VCSSVN_H += vcs-svn/sliding_window.h
+VCSSVN_H += vcs-svn/repo_tree.h
+VCSSVN_H += vcs-svn/fast_export.h
+VCSSVN_H += vcs-svn/svndiff.h
+VCSSVN_H += vcs-svn/svndump.h
+
+MISC_H += branch.h
+MISC_H += bundle.h
+MISC_H += bisect.h
+MISC_H += fetch-pack.h
+MISC_H += thread-utils.h
+MISC_H += send-pack.h
+MISC_H += shortlog.h
+MISC_H += reachable.h
+MISC_H += wt-status.h
+MISC_H += tar.h
+MISC_H += url.h
+MISC_H += walker.h
+
 LIB_H += advice.h
 LIB_H += archive.h
 LIB_H += argv-array.h
@@ -2170,24 +2200,8 @@ connect.o transport.o url.o http-backend.o: url.h
 http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
 
-XDIFF_H += xdiff/xinclude.h
-XDIFF_H += xdiff/xmacros.h
-XDIFF_H += xdiff/xdiff.h
-XDIFF_H += xdiff/xtypes.h
-XDIFF_H += xdiff/xutils.h
-XDIFF_H += xdiff/xprepare.h
-XDIFF_H += xdiff/xdiffi.h
-XDIFF_H += xdiff/xemit.h
-
 xdiff-interface.o $(XDIFF_OBJS): $(XDIFF_H)
 
-VCSSVN_H += vcs-svn/line_buffer.h
-VCSSVN_H += vcs-svn/sliding_window.h
-VCSSVN_H += vcs-svn/repo_tree.h
-VCSSVN_H += vcs-svn/fast_export.h
-VCSSVN_H += vcs-svn/svndiff.h
-VCSSVN_H += vcs-svn/svndump.h
-
 $(VCSSVN_OBJS) $(VCSSVN_TEST_OBJS): $(LIB_H) $(VCSSVN_H)
 endif
 
@@ -2282,7 +2296,7 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
 	--keyword=_ --keyword=N_ --keyword="Q_:1,2"
 XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell
 XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
-LOCALIZED_C := $(C_OBJ:o=c)
+LOCALIZED_C := $(C_OBJ:o=c) $(LIB_H) $(XDIFF_H) $(VCSSVN_H) $(MISC_H)
 LOCALIZED_SH := $(SCRIPT_SH)
 LOCALIZED_PERL := $(SCRIPT_PERL)
 
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 02/10] Add three convenient format printing functions with \n automatically appended
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
  2012-04-23 12:30 ` [PATCH 01/10] Makefile: feed all header files to xgettext Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-23 16:15   ` Jonathan Nieder
  2012-04-23 12:30 ` [PATCH 03/10] i18n: mark relative dates for translation Nguyễn Thái Ngọc Duy
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

These functions are helpful when we do not want to expose \n to
translators. For example

    printf("hello world\n");

can be converted to

    printf_ln(_("hello world"));

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 strbuf.c |   33 +++++++++++++++++++++++++++++++++
 strbuf.h |    7 +++++++
 2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/strbuf.c b/strbuf.c
index 5135d59..82d1fa2 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -464,3 +464,36 @@ void strbuf_addstr_urlencode(struct strbuf *sb, const char *s,
 {
 	strbuf_add_urlencode(sb, s, strlen(s), reserved);
 }
+
+void strbuf_addf_ln(struct strbuf *sb, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	strbuf_vaddf(sb, fmt, ap);
+	va_end(ap);
+	strbuf_addch(sb, '\n');
+}
+
+int printf_ln(const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+	va_start(ap, fmt);
+	ret = vprintf(fmt, ap);
+	va_end(ap);
+	if (ret >= 0)
+		ret += printf("\n");
+	return ret;
+}
+
+int fprintf_ln(FILE *fp, const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+	va_start(ap, fmt);
+	ret = vfprintf(fp, fmt, ap);
+	va_end(ap);
+	if (ret >= 0 && fputc('\n', fp) != EOF)
+		ret++;
+	return ret;
+}
diff --git a/strbuf.h b/strbuf.h
index 3effaa8..b888d40 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -99,6 +99,8 @@ __attribute__((format (printf,2,3)))
 extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
 __attribute__((format (printf,2,0)))
 extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);
+__attribute__((format (printf,2,3)))
+extern void strbuf_addf_ln(struct strbuf *sb, const char *fmt, ...);
 
 extern void strbuf_add_lines(struct strbuf *sb, const char *prefix, const char *buf, size_t size);
 
@@ -129,4 +131,9 @@ extern void strbuf_add_urlencode(struct strbuf *, const char *, size_t,
 extern void strbuf_addstr_urlencode(struct strbuf *, const char *,
 				    int reserved);
 
+__attribute__((format (printf,1,2)))
+extern int printf_ln(const char *fmt, ...);
+__attribute__((format (printf,2,3)))
+extern int fprintf_ln(FILE *fp, const char *fmt, ...);
+
 #endif /* STRBUF_H */
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
  2012-04-23 12:30 ` [PATCH 01/10] Makefile: feed all header files to xgettext Nguyễn Thái Ngọc Duy
  2012-04-23 12:30 ` [PATCH 02/10] Add three convenient format printing functions with \n automatically appended Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-24 20:04   ` Junio C Hamano
  2012-04-23 12:30 ` [PATCH 04/10] i18n: help: mark strings " Nguyễn Thái Ngọc Duy
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

From: Jonathan Nieder <jrnieder@gmail.com>

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 cache.h     |    6 +--
 date.c      |   95 ++++++++++++++++++++++++++++++++++------------------------
 test-date.c |    7 ++--
 3 files changed, 62 insertions(+), 46 deletions(-)

diff --git a/cache.h b/cache.h
index a8aceb5..aa9f8f9 100644
--- a/cache.h
+++ b/cache.h
@@ -906,10 +906,8 @@ enum date_mode {
 };
 
 const char *show_date(unsigned long time, int timezone, enum date_mode mode);
-const char *show_date_relative(unsigned long time, int tz,
-			       const struct timeval *now,
-			       char *timebuf,
-			       size_t timebuf_size);
+void show_date_relative(unsigned long time, int tz, const struct timeval *now,
+			struct strbuf *timebuf);
 int parse_date(const char *date, char *buf, int bufsize);
 int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
 void datestamp(char *buf, int bufsize);
diff --git a/date.c b/date.c
index a5055ca..1fdcf7c 100644
--- a/date.c
+++ b/date.c
@@ -86,83 +86,98 @@ static int local_tzoffset(unsigned long time)
 	return offset * eastwest;
 }
 
-const char *show_date_relative(unsigned long time, int tz,
+void show_date_relative(unsigned long time, int tz,
 			       const struct timeval *now,
-			       char *timebuf,
-			       size_t timebuf_size)
+			       struct strbuf *timebuf)
 {
 	unsigned long diff;
-	if (now->tv_sec < time)
-		return "in the future";
+	if (now->tv_sec < time) {
+		strbuf_addstr(timebuf, _("in the future"));
+		return;
+	}
 	diff = now->tv_sec - time;
 	if (diff < 90) {
-		snprintf(timebuf, timebuf_size, "%lu seconds ago", diff);
-		return timebuf;
+		strbuf_addf(timebuf,
+			 Q_("%lu second ago", "%lu seconds ago", diff), diff);
+		return;
 	}
 	/* Turn it into minutes */
 	diff = (diff + 30) / 60;
 	if (diff < 90) {
-		snprintf(timebuf, timebuf_size, "%lu minutes ago", diff);
-		return timebuf;
+		strbuf_addf(timebuf,
+			 Q_("%lu minute ago", "%lu minutes ago", diff), diff);
+		return;
 	}
 	/* Turn it into hours */
 	diff = (diff + 30) / 60;
 	if (diff < 36) {
-		snprintf(timebuf, timebuf_size, "%lu hours ago", diff);
-		return timebuf;
+		strbuf_addf(timebuf,
+			 Q_("%lu hour ago", "%lu hours ago", diff), diff);
+		return;
 	}
 	/* We deal with number of days from here on */
 	diff = (diff + 12) / 24;
 	if (diff < 14) {
-		snprintf(timebuf, timebuf_size, "%lu days ago", diff);
-		return timebuf;
+		strbuf_addf(timebuf,
+			 Q_("%lu day ago", "%lu days ago", diff), diff);
+		return;
 	}
 	/* Say weeks for the past 10 weeks or so */
 	if (diff < 70) {
-		snprintf(timebuf, timebuf_size, "%lu weeks ago", (diff + 3) / 7);
-		return timebuf;
+		strbuf_addf(timebuf,
+			 Q_("%lu week ago", "%lu weeks ago", (diff + 3) / 7),
+			 (diff + 3) / 7);
+		return;
 	}
 	/* Say months for the past 12 months or so */
 	if (diff < 365) {
-		snprintf(timebuf, timebuf_size, "%lu months ago", (diff + 15) / 30);
-		return timebuf;
+		strbuf_addf(timebuf,
+			 Q_("%lu month ago", "%lu months ago", (diff + 15) / 30),
+			 (diff + 15) / 30);
+		return;
 	}
 	/* Give years and months for 5 years or so */
 	if (diff < 1825) {
 		unsigned long totalmonths = (diff * 12 * 2 + 365) / (365 * 2);
 		unsigned long years = totalmonths / 12;
 		unsigned long months = totalmonths % 12;
-		int n;
-		n = snprintf(timebuf, timebuf_size, "%lu year%s",
-				years, (years > 1 ? "s" : ""));
-		if (months)
-			snprintf(timebuf + n, timebuf_size - n,
-					", %lu month%s ago",
-					months, (months > 1 ? "s" : ""));
-		else
-			snprintf(timebuf + n, timebuf_size - n, " ago");
-		return timebuf;
+		if (months) {
+			struct strbuf sb = STRBUF_INIT;
+			strbuf_addf(&sb, Q_("%lu year", "%lu years", years), years);
+			/* TRANSLATORS: "%s" is "<n> years" */
+			strbuf_addf(timebuf,
+				 Q_("%s, %lu month ago", "%s, %lu months ago", months),
+				 sb.buf, months);
+			strbuf_release(&sb);
+		} else
+			strbuf_addf(timebuf,
+				 Q_("%lu year ago", "%lu years ago", years), years);
+		return;
 	}
 	/* Otherwise, just years. Centuries is probably overkill. */
-	snprintf(timebuf, timebuf_size, "%lu years ago", (diff + 183) / 365);
-	return timebuf;
+	strbuf_addf(timebuf,
+		 Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
+		 (diff + 183) / 365);
 }
 
 const char *show_date(unsigned long time, int tz, enum date_mode mode)
 {
 	struct tm *tm;
-	static char timebuf[200];
+	static struct strbuf timebuf = STRBUF_INIT;
 
 	if (mode == DATE_RAW) {
-		snprintf(timebuf, sizeof(timebuf), "%lu %+05d", time, tz);
-		return timebuf;
+		strbuf_reset(&timebuf);
+		strbuf_addf(&timebuf, "%lu %+05d", time, tz);
+		return timebuf.buf;
 	}
 
 	if (mode == DATE_RELATIVE) {
 		struct timeval now;
+
+		strbuf_reset(&timebuf);
 		gettimeofday(&now, NULL);
-		return show_date_relative(time, tz, &now,
-					  timebuf, sizeof(timebuf));
+		show_date_relative(time, tz, &now, &timebuf);
+		return timebuf.buf;
 	}
 
 	if (mode == DATE_LOCAL)
@@ -171,23 +186,25 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
 	tm = time_to_tm(time, tz);
 	if (!tm)
 		return NULL;
+
+	strbuf_reset(&timebuf);
 	if (mode == DATE_SHORT)
-		sprintf(timebuf, "%04d-%02d-%02d", tm->tm_year + 1900,
+		strbuf_addf(&timebuf, "%04d-%02d-%02d", tm->tm_year + 1900,
 				tm->tm_mon + 1, tm->tm_mday);
 	else if (mode == DATE_ISO8601)
-		sprintf(timebuf, "%04d-%02d-%02d %02d:%02d:%02d %+05d",
+		strbuf_addf(&timebuf, "%04d-%02d-%02d %02d:%02d:%02d %+05d",
 				tm->tm_year + 1900,
 				tm->tm_mon + 1,
 				tm->tm_mday,
 				tm->tm_hour, tm->tm_min, tm->tm_sec,
 				tz);
 	else if (mode == DATE_RFC2822)
-		sprintf(timebuf, "%.3s, %d %.3s %d %02d:%02d:%02d %+05d",
+		strbuf_addf(&timebuf, "%.3s, %d %.3s %d %02d:%02d:%02d %+05d",
 			weekday_names[tm->tm_wday], tm->tm_mday,
 			month_names[tm->tm_mon], tm->tm_year + 1900,
 			tm->tm_hour, tm->tm_min, tm->tm_sec, tz);
 	else
-		sprintf(timebuf, "%.3s %.3s %d %02d:%02d:%02d %d%c%+05d",
+		strbuf_addf(&timebuf, "%.3s %.3s %d %02d:%02d:%02d %d%c%+05d",
 				weekday_names[tm->tm_wday],
 				month_names[tm->tm_mon],
 				tm->tm_mday,
@@ -195,7 +212,7 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
 				tm->tm_year + 1900,
 				(mode == DATE_LOCAL) ? 0 : ' ',
 				tz);
-	return timebuf;
+	return timebuf.buf;
 }
 
 /*
diff --git a/test-date.c b/test-date.c
index 6bcd5b0..10afaab 100644
--- a/test-date.c
+++ b/test-date.c
@@ -7,13 +7,14 @@ static const char *usage_msg = "\n"
 
 static void show_dates(char **argv, struct timeval *now)
 {
-	char buf[128];
+	struct strbuf buf = STRBUF_INIT;
 
 	for (; *argv; argv++) {
 		time_t t = atoi(*argv);
-		show_date_relative(t, 0, now, buf, sizeof(buf));
-		printf("%s -> %s\n", *argv, buf);
+		show_date_relative(t, 0, now, &buf);
+		printf("%s -> %s\n", *argv, buf.buf);
 	}
+	strbuf_release(&buf);
 }
 
 static void parse_dates(char **argv, struct timeval *now)
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 04/10] i18n: help: mark strings for translation
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (2 preceding siblings ...)
  2012-04-23 12:30 ` [PATCH 03/10] i18n: mark relative dates for translation Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-23 16:30   ` Jonathan Nieder
  2012-04-23 12:30 ` [PATCH 05/10] i18n: make warn_dangling_symref() automatically append \n Nguyễn Thái Ngọc Duy
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

This patch also marks most common commands' synopsis for translation
so that "git help" gives a friendly listing.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Makefile            |    1 +
 builtin/help.c      |   48 ++++++++++++++++++++++++------------------------
 generate-cmdlist.sh |    2 +-
 git.c               |    2 +-
 help.c              |   32 ++++++++++++++++++++------------
 5 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/Makefile b/Makefile
index dab7362..39a3c6b 100644
--- a/Makefile
+++ b/Makefile
@@ -563,6 +563,7 @@ VCSSVN_H += vcs-svn/svndump.h
 MISC_H += branch.h
 MISC_H += bundle.h
 MISC_H += bisect.h
+MISC_H += common-cmds.h
 MISC_H += fetch-pack.h
 MISC_H += thread-utils.h
 MISC_H += send-pack.h
diff --git a/builtin/help.c b/builtin/help.c
index 61ff798..96a462c 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -54,7 +54,7 @@ static enum help_format parse_help_format(const char *format)
 		return HELP_FORMAT_INFO;
 	if (!strcmp(format, "web") || !strcmp(format, "html"))
 		return HELP_FORMAT_WEB;
-	die("unrecognized help format '%s'", format);
+	die(_("unrecognized help format '%s'"), format);
 }
 
 static const char *get_man_viewer_info(const char *name)
@@ -82,7 +82,7 @@ static int check_emacsclient_version(void)
 	ec_process.err = -1;
 	ec_process.stdout_to_stderr = 1;
 	if (start_command(&ec_process))
-		return error("Failed to start emacsclient.");
+		return error(_("Failed to start emacsclient."));
 
 	strbuf_read(&buffer, ec_process.err, 20);
 	close(ec_process.err);
@@ -95,7 +95,7 @@ static int check_emacsclient_version(void)
 
 	if (prefixcmp(buffer.buf, "emacsclient")) {
 		strbuf_release(&buffer);
-		return error("Failed to parse emacsclient version.");
+		return error(_("Failed to parse emacsclient version."));
 	}
 
 	strbuf_remove(&buffer, 0, strlen("emacsclient"));
@@ -103,7 +103,7 @@ static int check_emacsclient_version(void)
 
 	if (version < 22) {
 		strbuf_release(&buffer);
-		return error("emacsclient version '%d' too old (< 22).",
+		return error(_("emacsclient version '%d' too old (< 22)."),
 			version);
 	}
 
@@ -121,7 +121,7 @@ static void exec_woman_emacs(const char *path, const char *page)
 			path = "emacsclient";
 		strbuf_addf(&man_page, "(woman \"%s\")", page);
 		execlp(path, "emacsclient", "-e", man_page.buf, (char *)NULL);
-		warning("failed to exec '%s': %s", path, strerror(errno));
+		warning(_("failed to exec '%s': %s"), path, strerror(errno));
 	}
 }
 
@@ -149,7 +149,7 @@ static void exec_man_konqueror(const char *path, const char *page)
 			path = "kfmclient";
 		strbuf_addf(&man_page, "man:%s(1)", page);
 		execlp(path, filename, "newTab", man_page.buf, (char *)NULL);
-		warning("failed to exec '%s': %s", path, strerror(errno));
+		warning(_("failed to exec '%s': %s"), path, strerror(errno));
 	}
 }
 
@@ -158,7 +158,7 @@ static void exec_man_man(const char *path, const char *page)
 	if (!path)
 		path = "man";
 	execlp(path, "man", page, (char *)NULL);
-	warning("failed to exec '%s': %s", path, strerror(errno));
+	warning(_("failed to exec '%s': %s"), path, strerror(errno));
 }
 
 static void exec_man_cmd(const char *cmd, const char *page)
@@ -166,7 +166,7 @@ static void exec_man_cmd(const char *cmd, const char *page)
 	struct strbuf shell_cmd = STRBUF_INIT;
 	strbuf_addf(&shell_cmd, "%s %s", cmd, page);
 	execl("/bin/sh", "sh", "-c", shell_cmd.buf, (char *)NULL);
-	warning("failed to exec '%s': %s", cmd, strerror(errno));
+	warning(_("failed to exec '%s': %s"), cmd, strerror(errno));
 }
 
 static void add_man_viewer(const char *name)
@@ -206,8 +206,8 @@ static int add_man_viewer_path(const char *name,
 	if (supported_man_viewer(name, len))
 		do_add_man_viewer_info(name, len, value);
 	else
-		warning("'%s': path for unsupported man viewer.\n"
-			"Please consider using 'man.<tool>.cmd' instead.",
+		warning(_("'%s': path for unsupported man viewer.\n"
+			  "Please consider using 'man.<tool>.cmd' instead."),
 			name);
 
 	return 0;
@@ -218,8 +218,8 @@ static int add_man_viewer_cmd(const char *name,
 			      const char *value)
 {
 	if (supported_man_viewer(name, len))
-		warning("'%s': cmd for supported man viewer.\n"
-			"Please consider using 'man.<tool>.path' instead.",
+		warning(_("'%s': cmd for supported man viewer.\n"
+			  "Please consider using 'man.<tool>.path' instead."),
 			name);
 	else
 		do_add_man_viewer_info(name, len, value);
@@ -280,11 +280,11 @@ void list_common_cmds_help(void)
 			longest = strlen(common_cmds[i].name);
 	}
 
-	puts("The most commonly used git commands are:");
+	puts(_("The most commonly used git commands are:"));
 	for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
 		printf("   %s   ", common_cmds[i].name);
 		mput_char(' ', longest - strlen(common_cmds[i].name));
-		puts(common_cmds[i].help);
+		puts(_(common_cmds[i].help));
 	}
 }
 
@@ -348,7 +348,7 @@ static void exec_viewer(const char *name, const char *page)
 	else if (info)
 		exec_man_cmd(info, page);
 	else
-		warning("'%s': unknown man viewer.", name);
+		warning(_("'%s': unknown man viewer."), name);
 }
 
 static void show_man_page(const char *git_cmd)
@@ -365,7 +365,7 @@ static void show_man_page(const char *git_cmd)
 	if (fallback)
 		exec_viewer(fallback, page);
 	exec_viewer("man", page);
-	die("no man viewer handled the request");
+	die(_("no man viewer handled the request"));
 }
 
 static void show_info_page(const char *git_cmd)
@@ -373,7 +373,7 @@ static void show_info_page(const char *git_cmd)
 	const char *page = cmd_to_page(git_cmd);
 	setenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
 	execlp("info", "info", "gitman", page, (char *)NULL);
-	die("no info viewer handled the request");
+	die(_("no info viewer handled the request"));
 }
 
 static void get_html_page_path(struct strbuf *page_path, const char *page)
@@ -384,7 +384,7 @@ static void get_html_page_path(struct strbuf *page_path, const char *page)
 	/* Check that we have a git documentation directory. */
 	if (stat(mkpath("%s/git.html", html_path), &st)
 	    || !S_ISREG(st.st_mode))
-		die("'%s': not a documentation directory.", html_path);
+		die(_("'%s': not a documentation directory."), html_path);
 
 	strbuf_init(page_path, 0);
 	strbuf_addf(page_path, "%s/%s.html", html_path, page);
@@ -424,16 +424,16 @@ int cmd_help(int argc, const char **argv, const char *prefix)
 	parsed_help_format = help_format;
 
 	if (show_all) {
-		printf("usage: %s\n\n", git_usage_string);
-		list_commands("git commands", &main_cmds, &other_cmds);
-		printf("%s\n", git_more_info_string);
+		printf(_("usage: %s%s"), _(git_usage_string), "\n\n");
+		list_commands(_("git commands"), &main_cmds, &other_cmds);
+		printf("%s\n", _(git_more_info_string));
 		return 0;
 	}
 
 	if (!argv[0]) {
-		printf("usage: %s\n\n", git_usage_string);
+		printf(_("usage: %s%s"), _(git_usage_string), "\n\n");
 		list_common_cmds_help();
-		printf("\n%s\n", git_more_info_string);
+		printf("\n%s\n", _(git_more_info_string));
 		return 0;
 	}
 
@@ -445,7 +445,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
 
 	alias = alias_lookup(argv[0]);
 	if (alias && !is_git_command(argv[0])) {
-		printf("`git %s' is aliased to `%s'\n", argv[0], alias);
+		printf_ln(_("`git %s' is aliased to `%s'"), argv[0], alias);
 		return 0;
 	}
 
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index 1093ef4..9a4c9b9 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -16,7 +16,7 @@ do
      /^NAME/,/git-'"$cmd"'/H
      ${
 	    x
-	    s/.*git-'"$cmd"' - \(.*\)/  {"'"$cmd"'", "\1"},/
+	    s/.*git-'"$cmd"' - \(.*\)/  {"'"$cmd"'", N_("\1")},/
 	    p
      }' "Documentation/git-$cmd.txt"
 done
diff --git a/git.c b/git.c
index 3805616..4486deb 100644
--- a/git.c
+++ b/git.c
@@ -13,7 +13,7 @@ const char git_usage_string[] =
 	"           <command> [<args>]";
 
 const char git_more_info_string[] =
-	"See 'git help <command>' for more information on a specific command.";
+	N_("See 'git help <command>' for more information on a specific command.");
 
 static struct startup_info git_startup_info;
 static int use_pager = -1;
diff --git a/help.c b/help.c
index 14eefc9..9e6e0f2 100644
--- a/help.c
+++ b/help.c
@@ -217,8 +217,9 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
 
 	if (main_cmds->cnt) {
 		const char *exec_path = git_exec_path();
-		printf("available %s in '%s'\n", title, exec_path);
-		printf("----------------");
+		printf_ln(_("available %s in '%s'"), title, exec_path);
+		/* TRANSLATORS: this must align with "available %s in '%s'" */
+		printf(_("----------------"));
 		mput_char('-', strlen(title) + strlen(exec_path));
 		putchar('\n');
 		pretty_print_string_list(main_cmds, longest);
@@ -226,8 +227,12 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
 	}
 
 	if (other_cmds->cnt) {
-		printf("%s available from elsewhere on your $PATH\n", title);
-		printf("---------------------------------------");
+		printf_ln(_("%s available from elsewhere on your $PATH"), title);
+		/* TRANSLATORS:
+		 * this must align with
+		 * "%s available from elsewhere on your $PATH"
+		 */
+		printf(_("---------------------------------------"));
 		mput_char('-', strlen(title));
 		putchar('\n');
 		pretty_print_string_list(other_cmds, longest);
@@ -341,7 +346,7 @@ const char *help_unknown_cmd(const char *cmd)
 	      sizeof(*main_cmds.names), levenshtein_compare);
 
 	if (!main_cmds.cnt)
-		die ("Uh oh. Your system reports no Git commands at all.");
+		die(_("Uh oh. Your system reports no Git commands at all."));
 
 	/* skip and count prefix matches */
 	for (n = 0; n < main_cmds.cnt && !main_cmds.names[n]->len; n++)
@@ -362,23 +367,26 @@ const char *help_unknown_cmd(const char *cmd)
 		const char *assumed = main_cmds.names[0]->name;
 		main_cmds.names[0] = NULL;
 		clean_cmdnames(&main_cmds);
-		fprintf(stderr, "WARNING: You called a Git command named '%s', "
-			"which does not exist.\n"
-			"Continuing under the assumption that you meant '%s'\n",
+		fprintf_ln(stderr,
+			   _("WARNING: You called a Git command named '%s', "
+			     "which does not exist.\n"
+			     "Continuing under the assumption that you meant '%s'"),
 			cmd, assumed);
 		if (autocorrect > 0) {
-			fprintf(stderr, "in %0.1f seconds automatically...\n",
+			fprintf_ln(stderr, _("in %0.1f seconds automatically..."),
 				(float)autocorrect/10.0);
 			poll(NULL, 0, autocorrect * 100);
 		}
 		return assumed;
 	}
 
-	fprintf(stderr, "git: '%s' is not a git command. See 'git --help'.\n", cmd);
+	fprintf_ln(stderr, _("git: '%s' is not a git command. See 'git --help'."), cmd);
 
 	if (SIMILAR_ENOUGH(best_similarity)) {
-		fprintf(stderr, "\nDid you mean %s?\n",
-			n < 2 ? "this": "one of these");
+		fprintf_ln(stderr,
+			   Q_("\nDid you mean this?",
+			      "\nDid you mean one of these?",
+			   n));
 
 		for (i = 0; i < n; i++)
 			fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 05/10] i18n: make warn_dangling_symref() automatically append \n
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (3 preceding siblings ...)
  2012-04-23 12:30 ` [PATCH 04/10] i18n: help: mark strings " Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-23 12:30 ` [PATCH 06/10] i18n: remote: mark strings for translation Nguyễn Thái Ngọc Duy
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

This helps remove \n from translatable strings

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/fetch.c  |    4 ++--
 builtin/remote.c |    4 ++--
 refs.c           |    1 +
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/builtin/fetch.c b/builtin/fetch.c
index 65f5f9b..a8c3e4c 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -537,8 +537,8 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map)
 	int result = 0;
 	struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map);
 	const char *dangling_msg = dry_run
-		? _("   (%s will become dangling)\n")
-		: _("   (%s has become dangling)\n");
+		? _("   (%s will become dangling)")
+		: _("   (%s has become dangling)");
 
 	for (ref = stale_refs; ref; ref = ref->next) {
 		if (!dry_run)
diff --git a/builtin/remote.c b/builtin/remote.c
index fec92bc..1b03473 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1260,8 +1260,8 @@ static int prune_remote(const char *remote, int dry_run)
 	int result = 0, i;
 	struct ref_states states;
 	const char *dangling_msg = dry_run
-		? " %s will become dangling!\n"
-		: " %s has become dangling!\n";
+		? " %s will become dangling!"
+		: " %s has become dangling!";
 
 	memset(&states, 0, sizeof(states));
 	get_remote_ref_states(remote, &states, GET_REF_STATES);
diff --git a/refs.c b/refs.c
index c9f6835..052c2f6 100644
--- a/refs.c
+++ b/refs.c
@@ -395,6 +395,7 @@ static int warn_if_dangling_symref(const char *refname, const unsigned char *sha
 		return 0;
 
 	fprintf(d->fp, d->msg_fmt, refname);
+	fputc('\n', d->fp);
 	return 0;
 }
 
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 06/10] i18n: remote: mark strings for translation
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (4 preceding siblings ...)
  2012-04-23 12:30 ` [PATCH 05/10] i18n: make warn_dangling_symref() automatically append \n Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-25 22:54   ` Junio C Hamano
  2012-04-23 12:30 ` [PATCH 07/10] i18n: apply: " Nguyễn Thái Ngọc Duy
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/remote.c |  227 +++++++++++++++++++++++++++++-------------------------
 1 files changed, 121 insertions(+), 106 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index 1b03473..51434fa 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -95,9 +95,9 @@ static int fetch_remote(const char *name)
 		argv[1] = "-v";
 		argv[2] = name;
 	}
-	printf("Updating %s\n", name);
+	printf_ln(_("Updating %s"), name);
 	if (run_command_v_opt(argv, RUN_GIT_CMD))
-		return error("Could not fetch %s", name);
+		return error(_("Could not fetch %s"), name);
 	return 0;
 }
 
@@ -127,8 +127,8 @@ static int add_branch(const char *key, const char *branchname,
 }
 
 static const char mirror_advice[] =
-"--mirror is dangerous and deprecated; please\n"
-"\t use --mirror=fetch or --mirror=push instead";
+N_("--mirror is dangerous and deprecated; please\n"
+   "\t use --mirror=fetch or --mirror=push instead");
 
 static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
 {
@@ -136,7 +136,7 @@ static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
 	if (not)
 		*mirror = MIRROR_NONE;
 	else if (!arg) {
-		warning("%s", mirror_advice);
+		warning("%s", _(mirror_advice));
 		*mirror = MIRROR_BOTH;
 	}
 	else if (!strcmp(arg, "fetch"))
@@ -144,7 +144,7 @@ static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
 	else if (!strcmp(arg, "push"))
 		*mirror = MIRROR_PUSH;
 	else
-		return error("unknown mirror argument: %s", arg);
+		return error(_("unknown mirror argument: %s"), arg);
 	return 0;
 }
 
@@ -182,9 +182,9 @@ static int add(int argc, const char **argv)
 		usage_with_options(builtin_remote_add_usage, options);
 
 	if (mirror && master)
-		die("specifying a master branch makes no sense with --mirror");
+		die(_("specifying a master branch makes no sense with --mirror"));
 	if (mirror && !(mirror & MIRROR_FETCH) && track.nr)
-		die("specifying branches to track makes sense only with fetch mirrors");
+		die(_("specifying branches to track makes sense only with fetch mirrors"));
 
 	name = argv[0];
 	url = argv[1];
@@ -192,11 +192,11 @@ static int add(int argc, const char **argv)
 	remote = remote_get(name);
 	if (remote && (remote->url_nr > 1 || strcmp(name, remote->url[0]) ||
 			remote->fetch_refspec_nr))
-		die("remote %s already exists.", name);
+		die(_("remote %s already exists."), name);
 
 	strbuf_addf(&buf2, "refs/heads/test:refs/remotes/%s/test", name);
 	if (!valid_fetch_refspec(buf2.buf))
-		die("'%s' is not a valid remote name", name);
+		die(_("'%s' is not a valid remote name"), name);
 
 	strbuf_addf(&buf, "remote.%s.url", name);
 	if (git_config_set(buf.buf, url))
@@ -240,7 +240,7 @@ static int add(int argc, const char **argv)
 		strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master);
 
 		if (create_symref(buf.buf, buf2.buf, "remote add"))
-			return error("Could not setup master '%s'", master);
+			return error(_("Could not setup master '%s'"), master);
 	}
 
 	strbuf_release(&buf);
@@ -296,7 +296,7 @@ static int config_read_branches(const char *key, const char *value, void *cb)
 		info = item->util;
 		if (type == REMOTE) {
 			if (info->remote_name)
-				warning("more than one %s", orig_key);
+				warning(_("more than one %s"), orig_key);
 			info->remote_name = xstrdup(value);
 		} else if (type == MERGE) {
 			char *space = strchr(value, ' ');
@@ -336,7 +336,7 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
 
 	for (i = 0; i < states->remote->fetch_refspec_nr; i++)
 		if (get_fetch_map(remote_refs, states->remote->fetch + i, &tail, 1))
-			die("Could not get fetch map for refspec %s",
+			die(_("Could not get fetch map for refspec %s"),
 				states->remote->fetch_refspec[i]);
 
 	states->new.strdup_strings = 1;
@@ -437,7 +437,7 @@ static int get_push_ref_states_noquery(struct ref_states *states)
 
 	states->push.strdup_strings = 1;
 	if (!remote->push_refspec_nr) {
-		item = string_list_append(&states->push, "(matching)");
+		item = string_list_append(&states->push, _("(matching)"));
 		info = item->util = xcalloc(sizeof(struct push_info), 1);
 		info->status = PUSH_STATUS_NOTQUERIED;
 		info->dest = xstrdup(item->string);
@@ -445,11 +445,11 @@ static int get_push_ref_states_noquery(struct ref_states *states)
 	for (i = 0; i < remote->push_refspec_nr; i++) {
 		struct refspec *spec = remote->push + i;
 		if (spec->matching)
-			item = string_list_append(&states->push, "(matching)");
+			item = string_list_append(&states->push, _("(matching)"));
 		else if (strlen(spec->src))
 			item = string_list_append(&states->push, spec->src);
 		else
-			item = string_list_append(&states->push, "(delete)");
+			item = string_list_append(&states->push, _("(delete)"));
 
 		info = item->util = xcalloc(sizeof(struct push_info), 1);
 		info->forced = spec->force;
@@ -592,19 +592,19 @@ static int migrate_file(struct remote *remote)
 	strbuf_addf(&buf, "remote.%s.url", remote->name);
 	for (i = 0; i < remote->url_nr; i++)
 		if (git_config_set_multivar(buf.buf, remote->url[i], "^$", 0))
-			return error("Could not append '%s' to '%s'",
+			return error(_("Could not append '%s' to '%s'"),
 					remote->url[i], buf.buf);
 	strbuf_reset(&buf);
 	strbuf_addf(&buf, "remote.%s.push", remote->name);
 	for (i = 0; i < remote->push_refspec_nr; i++)
 		if (git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0))
-			return error("Could not append '%s' to '%s'",
+			return error(_("Could not append '%s' to '%s'"),
 					remote->push_refspec[i], buf.buf);
 	strbuf_reset(&buf);
 	strbuf_addf(&buf, "remote.%s.fetch", remote->name);
 	for (i = 0; i < remote->fetch_refspec_nr; i++)
 		if (git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0))
-			return error("Could not append '%s' to '%s'",
+			return error(_("Could not append '%s' to '%s'"),
 					remote->fetch_refspec[i], buf.buf);
 	if (remote->origin == REMOTE_REMOTES)
 		path = git_path("remotes/%s", remote->name);
@@ -636,30 +636,30 @@ static int mv(int argc, const char **argv)
 
 	oldremote = remote_get(rename.old);
 	if (!oldremote)
-		die("No such remote: %s", rename.old);
+		die(_("No such remote: %s"), rename.old);
 
 	if (!strcmp(rename.old, rename.new) && oldremote->origin != REMOTE_CONFIG)
 		return migrate_file(oldremote);
 
 	newremote = remote_get(rename.new);
 	if (newremote && (newremote->url_nr > 1 || newremote->fetch_refspec_nr))
-		die("remote %s already exists.", rename.new);
+		die(_("remote %s already exists."), rename.new);
 
 	strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new);
 	if (!valid_fetch_refspec(buf.buf))
-		die("'%s' is not a valid remote name", rename.new);
+		die(_("'%s' is not a valid remote name"), rename.new);
 
 	strbuf_reset(&buf);
 	strbuf_addf(&buf, "remote.%s", rename.old);
 	strbuf_addf(&buf2, "remote.%s", rename.new);
 	if (git_config_rename_section(buf.buf, buf2.buf) < 1)
-		return error("Could not rename config section '%s' to '%s'",
+		return error(_("Could not rename config section '%s' to '%s'"),
 				buf.buf, buf2.buf);
 
 	strbuf_reset(&buf);
 	strbuf_addf(&buf, "remote.%s.fetch", rename.new);
 	if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
-		return error("Could not remove config section '%s'", buf.buf);
+		return error(_("Could not remove config section '%s'"), buf.buf);
 	strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old);
 	for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
 		char *ptr;
@@ -674,13 +674,13 @@ static int mv(int argc, const char **argv)
 				      strlen(rename.old), rename.new,
 				      strlen(rename.new));
 		} else
-			warning("Not updating non-default fetch respec\n"
-				"\t%s\n"
-				"\tPlease update the configuration manually if necessary.",
+			warning(_("Not updating non-default fetch respec\n"
+				  "\t%s\n"
+				  "\tPlease update the configuration manually if necessary."),
 				buf2.buf);
 
 		if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
-			return error("Could not append '%s'", buf.buf);
+			return error(_("Could not append '%s'"), buf.buf);
 	}
 
 	read_branches();
@@ -691,7 +691,7 @@ static int mv(int argc, const char **argv)
 			strbuf_reset(&buf);
 			strbuf_addf(&buf, "branch.%s.remote", item->string);
 			if (git_config_set(buf.buf, rename.new)) {
-				return error("Could not set '%s'", buf.buf);
+				return error(_("Could not set '%s'"), buf.buf);
 			}
 		}
 	}
@@ -713,7 +713,7 @@ static int mv(int argc, const char **argv)
 		if (!(flag & REF_ISSYMREF))
 			continue;
 		if (delete_ref(item->string, NULL, REF_NODEREF))
-			die("deleting '%s' failed", item->string);
+			die(_("deleting '%s' failed"), item->string);
 	}
 	for (i = 0; i < remote_branches.nr; i++) {
 		struct string_list_item *item = remote_branches.items + i;
@@ -728,7 +728,7 @@ static int mv(int argc, const char **argv)
 		strbuf_addf(&buf2, "remote: renamed %s to %s",
 				item->string, buf.buf);
 		if (rename_ref(item->string, buf.buf, buf2.buf))
-			die("renaming '%s' failed", item->string);
+			die(_("renaming '%s' failed"), item->string);
 	}
 	for (i = 0; i < remote_branches.nr; i++) {
 		struct string_list_item *item = remote_branches.items + i;
@@ -747,7 +747,7 @@ static int mv(int argc, const char **argv)
 		strbuf_addf(&buf3, "remote: renamed %s to %s",
 				item->string, buf.buf);
 		if (create_symref(buf.buf, buf2.buf, buf3.buf))
-			die("creating '%s' failed", buf.buf);
+			die(_("creating '%s' failed"), buf.buf);
 	}
 	return 0;
 }
@@ -761,7 +761,7 @@ static int remove_branches(struct string_list *branches)
 		unsigned char *sha1 = item->util;
 
 		if (delete_ref(refname, sha1, 0))
-			result |= error("Could not remove branch %s", refname);
+			result |= error(_("Could not remove branch %s"), refname);
 	}
 	return result;
 }
@@ -789,14 +789,14 @@ static int rm(int argc, const char **argv)
 
 	remote = remote_get(argv[1]);
 	if (!remote)
-		die("No such remote: %s", argv[1]);
+		die(_("No such remote: %s"), argv[1]);
 
 	known_remotes.to_delete = remote;
 	for_each_remote(add_known_remote, &known_remotes);
 
 	strbuf_addf(&buf, "remote.%s", remote->name);
 	if (git_config_rename_section(buf.buf, NULL) < 1)
-		return error("Could not remove config section '%s'", buf.buf);
+		return error(_("Could not remove config section '%s'"), buf.buf);
 
 	read_branches();
 	for (i = 0; i < branch_list.nr; i++) {
@@ -830,11 +830,12 @@ static int rm(int argc, const char **argv)
 	string_list_clear(&branches, 1);
 
 	if (skipped.nr) {
-		fprintf(stderr, skipped.nr == 1 ?
-			"Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
-			"to delete it, use:\n" :
-			"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
-			"to delete them, use:\n");
+		fprintf_ln(stderr,
+			   Q_("Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
+			      "to delete it, use:",
+			      "Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
+			      "to delete them, use:",
+			      skipped.nr));
 		for (i = 0; i < skipped.nr; i++)
 			fprintf(stderr, "  git branch -d %s\n",
 				skipped.items[i].string);
@@ -886,7 +887,7 @@ static int get_remote_ref_states(const char *name,
 
 	states->remote = remote_get(name);
 	if (!states->remote)
-		return error("No such remote: %s", name);
+		return error(_("No such remote: %s"), name);
 
 	read_branches();
 
@@ -939,14 +940,14 @@ static int show_remote_info_item(struct string_list_item *item, void *cb_data)
 		const char *fmt = "%s";
 		const char *arg = "";
 		if (string_list_has_string(&states->new, name)) {
-			fmt = " new (next fetch will store in remotes/%s)";
+			fmt = _(" new (next fetch will store in remotes/%s)");
 			arg = states->remote->name;
 		} else if (string_list_has_string(&states->tracked, name))
-			arg = " tracked";
+			arg = _(" tracked");
 		else if (string_list_has_string(&states->stale, name))
-			arg = " stale (use 'git remote prune' to remove)";
+			arg = _(" stale (use 'git remote prune' to remove)");
 		else
-			arg = " ???";
+			arg = _(" ???");
 		printf("    %-*s", info->width, name);
 		printf(fmt, arg);
 		printf("\n");
@@ -987,21 +988,21 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data)
 	int i;
 
 	if (branch_info->rebase && branch_info->merge.nr > 1) {
-		error("invalid branch.%s.merge; cannot rebase onto > 1 branch",
+		error(_("invalid branch.%s.merge; cannot rebase onto > 1 branch"),
 			item->string);
 		return 0;
 	}
 
 	printf("    %-*s ", show_info->width, item->string);
 	if (branch_info->rebase) {
-		printf("rebases onto remote %s\n", merge->items[0].string);
+		printf_ln(_("rebases onto remote %s"), merge->items[0].string);
 		return 0;
 	} else if (show_info->any_rebase) {
-		printf(" merges with remote %s\n", merge->items[0].string);
-		also = "    and with remote";
+		printf_ln(_(" merges with remote %s"), merge->items[0].string);
+		also = _("    and with remote");
 	} else {
-		printf("merges with remote %s\n", merge->items[0].string);
-		also = "   and with remote";
+		printf_ln(_("merges with remote %s"), merge->items[0].string);
+		also = _("   and with remote");
 	}
 	for (i = 1; i < merge->nr; i++)
 		printf("    %-*s %s %s\n", show_info->width, "", also,
@@ -1043,36 +1044,43 @@ static int show_push_info_item(struct string_list_item *item, void *cb_data)
 {
 	struct show_info *show_info = cb_data;
 	struct push_info *push_info = item->util;
-	char *src = item->string, *status = NULL;
+	const char *src = item->string, *status = NULL;
 
 	switch (push_info->status) {
 	case PUSH_STATUS_CREATE:
-		status = "create";
+		status = _("create");
 		break;
 	case PUSH_STATUS_DELETE:
-		status = "delete";
-		src = "(none)";
+		status = _("delete");
+		src = _("(none)");
 		break;
 	case PUSH_STATUS_UPTODATE:
-		status = "up to date";
+		status = _("up to date");
 		break;
 	case PUSH_STATUS_FASTFORWARD:
-		status = "fast-forwardable";
+		status = _("fast-forwardable");
 		break;
 	case PUSH_STATUS_OUTOFDATE:
-		status = "local out of date";
+		status = _("local out of date");
 		break;
 	case PUSH_STATUS_NOTQUERIED:
 		break;
 	}
-	if (status)
-		printf("    %-*s %s to %-*s (%s)\n", show_info->width, src,
-			push_info->forced ? "forces" : "pushes",
-			show_info->width2, push_info->dest, status);
-	else
-		printf("    %-*s %s to %s\n", show_info->width, src,
-			push_info->forced ? "forces" : "pushes",
-			push_info->dest);
+	if (status) {
+		if (push_info->forced)
+			printf_ln(_("    %-*s forces to %-*s (%s)"), show_info->width, src,
+			       show_info->width2, push_info->dest, status);
+		else
+			printf_ln(_("    %-*s pushes to %-*s (%s)"), show_info->width, src,
+			       show_info->width2, push_info->dest, status);
+	} else {
+		if (push_info->forced)
+			printf_ln(_("    %-*s forces to %s"), show_info->width, src,
+			       push_info->dest);
+		else
+			printf_ln(_("    %-*s pushes to %s"), show_info->width, src,
+			       push_info->dest);
+	}
 	return 0;
 }
 
@@ -1107,9 +1115,9 @@ static int show(int argc, const char **argv)
 
 		get_remote_ref_states(*argv, &states, query_flag);
 
-		printf("* remote %s\n", *argv);
-		printf("  Fetch URL: %s\n", states.remote->url_nr > 0 ?
-			states.remote->url[0] : "(no URL)");
+		printf_ln(_("* remote %s"), *argv);
+		printf_ln(_("  Fetch URL: %s"), states.remote->url_nr > 0 ?
+		       states.remote->url[0] : _("(no URL)"));
 		if (states.remote->pushurl_nr) {
 			url = states.remote->pushurl;
 			url_nr = states.remote->pushurl_nr;
@@ -1118,18 +1126,18 @@ static int show(int argc, const char **argv)
 			url_nr = states.remote->url_nr;
 		}
 		for (i = 0; i < url_nr; i++)
-			printf("  Push  URL: %s\n", url[i]);
+			printf_ln(_("  Push  URL: %s"), url[i]);
 		if (!i)
-			printf("  Push  URL: %s\n", "(no URL)");
+			printf_ln(_("  Push  URL: %s"), "(no URL)");
 		if (no_query)
-			printf("  HEAD branch: (not queried)\n");
+			printf_ln(_("  HEAD branch: %s"), "(not queried)");
 		else if (!states.heads.nr)
-			printf("  HEAD branch: (unknown)\n");
+			printf_ln(_("  HEAD branch: %s"), "(unknown)");
 		else if (states.heads.nr == 1)
-			printf("  HEAD branch: %s\n", states.heads.items[0].string);
+			printf_ln(_("  HEAD branch: %s"), states.heads.items[0].string);
 		else {
-			printf("  HEAD branch (remote HEAD is ambiguous,"
-			       " may be one of the following):\n");
+			printf(_("  HEAD branch (remote HEAD is ambiguous,"
+				 " may be one of the following):\n"));
 			for (i = 0; i < states.heads.nr; i++)
 				printf("    %s\n", states.heads.items[i].string);
 		}
@@ -1140,9 +1148,10 @@ static int show(int argc, const char **argv)
 		for_each_string_list(&states.tracked, add_remote_to_show_info, &info);
 		for_each_string_list(&states.stale, add_remote_to_show_info, &info);
 		if (info.list->nr)
-			printf("  Remote branch%s:%s\n",
-			       info.list->nr > 1 ? "es" : "",
-				no_query ? " (status not queried)" : "");
+			printf_ln(Q_("  Remote branch:%s",
+				     "  Remote branches:%s",
+				     info.list->nr),
+				  no_query ? _(" (status not queried)") : "");
 		for_each_string_list(info.list, show_remote_info_item, &info);
 		string_list_clear(info.list, 0);
 
@@ -1151,23 +1160,25 @@ static int show(int argc, const char **argv)
 		info.any_rebase = 0;
 		for_each_string_list(&branch_list, add_local_to_show_info, &info);
 		if (info.list->nr)
-			printf("  Local branch%s configured for 'git pull':\n",
-			       info.list->nr > 1 ? "es" : "");
+			printf_ln(Q_("  Local branch configured for 'git pull':",
+				     "  Local branches configured for 'git pull':",
+				     info.list->nr));
 		for_each_string_list(info.list, show_local_info_item, &info);
 		string_list_clear(info.list, 0);
 
 		/* git push info */
 		if (states.remote->mirror)
-			printf("  Local refs will be mirrored by 'git push'\n");
+			printf_ln(_("  Local refs will be mirrored by 'git push'"));
 
 		info.width = info.width2 = 0;
 		for_each_string_list(&states.push, add_push_to_show_info, &info);
 		qsort(info.list->items, info.list->nr,
 			sizeof(*info.list->items), cmp_string_with_push);
 		if (info.list->nr)
-			printf("  Local ref%s configured for 'git push'%s:\n",
-				info.list->nr > 1 ? "s" : "",
-				no_query ? " (status not queried)" : "");
+			printf_ln(Q_("  Local ref configured for 'git push'%s:",
+				     "  Local refs configured for 'git push'%s:",
+				     info.list->nr),
+				  no_query ? _(" (status not queried)") : "");
 		for_each_string_list(info.list, show_push_info_item, &info);
 		string_list_clear(info.list, 0);
 
@@ -1202,10 +1213,10 @@ static int set_head(int argc, const char **argv)
 		memset(&states, 0, sizeof(states));
 		get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
 		if (!states.heads.nr)
-			result |= error("Cannot determine remote HEAD");
+			result |= error(_("Cannot determine remote HEAD"));
 		else if (states.heads.nr > 1) {
-			result |= error("Multiple remote HEAD branches. "
-					"Please choose one explicitly with:");
+			result |= error(_("Multiple remote HEAD branches. "
+					  "Please choose one explicitly with:"));
 			for (i = 0; i < states.heads.nr; i++)
 				fprintf(stderr, "  git remote set-head %s %s\n",
 					argv[0], states.heads.items[i].string);
@@ -1214,7 +1225,7 @@ static int set_head(int argc, const char **argv)
 		free_remote_ref_states(&states);
 	} else if (opt_d && !opt_a && argc == 1) {
 		if (delete_ref(buf.buf, NULL, REF_NODEREF))
-			result |= error("Could not delete %s", buf.buf);
+			result |= error(_("Could not delete %s"), buf.buf);
 	} else
 		usage_with_options(builtin_remote_sethead_usage, options);
 
@@ -1222,9 +1233,9 @@ static int set_head(int argc, const char **argv)
 		strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
 		/* make sure it's valid */
 		if (!ref_exists(buf2.buf))
-			result |= error("Not a valid ref: %s", buf2.buf);
+			result |= error(_("Not a valid ref: %s"), buf2.buf);
 		else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
-			result |= error("Could not setup %s", buf.buf);
+			result |= error(_("Could not setup %s"), buf.buf);
 		if (opt_a)
 			printf("%s/HEAD set to %s\n", argv[0], head_name);
 		free(head_name);
@@ -1260,18 +1271,18 @@ static int prune_remote(const char *remote, int dry_run)
 	int result = 0, i;
 	struct ref_states states;
 	const char *dangling_msg = dry_run
-		? " %s will become dangling!"
-		: " %s has become dangling!";
+		? _(" %s will become dangling!")
+		: _(" %s has become dangling!");
 
 	memset(&states, 0, sizeof(states));
 	get_remote_ref_states(remote, &states, GET_REF_STATES);
 
 	if (states.stale.nr) {
-		printf("Pruning %s\n", remote);
-		printf("URL: %s\n",
+		printf_ln(_("Pruning %s"), remote);
+		printf_ln(_("URL: %s"),
 		       states.remote->url_nr
 		       ? states.remote->url[0]
-		       : "(no URL)");
+		       : _("(no URL)"));
 	}
 
 	for (i = 0; i < states.stale.nr; i++) {
@@ -1280,8 +1291,12 @@ static int prune_remote(const char *remote, int dry_run)
 		if (!dry_run)
 			result |= delete_ref(refname, NULL, 0);
 
-		printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
-		       abbrev_ref(refname, "refs/remotes/"));
+		if (dry_run)
+			printf_ln(_(" * [would prune] %s"),
+			       abbrev_ref(refname, "refs/remotes/"));
+		else
+			printf_ln(_(" * [pruned] %s"),
+			       abbrev_ref(refname, "refs/remotes/"));
 		warn_dangling_symref(stdout, dangling_msg, refname);
 	}
 
@@ -1369,7 +1384,7 @@ static int set_remote_branches(const char *remotename, const char **branches,
 	strbuf_addf(&key, "remote.%s.fetch", remotename);
 
 	if (!remote_is_configured(remotename))
-		die("No such remote '%s'", remotename);
+		die(_("No such remote '%s'"), remotename);
 	remote = remote_get(remotename);
 
 	if (!add_mode && remove_all_fetch_refspecs(remotename, key.buf)) {
@@ -1396,7 +1411,7 @@ static int set_branches(int argc, const char **argv)
 	argc = parse_options(argc, argv, NULL, options,
 			     builtin_remote_setbranches_usage, 0);
 	if (argc == 0) {
-		error("no remote specified");
+		error(_("no remote specified"));
 		usage_with_options(builtin_remote_setbranches_usage, options);
 	}
 	argv[argc] = NULL;
@@ -1429,7 +1444,7 @@ static int set_url(int argc, const char **argv)
 			     PARSE_OPT_KEEP_ARGV0);
 
 	if (add_mode && delete_mode)
-		die("--add --delete doesn't make sense");
+		die(_("--add --delete doesn't make sense"));
 
 	if (argc < 3 || argc > 4 || ((add_mode || delete_mode) && argc != 3))
 		usage_with_options(builtin_remote_seturl_usage, options);
@@ -1443,7 +1458,7 @@ static int set_url(int argc, const char **argv)
 		oldurl = newurl;
 
 	if (!remote_is_configured(remotename))
-		die("No such remote '%s'", remotename);
+		die(_("No such remote '%s'"), remotename);
 	remote = remote_get(remotename);
 
 	if (push_mode) {
@@ -1469,7 +1484,7 @@ static int set_url(int argc, const char **argv)
 
 	/* Old URL specified. Demand that one matches. */
 	if (regcomp(&old_regex, oldurl, REG_EXTENDED))
-		die("Invalid old URL pattern: %s", oldurl);
+		die(_("Invalid old URL pattern: %s"), oldurl);
 
 	for (i = 0; i < urlset_nr; i++)
 		if (!regexec(&old_regex, urlset[i], 0, NULL, 0))
@@ -1477,9 +1492,9 @@ static int set_url(int argc, const char **argv)
 		else
 			negative_matches++;
 	if (!delete_mode && !matches)
-		die("No such URL found: %s", oldurl);
+		die(_("No such URL found: %s"), oldurl);
 	if (delete_mode && !negative_matches && !push_mode)
-		die("Will not delete all non-push URLs");
+		die(_("Will not delete all non-push URLs"));
 
 	regfree(&old_regex);
 
@@ -1580,7 +1595,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
 	else if (!strcmp(argv[0], "update"))
 		result = update(argc, argv);
 	else {
-		error("Unknown subcommand: %s", argv[0]);
+		error(_("Unknown subcommand: %s"), argv[0]);
 		usage_with_options(builtin_remote_usage, options);
 	}
 
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 07/10] i18n: apply: mark strings for translation
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (5 preceding siblings ...)
  2012-04-23 12:30 ` [PATCH 06/10] i18n: remote: mark strings for translation Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-25 22:50   ` Junio C Hamano
  2012-04-23 12:30 ` [PATCH 08/10] i18n: apply: update say_patch_name to give translators complete sentence Nguyễn Thái Ngọc Duy
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/apply.c |  174 +++++++++++++++++++++++++++++--------------------------
 1 files changed, 91 insertions(+), 83 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 389898f..4bb6354 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -103,7 +103,7 @@ static void parse_whitespace_option(const char *option)
 		ws_error_action = correct_ws_error;
 		return;
 	}
-	die("unrecognized whitespace option '%s'", option);
+	die(_("unrecognized whitespace option '%s'"), option);
 }
 
 static void parse_ignorewhitespace_option(const char *option)
@@ -118,7 +118,7 @@ static void parse_ignorewhitespace_option(const char *option)
 		ws_ignore_action = ignore_ws_change;
 		return;
 	}
-	die("unrecognized whitespace ignore option '%s'", option);
+	die(_("unrecognized whitespace ignore option '%s'"), option);
 }
 
 static void set_default_whitespace_mode(const char *whitespace_option)
@@ -770,7 +770,7 @@ static int has_epoch_timestamp(const char *nameline)
 	if (!stamp) {
 		stamp = xmalloc(sizeof(*stamp));
 		if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) {
-			warning("Cannot prepare timestamp regexp %s",
+			warning(_("Cannot prepare timestamp regexp %s"),
 				stamp_regexp);
 			return 0;
 		}
@@ -779,7 +779,7 @@ static int has_epoch_timestamp(const char *nameline)
 	status = regexec(stamp, timestamp, ARRAY_SIZE(m), m, 0);
 	if (status) {
 		if (status != REG_NOMATCH)
-			warning("regexec returned %d for input: %s",
+			warning(_("regexec returned %d for input: %s"),
 				status, timestamp);
 		return 0;
 	}
@@ -857,7 +857,7 @@ static void parse_traditional_patch(const char *first, const char *second, struc
 		}
 	}
 	if (!name)
-		die("unable to find filename in patch at line %d", linenr);
+		die(_("unable to find filename in patch at line %d"), linenr);
 }
 
 static int gitdiff_hdrend(const char *line, struct patch *patch)
@@ -886,17 +886,17 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
 		name = orig_name;
 		len = strlen(name);
 		if (isnull)
-			die("git apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
+			die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), name, linenr);
 		another = find_name(line, NULL, p_value, TERM_TAB);
 		if (!another || memcmp(another, name, len + 1))
-			die("git apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
+			die(_("git apply: bad git-diff - inconsistent %s filename on line %d"), oldnew, linenr);
 		free(another);
 		return orig_name;
 	}
 	else {
 		/* expect "/dev/null" */
 		if (memcmp("/dev/null", line, 9) || line[9] != '\n')
-			die("git apply: bad git-diff - expected /dev/null on line %d", linenr);
+			die(_("git apply: bad git-diff - expected /dev/null on line %d"), linenr);
 		return NULL;
 	}
 }
@@ -1327,7 +1327,7 @@ static void recount_diff(char *line, int size, struct fragment *fragment)
 			break;
 		}
 		if (ret) {
-			warning("recount: unexpected line: %.*s",
+			warning(_("recount: unexpected line: %.*s"),
 				(int)linelen(line, size), line);
 			return;
 		}
@@ -1384,7 +1384,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
 			struct fragment dummy;
 			if (parse_fragment_header(line, len, &dummy) < 0)
 				continue;
-			die("patch fragment without header at line %d: %.*s",
+			die(_("patch fragment without header at line %d: %.*s"),
 			    linenr, (int)len-1, line);
 		}
 
@@ -1401,8 +1401,12 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
 				continue;
 			if (!patch->old_name && !patch->new_name) {
 				if (!patch->def_name)
-					die("git diff header lacks filename information when removing "
-					    "%d leading pathname components (line %d)" , p_value, linenr);
+					die(Q_("git diff header lacks filename information when removing "
+					       "%d leading pathname component (line %d)",
+					       "git diff header lacks filename information when removing "
+					       "%d leading pathname components (line %d)",
+					       p_value),
+					    p_value, linenr);
 				patch->old_name = patch->new_name = patch->def_name;
 			}
 			if (!patch->is_delete && !patch->new_name)
@@ -1556,9 +1560,9 @@ static int parse_fragment(char *line, unsigned long size,
 	patch->lines_deleted += deleted;
 
 	if (0 < patch->is_new && oldlines)
-		return error("new file depends on old contents");
+		return error(_("new file depends on old contents"));
 	if (0 < patch->is_delete && newlines)
-		return error("deleted file still has contents");
+		return error(_("deleted file still has contents"));
 	return offset;
 }
 
@@ -1576,7 +1580,7 @@ static int parse_single_patch(char *line, unsigned long size, struct patch *patc
 		fragment->linenr = linenr;
 		len = parse_fragment(line, size, patch, fragment);
 		if (len <= 0)
-			die("corrupt patch at line %d", linenr);
+			die(_("corrupt patch at line %d"), linenr);
 		fragment->patch = line;
 		fragment->size = len;
 		oldlines += fragment->oldlines;
@@ -1612,12 +1616,14 @@ static int parse_single_patch(char *line, unsigned long size, struct patch *patc
 		patch->is_delete = 0;
 
 	if (0 < patch->is_new && oldlines)
-		die("new file %s depends on old contents", patch->new_name);
+		die(_("new file %s depends on old contents"), patch->new_name);
 	if (0 < patch->is_delete && newlines)
-		die("deleted file %s still has contents", patch->old_name);
+		die(_("deleted file %s still has contents"), patch->old_name);
 	if (!patch->is_delete && !newlines && context)
-		fprintf(stderr, "** warning: file %s becomes empty but "
-			"is not deleted\n", patch->new_name);
+		fprintf_ln(stderr,
+			   _("** warning: "
+			     "file %s becomes empty but is not deleted"),
+			   patch->new_name);
 
 	return offset;
 }
@@ -1755,7 +1761,7 @@ static struct fragment *parse_binary_hunk(char **buf_p,
  corrupt:
 	free(data);
 	*status_p = -1;
-	error("corrupt binary patch at line %d: %.*s",
+	error(_("corrupt binary patch at line %d: %.*s"),
 	      linenr-1, llen-1, buffer);
 	return NULL;
 }
@@ -1784,7 +1790,7 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
 	forward = parse_binary_hunk(&buffer, &size, &status, &used);
 	if (!forward && !status)
 		/* there has to be one hunk (forward hunk) */
-		return error("unrecognized binary patch at line %d", linenr-1);
+		return error(_("unrecognized binary patch at line %d"), linenr-1);
 	if (status)
 		/* otherwise we already gave an error message */
 		return status;
@@ -1863,7 +1869,7 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
 		 */
 		if ((apply || check) &&
 		    (!patch->is_binary && !metadata_changes(patch)))
-			die("patch with only garbage at line %d", linenr);
+			die(_("patch with only garbage at line %d"), linenr);
 	}
 
 	return offset + hdrsize + patchsize;
@@ -1953,11 +1959,11 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
 	switch (st->st_mode & S_IFMT) {
 	case S_IFLNK:
 		if (strbuf_readlink(buf, path, st->st_size) < 0)
-			return error("unable to read symlink %s", path);
+			return error(_("unable to read symlink %s"), path);
 		return 0;
 	case S_IFREG:
 		if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
-			return error("unable to open or read %s", path);
+			return error(_("unable to open or read %s"), path);
 		convert_to_git(path, buf->buf, buf->len, buf, 0);
 		return 0;
 	default:
@@ -2028,7 +2034,7 @@ static void update_pre_post_images(struct image *preimage,
 			ctx++;
 		}
 		if (preimage->nr <= ctx)
-			die("oops");
+			die(_("oops"));
 
 		/* and copy it in, while fixing the line length */
 		len = preimage->line[ctx].len;
@@ -2540,7 +2546,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 			break;
 		default:
 			if (apply_verbosely)
-				error("invalid start of line: '%c'", first);
+				error(_("invalid start of line: '%c'"), first);
 			return -1;
 		}
 		if (added_blank_line) {
@@ -2657,9 +2663,11 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 			int offset = applied_pos - pos;
 			if (apply_in_reverse)
 				offset = 0 - offset;
-			fprintf(stderr,
-				"Hunk #%d succeeded at %d (offset %d lines).\n",
-				nth_fragment, applied_pos + 1, offset);
+			fprintf_ln(stderr,
+				   Q_("Hunk #%d succeeded at %d (offset %d line).",
+				      "Hunk #%d succeeded at %d (offset %d lines).",
+				      offset),
+				   nth_fragment, applied_pos + 1, offset);
 		}
 
 		/*
@@ -2668,13 +2676,13 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 		 */
 		if ((leading != frag->leading) ||
 		    (trailing != frag->trailing))
-			fprintf(stderr, "Context reduced to (%ld/%ld)"
-				" to apply fragment at %d\n",
-				leading, trailing, applied_pos+1);
+			fprintf_ln(stderr, _("Context reduced to (%ld/%ld)"
+					     " to apply fragment at %d"),
+				   leading, trailing, applied_pos+1);
 		update_image(img, applied_pos, &preimage, &postimage);
 	} else {
 		if (apply_verbosely)
-			error("while searching for:\n%.*s",
+			error(_("while searching for:\n%.*s"),
 			      (int)(old - oldlines), oldlines);
 	}
 
@@ -2693,7 +2701,7 @@ static int apply_binary_fragment(struct image *img, struct patch *patch)
 	void *dst;
 
 	if (!fragment)
-		return error("missing binary patch data for '%s'",
+		return error(_("missing binary patch data for '%s'"),
 			     patch->new_name ?
 			     patch->new_name :
 			     patch->old_name);
@@ -2790,13 +2798,13 @@ static int apply_binary(struct image *img, struct patch *patch)
 		 * in the patch->fragments->{patch,size}.
 		 */
 		if (apply_binary_fragment(img, patch))
-			return error("binary patch does not apply to '%s'",
+			return error(_("binary patch does not apply to '%s'"),
 				     name);
 
 		/* verify that the result matches */
 		hash_sha1_file(img->buf, img->len, blob_type, sha1);
 		if (strcmp(sha1_to_hex(sha1), patch->new_sha1_prefix))
-			return error("binary patch to '%s' creates incorrect result (expecting %s, got %s)",
+			return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"),
 				name, patch->new_sha1_prefix, sha1_to_hex(sha1));
 	}
 
@@ -2817,7 +2825,7 @@ static int apply_fragments(struct image *img, struct patch *patch)
 	while (frag) {
 		nth++;
 		if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule, nth)) {
-			error("patch failed: %s:%ld", name, frag->oldpos);
+			error(_("patch failed: %s:%ld"), name, frag->oldpos);
 			if (!apply_with_reject)
 				return -1;
 			frag->rejected = 1;
@@ -2932,14 +2940,14 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
 	if (!(patch->is_copy || patch->is_rename) &&
 	    (tpatch = in_fn_table(patch->old_name)) != NULL && !to_be_deleted(tpatch)) {
 		if (was_deleted(tpatch)) {
-			return error("patch %s has been renamed/deleted",
+			return error(_("patch %s has been renamed/deleted"),
 				patch->old_name);
 		}
 		/* We have a patched copy in memory use that */
 		strbuf_add(&buf, tpatch->result, tpatch->resultsize);
 	} else if (cached) {
 		if (read_file_or_gitlink(ce, &buf))
-			return error("read of %s failed", patch->old_name);
+			return error(_("read of %s failed"), patch->old_name);
 	} else if (patch->old_name) {
 		if (S_ISGITLINK(patch->old_mode)) {
 			if (ce) {
@@ -2953,7 +2961,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
 			}
 		} else {
 			if (read_old_data(st, patch->old_name, &buf))
-				return error("read of %s failed", patch->old_name);
+				return error(_("read of %s failed"), patch->old_name);
 		}
 	}
 
@@ -2968,7 +2976,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
 	free(image.line_allocated);
 
 	if (0 < patch->is_delete && patch->resultsize)
-		return error("removal patch leaves file contents");
+		return error(_("removal patch leaves file contents"));
 
 	return 0;
 }
@@ -2989,7 +2997,7 @@ static int check_to_create_blob(const char *new_name, int ok_if_exists)
 		if (has_symlink_leading_path(new_name, strlen(new_name)))
 			return 0;
 
-		return error("%s: already exists in working directory", new_name);
+		return error(_("%s: already exists in working directory"), new_name);
 	}
 	else if ((errno != ENOENT) && (errno != ENOTDIR))
 		return error("%s: %s", new_name, strerror(errno));
@@ -3027,12 +3035,12 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
 	if (!(patch->is_copy || patch->is_rename) &&
 	    (tpatch = in_fn_table(old_name)) != NULL && !to_be_deleted(tpatch)) {
 		if (was_deleted(tpatch))
-			return error("%s: has been deleted/renamed", old_name);
+			return error(_("%s: has been deleted/renamed"), old_name);
 		st_mode = tpatch->new_mode;
 	} else if (!cached) {
 		stat_ret = lstat(old_name, st);
 		if (stat_ret && errno != ENOENT)
-			return error("%s: %s", old_name, strerror(errno));
+			return error(_("%s: %s"), old_name, strerror(errno));
 	}
 
 	if (to_be_deleted(tpatch))
@@ -3043,7 +3051,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
 		if (pos < 0) {
 			if (patch->is_new < 0)
 				goto is_new;
-			return error("%s: does not exist in index", old_name);
+			return error(_("%s: does not exist in index"), old_name);
 		}
 		*ce = active_cache[pos];
 		if (stat_ret < 0) {
@@ -3057,13 +3065,13 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
 				return -1;
 		}
 		if (!cached && verify_index_match(*ce, st))
-			return error("%s: does not match index", old_name);
+			return error(_("%s: does not match index"), old_name);
 		if (cached)
 			st_mode = (*ce)->ce_mode;
 	} else if (stat_ret < 0) {
 		if (patch->is_new < 0)
 			goto is_new;
-		return error("%s: %s", old_name, strerror(errno));
+		return error(_("%s: %s"), old_name, strerror(errno));
 	}
 
 	if (!cached && !tpatch)
@@ -3074,9 +3082,9 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
 	if (!patch->old_mode)
 		patch->old_mode = st_mode;
 	if ((st_mode ^ patch->old_mode) & S_IFMT)
-		return error("%s: wrong type", old_name);
+		return error(_("%s: wrong type"), old_name);
 	if (st_mode != patch->old_mode)
-		warning("%s has type %o, expected %o",
+		warning(_("%s has type %o, expected %o"),
 			old_name, st_mode, patch->old_mode);
 	if (!patch->new_mode && !patch->is_delete)
 		patch->new_mode = st_mode;
@@ -3126,7 +3134,7 @@ static int check_patch(struct patch *patch)
 		if (check_index &&
 		    cache_name_pos(new_name, strlen(new_name)) >= 0 &&
 		    !ok_if_exists)
-			return error("%s: already exists in index", new_name);
+			return error(_("%s: already exists in index"), new_name);
 		if (!cached) {
 			int err = check_to_create_blob(new_name, ok_if_exists);
 			if (err)
@@ -3145,13 +3153,13 @@ static int check_patch(struct patch *patch)
 		if (!patch->new_mode)
 			patch->new_mode = patch->old_mode;
 		if ((patch->old_mode ^ patch->new_mode) & S_IFMT)
-			return error("new mode (%o) of %s does not match old mode (%o)%s%s",
+			return error(_("new mode (%o) of %s does not match old mode (%o)%s%s"),
 				patch->new_mode, new_name, patch->old_mode,
 				same ? "" : " of ", same ? "" : old_name);
 	}
 
 	if (apply_data(patch, &st, ce) < 0)
-		return error("%s: patch does not apply", name);
+		return error(_("%s: patch does not apply"), name);
 	patch->rejected = 0;
 	return 0;
 }
@@ -3219,7 +3227,7 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
 
 		ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0);
 		if (!ce)
-			die("make_cache_entry failed for path '%s'", name);
+			die(_("make_cache_entry failed for path '%s'"), name);
 		if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
 			die ("Could not add %s to temporary index", name);
 	}
@@ -3362,7 +3370,7 @@ static void remove_file(struct patch *patch, int rmdir_empty)
 {
 	if (update_index) {
 		if (remove_file_from_cache(patch->old_name) < 0)
-			die("unable to remove %s from index", patch->old_name);
+			die(_("unable to remove %s from index"), patch->old_name);
 	}
 	if (!cached) {
 		if (!remove_or_warn(patch->old_mode, patch->old_name) && rmdir_empty) {
@@ -3389,19 +3397,19 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
 		const char *s = buf;
 
 		if (get_sha1_hex(s + strlen("Subproject commit "), ce->sha1))
-			die("corrupt patch for subproject %s", path);
+			die(_("corrupt patch for subproject %s"), path);
 	} else {
 		if (!cached) {
 			if (lstat(path, &st) < 0)
-				die_errno("unable to stat newly created file '%s'",
+				die_errno(_("unable to stat newly created file '%s'"),
 					  path);
 			fill_stat_cache_info(ce, &st);
 		}
 		if (write_sha1_file(buf, size, blob_type, ce->sha1) < 0)
-			die("unable to create backing store for newly created file %s", path);
+			die(_("unable to create backing store for newly created file %s"), path);
 	}
 	if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0)
-		die("unable to add cache entry for %s", path);
+		die(_("unable to add cache entry for %s"), path);
 }
 
 static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
@@ -3434,7 +3442,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
 	strbuf_release(&nbuf);
 
 	if (close(fd) < 0)
-		die_errno("closing file '%s'", path);
+		die_errno(_("closing file '%s'"), path);
 	return 0;
 }
 
@@ -3483,7 +3491,7 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
 			++nr;
 		}
 	}
-	die_errno("unable to write file '%s' mode %o", path, mode);
+	die_errno(_("unable to write file '%s' mode %o"), path, mode);
 }
 
 static void create_file(struct patch *patch)
@@ -3546,7 +3554,7 @@ static int write_out_one_reject(struct patch *patch)
 	 * contents are marked "rejected" at the patch level.
 	 */
 	if (!patch->new_name)
-		die("internal error");
+		die(_("internal error"));
 
 	/* Say this even without --verbose */
 	say_patch_name(stderr, "Applying patch ", patch, " with");
@@ -3555,7 +3563,7 @@ static int write_out_one_reject(struct patch *patch)
 	cnt = strlen(patch->new_name);
 	if (ARRAY_SIZE(namebuf) <= cnt + 5) {
 		cnt = ARRAY_SIZE(namebuf) - 5;
-		warning("truncating .rej filename to %.*s.rej",
+		warning(_("truncating .rej filename to %.*s.rej"),
 			cnt - 1, patch->new_name);
 	}
 	memcpy(namebuf, patch->new_name, cnt);
@@ -3563,7 +3571,7 @@ static int write_out_one_reject(struct patch *patch)
 
 	rej = fopen(namebuf, "w");
 	if (!rej)
-		return error("cannot open %s: %s", namebuf, strerror(errno));
+		return error(_("cannot open %s: %s"), namebuf, strerror(errno));
 
 	/* Normal git tools never deal with .rej, so do not pretend
 	 * this is a git patch by saying --git nor give extended
@@ -3576,10 +3584,10 @@ static int write_out_one_reject(struct patch *patch)
 	     frag;
 	     cnt++, frag = frag->next) {
 		if (!frag->rejected) {
-			fprintf(stderr, "Hunk #%d applied cleanly.\n", cnt);
+			fprintf_ln(stderr, _("Hunk #%d applied cleanly."), cnt);
 			continue;
 		}
-		fprintf(stderr, "Rejected hunk #%d.\n", cnt);
+		fprintf_ln(stderr, _("Rejected hunk #%d."), cnt);
 		fprintf(rej, "%.*s", frag->size, frag->patch);
 		if (frag->patch[frag->size-1] != '\n')
 			fputc('\n', rej);
@@ -3720,7 +3728,7 @@ static int apply_patch(int fd, const char *filename, int options)
 	}
 
 	if (!list && !skipped_patch)
-		die("unrecognized input");
+		die(_("unrecognized input"));
 
 	if (whitespace_error && (ws_error_action == die_on_ws_error))
 		apply = 0;
@@ -3731,7 +3739,7 @@ static int apply_patch(int fd, const char *filename, int options)
 
 	if (check_index) {
 		if (read_cache() < 0)
-			die("unable to read index file");
+			die(_("unable to read index file"));
 	}
 
 	if ((check || apply) &&
@@ -3924,10 +3932,10 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 	if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor))
 		apply = 0;
 	if (check_index && is_not_gitdir)
-		die("--index outside a repository");
+		die(_("--index outside a repository"));
 	if (cached) {
 		if (is_not_gitdir)
-			die("--cached outside a repository");
+			die(_("--cached outside a repository"));
 		check_index = 1;
 	}
 	for (i = 0; i < argc; i++) {
@@ -3943,7 +3951,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 
 		fd = open(arg, O_RDONLY);
 		if (fd < 0)
-			die_errno("can't open patch '%s'", arg);
+			die_errno(_("can't open patch '%s'"), arg);
 		read_stdin = 0;
 		set_default_whitespace_mode(whitespace_option);
 		errs |= apply_patch(fd, arg, options);
@@ -3957,32 +3965,32 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 		    squelch_whitespace_errors < whitespace_error) {
 			int squelched =
 				whitespace_error - squelch_whitespace_errors;
-			warning("squelched %d "
-				"whitespace error%s",
-				squelched,
-				squelched == 1 ? "" : "s");
+			warning(Q_("squelched %d whitespace error",
+				   "squelched %d whitespace errors",
+				   squelched),
+				squelched);
 		}
 		if (ws_error_action == die_on_ws_error)
-			die("%d line%s add%s whitespace errors.",
-			    whitespace_error,
-			    whitespace_error == 1 ? "" : "s",
-			    whitespace_error == 1 ? "s" : "");
+			die(Q_("%d line adds whitespace errors.",
+			       "%d lines add whitespace errors.",
+			       whitespace_error),
+			    whitespace_error);
 		if (applied_after_fixing_ws && apply)
 			warning("%d line%s applied after"
 				" fixing whitespace errors.",
 				applied_after_fixing_ws,
 				applied_after_fixing_ws == 1 ? "" : "s");
 		else if (whitespace_error)
-			warning("%d line%s add%s whitespace errors.",
-				whitespace_error,
-				whitespace_error == 1 ? "" : "s",
-				whitespace_error == 1 ? "s" : "");
+			warning(Q_("%d line adds whitespace errors.",
+				   "%d lines add whitespace errors.",
+				   whitespace_error),
+				whitespace_error);
 	}
 
 	if (update_index) {
 		if (write_cache(newfd, active_cache, active_nr) ||
 		    commit_locked_index(&lock_file))
-			die("Unable to write new index file");
+			die(_("Unable to write new index file"));
 	}
 
 	return !!errs;
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 08/10] i18n: apply: update say_patch_name to give translators complete sentence
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (6 preceding siblings ...)
  2012-04-23 12:30 ` [PATCH 07/10] i18n: apply: " Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-23 12:30 ` [PATCH 09/10] i18n: index-pack: mark strings for translation Nguyễn Thái Ngọc Duy
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/apply.c |   32 ++++++++++++++++++++------------
 1 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 4bb6354..c768b7f 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -335,22 +335,25 @@ static void clear_image(struct image *image)
 	image->len = 0;
 }
 
-static void say_patch_name(FILE *output, const char *pre,
-			   struct patch *patch, const char *post)
+/* fmt must contain _one_ %s and no other substitution */
+static void say_patch_name(FILE *output, const char *fmt, struct patch *patch)
 {
-	fputs(pre, output);
+	struct strbuf sb = STRBUF_INIT;
+
 	if (patch->old_name && patch->new_name &&
 	    strcmp(patch->old_name, patch->new_name)) {
-		quote_c_style(patch->old_name, NULL, output, 0);
-		fputs(" => ", output);
-		quote_c_style(patch->new_name, NULL, output, 0);
+		quote_c_style(patch->old_name, &sb, NULL, 0);
+		strbuf_addstr(&sb, " => ");
+		quote_c_style(patch->new_name, &sb, NULL, 0);
 	} else {
 		const char *n = patch->new_name;
 		if (!n)
 			n = patch->old_name;
-		quote_c_style(n, NULL, output, 0);
+		quote_c_style(n, &sb, NULL, 0);
 	}
-	fputs(post, output);
+	fprintf(output, fmt, sb.buf);
+	fputc('\n', output);
+	strbuf_release(&sb);
 }
 
 #define CHUNKSIZE (8192)
@@ -3172,7 +3175,7 @@ static int check_patch_list(struct patch *patch)
 	while (patch) {
 		if (apply_verbosely)
 			say_patch_name(stderr,
-				       "Checking patch ", patch, "...\n");
+				       _("Checking patch %s..."), patch);
 		err |= check_patch(patch);
 		patch = patch->next;
 	}
@@ -3536,6 +3539,7 @@ static int write_out_one_reject(struct patch *patch)
 	char namebuf[PATH_MAX];
 	struct fragment *frag;
 	int cnt = 0;
+	struct strbuf sb = STRBUF_INIT;
 
 	for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
 		if (!frag->rejected)
@@ -3546,7 +3550,7 @@ static int write_out_one_reject(struct patch *patch)
 	if (!cnt) {
 		if (apply_verbosely)
 			say_patch_name(stderr,
-				       "Applied patch ", patch, " cleanly.\n");
+				       _("Applied patch %s cleanly."), patch);
 		return 0;
 	}
 
@@ -3557,8 +3561,12 @@ static int write_out_one_reject(struct patch *patch)
 		die(_("internal error"));
 
 	/* Say this even without --verbose */
-	say_patch_name(stderr, "Applying patch ", patch, " with");
-	fprintf(stderr, " %d rejects...\n", cnt);
+	strbuf_addf(&sb, Q_("Applying patch %%s with %d reject...",
+			    "Applying patch %%s with %d rejects...",
+			    cnt),
+		    cnt);
+	say_patch_name(stderr, sb.buf, patch);
+	strbuf_release(&sb);
 
 	cnt = strlen(patch->new_name);
 	if (ARRAY_SIZE(namebuf) <= cnt + 5) {
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 09/10] i18n: index-pack: mark strings for translation
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (7 preceding siblings ...)
  2012-04-23 12:30 ` [PATCH 08/10] i18n: apply: update say_patch_name to give translators complete sentence Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-23 12:30 ` [PATCH 10/10] i18n: bundle: " Nguyễn Thái Ngọc Duy
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/index-pack.c |  125 +++++++++++++++++++++++++++-----------------------
 1 files changed, 68 insertions(+), 57 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index dd1c5c9..83555e5 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -81,7 +81,7 @@ static int mark_link(struct object *obj, int type, void *data)
 		return -1;
 
 	if (type != OBJ_ANY && obj->type != type)
-		die("object type mismatch at %s", sha1_to_hex(obj->sha1));
+		die(_("object type mismatch at %s"), sha1_to_hex(obj->sha1));
 
 	obj->flags |= FLAG_LINK;
 	return 0;
@@ -101,7 +101,7 @@ static void check_object(struct object *obj)
 		unsigned long size;
 		int type = sha1_object_info(obj->sha1, &size);
 		if (type != obj->type || type <= 0)
-			die("object of unexpected type");
+			die(_("object of unexpected type"));
 		obj->flags |= FLAG_CHECKED;
 		return;
 	}
@@ -138,15 +138,18 @@ static void *fill(int min)
 	if (min <= input_len)
 		return input_buffer + input_offset;
 	if (min > sizeof(input_buffer))
-		die("cannot fill %d bytes", min);
+		die(Q_("cannot fill %d byte",
+		       "cannot fill %d bytes",
+		       min),
+		    min);
 	flush();
 	do {
 		ssize_t ret = xread(input_fd, input_buffer + input_len,
 				sizeof(input_buffer) - input_len);
 		if (ret <= 0) {
 			if (!ret)
-				die("early EOF");
-			die_errno("read error on input");
+				die(_("early EOF"));
+			die_errno(_("read error on input"));
 		}
 		input_len += ret;
 		if (from_stdin)
@@ -158,14 +161,14 @@ static void *fill(int min)
 static void use(int bytes)
 {
 	if (bytes > input_len)
-		die("used more bytes than were available");
+		die(_("used more bytes than were available"));
 	input_crc32 = crc32(input_crc32, input_buffer + input_offset, bytes);
 	input_len -= bytes;
 	input_offset += bytes;
 
 	/* make sure off_t is sufficiently large not to wrap */
 	if (signed_add_overflows(consumed_bytes, bytes))
-		die("pack too large for current definition of off_t");
+		die(_("pack too large for current definition of off_t"));
 	consumed_bytes += bytes;
 }
 
@@ -181,12 +184,12 @@ static const char *open_pack_file(const char *pack_name)
 		} else
 			output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
 		if (output_fd < 0)
-			die_errno("unable to create '%s'", pack_name);
+			die_errno(_("unable to create '%s'"), pack_name);
 		pack_fd = output_fd;
 	} else {
 		input_fd = open(pack_name, O_RDONLY);
 		if (input_fd < 0)
-			die_errno("cannot open packfile '%s'", pack_name);
+			die_errno(_("cannot open packfile '%s'"), pack_name);
 		output_fd = -1;
 		pack_fd = input_fd;
 	}
@@ -200,7 +203,7 @@ static void parse_pack_header(void)
 
 	/* Header consistency check */
 	if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
-		die("pack signature mismatch");
+		die(_("pack signature mismatch"));
 	if (!pack_version_ok(hdr->hdr_version))
 		die("pack version %"PRIu32" unsupported",
 			ntohl(hdr->hdr_version));
@@ -220,7 +223,7 @@ static NORETURN void bad_object(unsigned long offset, const char *format, ...)
 	va_start(params, format);
 	vsnprintf(buf, sizeof(buf), format, params);
 	va_end(params);
-	die("pack has bad object at offset %lu: %s", offset, buf);
+	die(_("pack has bad object at offset %lu: %s"), offset, buf);
 }
 
 static struct base_data *alloc_base_data(void)
@@ -294,7 +297,7 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size)
 		use(input_len - stream.avail_in);
 	} while (status == Z_OK);
 	if (stream.total_out != size || status != Z_STREAM_END)
-		bad_object(offset, "inflate returned %d", status);
+		bad_object(offset, _("inflate returned %d"), status);
 	git_inflate_end(&stream);
 	return buf;
 }
@@ -339,7 +342,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_
 		while (c & 128) {
 			base_offset += 1;
 			if (!base_offset || MSB(base_offset, 7))
-				bad_object(obj->idx.offset, "offset value overflow for delta base object");
+				bad_object(obj->idx.offset, _("offset value overflow for delta base object"));
 			p = fill(1);
 			c = *p;
 			use(1);
@@ -347,7 +350,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_
 		}
 		delta_base->offset = obj->idx.offset - base_offset;
 		if (delta_base->offset <= 0 || delta_base->offset >= obj->idx.offset)
-			bad_object(obj->idx.offset, "delta base offset is out of bound");
+			bad_object(obj->idx.offset, _("delta base offset is out of bound"));
 		break;
 	case OBJ_COMMIT:
 	case OBJ_TREE:
@@ -355,7 +358,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_
 	case OBJ_TAG:
 		break;
 	default:
-		bad_object(obj->idx.offset, "unknown object type %d", obj->type);
+		bad_object(obj->idx.offset, _("unknown object type %d"), obj->type);
 	}
 	obj->hdr_size = consumed_bytes - obj->idx.offset;
 
@@ -384,9 +387,12 @@ static void *get_data_from_pack(struct object_entry *obj)
 		ssize_t n = (len < 64*1024) ? len : 64*1024;
 		n = pread(pack_fd, inbuf, n, from);
 		if (n < 0)
-			die_errno("cannot pread pack file");
+			die_errno(_("cannot pread pack file"));
 		if (!n)
-			die("premature end of pack file, %lu bytes missing", len);
+			die(Q_("premature end of pack file, %lu byte missing",
+			       "premature end of pack file, %lu bytes missing",
+			       len),
+			    len);
 		from += n;
 		len -= n;
 		stream.next_in = inbuf;
@@ -396,7 +402,7 @@ static void *get_data_from_pack(struct object_entry *obj)
 
 	/* This has been inflated OK when first encountered, so... */
 	if (status != Z_STREAM_END || stream.total_out != obj->size)
-		die("serious inflate inconsistency");
+		die(_("serious inflate inconsistency"));
 
 	git_inflate_end(&stream);
 	free(inbuf);
@@ -467,10 +473,10 @@ static void sha1_object(const void *data, unsigned long size,
 		unsigned long has_size;
 		has_data = read_sha1_file(sha1, &has_type, &has_size);
 		if (!has_data)
-			die("cannot read existing object %s", sha1_to_hex(sha1));
+			die(_("cannot read existing object %s"), sha1_to_hex(sha1));
 		if (size != has_size || type != has_type ||
 		    memcmp(data, has_data, size) != 0)
-			die("SHA1 COLLISION FOUND WITH %s !", sha1_to_hex(sha1));
+			die(_("SHA1 COLLISION FOUND WITH %s !"), sha1_to_hex(sha1));
 		free(has_data);
 	}
 	if (strict) {
@@ -479,7 +485,7 @@ static void sha1_object(const void *data, unsigned long size,
 			if (blob)
 				blob->object.flags |= FLAG_CHECKED;
 			else
-				die("invalid blob object %s", sha1_to_hex(sha1));
+				die(_("invalid blob object %s"), sha1_to_hex(sha1));
 		} else {
 			struct object *obj;
 			int eaten;
@@ -491,11 +497,11 @@ static void sha1_object(const void *data, unsigned long size,
 			 */
 			obj = parse_object_buffer(sha1, type, size, buf, &eaten);
 			if (!obj)
-				die("invalid %s", typename(type));
+				die(_("invalid %s"), typename(type));
 			if (fsck_object(obj, 1, fsck_error_function))
-				die("Error in object");
+				die(_("Error in object"));
 			if (fsck_walk(obj, mark_link, NULL))
-				die("Not all child objects of %s are reachable", sha1_to_hex(obj->sha1));
+				die(_("Not all child objects of %s are reachable"), sha1_to_hex(obj->sha1));
 
 			if (obj->type == OBJ_TREE) {
 				struct tree *item = (struct tree *) obj;
@@ -567,7 +573,7 @@ static void *get_base_data(struct base_data *c)
 				&c->size);
 			free(raw);
 			if (!c->data)
-				bad_object(obj->idx.offset, "failed to apply delta");
+				bad_object(obj->idx.offset, _("failed to apply delta"));
 			base_cache_used += c->size;
 			prune_base_data(c);
 		}
@@ -593,7 +599,7 @@ static void resolve_delta(struct object_entry *delta_obj,
 				   delta_data, delta_obj->size, &result->size);
 	free(delta_data);
 	if (!result->data)
-		bad_object(delta_obj->idx.offset, "failed to apply delta");
+		bad_object(delta_obj->idx.offset, _("failed to apply delta"));
 	sha1_object(result->data, result->size, delta_obj->real_type,
 		    delta_obj->idx.sha1);
 	nr_resolved_deltas++;
@@ -697,7 +703,7 @@ static void parse_pack_objects(unsigned char *sha1)
 	 */
 	if (verbose)
 		progress = start_progress(
-				from_stdin ? "Receiving objects" : "Indexing objects",
+				from_stdin ? _("Receiving objects") : _("Indexing objects"),
 				nr_objects);
 	for (i = 0; i < nr_objects; i++) {
 		struct object_entry *obj = &objects[i];
@@ -719,15 +725,15 @@ static void parse_pack_objects(unsigned char *sha1)
 	flush();
 	git_SHA1_Final(sha1, &input_ctx);
 	if (hashcmp(fill(20), sha1))
-		die("pack is corrupted (SHA1 mismatch)");
+		die(_("pack is corrupted (SHA1 mismatch)"));
 	use(20);
 
 	/* If input_fd is a file, we should have reached its end now. */
 	if (fstat(input_fd, &st))
-		die_errno("cannot fstat packfile");
+		die_errno(_("cannot fstat packfile"));
 	if (S_ISREG(st.st_mode) &&
 			lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
-		die("pack has junk at the end");
+		die(_("pack has junk at the end"));
 
 	if (!nr_deltas)
 		return;
@@ -745,7 +751,7 @@ static void parse_pack_objects(unsigned char *sha1)
 	 *   for some more deltas.
 	 */
 	if (verbose)
-		progress = start_progress("Resolving deltas", nr_deltas);
+		progress = start_progress(_("Resolving deltas"), nr_deltas);
 	for (i = 0; i < nr_objects; i++) {
 		struct object_entry *obj = &objects[i];
 		struct base_data *base_obj = alloc_base_data();
@@ -778,7 +784,7 @@ static int write_compressed(struct sha1file *f, void *in, unsigned int size)
 	} while (status == Z_OK);
 
 	if (status != Z_STREAM_END)
-		die("unable to deflate appended object (%d)", status);
+		die(_("unable to deflate appended object (%d)"), status);
 	size = stream.total_out;
 	git_deflate_end(&stream);
 	return size;
@@ -857,7 +863,7 @@ static void fix_unresolved_deltas(struct sha1file *f, int nr_unresolved)
 
 		if (check_sha1_signature(d->base.sha1, base_obj->data,
 				base_obj->size, typename(type)))
-			die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
+			die(_("local object %s is corrupt"), sha1_to_hex(d->base.sha1));
 		base_obj->obj = append_obj_to_pack(f, d->base.sha1,
 					base_obj->data, base_obj->size, type);
 		find_unresolved_deltas(base_obj);
@@ -881,7 +887,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 		fsync_or_die(output_fd, curr_pack_name);
 		err = close(output_fd);
 		if (err)
-			die_errno("error while closing pack file");
+			die_errno(_("error while closing pack file"));
 	}
 
 	if (keep_msg) {
@@ -894,7 +900,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 
 		if (keep_fd < 0) {
 			if (errno != EEXIST)
-				die_errno("cannot write keep file '%s'",
+				die_errno(_("cannot write keep file '%s'"),
 					  keep_name);
 		} else {
 			if (keep_msg_len > 0) {
@@ -902,7 +908,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 				write_or_die(keep_fd, "\n", 1);
 			}
 			if (close(keep_fd) != 0)
-				die_errno("cannot close written keep file '%s'",
+				die_errno(_("cannot close written keep file '%s'"),
 				    keep_name);
 			report = "keep";
 		}
@@ -915,7 +921,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 			final_pack_name = name;
 		}
 		if (move_temp_to_file(curr_pack_name, final_pack_name))
-			die("cannot store pack file");
+			die(_("cannot store pack file"));
 	} else if (from_stdin)
 		chmod(final_pack_name, 0444);
 
@@ -926,7 +932,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 			final_index_name = name;
 		}
 		if (move_temp_to_file(curr_index_name, final_index_name))
-			die("cannot store index file");
+			die(_("cannot store index file"));
 	} else
 		chmod(final_index_name, 0444);
 
@@ -1015,9 +1021,9 @@ static void read_idx_option(struct pack_idx_option *opts, const char *pack_name)
 	struct packed_git *p = add_packed_git(pack_name, strlen(pack_name), 1);
 
 	if (!p)
-		die("Cannot open existing pack file '%s'", pack_name);
+		die(_("Cannot open existing pack file '%s'"), pack_name);
 	if (open_pack_index(p))
-		die("Cannot open existing pack idx file for '%s'", pack_name);
+		die(_("Cannot open existing pack idx file for '%s'"), pack_name);
 
 	/* Read the attributes from the existing idx file */
 	opts->version = p->index_version;
@@ -1064,15 +1070,18 @@ static void show_pack_info(int stat_only)
 	}
 
 	if (baseobjects)
-		printf("non delta: %d object%s\n",
-		       baseobjects, baseobjects > 1 ? "s" : "");
+		printf_ln(Q_("non delta: %d object",
+			     "non delta: %d objects",
+			     baseobjects),
+			  baseobjects);
 	for (i = 0; i < deepest_delta; i++) {
 		if (!chain_histogram[i])
 			continue;
-		printf("chain length = %d: %lu object%s\n",
-		       i + 1,
-		       chain_histogram[i],
-		       chain_histogram[i] > 1 ? "s" : "");
+		printf_ln(Q_("chain length = %d: %lu object",
+			     "chain length = %d: %lu objects",
+			     chain_histogram[i]),
+			  i + 1,
+			  chain_histogram[i]);
 	}
 }
 
@@ -1095,7 +1104,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	reset_pack_idx_option(&opts);
 	git_config(git_index_pack_config, &opts);
 	if (prefix && chdir(prefix))
-		die("Cannot come back to cwd");
+		die(_("Cannot come back to cwd"));
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
@@ -1128,10 +1137,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 				hdr->hdr_signature = htonl(PACK_SIGNATURE);
 				hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
 				if (*c != ',')
-					die("bad %s", arg);
+					die(_("bad %s"), arg);
 				hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
 				if (*c)
-					die("bad %s", arg);
+					die(_("bad %s"), arg);
 				input_len = sizeof(*hdr);
 			} else if (!strcmp(arg, "-v")) {
 				verbose = 1;
@@ -1143,11 +1152,11 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 				char *c;
 				opts.version = strtoul(arg + 16, &c, 10);
 				if (opts.version > 2)
-					die("bad %s", arg);
+					die(_("bad %s"), arg);
 				if (*c == ',')
 					opts.off32_limit = strtoul(c+1, &c, 0);
 				if (*c || opts.off32_limit & 0x80000000)
-					die("bad %s", arg);
+					die(_("bad %s"), arg);
 			} else
 				usage(index_pack_usage);
 			continue;
@@ -1161,11 +1170,11 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (!pack_name && !from_stdin)
 		usage(index_pack_usage);
 	if (fix_thin_pack && !from_stdin)
-		die("--fix-thin cannot be used without --stdin");
+		die(_("--fix-thin cannot be used without --stdin"));
 	if (!index_name && pack_name) {
 		int len = strlen(pack_name);
 		if (!has_extension(pack_name, ".pack"))
-			die("packfile name '%s' does not end with '.pack'",
+			die(_("packfile name '%s' does not end with '.pack'"),
 			    pack_name);
 		index_name_buf = xmalloc(len);
 		memcpy(index_name_buf, pack_name, len - 5);
@@ -1175,7 +1184,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (keep_msg && !keep_name && pack_name) {
 		int len = strlen(pack_name);
 		if (!has_extension(pack_name, ".pack"))
-			die("packfile name '%s' does not end with '.pack'",
+			die(_("packfile name '%s' does not end with '.pack'"),
 			    pack_name);
 		keep_name_buf = xmalloc(len);
 		memcpy(keep_name_buf, pack_name, len - 5);
@@ -1184,7 +1193,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	}
 	if (verify) {
 		if (!index_name)
-			die("--verify with no packfile name given");
+			die(_("--verify with no packfile name given"));
 		read_idx_option(&opts, index_name);
 		opts.flags |= WRITE_IDX_VERIFY | WRITE_IDX_STRICT;
 	}
@@ -1208,7 +1217,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 			int nr_unresolved = nr_deltas - nr_resolved_deltas;
 			int nr_objects_initial = nr_objects;
 			if (nr_unresolved <= 0)
-				die("confusion beyond insanity");
+				die(_("confusion beyond insanity"));
 			objects = xrealloc(objects,
 					   (nr_objects + nr_unresolved + 1)
 					   * sizeof(*objects));
@@ -1227,7 +1236,9 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 				    "(disk corruption?)", curr_pack);
 		}
 		if (nr_deltas != nr_resolved_deltas)
-			die("pack has %d unresolved deltas",
+			die(Q_("pack has %d unresolved delta",
+			       "pack has %d unresolved deltas",
+			       nr_deltas - nr_resolved_deltas),
 			    nr_deltas - nr_resolved_deltas);
 	}
 	free(deltas);
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 10/10] i18n: bundle: mark strings for translation
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (8 preceding siblings ...)
  2012-04-23 12:30 ` [PATCH 09/10] i18n: index-pack: mark strings for translation Nguyễn Thái Ngọc Duy
@ 2012-04-23 12:30 ` Nguyễn Thái Ngọc Duy
  2012-04-25 22:43   ` Junio C Hamano
  2012-04-23 16:41 ` [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Jonathan Nieder
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-23 12:30 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 bundle.c |   38 +++++++++++++++++++++-----------------
 1 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/bundle.c b/bundle.c
index d9cfd90..6d21c77 100644
--- a/bundle.c
+++ b/bundle.c
@@ -33,7 +33,7 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
 	if (strbuf_getwholeline_fd(&buf, fd, '\n') ||
 	    strcmp(buf.buf, bundle_signature)) {
 		if (report_path)
-			error("'%s' does not look like a v2 bundle file",
+			error(_("'%s' does not look like a v2 bundle file"),
 			      report_path);
 		status = -1;
 		goto abort;
@@ -60,7 +60,7 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
 		    (40 <= buf.len && !isspace(buf.buf[40])) ||
 		    (!is_prereq && buf.len <= 40)) {
 			if (report_path)
-				error("unrecognized header: %s%s (%d)",
+				error(_("unrecognized header: %s%s (%d)"),
 				      (is_prereq ? "-" : ""), buf.buf, (int)buf.len);
 			status = -1;
 			break;
@@ -86,7 +86,7 @@ int read_bundle_header(const char *path, struct bundle_header *header)
 	int fd = open(path, O_RDONLY);
 
 	if (fd < 0)
-		return error("could not open '%s'", path);
+		return error(_("could not open '%s'"), path);
 	return parse_bundle_header(fd, header, path);
 }
 
@@ -137,7 +137,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
 	struct object_array refs;
 	struct commit *commit;
 	int i, ret = 0, req_nr;
-	const char *message = "Repository lacks these prerequisite commits:";
+	const char *message = _("Repository lacks these prerequisite commits:");
 
 	init_revisions(&revs, NULL);
 	for (i = 0; i < p->nr; i++) {
@@ -161,7 +161,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
 	revs.leak_pending = 1;
 
 	if (prepare_revision_walk(&revs))
-		die("revision walk setup failed");
+		die(_("revision walk setup failed"));
 
 	i = req_nr;
 	while (i && (commit = get_revision(&revs)))
@@ -183,12 +183,16 @@ int verify_bundle(struct bundle_header *header, int verbose)
 		struct ref_list *r;
 
 		r = &header->references;
-		printf("The bundle contains %d ref%s\n",
-		       r->nr, (1 < r->nr) ? "s" : "");
+		printf_ln(Q_("The bundle contains %d ref",
+			     "The bundle contains %d refs",
+			     r->nr),
+			  r->nr);
 		list_refs(r, 0, NULL);
 		r = &header->prerequisites;
-		printf("The bundle requires these %d ref%s\n",
-		       r->nr, (1 < r->nr) ? "s" : "");
+		printf_ln(Q_("The bundle requires this ref",
+			     "The bundle requires these %d refs",
+			     r->nr),
+			  r->nr);
 		list_refs(r, 0, NULL);
 	}
 	return ret;
@@ -283,13 +287,13 @@ int create_bundle(struct bundle_header *header, const char *path,
 	strbuf_release(&buf);
 	fclose(rls_fout);
 	if (finish_command(&rls))
-		return error("rev-list died");
+		return error(_("rev-list died"));
 
 	/* write references */
 	argc = setup_revisions(argc, argv, &revs, NULL);
 
 	if (argc > 1)
-		return error("unrecognized argument: %s'", argv[1]);
+		return error(_("unrecognized argument: %s'"), argv[1]);
 
 	object_array_remove_duplicates(&revs.pending);
 
@@ -324,7 +328,7 @@ int create_bundle(struct bundle_header *header, const char *path,
 		 * constraints.
 		 */
 		if (!(e->item->flags & SHOWN) && e->item->type == OBJ_COMMIT) {
-			warning("ref '%s' is excluded by the rev-list options",
+			warning(_("ref '%s' is excluded by the rev-list options"),
 				e->name);
 			free(ref);
 			continue;
@@ -369,7 +373,7 @@ int create_bundle(struct bundle_header *header, const char *path,
 		free(ref);
 	}
 	if (!ref_count)
-		die ("Refusing to create empty bundle.");
+		die(_("Refusing to create empty bundle."));
 
 	/* end header */
 	write_or_die(bundle_fd, "\n", 1);
@@ -387,7 +391,7 @@ int create_bundle(struct bundle_header *header, const char *path,
 	rls.out = bundle_fd;
 	rls.git_cmd = 1;
 	if (start_command(&rls))
-		return error("Could not spawn pack-objects");
+		return error(_("Could not spawn pack-objects"));
 
 	/*
 	 * start_command closed bundle_fd if it was > 1
@@ -405,10 +409,10 @@ int create_bundle(struct bundle_header *header, const char *path,
 	}
 	close(rls.in);
 	if (finish_command(&rls))
-		return error ("pack-objects died");
+		return error(_("pack-objects died"));
 	if (!bundle_to_stdout) {
 		if (commit_lock_file(&lock))
-			die_errno("cannot create '%s'", path);
+			die_errno(_("cannot create '%s'"), path);
 	}
 	return 0;
 }
@@ -430,6 +434,6 @@ int unbundle(struct bundle_header *header, int bundle_fd, int flags)
 	ip.no_stdout = 1;
 	ip.git_cmd = 1;
 	if (run_command(&ip))
-		return error("index-pack died");
+		return error(_("index-pack died"));
 	return 0;
 }
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH 02/10] Add three convenient format printing functions with \n automatically appended
  2012-04-23 12:30 ` [PATCH 02/10] Add three convenient format printing functions with \n automatically appended Nguyễn Thái Ngọc Duy
@ 2012-04-23 16:15   ` Jonathan Nieder
  0 siblings, 0 replies; 43+ messages in thread
From: Jonathan Nieder @ 2012-04-23 16:15 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Junio C Hamano, Ævar Arnfjörð Bjarmason,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy wrote:

> --- a/strbuf.c
> +++ b/strbuf.c
> @@ -464,3 +464,36 @@ void strbuf_addstr_urlencode(struct strbuf *sb, const char *s,
[...]
> +int printf_ln(const char *fmt, ...)
> +{
> +	int ret;
> +	va_list ap;
> +	va_start(ap, fmt);
> +	ret = vprintf(fmt, ap);
> +	va_end(ap);
> +	if (ret >= 0)
> +		ret += printf("\n");

Missed a spot.  I'd do

	if (ret < 0 || putchar('\n') == EOF)
		return -1;
	return ret + 1;

And likewise, for the fprintf version:

	if (ret < 0 || putc('\n', fp) == EOF)
		return -1;
	return ret + 1;

Hope that helps,
Jonathan

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 04/10] i18n: help: mark strings for translation
  2012-04-23 12:30 ` [PATCH 04/10] i18n: help: mark strings " Nguyễn Thái Ngọc Duy
@ 2012-04-23 16:30   ` Jonathan Nieder
  2012-04-23 18:18     ` Junio C Hamano
  0 siblings, 1 reply; 43+ messages in thread
From: Jonathan Nieder @ 2012-04-23 16:30 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Junio C Hamano, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy wrote:

> --- a/help.c
> +++ b/help.c
> @@ -217,8 +217,9 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
>  
>  	if (main_cmds->cnt) {
>  		const char *exec_path = git_exec_path();
> -		printf("available %s in '%s'\n", title, exec_path);
> -		printf("----------------");
> +		printf_ln(_("available %s in '%s'"), title, exec_path);
> +		/* TRANSLATORS: this must align with "available %s in '%s'" */
> +		printf(_("----------------"));
>  		mput_char('-', strlen(title) + strlen(exec_path));

Yuck. :)

I would be tempted to do:

	static int strbuf_utf8_width(const struct strbuf *sb)
	{
		char char *p = sb->buf;
		size_t remainder = sb->len;
		int width;

		width = utf8_width(&p, &remainder);
		if (!p || remainder)
			return sb->len;
		return width;
	}
	...

		struct strbuf sb = STRBUF_INIT;
		const char *p;

		strbuf_addf(&sb, _("available %s in '%s'"), title, exec_path);
		fwrite(sb.buf, sb.len, 1, stdout);
		putchar('\n');

		/* NEEDSWORK: handle non-UTF8 locales? */
		mput_char('-', strbuf_utf8_width(&sb));

		strbuf_release(&sb);

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (9 preceding siblings ...)
  2012-04-23 12:30 ` [PATCH 10/10] i18n: bundle: " Nguyễn Thái Ngọc Duy
@ 2012-04-23 16:41 ` Jonathan Nieder
  2012-04-23 18:56 ` Junio C Hamano
  2012-04-24 12:19 ` Nguyen Thai Ngoc Duy
  12 siblings, 0 replies; 43+ messages in thread
From: Jonathan Nieder @ 2012-04-23 16:41 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Junio C Hamano, Ævar Arnfjörð Bjarmason,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy wrote:

> Compared to v1 [1], parseopt patch is taken out. I attempted to
> convert all struct option, and it turned into a huge series [2]. Not
> sure how to submit that series yet.

With the exception of the two nits mentioned, looks good.  I haven't
tested yet with GETTEXT_POISON=Yes, though.  Thanks for your
perseverance.

Jonathan

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 04/10] i18n: help: mark strings for translation
  2012-04-23 16:30   ` Jonathan Nieder
@ 2012-04-23 18:18     ` Junio C Hamano
  2012-04-23 18:34       ` Jonathan Nieder
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-04-23 18:18 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Nguyễn Thái Ngọc Duy, git,
	Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Jonathan Nieder <jrnieder@gmail.com> writes:

> Nguyễn Thái Ngọc Duy wrote:
>
>> --- a/help.c
>> +++ b/help.c
>> @@ -217,8 +217,9 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
>>  
>>  	if (main_cmds->cnt) {
>>  		const char *exec_path = git_exec_path();
>> -		printf("available %s in '%s'\n", title, exec_path);
>> -		printf("----------------");
>> +		printf_ln(_("available %s in '%s'"), title, exec_path);
>> +		/* TRANSLATORS: this must align with "available %s in '%s'" */
>> +		printf(_("----------------"));
>>  		mput_char('-', strlen(title) + strlen(exec_path));
>
> Yuck. :)

Yuck indeed.  Do we even care these pseudo-underline?  Wouldn't a simple
and clean "blank line" look better?

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 04/10] i18n: help: mark strings for translation
  2012-04-23 18:18     ` Junio C Hamano
@ 2012-04-23 18:34       ` Jonathan Nieder
  2012-04-25 11:21         ` [PATCH] help: replace underlining "help -a" headers using hyphens with a blank line Nguyễn Thái Ngọc Duy
  0 siblings, 1 reply; 43+ messages in thread
From: Jonathan Nieder @ 2012-04-23 18:34 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Nguyễn Thái Ngọc Duy, git,
	Ævar Arnfjörð Bjarmason, Jiang Xin,
	Zbigniew Jędrzejewski-Szmek

Junio C Hamano wrote:

>                                                        Wouldn't a simple
> and clean "blank line" look better?

Yes, based on a quick test with "vi" it looks reasonable.  Thanks for
a sanity check.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (10 preceding siblings ...)
  2012-04-23 16:41 ` [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Jonathan Nieder
@ 2012-04-23 18:56 ` Junio C Hamano
  2012-04-23 20:06   ` Ævar Arnfjörð Bjarmason
  2012-04-24 12:19 ` Nguyen Thai Ngoc Duy
  12 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-04-23 18:56 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy, Jonathan Niedier
  Cc: git, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

This series looked sensible overall, so I'll queue but please eyeball my
conflict resolutions after I push it out on 'pu' in several hours.

Thanks, both.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle
  2012-04-23 18:56 ` Junio C Hamano
@ 2012-04-23 20:06   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 43+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2012-04-23 20:06 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Nguyễn Thái Ngọc, Jonathan Niedier, git,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

On Mon, Apr 23, 2012 at 20:56, Junio C Hamano <gitster@pobox.com> wrote:
> This series looked sensible overall, so I'll queue but please eyeball my
> conflict resolutions after I push it out on 'pu' in several hours.

Same here. It looks good to me. Thanks for working on this.

Some of it uses strings concated to other strings, but in those cases
it would be tricky to provide the translators with all the
alternatives, and in any case it's a huge improvement on not making
things translatable at all.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle
  2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
                   ` (11 preceding siblings ...)
  2012-04-23 18:56 ` Junio C Hamano
@ 2012-04-24 12:19 ` Nguyen Thai Ngoc Duy
  2012-04-24 19:50   ` Junio C Hamano
  12 siblings, 1 reply; 43+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-04-24 12:19 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

On Mon, Apr 23, 2012 at 07:30:20PM +0700, Nguyễn Thái Ngọc Duy wrote:
> I attempted to
> convert all struct option, and it turned into a huge series [2]. Not
> sure how to submit that series yet.
>
> [2] https://github.com/pclouds/git/tree/parseopt-i18n

The 62 patch series looks lame compared to this approach, but cross
compile guys, including myself, will hate me in principle.

The idea is modify all git commands and output all marked strings in
"struct option" and usage strings, instead of manually marking them
one by one. The marked strings will be collected by xgettext just like
another source file.

This adds a runnable git as a dependency to git.pot. But changes are
much cleaner and devs don't need to care about i18n when they update
"struct option". Big plus to me. Introduction of new parse_options()
call sites still require attention though.

Just a PoC patch for string generation (about 1000 new strings by the
way). When GIT_I18N is set, git will print then quit. Good to go?

-- 8< --
diff --git a/Makefile b/Makefile
index dab7362..5de3f1f 100644
--- a/Makefile
+++ b/Makefile
@@ -2306,8 +2306,18 @@ LOCALIZED_SH += t/t0200/test.sh
 LOCALIZED_PERL += t/t0200/test.perl
 endif
 
+I18N_CMDS =
+I18N_CMDS += add apply archive bisect--helper branch cat-file check-attr checkout checkout-index
+I18N_CMDS += cherry cherry-pick clean clone commit config count-objects describe fast-export fetch
+I18N_CMDS += fmt-merge-msg for-each-ref format-patch fsck gc grep hash-object init-db log ls-files
+I18N_CMDS += ls-tree merge merge-base merge-file mktree mv name-rev notes pack-objects pack-refs
+I18N_CMDS += prune prune-packed push read-tree remote replace rerere reset revert rm shortlog show-branch
+I18N_CMDS += show-ref status symbolic-ref tag update-index update-ref update-server-info verify-pack
+I18N_CMDS += verify-tag write-tree
+
 po/git.pot: $(LOCALIZED_C)
-	$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ $(XGETTEXT_FLAGS_C) $(LOCALIZED_C)
+	for cmd in $(I18N_CMDS); do GIT_I18N=1 ./git $$cmd; done > text.c
+	$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ $(XGETTEXT_FLAGS_C) $(LOCALIZED_C) text.c
 	$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_SH) \
 		$(LOCALIZED_SH)
 	$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_PERL) \
diff --git a/archive.c b/archive.c
index 1ee837d..311fd18 100644
--- a/archive.c
+++ b/archive.c
@@ -361,6 +361,8 @@ static int parse_archive_args(int argc, const char **argv,
 		OPT_END()
 	};
 
+	if (generate_parseopt_strings(__FILE__, __LINE__, opts, archive_usage))
+		exit(0);
 	argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
 
 	if (remote)
diff --git a/builtin/add.c b/builtin/add.c
index b79336d..2d886f6 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -375,6 +375,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	git_config(add_config, NULL);
 
+	GEN_PARSEOPT(builtin_add_options, builtin_add_usage);
 	argc = parse_options(argc, argv, prefix, builtin_add_options,
 			  builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
 	if (patch_interactive)
diff --git a/builtin/apply.c b/builtin/apply.c
index 389898f..1d02cf7 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3916,6 +3916,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 	if (apply_default_ignorewhitespace)
 		parse_ignorewhitespace_option(apply_default_ignorewhitespace);
 
+	GEN_PARSEOPT(builtin_apply_options, apply_usage);
 	argc = parse_options(argc, argv, prefix, builtin_apply_options,
 			apply_usage, 0);
 
diff --git a/builtin/archive.c b/builtin/archive.c
index 931956d..545f82e 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -97,6 +97,12 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	if (generate_parseopt_strings(__FILE__, __LINE__, local_opts, NULL)) {
+		/* dummy args just enough to get to parse_archive_args() */
+		write_archive(0, NULL, NULL, 0, NULL, 0);
+		assert(!"archive.c:parse_archive_args() should have called exit(0)");
+		return 0;
+	}
 	argc = parse_options(argc, argv, prefix, local_opts, NULL,
 			     PARSE_OPT_KEEP_ALL);
 
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 8d325a5..4155f31 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -20,6 +20,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, git_bisect_helper_usage);
 	argc = parse_options(argc, argv, prefix, options,
 			     git_bisect_helper_usage, 0);
 
diff --git a/builtin/blame.c b/builtin/blame.c
index a9845bb..1431ea0 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2322,6 +2322,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	save_commit_buffer = 0;
 	dashdash_pos = 0;
 
+	GEN_PARSEOPT(options, blame_opt_usage);
 	parse_options_start(&ctx, argc, argv, prefix, options,
 			    PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
 	for (;;) {
diff --git a/builtin/branch.c b/builtin/branch.c
index d8cccf7..488e643 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -734,6 +734,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_END(),
 	};
 
+	GEN_PARSEOPT(options, builtin_branch_usage);
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(builtin_branch_usage, options);
 
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 36a9104..8ea3891 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -282,6 +282,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
 
 	git_config(git_cat_file_config, NULL);
 
+	GEN_PARSEOPT(options, cat_file_usage);
 	if (argc != 3 && argc != 2)
 		usage_with_options(cat_file_usage, options);
 
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 44c421e..e31acba 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -96,6 +96,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
 
 	git_config(git_default_config, NULL);
 
+	GEN_PARSEOPT(check_attr_options, check_attr_usage);
 	argc = parse_options(argc, argv, prefix, check_attr_options,
 			     check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
 
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index c16d82b..8b784de 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -220,6 +220,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 		die("invalid cache");
 	}
 
+	GEN_PARSEOPT(builtin_checkout_index_options, builtin_checkout_index_usage);
 	argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
 			builtin_checkout_index_usage, 0);
 	state.force = force;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 6b9061f..58c27b4 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -964,6 +964,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 
 	opts.track = BRANCH_TRACK_UNSPECIFIED;
 
+	GEN_PARSEOPT(options, checkout_usage);
 	argc = parse_options(argc, argv, prefix, options, checkout_usage,
 			     PARSE_OPT_KEEP_DASHDASH);
 
diff --git a/builtin/clean.c b/builtin/clean.c
index 0c7b3d0..77bb90d 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -67,6 +67,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	else
 		config_set = 1;
 
+	GEN_PARSEOPT(options, builtin_clean_usage);
 	argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
 			     0);
 
diff --git a/builtin/clone.c b/builtin/clone.c
index bbd5c96..b8837ef 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -632,6 +632,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	junk_pid = getpid();
 
 	packet_trace_identity("clone");
+	GEN_PARSEOPT(builtin_clone_options, builtin_clone_usage);
 	argc = parse_options(argc, argv, prefix, builtin_clone_options,
 			     builtin_clone_usage, 0);
 
diff --git a/builtin/commit.c b/builtin/commit.c
index 7808be3..7de09ff 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1229,6 +1229,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 		OPT_END(),
 	};
 
+	GEN_PARSEOPT(builtin_status_options, builtin_status_usage);
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(builtin_status_usage, builtin_status_options);
 
@@ -1416,6 +1417,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 	struct commit *current_head = NULL;
 	struct commit_extra_header *extra = NULL;
 
+	GEN_PARSEOPT(builtin_commit_options, builtin_commit_usage);
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(builtin_commit_usage, builtin_commit_options);
 
diff --git a/builtin/config.c b/builtin/config.c
index 33c8820..3389778 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -369,6 +369,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 
 	given_config_file = getenv(CONFIG_ENVIRONMENT);
 
+	GEN_PARSEOPT(builtin_config_options, builtin_config_usage);
 	argc = parse_options(argc, argv, prefix, builtin_config_options,
 			     builtin_config_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index c37cb98..5c2756e 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -83,6 +83,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
 		OPT_END(),
 	};
 
+	GEN_PARSEOPT(opts, count_objects_usage);
 	argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
 	/* we do not take arguments other than flags for now */
 	if (argc)
diff --git a/builtin/describe.c b/builtin/describe.c
index 9f63067..11b5858 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -421,6 +421,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(options, describe_usage);
 	argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
 	if (abbrev < 0)
 		abbrev = DEFAULT_ABBREV;
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 19509ea..88ff132 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -651,6 +651,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, fast_export_usage);
 	if (argc == 1)
 		usage_with_options (fast_export_usage, options);
 
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 65f5f9b..f8c624b 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -953,6 +953,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 	for (i = 1; i < argc; i++)
 		strbuf_addf(&default_rla, " %s", argv[i]);
 
+	GEN_PARSEOPT(builtin_fetch_options, builtin_fetch_usage);
 	argc = parse_options(argc, argv, prefix,
 			     builtin_fetch_options, builtin_fetch_usage, 0);
 
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index c81a7fe..98917f5 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -451,6 +451,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
 	struct fmt_merge_msg_opts opts;
 
 	git_config(fmt_merge_msg_config, NULL);
+	GEN_PARSEOPT(options, fmt_merge_msg_usage);
 	argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,
 			     0);
 	if (argc > 0)
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index b01d76a..26b9404 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -1005,6 +1005,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 		OPT_END(),
 	};
 
+	GEN_PARSEOPT(opts, for_each_ref_usage);
 	parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
 	if (maxcount < 0) {
 		error("invalid --count argument: `%d'", maxcount);
diff --git a/builtin/fsck.c b/builtin/fsck.c
index a710227..51fccd1 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -633,6 +633,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 	errors_found = 0;
 	read_replace_refs = 0;
 
+	GEN_PARSEOPT(fsck_opts,  fsck_usage);
 	argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
 
 	if (show_progress == -1)
diff --git a/builtin/gc.c b/builtin/gc.c
index 271376d..49e57ee 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -197,6 +197,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 	if (pack_refs < 0)
 		pack_refs = !is_bare_repository();
 
+	GEN_PARSEOPT(builtin_gc_options, builtin_gc_usage);
 	argc = parse_options(argc, argv, prefix, builtin_gc_options,
 			     builtin_gc_usage, 0);
 	if (argc > 0)
diff --git a/builtin/grep.c b/builtin/grep.c
index 643938d..5808242 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -790,6 +790,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	 * 'git grep -h', unlike 'git grep -h <pattern>', is a request
 	 * to show usage information and exit.
 	 */
+	GEN_PARSEOPT(options, grep_usage);
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(grep_usage, options);
 
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 33911fd..50af09e 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -86,6 +86,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
 
 	type = blob_type;
 
+	GEN_PARSEOPT(hash_object_options, hash_object_usage);
 	argc = parse_options(argc, argv, NULL, hash_object_options,
 			     hash_object_usage, 0);
 
diff --git a/builtin/help.c b/builtin/help.c
index 61ff798..b189d3f 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -419,6 +419,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
 	enum help_format parsed_help_format;
 	load_command_list("git-", &main_cmds, &other_cmds);
 
+	GEN_PARSEOPT(builtin_help_options, builtin_help_usage);
 	argc = parse_options(argc, argv, prefix, builtin_help_options,
 			builtin_help_usage, 0);
 	parsed_help_format = help_format;
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 0dacb8b..f63a7de 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -495,6 +495,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(init_db_options, init_db_usage);
 	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
 
 	if (real_git_dir && !is_absolute_path(real_git_dir))
diff --git a/builtin/log.c b/builtin/log.c
index 02d070b..28b4706 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -103,6 +103,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
 		OPT_END()
 	};
 
+	if (generate_parseopt_strings(__FILE__, __LINE__, builtin_log_options, builtin_log_usage))
+		exit(0);
 	argc = parse_options(argc, argv, prefix,
 			     builtin_log_options, builtin_log_usage,
 			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
@@ -1165,6 +1167,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	 * like "git format-patch -o a123 HEAD^.." may fail; a123 is
 	 * possibly a valid SHA1.
 	 */
+	GEN_PARSEOPT(builtin_format_patch_options, builtin_format_patch_usage);
 	argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
 			     builtin_format_patch_usage,
 			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
@@ -1500,6 +1503,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, cherry_usage);
 	argc = parse_options(argc, argv, prefix, options, cherry_usage, 0);
 
 	switch (argc) {
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 7cff175..7cc7b98 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -500,6 +500,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(builtin_ls_files_options, ls_files_usage);
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(ls_files_usage, builtin_ls_files_options);
 
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 6b666e1..41d7940 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -150,6 +150,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 	if (prefix && *prefix)
 		chomp_prefix = strlen(prefix);
 
+	GEN_PARSEOPT(ls_tree_options, ls_tree_usage);
 	argc = parse_options(argc, argv, prefix, ls_tree_options,
 			     ls_tree_usage, 0);
 	if (full_tree) {
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 4f30f1b..6e663a6 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -86,6 +86,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(options, merge_base_usage);
 	argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
 	if (!octopus && !reduce && argc < 2)
 		usage_with_options(merge_base_usage, options);
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index 237abd3..31336c4 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -57,6 +57,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 			xmp.style = git_xmerge_style;
 	}
 
+	GEN_PARSEOPT(options, merge_file_usage);
 	argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
 	if (argc != 3)
 		usage_with_options(merge_file_usage, options);
diff --git a/builtin/merge.c b/builtin/merge.c
index 08e01e8..8c0fc7f 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1153,6 +1153,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	struct commit_list **remotes = &remoteheads;
 	void *branch_to_free;
 
+	GEN_PARSEOPT(builtin_merge_options, builtin_merge_usage);
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(builtin_merge_usage, builtin_merge_options);
 
diff --git a/builtin/mktree.c b/builtin/mktree.c
index 4ae1c41..d842fee 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -156,6 +156,7 @@ int cmd_mktree(int ac, const char **av, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(option, mktree_usage);
 	ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
 
 	while (!got_eof) {
diff --git a/builtin/mv.c b/builtin/mv.c
index 2a144b0..c3a4efa 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -72,6 +72,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 
 	git_config(git_default_config, NULL);
 
+	GEN_PARSEOPT(builtin_mv_options, builtin_mv_usage);
 	argc = parse_options(argc, argv, prefix, builtin_mv_options,
 			     builtin_mv_usage, 0);
 	if (--argc < 1)
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 1b37458..5b4fc54 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -240,6 +240,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(opts, name_rev_usage);
 	argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
 	if (!!all + !!transform_stdin + !!argc > 1) {
 		error("Specify either a list, or --all, not both!");
diff --git a/builtin/notes.c b/builtin/notes.c
index 3644d14..33eca95 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -492,6 +492,7 @@ static int list(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, git_notes_list_usage);
 	if (argc)
 		argc = parse_options(argc, argv, prefix, options,
 				     git_notes_list_usage, 0);
@@ -547,6 +548,7 @@ static int add(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, git_notes_add_usage);
 	argc = parse_options(argc, argv, prefix, options, git_notes_add_usage,
 			     PARSE_OPT_KEEP_ARGV0);
 
@@ -619,6 +621,7 @@ static int copy(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, git_notes_copy_usage);
 	argc = parse_options(argc, argv, prefix, options, git_notes_copy_usage,
 			     0);
 
@@ -705,6 +708,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)
 	int edit = !strcmp(argv[0], "edit");
 
 	usage = edit ? git_notes_edit_usage : git_notes_append_usage;
+	GEN_PARSEOPT(options, usage);
 	argc = parse_options(argc, argv, prefix, options, usage,
 			     PARSE_OPT_KEEP_ARGV0);
 
@@ -752,6 +756,7 @@ static int show(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, git_notes_show_usage);
 	argc = parse_options(argc, argv, prefix, options, git_notes_show_usage,
 			     0);
 
@@ -878,6 +883,7 @@ static int merge(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, git_notes_merge_usage);
 	argc = parse_options(argc, argv, prefix, options,
 			     git_notes_merge_usage, 0);
 
@@ -989,6 +995,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
 	struct notes_tree *t;
 	int retval = 0;
 
+	GEN_PARSEOPT(options, git_notes_remove_usage);
 	argc = parse_options(argc, argv, prefix, options,
 			     git_notes_remove_usage, 0);
 
@@ -1026,6 +1033,7 @@ static int prune(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, git_notes_prune_usage);
 	argc = parse_options(argc, argv, prefix, options, git_notes_prune_usage,
 			     0);
 
@@ -1047,6 +1055,7 @@ static int prune(int argc, const char **argv, const char *prefix)
 static int get_ref(int argc, const char **argv, const char *prefix)
 {
 	struct option options[] = { OPT_END() };
+	GEN_PARSEOPT(options, git_notes_get_ref_usage);
 	argc = parse_options(argc, argv, prefix, options,
 			     git_notes_get_ref_usage, 0);
 
@@ -1069,6 +1078,23 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	if (generate_parseopt_strings(__FILE__, __LINE__,
+				      options, git_notes_usage)) {
+		const char *edit_cmd[] = { "edit", NULL };
+		const char *append_cmd[] = { "append", NULL };
+		list(0, NULL, NULL);
+		add(0, NULL, NULL);
+		copy(0, NULL, NULL);
+		append_edit(0, edit_cmd, NULL);
+		append_edit(0, append_cmd, NULL);
+		show(0, NULL, NULL);
+		merge(0, NULL, NULL);
+		remove_cmd(0, NULL, NULL);
+		prune(0, NULL, NULL);
+		get_ref(0, NULL, NULL);
+		return 0;
+	}
+
 	git_config(git_default_config, NULL);
 	argc = parse_options(argc, argv, prefix, options, git_notes_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 7b07c09..05665ad 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2413,6 +2413,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		pack_compression_level = core_compression_level;
 
 	progress = isatty(2);
+	GEN_PARSEOPT(pack_objects_options, pack_usage);
 	argc = parse_options(argc, argv, prefix, pack_objects_options,
 			     pack_usage, 0);
 
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index 39a9d89..f3292c4 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -15,6 +15,7 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
 		OPT_BIT(0, "prune", &flags, "prune loose refs (default)", PACK_REFS_PRUNE),
 		OPT_END(),
 	};
+	GEN_PARSEOPT(opts, pack_refs_usage);
 	if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
 		usage_with_options(pack_refs_usage, opts);
 	return pack_refs(flags);
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index b58a2e1..222a726 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -78,6 +78,7 @@ int cmd_prune_packed(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(prune_packed_options, prune_packed_usage);
 	argc = parse_options(argc, argv, prefix, prune_packed_options,
 			     prune_packed_usage, 0);
 
diff --git a/builtin/prune.c b/builtin/prune.c
index b99b635..faac378 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -142,6 +142,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
 	read_replace_refs = 0;
 	init_revisions(&revs, prefix);
 
+	GEN_PARSEOPT(options, prune_usage);
 	argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
 	while (argc--) {
 		unsigned char sha1[20];
diff --git a/builtin/push.c b/builtin/push.c
index d315475..fb00e0b 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -268,6 +268,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 
 	packet_trace_identity("push");
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(options, push_usage);
 	argc = parse_options(argc, argv, prefix, options, push_usage, 0);
 
 	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index df6c4c8..b6c5c58 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -145,6 +145,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
 
 	git_config(git_default_config, NULL);
 
+	GEN_PARSEOPT(read_tree_options, read_tree_usage);
 	argc = parse_options(argc, argv, unused_prefix, read_tree_options,
 			     read_tree_usage, 0);
 
diff --git a/builtin/remote.c b/builtin/remote.c
index fec92bc..97da0d5 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -175,6 +175,7 @@ static int add(int argc, const char **argv)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, builtin_remote_add_usage);
 	argc = parse_options(argc, argv, NULL, options, builtin_remote_add_usage,
 			     0);
 
@@ -627,6 +628,8 @@ static int mv(int argc, const char **argv)
 	struct rename_info rename;
 	int i, refspec_updated = 0;
 
+	GEN_PARSEOPT(options, builtin_remote_rename_usage);
+
 	if (argc != 3)
 		usage_with_options(builtin_remote_rename_usage, options);
 
@@ -784,6 +787,7 @@ static int rm(int argc, const char **argv)
 	cb_data.skipped = &skipped;
 	cb_data.keep = &known_remotes;
 
+	GEN_PARSEOPT(options, builtin_remote_rm_usage);
 	if (argc != 2)
 		usage_with_options(builtin_remote_rm_usage, options);
 
@@ -1087,6 +1091,7 @@ static int show(int argc, const char **argv)
 	struct string_list info_list = STRING_LIST_INIT_NODUP;
 	struct show_info info;
 
+	GEN_PARSEOPT(options, builtin_remote_show_usage);
 	argc = parse_options(argc, argv, NULL, options, builtin_remote_show_usage,
 			     0);
 
@@ -1190,6 +1195,7 @@ static int set_head(int argc, const char **argv)
 			    "delete refs/remotes/<name>/HEAD"),
 		OPT_END()
 	};
+	GEN_PARSEOPT(options, builtin_remote_sethead_usage);
 	argc = parse_options(argc, argv, NULL, options, builtin_remote_sethead_usage,
 			     0);
 	if (argc)
@@ -1243,6 +1249,7 @@ static int prune(int argc, const char **argv)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, builtin_remote_prune_usage);
 	argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage,
 			     0);
 
@@ -1312,6 +1319,7 @@ static int update(int argc, const char **argv)
 
 	fetch_argv = xmalloc(sizeof(char *) * (argc+5));
 
+	GEN_PARSEOPT(options, builtin_remote_update_usage);
 	argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
 			     PARSE_OPT_KEEP_ARGV0);
 
@@ -1393,6 +1401,7 @@ static int set_branches(int argc, const char **argv)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, builtin_remote_setbranches_usage);
 	argc = parse_options(argc, argv, NULL, options,
 			     builtin_remote_setbranches_usage, 0);
 	if (argc == 0) {
@@ -1425,6 +1434,7 @@ static int set_url(int argc, const char **argv)
 			    "delete URLs"),
 		OPT_END()
 	};
+	GEN_PARSEOPT(options, builtin_remote_seturl_usage);
 	argc = parse_options(argc, argv, NULL, options, builtin_remote_seturl_usage,
 			     PARSE_OPT_KEEP_ARGV0);
 
@@ -1556,6 +1566,21 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
 	};
 	int result;
 
+	if (generate_parseopt_strings(__FILE__, __LINE__,
+				      options, builtin_remote_usage)) {
+
+		/* these just generate strings and do nothing */
+		add(0, NULL);
+		mv(0, NULL);
+		prune(0, NULL);
+		rm(0, NULL);
+		set_branches(0, NULL);
+		set_head(0, NULL);
+		set_url(0, NULL);
+		show(0, NULL);
+		update(0, NULL);
+		return 0;
+	}
 	argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
 		PARSE_OPT_STOP_AT_NON_OPTION);
 
diff --git a/builtin/replace.c b/builtin/replace.c
index 4a8970e..e4ec1c2 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -121,6 +121,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, git_replace_usage);
 	argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
 
 	if (list && delete)
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 08213c7..bef1b0a 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -57,6 +57,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
 		OPT_END(),
 	};
 
+	GEN_PARSEOPT(options, rerere_usage);
 	argc = parse_options(argc, argv, prefix, options, rerere_usage, 0);
 
 	if (autoupdate == 1)
diff --git a/builtin/reset.c b/builtin/reset.c
index 8c2c1d5..7d56fb9 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -251,6 +251,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	git_config(git_default_config, NULL);
 
+	GEN_PARSEOPT(options, git_reset_usage);
 	argc = parse_options(argc, argv, prefix, options, git_reset_usage,
 						PARSE_OPT_KEEP_DASHDASH);
 
diff --git a/builtin/revert.c b/builtin/revert.c
index e6840f2..8d7bb74 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -126,6 +126,8 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
 			die(_("program error"));
 	}
 
+	if (generate_parseopt_strings(__FILE__, __LINE__, options, usage_str))
+		exit(0);
 	argc = parse_options(argc, argv, NULL, options, usage_str,
 			PARSE_OPT_KEEP_ARGV0 |
 			PARSE_OPT_KEEP_UNKNOWN);
diff --git a/builtin/rm.c b/builtin/rm.c
index 90c8a50..126efc6 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -148,6 +148,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
 	git_config(git_default_config, NULL);
 
+	GEN_PARSEOPT(builtin_rm_options, builtin_rm_usage);
 	argc = parse_options(argc, argv, prefix, builtin_rm_options,
 			     builtin_rm_usage, 0);
 	if (!argc)
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 37f3193..bf46bf3 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -265,6 +265,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
 	git_config(git_default_config, NULL);
 	shortlog_init(&log);
 	init_revisions(&rev, prefix);
+	GEN_PARSEOPT(options, shortlog_usage);
 	parse_options_start(&ctx, argc, argv, prefix, options,
 			    PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
 
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index a59e088..7e2dd31 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -691,6 +691,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 		av = default_arg;
 	}
 
+	GEN_PARSEOPT(builtin_show_branch_options, show_branch_usage);
 	ac = parse_options(ac, av, prefix, builtin_show_branch_options,
 			   show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
 	if (all_heads)
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 3911661..72805a2 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -208,6 +208,7 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(show_ref_usage, show_ref_options);
 
+	GEN_PARSEOPT(show_ref_options, show_ref_usage);
 	argc = parse_options(argc, argv, prefix, show_ref_options,
 			     show_ref_usage, PARSE_OPT_NO_INTERNAL_HELP);
 
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index 801d62e..8915c03 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -42,6 +42,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(options, git_symbolic_ref_usage);
 	argc = parse_options(argc, argv, prefix, options,
 			     git_symbolic_ref_usage, 0);
 	if (msg &&!*msg)
diff --git a/builtin/tag.c b/builtin/tag.c
index fe7e5e5..bcc5517 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -478,6 +478,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 
 	memset(&opt, 0, sizeof(opt));
 
+	GEN_PARSEOPT(options, git_tag_usage);
 	argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
 
 	if (keyid) {
diff --git a/builtin/update-index.c b/builtin/update-index.c
index a6a23fa..710b983 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -794,6 +794,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	GEN_PARSEOPT(options, update_index_usage);
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage(update_index_usage[0]);
 
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 835c62a..ab2bde2 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -23,6 +23,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(options, git_update_ref_usage);
 	argc = parse_options(argc, argv, prefix, options, git_update_ref_usage,
 			     0);
 	if (msg && !*msg)
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 0d63c44..fbf5e1f 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -16,6 +16,7 @@ int cmd_update_server_info(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(options, update_server_info_usage);
 	argc = parse_options(argc, argv, prefix, options,
 			     update_server_info_usage, 0);
 	if (argc > 0)
diff --git a/builtin/verify-pack.c b/builtin/verify-pack.c
index e841b4a..099ea2a 100644
--- a/builtin/verify-pack.c
+++ b/builtin/verify-pack.c
@@ -71,6 +71,7 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)
 	};
 
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(verify_pack_options, verify_pack_usage);
 	argc = parse_options(argc, argv, prefix, verify_pack_options,
 			     verify_pack_usage, 0);
 	if (argc < 1)
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index 986789f..35f9fa4 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -76,6 +76,7 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
 
 	git_config(git_verify_tag_config, NULL);
 
+	GEN_PARSEOPT(verify_tag_options, verify_tag_usage);
 	argc = parse_options(argc, argv, prefix, verify_tag_options,
 			     verify_tag_usage, PARSE_OPT_KEEP_ARGV0);
 	if (argc <= i)
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index b223af4..417c7ac 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -34,6 +34,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
 	};
 
 	git_config(git_default_config, NULL);
+	GEN_PARSEOPT(write_tree_options, write_tree_usage);
 	argc = parse_options(argc, argv, unused_prefix, write_tree_options,
 			     write_tree_usage, 0);
 
diff --git a/gettext.c b/gettext.c
index f75bca7..4ab29cd 100644
--- a/gettext.c
+++ b/gettext.c
@@ -4,6 +4,9 @@
 
 #include "git-compat-util.h"
 #include "gettext.h"
+#include "strbuf.h"
+#include "parse-options.h"
+#include "quote.h"
 
 #ifndef NO_GETTEXT
 #	include <locale.h>
@@ -129,3 +132,36 @@ void git_setup_gettext(void)
 	textdomain("git");
 }
 #endif
+
+static void strbuf_quote_gettext(struct strbuf *sb, const char *s)
+{
+	if (!*s)		/* do not generate empty strings */
+		return;
+	strbuf_addstr(sb, "_(\"");
+	quote_c_style(s, sb, NULL, 1);
+	strbuf_addstr(sb, "\");\n");
+}
+
+int generate_parseopt_strings(const char *file, int line,
+			      const struct option *opts,
+			      const char * const * usagestr)
+{
+	struct strbuf sb = STRBUF_INIT;
+
+	if (!getenv("GIT_I18N"))
+		return 0;
+
+	strbuf_addf(&sb, "/* parseopt %s:%d */\n", file, line);
+	for (; usagestr && *usagestr; usagestr++)
+		strbuf_quote_gettext(&sb, *usagestr);
+	for (; opts->type != OPTION_END; opts++) {
+		if (opts->argh)
+			strbuf_quote_gettext(&sb, opts->argh);
+		if (opts->help)
+			strbuf_quote_gettext(&sb, opts->help);
+	}
+	strbuf_addch(&sb, '\n');
+	fputs(sb.buf, stdout);
+	strbuf_release(&sb);
+	return 1;
+}
diff --git a/gettext.h b/gettext.h
index 57ba8bb..ae5c874 100644
--- a/gettext.h
+++ b/gettext.h
@@ -59,3 +59,12 @@ const char *Q_(const char *msgid, const char *plu, unsigned long n)
 #define N_(msgid) msgid
 
 #endif
+
+struct option;
+extern int generate_parseopt_strings(const char *file, int line,
+				     const struct option *opts,
+				     const char * const * usagestr);
+#define GEN_PARSEOPT(opts, usage) { \
+	if (generate_parseopt_strings(__FILE__, __LINE__, opts, usage)) \
+		return 0; \
+	}
-- 8< --
-- 
Duy

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle
  2012-04-24 12:19 ` Nguyen Thai Ngoc Duy
@ 2012-04-24 19:50   ` Junio C Hamano
  2012-04-25 11:42     ` Nguyen Thai Ngoc Duy
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-04-24 19:50 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy
  Cc: git, Junio C Hamano, Jonathan Niedier,
	Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:

> On Mon, Apr 23, 2012 at 07:30:20PM +0700, Nguyễn Thái Ngọc Duy wrote:
>> I attempted to
>> convert all struct option, and it turned into a huge series [2]. Not
>> sure how to submit that series yet.
>>
>> [2] https://github.com/pclouds/git/tree/parseopt-i18n
>
> The 62 patch series looks lame compared to this approach, but cross
> compile guys, including myself, will hate me in principle.
>
> The idea is modify all git commands and output all marked strings in
> "struct option" and usage strings, instead of manually marking them
> one by one. The marked strings will be collected by xgettext just like
> another source file.

Gaah, my eyes, my eyes.

No thanks.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-23 12:30 ` [PATCH 03/10] i18n: mark relative dates for translation Nguyễn Thái Ngọc Duy
@ 2012-04-24 20:04   ` Junio C Hamano
  2012-04-25 10:46     ` Nguyen Thai Ngoc Duy
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-04-24 20:04 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> From: Jonathan Nieder <jrnieder@gmail.com>
>
> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---

Looks nicely done ;-)

>  	/* Give years and months for 5 years or so */
>  	if (diff < 1825) {
> ...
>  	}
>  	/* Otherwise, just years. Centuries is probably overkill. */
> -	snprintf(timebuf, timebuf_size, "%lu years ago", (diff + 183) / 365);
> -	return timebuf;
> +	strbuf_addf(timebuf,
> +		 Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
> +		 (diff + 183) / 365);
>  }

This is just a tangent, but could we possibly come here and say "1 year
ago"?

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-24 20:04   ` Junio C Hamano
@ 2012-04-25 10:46     ` Nguyen Thai Ngoc Duy
  2012-04-25 11:07       ` Johannes Sixt
  2012-04-25 15:25       ` Jonathan Nieder
  0 siblings, 2 replies; 43+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-04-25 10:46 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

2012/4/25 Junio C Hamano <gitster@pobox.com>:
>>       /* Give years and months for 5 years or so */
>>       if (diff < 1825) {
>> ...
>>       }
>>       /* Otherwise, just years. Centuries is probably overkill. */
>> -     snprintf(timebuf, timebuf_size, "%lu years ago", (diff + 183) / 365);
>> -     return timebuf;
>> +     strbuf_addf(timebuf,
>> +              Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
>> +              (diff + 183) / 365);
>>  }
>
> This is just a tangent, but could we possibly come here and say "1 year
> ago"?

Nice catch. Singular form here is unnecessary. If you plan to revert
that, please put a comment so nobody will attempt to convert it to
Q_() again next time while searching for possible candidates.
-- 
Duy

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-25 10:46     ` Nguyen Thai Ngoc Duy
@ 2012-04-25 11:07       ` Johannes Sixt
  2012-04-25 11:25         ` Zbigniew Jędrzejewski-Szmek
  2012-04-25 11:29         ` Nguyen Thai Ngoc Duy
  2012-04-25 15:25       ` Jonathan Nieder
  1 sibling, 2 replies; 43+ messages in thread
From: Johannes Sixt @ 2012-04-25 11:07 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy
  Cc: Junio C Hamano, git, Jonathan Niedier,
	Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Am 4/25/2012 12:46, schrieb Nguyen Thai Ngoc Duy:
> 2012/4/25 Junio C Hamano <gitster@pobox.com>:
>>>       /* Give years and months for 5 years or so */
>>>       if (diff < 1825) {
>>> ...
>>>       }
>>>       /* Otherwise, just years. Centuries is probably overkill. */
>>> -     snprintf(timebuf, timebuf_size, "%lu years ago", (diff + 183) / 365);
>>> -     return timebuf;
>>> +     strbuf_addf(timebuf,
>>> +              Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
>>> +              (diff + 183) / 365);
>>>  }
>>
>> This is just a tangent, but could we possibly come here and say "1 year
>> ago"?
> 
> Nice catch. Singular form here is unnecessary. If you plan to revert
> that, please put a comment so nobody will attempt to convert it to
> Q_() again next time while searching for possible candidates.

I am sure that there are languages (Russian? Polish?) where a variation is
needed not only for the singular, but also for plural depending on the
number, so we still want to have this wrapped in Q_().

-- Hannes

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH] help: replace underlining "help -a" headers using hyphens with a blank line
  2012-04-23 18:34       ` Jonathan Nieder
@ 2012-04-25 11:21         ` Nguyễn Thái Ngọc Duy
  2012-04-25 17:30           ` Junio C Hamano
  0 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-04-25 11:21 UTC (permalink / raw)
  To: Jonathan Niedier
  Cc: git, Junio C Hamano, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

We want the underline to align with the text above, for example:

This is a header
----------------
content...

Unfortunately calculating text length could get complicated because
the text could be in any charset in translated Git. Avoid it and print
a blank line (i.e. charset neutral) instead. Readability is not
affected much. After the change we get:

This is a header:

content...

While at it, give translators more context to translate, e.g.
e.g.  "git commands available..." instead of "%s available..."

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 2012/4/24 Jonathan Nieder <jrnieder@gmail.com>:
 > Junio C Hamano wrote:
 >
 >>                                                        Wouldn't a simple
 >> and clean "blank line" look better?
 >
 > Yes, based on a quick test with "vi" it looks reasonable.  Thanks for
 > a sanity check.

 And it does _not_ assume the translated text is in utf-8.

 And thanks Junio for fixing the other nit before merging the seriess
 to next. I should have read and reacted on these posts yesterday.

 builtin/help.c |    2 +-
 help.c         |   16 +++-------------
 help.h         |    3 +--
 3 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/builtin/help.c b/builtin/help.c
index 96a462c..e63668a 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -425,7 +425,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
 
 	if (show_all) {
 		printf(_("usage: %s%s"), _(git_usage_string), "\n\n");
-		list_commands(_("git commands"), &main_cmds, &other_cmds);
+		list_commands(&main_cmds, &other_cmds);
 		printf("%s\n", _(git_more_info_string));
 		return 0;
 	}
diff --git a/help.c b/help.c
index 9e6e0f2..baaf379 100644
--- a/help.c
+++ b/help.c
@@ -203,8 +203,7 @@ void load_command_list(const char *prefix,
 	exclude_cmds(other_cmds, main_cmds);
 }
 
-void list_commands(const char *title, struct cmdnames *main_cmds,
-		   struct cmdnames *other_cmds)
+void list_commands(struct cmdnames *main_cmds, struct cmdnames *other_cmds)
 {
 	int i, longest = 0;
 
@@ -217,23 +216,14 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
 
 	if (main_cmds->cnt) {
 		const char *exec_path = git_exec_path();
-		printf_ln(_("available %s in '%s'"), title, exec_path);
-		/* TRANSLATORS: this must align with "available %s in '%s'" */
-		printf(_("----------------"));
-		mput_char('-', strlen(title) + strlen(exec_path));
+		printf_ln(_("available git commands in '%s':"), exec_path);
 		putchar('\n');
 		pretty_print_string_list(main_cmds, longest);
 		putchar('\n');
 	}
 
 	if (other_cmds->cnt) {
-		printf_ln(_("%s available from elsewhere on your $PATH"), title);
-		/* TRANSLATORS:
-		 * this must align with
-		 * "%s available from elsewhere on your $PATH"
-		 */
-		printf(_("---------------------------------------"));
-		mput_char('-', strlen(title));
+		printf_ln(_("git commands available from elsewhere on your $PATH:"));
 		putchar('\n');
 		pretty_print_string_list(other_cmds, longest);
 		putchar('\n');
diff --git a/help.h b/help.h
index b6b12d5..dc406c8 100644
--- a/help.h
+++ b/help.h
@@ -25,8 +25,7 @@ extern void add_cmdname(struct cmdnames *cmds, const char *name, int len);
 /* Here we require that excludes is a sorted list. */
 extern void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
 extern int is_in_cmdlist(struct cmdnames *cmds, const char *name);
-extern void list_commands(const char *title,
-			  struct cmdnames *main_cmds,
+extern void list_commands(struct cmdnames *main_cmds,
 			  struct cmdnames *other_cmds);
 
 #endif /* HELP_H */
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-25 11:07       ` Johannes Sixt
@ 2012-04-25 11:25         ` Zbigniew Jędrzejewski-Szmek
  2012-04-25 11:29         ` Nguyen Thai Ngoc Duy
  1 sibling, 0 replies; 43+ messages in thread
From: Zbigniew Jędrzejewski-Szmek @ 2012-04-25 11:25 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Nguyen Thai Ngoc Duy, Junio C Hamano, git, Jonathan Niedier,
	Ævar Arnfjörð,
	Jiang Xin

On 04/25/2012 01:07 PM, Johannes Sixt wrote:
> Am 4/25/2012 12:46, schrieb Nguyen Thai Ngoc Duy:
>> 2012/4/25 Junio C Hamano <gitster@pobox.com>:
>>>>       /* Give years and months for 5 years or so */
>>>>       if (diff < 1825) {
>>>> ...
>>>>       }
>>>>       /* Otherwise, just years. Centuries is probably overkill. */
>>>> -     snprintf(timebuf, timebuf_size, "%lu years ago", (diff + 183) / 365);
>>>> -     return timebuf;
>>>> +     strbuf_addf(timebuf,
>>>> +              Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
>>>> +              (diff + 183) / 365);
>>>>  }
>>>
>>> This is just a tangent, but could we possibly come here and say "1 year
>>> ago"?
>>
>> Nice catch. Singular form here is unnecessary. If you plan to revert
>> that, please put a comment so nobody will attempt to convert it to
>> Q_() again next time while searching for possible candidates.
> 
> I am sure that there are languages (Russian? Polish?) where a variation is
> needed not only for the singular, but also for plural depending on the
> number, so we still want to have this wrapped in Q_().
Yeah, both Polish and Russian...

Polish:
Plural-Forms: nplurals=3; \
  plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);

Russian:
Plural-Forms: nplurals=3; \
              plural=n%10==1 && n%100!=11 ? 0 : \
                     n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;

Looking at http://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/Plural-forms.html, basically all languages which have nplurals=3 or nplurals=4.

Zbyszek

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-25 11:07       ` Johannes Sixt
  2012-04-25 11:25         ` Zbigniew Jędrzejewski-Szmek
@ 2012-04-25 11:29         ` Nguyen Thai Ngoc Duy
  1 sibling, 0 replies; 43+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-04-25 11:29 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Junio C Hamano, git, Jonathan Niedier,
	Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

On Wed, Apr 25, 2012 at 6:07 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
> Am 4/25/2012 12:46, schrieb Nguyen Thai Ngoc Duy:
>> 2012/4/25 Junio C Hamano <gitster@pobox.com>:
>>>>       /* Give years and months for 5 years or so */
>>>>       if (diff < 1825) {
>>>> ...
>>>>       }
>>>>       /* Otherwise, just years. Centuries is probably overkill. */
>>>> -     snprintf(timebuf, timebuf_size, "%lu years ago", (diff + 183) / 365);
>>>> -     return timebuf;
>>>> +     strbuf_addf(timebuf,
>>>> +              Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
>>>> +              (diff + 183) / 365);
>>>>  }
>>>
>>> This is just a tangent, but could we possibly come here and say "1 year
>>> ago"?
>>
>> Nice catch. Singular form here is unnecessary. If you plan to revert
>> that, please put a comment so nobody will attempt to convert it to
>> Q_() again next time while searching for possible candidates.
>
> I am sure that there are languages (Russian? Polish?) where a variation is
> needed not only for the singular, but also for plural depending on the
> number, so we still want to have this wrapped in Q_().

Slovenian has special case for one and all numbers ending in 2, 3, 4
[1]. Oh my..

[1] http://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/Plural-forms.html
-- 
Duy

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle
  2012-04-24 19:50   ` Junio C Hamano
@ 2012-04-25 11:42     ` Nguyen Thai Ngoc Duy
  2012-04-25 16:11       ` Jonathan Nieder
  0 siblings, 1 reply; 43+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-04-25 11:42 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

On Wed, Apr 25, 2012 at 2:50 AM, Junio C Hamano <gitster@pobox.com> wrote:
>> The idea is modify all git commands and output all marked strings in
>> "struct option" and usage strings, instead of manually marking them
>> one by one. The marked strings will be collected by xgettext just like
>> another source file.
>
> Gaah, my eyes, my eyes.
>
> No thanks.
>

Good. What burned your eyes though? Are you ok with an approach that
does not change source code (much) and still marks strings using an
external tool? I'm looking at sparse, but perhaps a simple perl script
to look at "gcc -E" output and search for "struct option" would be
enough.
-- 
Duy

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-25 10:46     ` Nguyen Thai Ngoc Duy
  2012-04-25 11:07       ` Johannes Sixt
@ 2012-04-25 15:25       ` Jonathan Nieder
  2012-04-25 16:27         ` Junio C Hamano
  1 sibling, 1 reply; 43+ messages in thread
From: Jonathan Nieder @ 2012-04-25 15:25 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy
  Cc: Junio C Hamano, git, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyen Thai Ngoc Duy wrote:
> 2012/4/25 Junio C Hamano <gitster@pobox.com>:

>>> +     strbuf_addf(timebuf,
>>> +              Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
>>> +              (diff + 183) / 365);
>>>  }
>>
>> This is just a tangent, but could we possibly come here and say "1 year
>> ago"?
>
> Nice catch. Singular form here is unnecessary.

I think Junio meant

			Q_("1 year ago", "%lu years ago", ...)

That sound reasonable to me.  My only worry is a small one: what
happens if we want to change the %lu to some other format specifier
some day?  Will xgettext be smart enough to let translators know
without the msgid changing?

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle
  2012-04-25 11:42     ` Nguyen Thai Ngoc Duy
@ 2012-04-25 16:11       ` Jonathan Nieder
  0 siblings, 0 replies; 43+ messages in thread
From: Jonathan Nieder @ 2012-04-25 16:11 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy
  Cc: Junio C Hamano, git, Ævar Arnfjörð Bjarmason,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyen Thai Ngoc Duy wrote:

> Good. What burned your eyes though? Are you ok with an approach that
> does not change source code (much) and still marks strings using an
> external tool?

I'd like the translated messages to be marked in the source code if
possible so future coders know to be careful when changing them.

If the change can be made and checked by an automated process, that
would be great, of course.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-25 15:25       ` Jonathan Nieder
@ 2012-04-25 16:27         ` Junio C Hamano
  2012-04-25 17:26           ` Jonathan Nieder
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-04-25 16:27 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Nguyen Thai Ngoc Duy, git, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Jonathan Nieder <jrnieder@gmail.com> writes:

> Nguyen Thai Ngoc Duy wrote:
>> 2012/4/25 Junio C Hamano <gitster@pobox.com>:
>
>>>> +     strbuf_addf(timebuf,
>>>> +              Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
>>>> +              (diff + 183) / 365);
>>>>  }
>>>
>>> This is just a tangent, but could we possibly come here and say "1 year
>>> ago"?
>>
>> Nice catch. Singular form here is unnecessary.
>
> I think Junio meant
>
> 			Q_("1 year ago", "%lu years ago", ...)

No, I was just being stupid---what I meant was that diff will be so
large that this will always be feeding more than 1 to %lu, so the first
template string will never be used.

But it cannot be N_("%lu years ago", number), as others correctly
pointed out.  We want to use ngettext() here, because it is not enough
to know that number is always greater than 1 to correctly phrase this in
some languages.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 03/10] i18n: mark relative dates for translation
  2012-04-25 16:27         ` Junio C Hamano
@ 2012-04-25 17:26           ` Jonathan Nieder
  0 siblings, 0 replies; 43+ messages in thread
From: Jonathan Nieder @ 2012-04-25 17:26 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Nguyen Thai Ngoc Duy, git,
	Ævar Arnfjörð Bjarmason, Jiang Xin,
	Zbigniew Jędrzejewski-Szmek

Junio C Hamano wrote:

>                               what I meant was that diff will be so
> large that this will always be feeding more than 1 to %lu, so the first
> template string will never be used.
>
> But it cannot be N_("%lu years ago", number), as others correctly
> pointed out.  We want to use ngettext() here, because it is not enough
> to know that number is always greater than 1 to correctly phrase this in
> some languages.

Ah, I see now.  Thanks for a patient explanation.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] help: replace underlining "help -a" headers using hyphens with a blank line
  2012-04-25 11:21         ` [PATCH] help: replace underlining "help -a" headers using hyphens with a blank line Nguyễn Thái Ngọc Duy
@ 2012-04-25 17:30           ` Junio C Hamano
  0 siblings, 0 replies; 43+ messages in thread
From: Junio C Hamano @ 2012-04-25 17:30 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: Jonathan Niedier, git, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> We want the underline to align with the text above, for example:
>
> This is a header
> ----------------
> content...
>
> Unfortunately calculating text length could get complicated because
> the text could be in any charset in translated Git. Avoid it and print
> a blank line (i.e. charset neutral) instead. Readability is not
> affected much. After the change we get:

When I said we do not need *pseudo* underline, I really meant it.  I
tentatively amended your patch to read like this:

    We used to underline a header text, like this:

        This is a header
        ----------------
        content...

    But calculating text length so that the dashes align with the text
    could get complicated because the text could be in any charset in
    translated Git.

    There is no point to use this pseudo underline; simply a blank
    line would do and it even makes it easier to read:

        This is a header

        content...

and adjusted the code to match, but it may make more sense to use the
GIT_COLOR* stuff for this to highlight the header line, allowing us to
lose the extra empty line.

This patch obviously conflicts with your own nd/columns so we may want
to take this slowly and it is OK to wait until columns graduates.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 10/10] i18n: bundle: mark strings for translation
  2012-04-23 12:30 ` [PATCH 10/10] i18n: bundle: " Nguyễn Thái Ngọc Duy
@ 2012-04-25 22:43   ` Junio C Hamano
  2012-04-26  1:24     ` Nguyen Thai Ngoc Duy
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-04-25 22:43 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> @@ -283,13 +287,13 @@ int create_bundle(struct bundle_header *header, const char *path,
>  	strbuf_release(&buf);
>  	fclose(rls_fout);
>  	if (finish_command(&rls))
> -		return error("rev-list died");
> +		return error(_("rev-list died"));
>  
>  	/* write references */
>  	argc = setup_revisions(argc, argv, &revs, NULL);
>  
>  	if (argc > 1)
> -		return error("unrecognized argument: %s'", argv[1]);
> +		return error(_("unrecognized argument: %s'"), argv[1]);

This is a problem in the original but we see an unmatched sq here.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 07/10] i18n: apply: mark strings for translation
  2012-04-23 12:30 ` [PATCH 07/10] i18n: apply: " Nguyễn Thái Ngọc Duy
@ 2012-04-25 22:50   ` Junio C Hamano
  2012-05-06 13:13     ` [PATCH] apply: remove lego in i18n string in gitdiff_verify_name Nguyễn Thái Ngọc Duy
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-04-25 22:50 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> @@ -886,17 +886,17 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
> ...
>  		if (!another || memcmp(another, name, len + 1))
> -			die("git apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
> +			die(_("git apply: bad git-diff - inconsistent %s filename on line %d"), oldnew, linenr);
>  		free(another);
>  		return orig_name;
>  	}

In this function, the parameter oldnew has "old" or "new" and the
callers (gitdiff_oldname() and gitdiff_newname()) do not have it marked
for translation.  Even if they did, it would result in a lego
composition, so you may have to switch between two translatable messages
here.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 06/10] i18n: remote: mark strings for translation
  2012-04-23 12:30 ` [PATCH 06/10] i18n: remote: mark strings for translation Nguyễn Thái Ngọc Duy
@ 2012-04-25 22:54   ` Junio C Hamano
  2012-04-26  1:12     ` Nguyen Thai Ngoc Duy
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-04-25 22:54 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Junio C Hamano, Jonathan Niedier,
	Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> @@ -761,7 +761,7 @@ static int remove_branches(struct string_list *branches)
>  		unsigned char *sha1 = item->util;
>  
>  		if (delete_ref(refname, sha1, 0))
> -			result |= error("Could not remove branch %s", refname);
> +			result |= error(_("Could not remove branch %s"), refname);
>  	}

This is an issue in the original, but almost all messages in this
utility use sq around names of 'stuff' that can be specified by the end
user when it appears as part of a sentence, but not here.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 06/10] i18n: remote: mark strings for translation
  2012-04-25 22:54   ` Junio C Hamano
@ 2012-04-26  1:12     ` Nguyen Thai Ngoc Duy
  0 siblings, 0 replies; 43+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-04-26  1:12 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

2012/4/26 Junio C Hamano <gitster@pobox.com>:
> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:
>
>> @@ -761,7 +761,7 @@ static int remove_branches(struct string_list *branches)
>>               unsigned char *sha1 = item->util;
>>
>>               if (delete_ref(refname, sha1, 0))
>> -                     result |= error("Could not remove branch %s", refname);
>> +                     result |= error(_("Could not remove branch %s"), refname);
>>       }
>
> This is an issue in the original, but almost all messages in this
> utility use sq around names of 'stuff' that can be specified by the end
> user when it appears as part of a sentence, but not here.

If we are going to make a style consistency patch, should we also
agree on (at least for this command) whether to write initial letter
in capital or not?
-- 
Duy

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 10/10] i18n: bundle: mark strings for translation
  2012-04-25 22:43   ` Junio C Hamano
@ 2012-04-26  1:24     ` Nguyen Thai Ngoc Duy
  2012-04-26  5:53       ` [PATCH] bundle: remove stray single-quote from error message Jonathan Nieder
  0 siblings, 1 reply; 43+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-04-26  1:24 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

On Thu, Apr 26, 2012 at 5:43 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:
>
>> @@ -283,13 +287,13 @@ int create_bundle(struct bundle_header *header, const char *path,
>>       strbuf_release(&buf);
>>       fclose(rls_fout);
>>       if (finish_command(&rls))
>> -             return error("rev-list died");
>> +             return error(_("rev-list died"));
>>
>>       /* write references */
>>       argc = setup_revisions(argc, argv, &revs, NULL);
>>
>>       if (argc > 1)
>> -             return error("unrecognized argument: %s'", argv[1]);
>> +             return error(_("unrecognized argument: %s'"), argv[1]);
>
> This is a problem in the original but we see an unmatched sq here.

Yeah. I searched the code and that seems the only place with
unbalanced quotes (both single and double quotes). I'll leave it to
you to either drop it or add another one there.
-- 
Duy

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH] bundle: remove stray single-quote from error message
  2012-04-26  1:24     ` Nguyen Thai Ngoc Duy
@ 2012-04-26  5:53       ` Jonathan Nieder
  0 siblings, 0 replies; 43+ messages in thread
From: Jonathan Nieder @ 2012-04-26  5:53 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy
  Cc: Junio C Hamano, git, Ævar Arnfjörð Bjarmason,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

After running rev-list --boundary to retrieve the list of boundary
commits, "git bundle create" runs its own revision walk.  If in this
stage git encounters an unfamiliar option, it writes a message with an
unbalanced quotation mark:

	error: unrecognized argument: --foo'

Drop the stray quote to match the "unrecognized argument: %s" message
used elsewhere and save translators some work.

This is mostly a futureproofing measure: for now, the "rev-list
--boundary" command catches most strange arguments on its own and the
above message is not seen unless you try something esoteric like "git
bundle create test.bundle --header HEAD".

Reported-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Nguyen Thai Ngoc Duy wrote:

> Yeah. I searched the code and that seems the only place with
> unbalanced quotes (both single and double quotes). I'll leave it to
> you to either drop it or add another one there.

Ok, here you go.

 bundle.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bundle.c b/bundle.c
index d9cfd905..27ab32e4 100644
--- a/bundle.c
+++ b/bundle.c
@@ -289,7 +289,7 @@ int create_bundle(struct bundle_header *header, const char *path,
 	argc = setup_revisions(argc, argv, &revs, NULL);
 
 	if (argc > 1)
-		return error("unrecognized argument: %s'", argv[1]);
+		return error("unrecognized argument: %s", argv[1]);
 
 	object_array_remove_duplicates(&revs.pending);
 
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH] apply: remove lego in i18n string in gitdiff_verify_name
  2012-04-25 22:50   ` Junio C Hamano
@ 2012-05-06 13:13     ` Nguyễn Thái Ngọc Duy
  2012-05-07 18:00       ` Junio C Hamano
  0 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-05-06 13:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier, Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

Currently it marks the string "...inconsistent %s filename..." where
%s is either "old" or "new" from caller. Make it two strings
"...inconsistent new filename..." and "...inconsistent old filename..."

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 On Thu, Apr 26, 2012 at 5:50 AM, Junio C Hamano <gitster@pobox.com> wrote:
 > In this function, the parameter oldnew has "old" or "new" and the
 > callers (gitdiff_oldname() and gitdiff_newname()) do not have it marked
 > for translation.  Even if they did, it would result in a lego
 > composition, so you may have to switch between two translatable messages
 > here.

 Makes sense.

 builtin/apply.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 725712d..1edd3f7 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -919,7 +919,7 @@ static int gitdiff_hdrend(const char *line, struct patch *patch)
  * their names against any previous information, just
  * to make sure..
  */
-static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)
+static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, int new)
 {
 	if (!orig_name && !isnull)
 		return find_name(line, NULL, p_value, TERM_TAB);
@@ -934,7 +934,9 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
 			die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), name, linenr);
 		another = find_name(line, NULL, p_value, TERM_TAB);
 		if (!another || memcmp(another, name, len + 1))
-			die(_("git apply: bad git-diff - inconsistent %s filename on line %d"), oldnew, linenr);
+			die(new ?
+			    _("git apply: bad git-diff - inconsistent new filename on line %d") :
+			    _("git apply: bad git-diff - inconsistent old filename on line %d"), linenr);
 		free(another);
 		return orig_name;
 	}
@@ -949,7 +951,7 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
 static int gitdiff_oldname(const char *line, struct patch *patch)
 {
 	char *orig = patch->old_name;
-	patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, "old");
+	patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, 0);
 	if (orig != patch->old_name)
 		free(orig);
 	return 0;
@@ -958,7 +960,7 @@ static int gitdiff_oldname(const char *line, struct patch *patch)
 static int gitdiff_newname(const char *line, struct patch *patch)
 {
 	char *orig = patch->new_name;
-	patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, "new");
+	patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, 1);
 	if (orig != patch->new_name)
 		free(orig);
 	return 0;
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH] apply: remove lego in i18n string in gitdiff_verify_name
  2012-05-06 13:13     ` [PATCH] apply: remove lego in i18n string in gitdiff_verify_name Nguyễn Thái Ngọc Duy
@ 2012-05-07 18:00       ` Junio C Hamano
  2012-05-08 13:38         ` Nguyễn Thái Ngọc Duy
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-05-07 18:00 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Junio C Hamano, Jonathan Niedier,
	Ævar Arnfjörð,
	Jiang Xin, Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> Currently it marks the string "...inconsistent %s filename..." where
> %s is either "old" or "new" from caller. Make it two strings
> "...inconsistent new filename..." and "...inconsistent old filename..."
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
>  On Thu, Apr 26, 2012 at 5:50 AM, Junio C Hamano <gitster@pobox.com> wrote:
>  > In this function, the parameter oldnew has "old" or "new" and the
>  > callers (gitdiff_oldname() and gitdiff_newname()) do not have it marked
>  > for translation.  Even if they did, it would result in a lego
>  > composition, so you may have to switch between two translatable messages
>  > here.
>
>  Makes sense.
>
>  builtin/apply.c |   10 ++++++----
>  1 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/builtin/apply.c b/builtin/apply.c
> index 725712d..1edd3f7 100644
> --- a/builtin/apply.c
> +++ b/builtin/apply.c
> @@ -919,7 +919,7 @@ static int gitdiff_hdrend(const char *line, struct patch *patch)
>   * their names against any previous information, just
>   * to make sure..
>   */
> -static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)
> +static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, int new)
>  {

This change is unwarranted, though.  The callers were much clearer when
they passed "old" vs "new"; now they pass an unexplained 0 vs 1.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH] apply: remove lego in i18n string in gitdiff_verify_name
  2012-05-07 18:00       ` Junio C Hamano
@ 2012-05-08 13:38         ` Nguyễn Thái Ngọc Duy
  2012-05-08 17:07           ` Junio C Hamano
  0 siblings, 1 reply; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-05-08 13:38 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier,
	Ævar Arnfjörð Bjarmason, Jiang Xin,
	Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

Currently it marks the string "...inconsistent %s filename..." where
%s is either "old" or "new" from caller. From a translator point of
view, nothing hints what "%s" may be. Make it two strings
"...inconsistent new filename..." and "...inconsistent old
filename..."

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 On Tue, May 8, 2012 at 1:00 AM, Junio C Hamano <gitster@pobox.com> wrote:
 >> diff --git a/builtin/apply.c b/builtin/apply.c
 >> index 725712d..1edd3f7 100644
 >> --- a/builtin/apply.c
 >> +++ b/builtin/apply.c
 >> @@ -919,7 +919,7 @@ static int gitdiff_hdrend(const char *line, struct patch *patch)
 >>   * their names against any previous information, just
 >>   * to make sure..
 >>   */
 >> -static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)
 >> +static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, int new)
 >>  {
 >
 > This change is unwarranted, though.  The callers were much clearer when
 > they passed "old" vs "new"; now they pass an unexplained 0 vs 1.

 Hmm.. how about this?

 builtin/apply.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 725712d..92ba925 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -933,8 +933,15 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
 		if (isnull)
 			die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), name, linenr);
 		another = find_name(line, NULL, p_value, TERM_TAB);
-		if (!another || memcmp(another, name, len + 1))
-			die(_("git apply: bad git-diff - inconsistent %s filename on line %d"), oldnew, linenr);
+		if (!another || memcmp(another, name, len + 1)) {
+			if (!strcmp(oldnew, "old"))
+				die(_("git apply: bad git-diff - inconsistent old filename on line %d"), linenr);
+			else if (!strcmp(oldnew, "new"))
+				die(_("git apply: bad git-diff - inconsistent new filename on line %d"), linenr);
+			else
+				die("BUG: please add a new full string for '%s' similar to above code.\n"
+				    "It makes translators' life much simpler. Thanks!", oldnew);
+		}
 		free(another);
 		return orig_name;
 	}
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH] apply: remove lego in i18n string in gitdiff_verify_name
  2012-05-08 13:38         ` Nguyễn Thái Ngọc Duy
@ 2012-05-08 17:07           ` Junio C Hamano
  2012-05-09 12:29             ` Nguyễn Thái Ngọc Duy
  0 siblings, 1 reply; 43+ messages in thread
From: Junio C Hamano @ 2012-05-08 17:07 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Junio C Hamano, Jonathan Niedier,
	Ævar Arnfjörð Bjarmason, Jiang Xin,
	Zbigniew Jędrzejewski-Szmek

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> Currently it marks the string "...inconsistent %s filename..." where
> %s is either "old" or "new" from caller. From a translator point of
> view, nothing hints what "%s" may be. Make it two strings
> "...inconsistent new filename..." and "...inconsistent old
> filename..."

True.  Also depending on 'old' vs 'new', the translation of "filename" or
other parts of the message may have to inflect/conjugate, so the original
message structure was very unfriendly to i18n.

> +		if (!another || memcmp(another, name, len + 1)) {
> +			if (!strcmp(oldnew, "old"))
> +				die(_("git apply: bad git-diff - inconsistent old filename on line %d"), linenr);
> +			else if (!strcmp(oldnew, "new"))
> +				die(_("git apply: bad git-diff - inconsistent new filename on line %d"), linenr);
> +			else
> +				die("BUG: please add a new full string for '%s' similar to above code.\n"
> +				    "It makes translators' life much simpler. Thanks!", oldnew);
> +		}

I think this is way over-engineered.  enum { DIFF_OLD = 0, DIFF_NEW = 1 }
or even passing 'n' vs 'o' was what I was expecting to see.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH] apply: remove lego in i18n string in gitdiff_verify_name
  2012-05-08 17:07           ` Junio C Hamano
@ 2012-05-09 12:29             ` Nguyễn Thái Ngọc Duy
  0 siblings, 0 replies; 43+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-05-09 12:29 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jonathan Niedier,
	Ævar Arnfjörð Bjarmason, Jiang Xin,
	Zbigniew Jędrzejewski-Szmek,
	Nguyễn Thái Ngọc Duy

Currently it marks the string "...inconsistent %s filename..." where
%s is either "old" or "new" from caller. From a translator point of
view, nothing hints what "%s" may be and what grammatical form it may
use.

Make it two strings "...inconsistent new filename..." and
"...inconsistent old filename..."

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Another try. enum this time.

 builtin/apply.c |   17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 725712d..3362f4a 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -910,6 +910,11 @@ static int gitdiff_hdrend(const char *line, struct patch *patch)
 	return -1;
 }
 
+enum diff_filename {
+	DIFF_OLD,
+	DIFF_NEW
+};
+
 /*
  * We're anal about diff header consistency, to make
  * sure that we don't end up having strange ambiguous
@@ -919,7 +924,8 @@ static int gitdiff_hdrend(const char *line, struct patch *patch)
  * their names against any previous information, just
  * to make sure..
  */
-static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)
+static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
+				 enum diff_filename oldnew)
 {
 	if (!orig_name && !isnull)
 		return find_name(line, NULL, p_value, TERM_TAB);
@@ -934,7 +940,10 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
 			die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), name, linenr);
 		another = find_name(line, NULL, p_value, TERM_TAB);
 		if (!another || memcmp(another, name, len + 1))
-			die(_("git apply: bad git-diff - inconsistent %s filename on line %d"), oldnew, linenr);
+			die(oldnew == DIFF_OLD ?
+			    _("git apply: bad git-diff - inconsistent old filename on line %d") :
+			    _("git apply: bad git-diff - inconsistent new filename on line %d"),
+			    linenr);
 		free(another);
 		return orig_name;
 	}
@@ -949,7 +958,7 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
 static int gitdiff_oldname(const char *line, struct patch *patch)
 {
 	char *orig = patch->old_name;
-	patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, "old");
+	patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, DIFF_OLD);
 	if (orig != patch->old_name)
 		free(orig);
 	return 0;
@@ -958,7 +967,7 @@ static int gitdiff_oldname(const char *line, struct patch *patch)
 static int gitdiff_newname(const char *line, struct patch *patch)
 {
 	char *orig = patch->new_name;
-	patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, "new");
+	patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, DIFF_NEW);
 	if (orig != patch->new_name)
 		free(orig);
 	return 0;
-- 
1.7.8.36.g69ee2

^ permalink raw reply related	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2012-05-09 12:33 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-23 12:30 [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Nguyễn Thái Ngọc Duy
2012-04-23 12:30 ` [PATCH 01/10] Makefile: feed all header files to xgettext Nguyễn Thái Ngọc Duy
2012-04-23 12:30 ` [PATCH 02/10] Add three convenient format printing functions with \n automatically appended Nguyễn Thái Ngọc Duy
2012-04-23 16:15   ` Jonathan Nieder
2012-04-23 12:30 ` [PATCH 03/10] i18n: mark relative dates for translation Nguyễn Thái Ngọc Duy
2012-04-24 20:04   ` Junio C Hamano
2012-04-25 10:46     ` Nguyen Thai Ngoc Duy
2012-04-25 11:07       ` Johannes Sixt
2012-04-25 11:25         ` Zbigniew Jędrzejewski-Szmek
2012-04-25 11:29         ` Nguyen Thai Ngoc Duy
2012-04-25 15:25       ` Jonathan Nieder
2012-04-25 16:27         ` Junio C Hamano
2012-04-25 17:26           ` Jonathan Nieder
2012-04-23 12:30 ` [PATCH 04/10] i18n: help: mark strings " Nguyễn Thái Ngọc Duy
2012-04-23 16:30   ` Jonathan Nieder
2012-04-23 18:18     ` Junio C Hamano
2012-04-23 18:34       ` Jonathan Nieder
2012-04-25 11:21         ` [PATCH] help: replace underlining "help -a" headers using hyphens with a blank line Nguyễn Thái Ngọc Duy
2012-04-25 17:30           ` Junio C Hamano
2012-04-23 12:30 ` [PATCH 05/10] i18n: make warn_dangling_symref() automatically append \n Nguyễn Thái Ngọc Duy
2012-04-23 12:30 ` [PATCH 06/10] i18n: remote: mark strings for translation Nguyễn Thái Ngọc Duy
2012-04-25 22:54   ` Junio C Hamano
2012-04-26  1:12     ` Nguyen Thai Ngoc Duy
2012-04-23 12:30 ` [PATCH 07/10] i18n: apply: " Nguyễn Thái Ngọc Duy
2012-04-25 22:50   ` Junio C Hamano
2012-05-06 13:13     ` [PATCH] apply: remove lego in i18n string in gitdiff_verify_name Nguyễn Thái Ngọc Duy
2012-05-07 18:00       ` Junio C Hamano
2012-05-08 13:38         ` Nguyễn Thái Ngọc Duy
2012-05-08 17:07           ` Junio C Hamano
2012-05-09 12:29             ` Nguyễn Thái Ngọc Duy
2012-04-23 12:30 ` [PATCH 08/10] i18n: apply: update say_patch_name to give translators complete sentence Nguyễn Thái Ngọc Duy
2012-04-23 12:30 ` [PATCH 09/10] i18n: index-pack: mark strings for translation Nguyễn Thái Ngọc Duy
2012-04-23 12:30 ` [PATCH 10/10] i18n: bundle: " Nguyễn Thái Ngọc Duy
2012-04-25 22:43   ` Junio C Hamano
2012-04-26  1:24     ` Nguyen Thai Ngoc Duy
2012-04-26  5:53       ` [PATCH] bundle: remove stray single-quote from error message Jonathan Nieder
2012-04-23 16:41 ` [PATCH 00/10] i18n relative dates, help, remote, apply, index-pack and bundle Jonathan Nieder
2012-04-23 18:56 ` Junio C Hamano
2012-04-23 20:06   ` Ævar Arnfjörð Bjarmason
2012-04-24 12:19 ` Nguyen Thai Ngoc Duy
2012-04-24 19:50   ` Junio C Hamano
2012-04-25 11:42     ` Nguyen Thai Ngoc Duy
2012-04-25 16:11       ` Jonathan Nieder

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.