git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/5] Add infrastructure for translating Git with gettext

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
May 29, 2010, 22:45 UTC
Message-ID
<1275173125-21010-2-git-send-email-avarab@gmail.com>
In-Reply-To
<1275173125-21010-1-git-send-email-avarab@gmail.com>
From: Jeff Epler <jepler@unpythonic.net>

Change the build process to use GNU's libintl if it's available. If not we define our own skeleton replacement functions which degrade gracefully to English.

Signed-off-by: Jeff Epler <jepler@unpythonic.net>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Makefile    |   26 ++++++++++++
 gettext.c   |   17 ++++++++
 gettext.h   |   15 +++++++
 git.c       |    3 +
 wt-status.c |  129 ++++++++++++++++++++++++++++++-----------------------------
 5 files changed, 126 insertions(+), 64 deletions(-)
 create mode 100644 gettext.c
 create mode 100644 gettext.h
diff --git a/Makefile b/Makefile
index d5d6565..7989121 100644
--- a/Makefile
+++ b/Makefile
@@ -297,6 +297,8 @@ RPMBUILD = rpmbuild
 TCL_PATH = tclsh
 TCLTK_PATH = wish
 PTHREAD_LIBS = -lpthread
+XGETTEXT = xgettext
+MSGFMT = msgfmt
 
 export TCL_PATH TCLTK_PATH
 
@@ -523,6 +525,7 @@ LIB_H += userdiff.h
 LIB_H += utf8.h
 LIB_H += xdiff-interface.h
 LIB_H += xdiff/xdiff.h
+LIB_H += gettext.h
 
 LIB_OBJS += abspath.o
 LIB_OBJS += advice.o
@@ -564,6 +567,7 @@ LIB_OBJS += entry.o
 LIB_OBJS += environment.o
 LIB_OBJS += exec_cmd.o
 LIB_OBJS += fsck.o
+LIB_OBJS += gettext.o
 LIB_OBJS += graph.o
 LIB_OBJS += grep.o
 LIB_OBJS += hash.o
@@ -1386,6 +1390,12 @@ ifdef USE_NED_ALLOCATOR
        COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
 endif
 
+ifdef NO_GETTEXT
+	COMPAT_CFLAGS += -DNO_GETTEXT
+else
+	LIBINTL = -lintl
+endif
+
 ifeq ($(TCLTK_PATH),)
 NO_TCLTK=NoThanks
 endif
@@ -1415,6 +1425,7 @@ ifndef V
 	QUIET_BUILT_IN = @echo '   ' BUILTIN $@;
 	QUIET_GEN      = @echo '   ' GEN $@;
 	QUIET_LNCP     = @echo '   ' LN/CP $@;
+	QUIET_MSGFMT   = @echo '   ' MSGFMT $@;
 	QUIET_SUBDIR0  = +@subdir=
 	QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
 			 $(MAKE) $(PRINT_DIR) -C $$subdir
@@ -1442,6 +1453,7 @@ gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
 template_dir_SQ = $(subst ','\'',$(template_dir))
 htmldir_SQ = $(subst ','\'',$(htmldir))
 prefix_SQ = $(subst ','\'',$(prefix))
+sharedir_SQ = $(subst ','\'',$(sharedir))
 
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
@@ -1868,6 +1880,17 @@ cscope:
 	$(RM) cscope*
 	$(FIND) . -name '*.[hcS]' -print | xargs cscope -b
 
+pot:
+	$(XGETTEXT) -k_ -o po/git.pot $(C_OBJ:o=c)
+
+POFILES := $(wildcard po/*.po)
+MOFILES := $(patsubst po/%.po,share/locale/%/LC_MESSAGES/git.mo,$(POFILES))
+MODIRS := $(patsubst po/%.po,share/locale/%/LC_MESSAGES/,$(POFILES))
+all:: $(MOFILES)
+share/locale/%/LC_MESSAGES/git.mo: po/%.po
+	@mkdir -p $(dir $@)
+	$(QUIET_MSGFMT)$(MSGFMT) -o $@ $<
+
 ### Detect prefix changes
 TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\
              $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
@@ -1980,6 +2003,9 @@ install: all
 	$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
 	$(INSTALL) -m 644 $(SCRIPT_LIB) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
 	$(INSTALL) $(install_bindir_programs) '$(DESTDIR_SQ)$(bindir_SQ)'
+	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sharedir_SQ)/locale'
+	(cd share && tar cf - locale) | \
+		(cd '$(DESTDIR_SQ)$(sharedir_SQ)' && umask 022 && tar xof -)
 	$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
 ifndef NO_PERL
 	$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
diff --git a/gettext.c b/gettext.c
new file mode 100644
index 0000000..aadce19
--- /dev/null
+++ b/gettext.c
@@ -0,0 +1,17 @@
+#ifdef NO_GETTEXT
+void git_setup_gettext() {}
+#else
+#include "exec_cmd.h"
+#include <libintl.h>
+#include <stdlib.h>
+
+void git_setup_gettext() {
+    const char *podir = system_path("share/locale");
+    if(!podir) return;
+    char *ret = bindtextdomain("git", podir);
+    free((void*)podir);
+    ret = setlocale(LC_MESSAGES, "");
+    ret = setlocale(LC_CTYPE, "");
+    ret = textdomain("git");
+}
+#endif
diff --git a/gettext.h b/gettext.h
new file mode 100644
index 0000000..8b221b4
--- /dev/null
+++ b/gettext.h
@@ -0,0 +1,15 @@
+#ifndef GETTEXT_H
+#define GETTEXT_H
+
+void git_setup_gettext();
+
+#ifdef NO_GETTEXT
+#define _(s) (s)
+#define N_(s) (s)
+#else
+#include <libintl.h>
+#define _(s) gettext(s)
+#define N_(s) (s)
+#endif
+
+#endif
diff --git a/git.c b/git.c
index 99f0363..d749eab 100644
--- a/git.c
+++ b/git.c
@@ -3,6 +3,7 @@
 #include "cache.h"
 #include "quote.h"
 #include "run-command.h"
+#include "gettext.h"
 
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
@@ -490,6 +491,8 @@ int main(int argc, const char **argv)
 	if (!cmd)
 		cmd = "git-help";
 
+	git_setup_gettext();
+
 	/*
 	 * "git-xxxx" is the same as "git xxxx", but we obviously:
 	 *
diff --git a/wt-status.c b/wt-status.c
index 14e0acc..70b4293 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -9,6 +9,7 @@
 #include "quote.h"
 #include "run-command.h"
 #include "remote.h"
+#include "gettext.h"
 
 static char default_wt_status_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -49,33 +50,33 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
 {
 	const char *c = color(WT_STATUS_HEADER, s);
 
-	color_fprintf_ln(s->fp, c, "# Unmerged paths:");
+	color_fprintf_ln(s->fp, c, _("# Unmerged paths:"));
 	if (!advice_status_hints)
 		return;
 	if (s->in_merge)
 		;
 	else if (!s->is_initial)
-		color_fprintf_ln(s->fp, c, "#   (use \"git reset %s <file>...\" to unstage)", s->reference);
+		color_fprintf_ln(s->fp, c, _("#   (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
-		color_fprintf_ln(s->fp, c, "#   (use \"git rm --cached <file>...\" to unstage)");
-	color_fprintf_ln(s->fp, c, "#   (use \"git add/rm <file>...\" as appropriate to mark resolution)");
-	color_fprintf_ln(s->fp, c, "#");
+		color_fprintf_ln(s->fp, c, _("#   (use \"git rm --cached <file>...\" to unstage)"));
+	color_fprintf_ln(s->fp, c, _("#   (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
+	color_fprintf_ln(s->fp, c, _("#"));
 }
 
 static void wt_status_print_cached_header(struct wt_status *s)
 {
 	const char *c = color(WT_STATUS_HEADER, s);
 
-	color_fprintf_ln(s->fp, c, "# Changes to be committed:");
+	color_fprintf_ln(s->fp, c, _("# Changes to be committed:"));
 	if (!advice_status_hints)
 		return;
 	if (s->in_merge)
 		; /* NEEDSWORK: use "git reset --unresolve"??? */
 	else if (!s->is_initial)
-		color_fprintf_ln(s->fp, c, "#   (use \"git reset %s <file>...\" to unstage)", s->reference);
+		color_fprintf_ln(s->fp, c, _("#   (use \"git reset %s <file>...\" to unstage)"), s->reference);
 	else
-		color_fprintf_ln(s->fp, c, "#   (use \"git rm --cached <file>...\" to unstage)");
-	color_fprintf_ln(s->fp, c, "#");
+		color_fprintf_ln(s->fp, c, _("#   (use \"git rm --cached <file>...\" to unstage)"));
+	color_fprintf_ln(s->fp, c, _("#"));
 }
 
 static void wt_status_print_dirty_header(struct wt_status *s,
@@ -84,17 +85,17 @@ static void wt_status_print_dirty_header(struct wt_status *s,
 {
 	const char *c = color(WT_STATUS_HEADER, s);
 
-	color_fprintf_ln(s->fp, c, "# Changed but not updated:");
+	color_fprintf_ln(s->fp, c, _("# Changed but not updated:"));
 	if (!advice_status_hints)
 		return;
 	if (!has_deleted)
-		color_fprintf_ln(s->fp, c, "#   (use \"git add <file>...\" to update what will be committed)");
+		color_fprintf_ln(s->fp, c, _("#   (use \"git add <file>...\" to update what will be committed)"));
 	else
-		color_fprintf_ln(s->fp, c, "#   (use \"git add/rm <file>...\" to update what will be committed)");
-	color_fprintf_ln(s->fp, c, "#   (use \"git checkout -- <file>...\" to discard changes in working directory)");
+		color_fprintf_ln(s->fp, c, _("#   (use \"git add/rm <file>...\" to update what will be committed)"));
+	color_fprintf_ln(s->fp, c, _("#   (use \"git checkout -- <file>...\" to discard changes in working directory)"));
 	if (has_dirty_submodules)
-		color_fprintf_ln(s->fp, c, "#   (commit or discard the untracked or modified content in submodules)");
-	color_fprintf_ln(s->fp, c, "#");
+		color_fprintf_ln(s->fp, c, _("#   (commit or discard the untracked or modified content in submodules)"));
+	color_fprintf_ln(s->fp, c, _("#"));
 }
 
 static void wt_status_print_other_header(struct wt_status *s,
@@ -102,16 +103,16 @@ static void wt_status_print_other_header(struct wt_status *s,
 					 const char *how)
 {
 	const char *c = color(WT_STATUS_HEADER, s);
-	color_fprintf_ln(s->fp, c, "# %s files:", what);
+	color_fprintf_ln(s->fp, c, _("# %s files:"), what);
 	if (!advice_status_hints)
 		return;
-	color_fprintf_ln(s->fp, c, "#   (use \"git %s <file>...\" to include in what will be committed)", how);
-	color_fprintf_ln(s->fp, c, "#");
+	color_fprintf_ln(s->fp, c, _("#   (use \"git %s <file>...\" to include in what will be committed)"), how);
+	color_fprintf_ln(s->fp, c, _("#"));
 }
 
 static void wt_status_print_trailer(struct wt_status *s)
 {
-	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
+	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), _("#"));
 }
 
 #define quote_path quote_path_relative
@@ -122,20 +123,20 @@ static void wt_status_print_unmerged_data(struct wt_status *s,
 	const char *c = color(WT_STATUS_UNMERGED, s);
 	struct wt_status_change_data *d = it->util;
 	struct strbuf onebuf = STRBUF_INIT;
-	const char *one, *how = "bug";
+	const char *one, *how = _("bug");
 
 	one = quote_path(it->string, -1, &onebuf, s->prefix);
-	color_fprintf(s->fp, color(WT_STATUS_HEADER, s), "#\t");
+	color_fprintf(s->fp, color(WT_STATUS_HEADER, s), _("#\t"));
 	switch (d->stagemask) {
-	case 1: how = "both deleted:"; break;
-	case 2: how = "added by us:"; break;
-	case 3: how = "deleted by them:"; break;
-	case 4: how = "added by them:"; break;
-	case 5: how = "deleted by us:"; break;
-	case 6: how = "both added:"; break;
-	case 7: how = "both modified:"; break;
+	case 1: how = _("both deleted:"); break;
+	case 2: how = _("added by us:"); break;
+	case 3: how = _("deleted by them:"); break;
+	case 4: how = _("added by them:"); break;
+	case 5: how = _("deleted by us:"); break;
+	case 6: how = _("both added:"); break;
+	case 7: how = _("both modified:"); break;
 	}
-	color_fprintf(s->fp, c, "%-20s%s\n", how, one);
+	color_fprintf(s->fp, c, _("%-20s%s\n"), how, one);
 	strbuf_release(&onebuf);
 }
 
@@ -161,13 +162,13 @@ static void wt_status_print_change_data(struct wt_status *s,
 		break;
 	case WT_STATUS_CHANGED:
 		if (d->new_submodule_commits || d->dirty_submodule) {
-			strbuf_addstr(&extra, " (");
+			strbuf_addstr(&extra, _(" ("));
 			if (d->new_submodule_commits)
-				strbuf_addf(&extra, "new commits, ");
+				strbuf_addf(&extra, _("new commits, "));
 			if (d->dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
-				strbuf_addf(&extra, "modified content, ");
+				strbuf_addf(&extra, _("modified content, "));
 			if (d->dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
-				strbuf_addf(&extra, "untracked content, ");
+				strbuf_addf(&extra, _("untracked content, "));
 			strbuf_setlen(&extra, extra.len - 2);
 			strbuf_addch(&extra, ')');
 		}
@@ -178,40 +179,40 @@ static void wt_status_print_change_data(struct wt_status *s,
 	one = quote_path(one_name, -1, &onebuf, s->prefix);
 	two = quote_path(two_name, -1, &twobuf, s->prefix);
 
-	color_fprintf(s->fp, color(WT_STATUS_HEADER, s), "#\t");
+	color_fprintf(s->fp, color(WT_STATUS_HEADER, s), _("#\t"));
 	switch (status) {
 	case DIFF_STATUS_ADDED:
-		color_fprintf(s->fp, c, "new file:   %s", one);
+		color_fprintf(s->fp, c, _("new file:   %s"), one);
 		break;
 	case DIFF_STATUS_COPIED:
-		color_fprintf(s->fp, c, "copied:     %s -> %s", one, two);
+		color_fprintf(s->fp, c, _("copied:     %s -> %s"), one, two);
 		break;
 	case DIFF_STATUS_DELETED:
-		color_fprintf(s->fp, c, "deleted:    %s", one);
+		color_fprintf(s->fp, c, _("deleted:    %s"), one);
 		break;
 	case DIFF_STATUS_MODIFIED:
-		color_fprintf(s->fp, c, "modified:   %s", one);
+		color_fprintf(s->fp, c, _("modified:   %s"), one);
 		break;
 	case DIFF_STATUS_RENAMED:
-		color_fprintf(s->fp, c, "renamed:    %s -> %s", one, two);
+		color_fprintf(s->fp, c, _("renamed:    %s -> %s"), one, two);
 		break;
 	case DIFF_STATUS_TYPE_CHANGED:
-		color_fprintf(s->fp, c, "typechange: %s", one);
+		color_fprintf(s->fp, c, _("typechange: %s"), one);
 		break;
 	case DIFF_STATUS_UNKNOWN:
-		color_fprintf(s->fp, c, "unknown:    %s", one);
+		color_fprintf(s->fp, c, _("unknown:    %s"), one);
 		break;
 	case DIFF_STATUS_UNMERGED:
-		color_fprintf(s->fp, c, "unmerged:   %s", one);
+		color_fprintf(s->fp, c, _("unmerged:   %s"), one);
 		break;
 	default:
-		die("bug: unhandled diff status %c", status);
+		die(_("bug: unhandled diff status %c"), status);
 	}
 	if (extra.len) {
-		color_fprintf(s->fp, color(WT_STATUS_HEADER, s), "%s", extra.buf);
+		color_fprintf(s->fp, color(WT_STATUS_HEADER, s), _("%s"), extra.buf);
 		strbuf_release(&extra);
 	}
-	fprintf(s->fp, "\n");
+	fprintf(s->fp, _("\n"));
 	strbuf_release(&onebuf);
 	strbuf_release(&twobuf);
 }
@@ -618,14 +619,14 @@ void wt_status_print(struct wt_status *s)
 	const char *branch_color = color(WT_STATUS_HEADER, s);
 
 	if (s->branch) {
-		const char *on_what = "On branch ";
+		const char *on_what = _("On branch ");
 		const char *branch_name = s->branch;
 		if (!prefixcmp(branch_name, "refs/heads/"))
 			branch_name += 11;
 		else if (!strcmp(branch_name, "HEAD")) {
 			branch_name = "";
 			branch_color = color(WT_STATUS_NOBRANCH, s);
-			on_what = "Not currently on any branch.";
+			on_what = _("Not currently on any branch.");
 		}
 		color_fprintf(s->fp, color(WT_STATUS_HEADER, s), "# ");
 		color_fprintf_ln(s->fp, branch_color, "%s%s", on_what, branch_name);
@@ -634,9 +635,9 @@ void wt_status_print(struct wt_status *s)
 	}
 
 	if (s->is_initial) {
-		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
-		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "# Initial commit");
-		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
+		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), _("#"));
+		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), _("# Initial commit"));
+		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), _("#"));
 	}
 
 	wt_status_print_updated(s);
@@ -647,38 +648,38 @@ void wt_status_print(struct wt_status *s)
 		wt_status_print_submodule_summary(s, 1);  /* unstaged */
 	}
 	if (s->show_untracked_files) {
-		wt_status_print_other(s, &s->untracked, "Untracked", "add");
+		wt_status_print_other(s, &s->untracked, _("Untracked"), _("add"));
 		if (s->show_ignored_files)
-			wt_status_print_other(s, &s->ignored, "Ignored", "add -f");
+			wt_status_print_other(s, &s->ignored, _("Ignored"), _("add -f"));
 	} else if (s->commitable)
-		fprintf(s->fp, "# Untracked files not listed%s\n",
+		fprintf(s->fp, _("# Untracked files not listed%s\n"),
 			advice_status_hints
-			? " (use -u option to show untracked files)" : "");
+			? _(" (use -u option to show untracked files)") : "");
 
 	if (s->verbose)
 		wt_status_print_verbose(s);
 	if (!s->commitable) {
 		if (s->amend)
-			fprintf(s->fp, "# No changes\n");
+			fprintf(s->fp, _("# No changes\n"));
 		else if (s->nowarn)
 			; /* nothing */
 		else if (s->workdir_dirty)
-			printf("no changes added to commit%s\n",
+			printf(_("no changes added to commit%s\n"),
 				advice_status_hints
-				? " (use \"git add\" and/or \"git commit -a\")" : "");
+				? _(" (use \"git add\" and/or \"git commit -a\")") : "");
 		else if (s->untracked.nr)
-			printf("nothing added to commit but untracked files present%s\n",
+			printf(_("nothing added to commit but untracked files present%s\n"),
 				advice_status_hints
-				? " (use \"git add\" to track)" : "");
+				? _(" (use \"git add\" to track)") : "");
 		else if (s->is_initial)
 			printf("nothing to commit%s\n", advice_status_hints
-				? " (create/copy files and use \"git add\" to track)" : "");
+				? _(" (create/copy files and use \"git add\" to track)") : "");
 		else if (!s->show_untracked_files)
-			printf("nothing to commit%s\n", advice_status_hints
-				? " (use -u to show untracked files)" : "");
+			printf(_("nothing to commit%s\n"), advice_status_hints
+				? _(" (use -u to show untracked files)") : "");
 		else
-			printf("nothing to commit%s\n", advice_status_hints
-				? " (working directory clean)" : "");
+			printf(_("nothing to commit%s\n"), advice_status_hints
+				? _(" (working directory clean)") : "");
 	}
 }
 
-- 
1.7.1.242.ge2b63.dirty
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 2 of 56 in “Add internationalization support to Git”
  1. 0/5 Add internationalization support to GitÆvar Arnfjörð Bjarmason, May 29, 2010
  2. 1/5 Add infrastructure for translating Git with gettextÆvar Arnfjörð Bjarmason, May 29, 2010
  3. 2/5 gitignore: Ignore files generated by gettextÆvar Arnfjörð Bjarmason, May 29, 2010
  4. 3/5 Makefile: Remove Gettext files on make cleanÆvar Arnfjörð Bjarmason, May 29, 2010
  5. 4/5 gettext: Add a skeleton po/is.poÆvar Arnfjörð Bjarmason, May 29, 2010
  6. 5/5 Add infrastructure to make shellscripts translatableÆvar Arnfjörð Bjarmason, May 29, 2010
  7. Jonathan NiederMay 30, 2010
  8. Ævar Arnfjörð BjarmasonMay 30, 2010
  9. Jonathan NiederMay 30, 2010
  10. Ævar Arnfjörð BjarmasonMay 31, 2010
  11. 0/6 Add internationalization support to GitÆvar Arnfjörð Bjarmason, May 30, 2010
  12. 1/6 Add infrastructure for translating Git with gettextÆvar Arnfjörð Bjarmason, May 30, 2010
  13. Jakub NarebskiJun 1, 2010
  14. autoconf: Check if <libintl.h> exists and set NO_GETTEXTÆvar Arnfjörð Bjarmason, Jun 1, 2010
  15. Jakub NarebskiJun 1, 2010
  16. 2/6 gitignore: Ignore files generated by gettextÆvar Arnfjörð Bjarmason, May 30, 2010
  17. 3/6 Makefile: Remove Gettext files on make cleanÆvar Arnfjörð Bjarmason, May 30, 2010
  18. 4/6 gettext: Add a Gettext interface for shell scriptsÆvar Arnfjörð Bjarmason, May 30, 2010
  19. 5/6 gettext: Add a Gettext interface for PerlÆvar Arnfjörð Bjarmason, May 30, 2010
  20. Jakub NarebskiJun 1, 2010
  21. Ævar Arnfjörð BjarmasonJun 1, 2010
  22. Jakub NarebskiJun 2, 2010
  23. 6/6 gettext: Add a skeleton po/is.poÆvar Arnfjörð Bjarmason, May 30, 2010
  24. Jonathan NiederMay 30, 2010
  25. Jonathan NiederMay 30, 2010
  26. Ævar Arnfjörð BjarmasonMay 31, 2010
  27. 0/7 Add internationalization support to GitÆvar Arnfjörð Bjarmason, Jun 1, 2010
  28. Ævar Arnfjörð BjarmasonJun 2, 2010
  29. 0/7 Add internationalization support to GitÆvar Arnfjörð Bjarmason, Jun 2, 2010
  30. 1/7 Add infrastructure for translating Git with gettextÆvar Arnfjörð Bjarmason, Jun 2, 2010
  31. Peter KreftingJun 2, 2010
  32. Ævar Arnfjörð BjarmasonJun 2, 2010
  33. Peter KreftingJun 2, 2010
  34. Ævar Arnfjörð BjarmasonJun 2, 2010
  35. Peter KreftingJun 2, 2010
  36. 2/7 gettext: Add a Gettext interface for shell scriptsÆvar Arnfjörð Bjarmason, Jun 2, 2010
  37. 3/7 gettext: Add a Gettext interface for PerlÆvar Arnfjörð Bjarmason, Jun 2, 2010
  38. 4/7 Makefile: Don't install Gettext .mo files if NO_GETTEXTÆvar Arnfjörð Bjarmason, Jun 2, 2010
  39. 5/7 Makefile: Override --keyword= for all languagesÆvar Arnfjörð Bjarmason, Jun 2, 2010
  40. 6/7 gettext: Sanity tests for Git's Gettext supportÆvar Arnfjörð Bjarmason, Jun 2, 2010
  41. 7/7 gettext: Add a skeleton po/is.poÆvar Arnfjörð Bjarmason, Jun 2, 2010
  42. Johannes SixtJun 2, 2010
  43. 0/2 Add infrastructure for translating Git with gettextÆvar Arnfjörð Bjarmason, Jun 2, 2010
  44. 1/2 Add infrastructure for translating Git with gettextÆvar Arnfjörð Bjarmason, Jun 2, 2010
  45. 2/2 Add initial C, Shell and Perl gettext translationsÆvar Arnfjörð Bjarmason, Jun 2, 2010
  46. 1/7 Add infrastructure for translating Git with gettextÆvar Arnfjörð Bjarmason, Jun 1, 2010
  47. 2/7 gettext: Add a Gettext interface for shell scriptsÆvar Arnfjörð Bjarmason, Jun 1, 2010
  48. Johannes SixtJun 2, 2010
  49. Ævar Arnfjörð BjarmasonJun 2, 2010
  50. Johannes SixtJun 2, 2010
  51. 3/7 gettext: Add a Gettext interface for PerlÆvar Arnfjörð Bjarmason, Jun 1, 2010
  52. 4/7 Makefile: Don't install Gettext .mo files if NO_GETTEXTÆvar Arnfjörð Bjarmason, Jun 1, 2010
  53. 5/7 Makefile: Override --keyword= for all languagesÆvar Arnfjörð Bjarmason, Jun 1, 2010
  54. 6/7 gettext: Basic sanity tests for Git's Gettext supportÆvar Arnfjörð Bjarmason, Jun 1, 2010
  55. Johannes SixtJun 2, 2010
  56. 7/7 gettext: Add a skeleton po/is.poÆvar Arnfjörð Bjarmason, Jun 1, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.