Merge branch 'ab/enable-i18n'
* ab/enable-i18n: i18n: add infrastructure for translating Git with gettext Conflicts: Makefile
This commit is contained in:
commit
2dccad3c6f
@ -81,6 +81,10 @@ For shell scripts specifically (not exhaustive):
|
||||
are ERE elements not BRE (note that \? and \+ are not even part
|
||||
of BRE -- making them accessible from BRE is a GNU extension).
|
||||
|
||||
- Use Git's gettext wrappers in git-sh-i18n to make the user
|
||||
interface translatable. See "Marking strings for translation" in
|
||||
po/README.
|
||||
|
||||
For C programs:
|
||||
|
||||
- We use tabs to indent, and interpret tabs as taking up to
|
||||
@ -144,6 +148,9 @@ For C programs:
|
||||
- When we pass <string, length> pair to functions, we should try to
|
||||
pass them in that order.
|
||||
|
||||
- Use Git's gettext wrappers to make the user interface
|
||||
translatable. See "Marking strings for translation" in po/README.
|
||||
|
||||
Writing Documentation:
|
||||
|
||||
Every user-visible change should be reflected in the documentation.
|
||||
|
12
INSTALL
12
INSTALL
@ -106,6 +106,18 @@ Issues of note:
|
||||
history graphically, and in git-gui. If you don't want gitk or
|
||||
git-gui, you can use NO_TCLTK.
|
||||
|
||||
- A gettext library is used by default for localizing Git. The
|
||||
primary target is GNU libintl, but the Solaris gettext
|
||||
implementation also works.
|
||||
|
||||
We need a gettext.h on the system for C code, gettext.sh (or
|
||||
Solaris gettext(1)) for shell scripts, and libintl-perl for Perl
|
||||
programs.
|
||||
|
||||
Set NO_GETTEXT to disable localization support and make Git only
|
||||
use English. Under autoconf the configure script will do this
|
||||
automatically if it can't find libintl on the system.
|
||||
|
||||
- Some platform specific issues are dealt with Makefile rules,
|
||||
but depending on your specific installation, you may not
|
||||
have all the libraries/tools needed, or you may have
|
||||
|
81
Makefile
81
Makefile
@ -43,6 +43,22 @@ all::
|
||||
# Define EXPATDIR=/foo/bar if your expat header and library files are in
|
||||
# /foo/bar/include and /foo/bar/lib directories.
|
||||
#
|
||||
# Define NO_GETTEXT if you don't want Git output to be translated.
|
||||
# A translated Git requires GNU libintl or another gettext implementation,
|
||||
# plus libintl-perl at runtime.
|
||||
#
|
||||
# Define HAVE_LIBCHARSET_H if you haven't set NO_GETTEXT and you can't
|
||||
# trust the langinfo.h's nl_langinfo(CODESET) function to return the
|
||||
# current character set. GNU and Solaris have a nl_langinfo(CODESET),
|
||||
# FreeBSD can use either, but MinGW and some others need to use
|
||||
# libcharset.h's locale_charset() instead.
|
||||
#
|
||||
# Define LIBC_CONTAINS_LIBINTL if your gettext implementation doesn't
|
||||
# need -lintl when linking.
|
||||
#
|
||||
# Define NO_MSGFMT_EXTENDED_OPTIONS if your implementation of msgfmt
|
||||
# doesn't support GNU extensions like --check and --statistics
|
||||
#
|
||||
# Define HAVE_PATHS_H if you have paths.h and want to use the default PATH
|
||||
# it specifies.
|
||||
#
|
||||
@ -309,6 +325,7 @@ gitexecdir = libexec/git-core
|
||||
mergetoolsdir = $(gitexecdir)/mergetools
|
||||
sharedir = $(prefix)/share
|
||||
gitwebdir = $(sharedir)/gitweb
|
||||
localedir = $(sharedir)/locale
|
||||
template_dir = share/git-core/templates
|
||||
htmldir = share/doc/git-doc
|
||||
ETC_GITCONFIG = $(sysconfdir)/gitconfig
|
||||
@ -317,7 +334,7 @@ lib = lib
|
||||
# DESTDIR=
|
||||
pathsep = :
|
||||
|
||||
export prefix bindir sharedir sysconfdir gitwebdir
|
||||
export prefix bindir sharedir sysconfdir gitwebdir localedir
|
||||
|
||||
CC = gcc
|
||||
AR = ar
|
||||
@ -330,6 +347,7 @@ RPMBUILD = rpmbuild
|
||||
TCL_PATH = tclsh
|
||||
TCLTK_PATH = wish
|
||||
XGETTEXT = xgettext
|
||||
MSGFMT = msgfmt
|
||||
PTHREAD_LIBS = -lpthread
|
||||
PTHREAD_CFLAGS =
|
||||
GCOV = gcov
|
||||
@ -640,6 +658,7 @@ LIB_OBJS += environment.o
|
||||
LIB_OBJS += exec_cmd.o
|
||||
LIB_OBJS += fsck.o
|
||||
LIB_OBJS += gpg-interface.o
|
||||
LIB_OBJS += gettext.o
|
||||
LIB_OBJS += graph.o
|
||||
LIB_OBJS += grep.o
|
||||
LIB_OBJS += hash.o
|
||||
@ -836,12 +855,14 @@ ifeq ($(uname_S),Linux)
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
HAVE_PATHS_H = YesPlease
|
||||
LIBC_CONTAINS_LIBINTL = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),GNU/kFreeBSD)
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
HAVE_PATHS_H = YesPlease
|
||||
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
|
||||
LIBC_CONTAINS_LIBINTL = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),UnixWare)
|
||||
CC = cc
|
||||
@ -908,6 +929,7 @@ ifeq ($(uname_S),SunOS)
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_REGEX = YesPlease
|
||||
NO_FNMATCH_CASEFOLD = YesPlease
|
||||
NO_MSGFMT_EXTENDED_OPTIONS = YesPlease
|
||||
ifeq ($(uname_R),5.6)
|
||||
SOCKLEN_T = int
|
||||
NO_HSTRERROR = YesPlease
|
||||
@ -1031,6 +1053,7 @@ ifeq ($(uname_S),GNU)
|
||||
NO_STRLCPY=YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
HAVE_PATHS_H = YesPlease
|
||||
LIBC_CONTAINS_LIBINTL = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),IRIX)
|
||||
NO_SETENV = YesPlease
|
||||
@ -1249,6 +1272,7 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
|
||||
EXTLIBS += /mingw/lib/libz.a
|
||||
NO_R_TO_GCC_LINKER = YesPlease
|
||||
INTERNAL_QSORT = YesPlease
|
||||
HAVE_LIBCHARSET_H = YesPlease
|
||||
else
|
||||
NO_CURL = YesPlease
|
||||
endif
|
||||
@ -1437,6 +1461,11 @@ endif
|
||||
ifdef NEEDS_LIBGEN
|
||||
EXTLIBS += -lgen
|
||||
endif
|
||||
ifndef NO_GETTEXT
|
||||
ifndef LIBC_CONTAINS_LIBINTL
|
||||
EXTLIBS += -lintl
|
||||
endif
|
||||
endif
|
||||
ifdef NEEDS_SOCKET
|
||||
EXTLIBS += -lsocket
|
||||
endif
|
||||
@ -1479,9 +1508,11 @@ ifdef NO_SYMLINK_HEAD
|
||||
BASIC_CFLAGS += -DNO_SYMLINK_HEAD
|
||||
endif
|
||||
ifdef GETTEXT_POISON
|
||||
LIB_OBJS += gettext.o
|
||||
BASIC_CFLAGS += -DGETTEXT_POISON
|
||||
endif
|
||||
ifdef NO_GETTEXT
|
||||
BASIC_CFLAGS += -DNO_GETTEXT
|
||||
endif
|
||||
ifdef NO_STRCASESTR
|
||||
COMPAT_CFLAGS += -DNO_STRCASESTR
|
||||
COMPAT_OBJS += compat/strcasestr.o
|
||||
@ -1650,6 +1681,10 @@ ifdef HAVE_PATHS_H
|
||||
BASIC_CFLAGS += -DHAVE_PATHS_H
|
||||
endif
|
||||
|
||||
ifdef HAVE_LIBCHARSET_H
|
||||
BASIC_CFLAGS += -DHAVE_LIBCHARSET_H
|
||||
endif
|
||||
|
||||
ifdef DIR_HAS_BSD_GROUP_SEMANTICS
|
||||
COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
|
||||
endif
|
||||
@ -1670,6 +1705,10 @@ ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
|
||||
export GIT_TEST_CMP_USE_COPIED_CONTEXT
|
||||
endif
|
||||
|
||||
ifndef NO_MSGFMT_EXTENDED_OPTIONS
|
||||
MSGFMT += --check --statistics
|
||||
endif
|
||||
|
||||
ifeq ($(TCLTK_PATH),)
|
||||
NO_TCLTK=NoThanks
|
||||
endif
|
||||
@ -1700,6 +1739,7 @@ ifndef V
|
||||
QUIET_GEN = @echo ' ' GEN $@;
|
||||
QUIET_LNCP = @echo ' ' LN/CP $@;
|
||||
QUIET_XGETTEXT = @echo ' ' XGETTEXT $@;
|
||||
QUIET_MSGFMT = @echo ' ' MSGFMT $@;
|
||||
QUIET_GCOV = @echo ' ' GCOV $@;
|
||||
QUIET_SP = @echo ' ' SP $<;
|
||||
QUIET_SUBDIR0 = +@subdir=
|
||||
@ -1726,6 +1766,7 @@ bindir_SQ = $(subst ','\'',$(bindir))
|
||||
bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
|
||||
mandir_SQ = $(subst ','\'',$(mandir))
|
||||
infodir_SQ = $(subst ','\'',$(infodir))
|
||||
localedir_SQ = $(subst ','\'',$(localedir))
|
||||
gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
|
||||
template_dir_SQ = $(subst ','\'',$(template_dir))
|
||||
htmldir_SQ = $(subst ','\'',$(htmldir))
|
||||
@ -1781,7 +1822,7 @@ ifndef NO_TCLTK
|
||||
$(QUIET_SUBDIR0)gitk-git $(QUIET_SUBDIR1) all
|
||||
endif
|
||||
ifndef NO_PERL
|
||||
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
|
||||
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' localedir='$(localedir_SQ)' all
|
||||
endif
|
||||
ifndef NO_PYTHON
|
||||
$(QUIET_SUBDIR0)git_remote_helpers $(QUIET_SUBDIR1) PYTHON_PATH='$(PYTHON_PATH_SQ)' prefix='$(prefix_SQ)' all
|
||||
@ -1831,6 +1872,7 @@ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
|
||||
-e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
|
||||
-e 's|@@DIFF@@|$(DIFF_SQ)|' \
|
||||
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
||||
-e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' \
|
||||
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
|
||||
-e $(BROKEN_PATH_FIX) \
|
||||
$@.sh >$@+
|
||||
@ -2083,6 +2125,9 @@ config.sp config.s config.o: EXTRA_CPPFLAGS = \
|
||||
attr.sp attr.s attr.o: EXTRA_CPPFLAGS = \
|
||||
-DETC_GITATTRIBUTES='"$(ETC_GITATTRIBUTES_SQ)"'
|
||||
|
||||
gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \
|
||||
-DGIT_LOCALE_PATH='"$(localedir_SQ)"'
|
||||
|
||||
http.sp http.s http.o: EXTRA_CPPFLAGS = \
|
||||
-DGIT_HTTP_USER_AGENT='"git/$(GIT_VERSION)"'
|
||||
|
||||
@ -2156,17 +2201,37 @@ XGETTEXT_FLAGS = \
|
||||
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_SH := $(SCRIPT_SH)
|
||||
LOCALIZED_PERL := $(SCRIPT_PERL)
|
||||
|
||||
ifdef XGETTEXT_INCLUDE_TESTS
|
||||
LOCALIZED_C += t/t0200/test.c
|
||||
LOCALIZED_SH += t/t0200/test.sh
|
||||
LOCALIZED_PERL += t/t0200/test.perl
|
||||
endif
|
||||
|
||||
po/git.pot: $(LOCALIZED_C)
|
||||
$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ $(XGETTEXT_FLAGS_C) $(LOCALIZED_C)
|
||||
$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_SH) \
|
||||
$(LOCALIZED_SH)
|
||||
$(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_PERL) \
|
||||
$(LOCALIZED_PERL)
|
||||
mv $@+ $@
|
||||
|
||||
pot: po/git.pot
|
||||
|
||||
POFILES := $(wildcard po/*.po)
|
||||
MOFILES := $(patsubst po/%.po,po/build/locale/%/LC_MESSAGES/git.mo,$(POFILES))
|
||||
|
||||
ifndef NO_GETTEXT
|
||||
all:: $(MOFILES)
|
||||
endif
|
||||
|
||||
po/build/locale/%/LC_MESSAGES/git.mo: po/%.po
|
||||
$(QUIET_MSGFMT)mkdir -p $(dir $@) && $(MSGFMT) -o $@ $<
|
||||
|
||||
FIND_SOURCE_FILES = ( git ls-files '*.[hcS]' 2>/dev/null || \
|
||||
$(FIND) . \( -name .git -type d -prune \) \
|
||||
-o \( -name '*.[hcS]' -type f -print \) )
|
||||
@ -2185,7 +2250,8 @@ cscope:
|
||||
|
||||
### Detect prefix changes
|
||||
TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):\
|
||||
$(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
|
||||
$(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
|
||||
$(localedir_SQ)
|
||||
|
||||
GIT-CFLAGS: FORCE
|
||||
@FLAGS='$(TRACK_CFLAGS)'; \
|
||||
@ -2222,6 +2288,7 @@ endif
|
||||
ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
|
||||
@echo GIT_TEST_CMP_USE_COPIED_CONTEXT=YesPlease >>$@
|
||||
endif
|
||||
@echo NO_GETTEXT=\''$(subst ','\'',$(subst ','\'',$(NO_GETTEXT)))'\' >>$@
|
||||
@echo GETTEXT_POISON=\''$(subst ','\'',$(subst ','\'',$(GETTEXT_POISON)))'\' >>$@
|
||||
@echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@
|
||||
|
||||
@ -2338,6 +2405,11 @@ install: all
|
||||
$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
|
||||
$(INSTALL) -m 644 mergetools/* '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
|
||||
ifndef NO_GETTEXT
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(localedir_SQ)'
|
||||
(cd po/build/locale && $(TAR) cf - .) | \
|
||||
(cd '$(DESTDIR_SQ)$(localedir_SQ)' && umask 022 && $(TAR) xof -)
|
||||
endif
|
||||
ifndef NO_PERL
|
||||
$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
|
||||
$(MAKE) -C gitweb install
|
||||
@ -2474,6 +2546,7 @@ clean:
|
||||
$(RM) $(TEST_PROGRAMS)
|
||||
$(RM) -r bin-wrappers
|
||||
$(RM) -r $(dep_dirs)
|
||||
$(RM) -r po/build/
|
||||
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h $(ETAGS_TARGET) tags cscope*
|
||||
$(RM) -r autom4te.cache
|
||||
$(RM) config.log config.mak.autogen config.mak.append config.status config.cache
|
||||
|
@ -35,6 +35,9 @@ NO_CURL=@NO_CURL@
|
||||
NO_EXPAT=@NO_EXPAT@
|
||||
NO_LIBGEN_H=@NO_LIBGEN_H@
|
||||
HAVE_PATHS_H=@HAVE_PATHS_H@
|
||||
HAVE_LIBCHARSET_H=@HAVE_LIBCHARSET_H@
|
||||
NO_GETTEXT=@NO_GETTEXT@
|
||||
LIBC_CONTAINS_LIBINTL=@LIBC_CONTAINS_LIBINTL@
|
||||
NEEDS_LIBICONV=@NEEDS_LIBICONV@
|
||||
NEEDS_SOCKET=@NEEDS_SOCKET@
|
||||
NEEDS_RESOLV=@NEEDS_RESOLV@
|
||||
|
19
configure.ac
19
configure.ac
@ -636,6 +636,12 @@ AC_CHECK_LIB([c], [basename],
|
||||
AC_SUBST(NEEDS_LIBGEN)
|
||||
test -n "$NEEDS_LIBGEN" && LIBS="$LIBS -lgen"
|
||||
|
||||
AC_CHECK_LIB([c], [gettext],
|
||||
[LIBC_CONTAINS_LIBINTL=YesPlease],
|
||||
[LIBC_CONTAINS_LIBINTL=])
|
||||
AC_SUBST(LIBC_CONTAINS_LIBINTL)
|
||||
test -n "$LIBC_CONTAINS_LIBINTL" || LIBS="$LIBS -lintl"
|
||||
|
||||
## Checks for header files.
|
||||
AC_MSG_NOTICE([CHECKS for header files])
|
||||
#
|
||||
@ -818,6 +824,19 @@ AC_CHECK_HEADER([paths.h],
|
||||
[HAVE_PATHS_H=])
|
||||
AC_SUBST(HAVE_PATHS_H)
|
||||
#
|
||||
# Define NO_GETTEXT if you don't want Git output to be translated.
|
||||
# A translated Git requires GNU libintl or another gettext implementation
|
||||
AC_CHECK_HEADER([libintl.h],
|
||||
[NO_GETTEXT=],
|
||||
[NO_GETTEXT=YesPlease])
|
||||
AC_SUBST(NO_GETTEXT)
|
||||
#
|
||||
# Define HAVE_LIBCHARSET_H if have libcharset.h
|
||||
AC_CHECK_HEADER([libcharset.h],
|
||||
[HAVE_LIBCHARSET_H=YesPlease],
|
||||
[HAVE_LIBCHARSET_H=])
|
||||
AC_SUBST(HAVE_LIBCHARSET_H)
|
||||
#
|
||||
# Define NO_STRCASESTR if you don't have strcasestr.
|
||||
GIT_CHECK_FUNC(strcasestr,
|
||||
[NO_STRCASESTR=],
|
||||
|
2
daemon.c
2
daemon.c
@ -1099,6 +1099,8 @@ int main(int argc, char **argv)
|
||||
struct credentials *cred = NULL;
|
||||
int i;
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
@ -3305,6 +3305,8 @@ int main(int argc, const char **argv)
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage(fast_import_usage);
|
||||
|
||||
|
117
gettext.c
117
gettext.c
@ -5,6 +5,18 @@
|
||||
#include "git-compat-util.h"
|
||||
#include "gettext.h"
|
||||
|
||||
#ifndef NO_GETTEXT
|
||||
# include <locale.h>
|
||||
# include <libintl.h>
|
||||
# ifdef HAVE_LIBCHARSET_H
|
||||
# include <libcharset.h>
|
||||
# else
|
||||
# include <langinfo.h>
|
||||
# define locale_charset() nl_langinfo(CODESET)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef GETTEXT_POISON
|
||||
int use_gettext_poison(void)
|
||||
{
|
||||
static int poison_requested = -1;
|
||||
@ -12,3 +24,108 @@ int use_gettext_poison(void)
|
||||
poison_requested = getenv("GIT_GETTEXT_POISON") ? 1 : 0;
|
||||
return poison_requested;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_GETTEXT
|
||||
static void init_gettext_charset(const char *domain)
|
||||
{
|
||||
const char *charset;
|
||||
|
||||
/*
|
||||
This trick arranges for messages to be emitted in the user's
|
||||
requested encoding, but avoids setting LC_CTYPE from the
|
||||
environment for the whole program.
|
||||
|
||||
This primarily done to avoid a bug in vsnprintf in the GNU C
|
||||
Library [1]. which triggered a "your vsnprintf is broken" error
|
||||
on Git's own repository when inspecting v0.99.6~1 under a UTF-8
|
||||
locale.
|
||||
|
||||
That commit contains a ISO-8859-1 encoded author name, which
|
||||
the locale aware vsnprintf(3) won't interpolate in the format
|
||||
argument, due to mismatch between the data encoding and the
|
||||
locale.
|
||||
|
||||
Even if it wasn't for that bug we wouldn't want to use LC_CTYPE at
|
||||
this point, because it'd require auditing all the code that uses C
|
||||
functions whose semantics are modified by LC_CTYPE.
|
||||
|
||||
But only setting LC_MESSAGES as we do creates a problem, since
|
||||
we declare the encoding of our PO files[2] the gettext
|
||||
implementation will try to recode it to the user's locale, but
|
||||
without LC_CTYPE it'll emit something like this on 'git init'
|
||||
under the Icelandic locale:
|
||||
|
||||
Bj? til t?ma Git lind ? /hlagh/.git/
|
||||
|
||||
Gettext knows about the encoding of our PO file, but we haven't
|
||||
told it about the user's encoding, so all the non-US-ASCII
|
||||
characters get encoded to question marks.
|
||||
|
||||
But we're in luck! We can set LC_CTYPE from the environment
|
||||
only while we call nl_langinfo and
|
||||
bind_textdomain_codeset. That suffices to tell gettext what
|
||||
encoding it should emit in, so it'll now say:
|
||||
|
||||
Bjó til tóma Git lind í /hlagh/.git/
|
||||
|
||||
And the equivalent ISO-8859-1 string will be emitted under a
|
||||
ISO-8859-1 locale.
|
||||
|
||||
With this change way we get the advantages of setting LC_CTYPE
|
||||
(talk to the user in his language/encoding), without the major
|
||||
drawbacks (changed semantics for C functions we rely on).
|
||||
|
||||
However foreign functions using other message catalogs that
|
||||
aren't using our neat trick will still have a problem, e.g. if
|
||||
we have to call perror(3):
|
||||
|
||||
#include <stdio.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setlocale(LC_MESSAGES, "");
|
||||
setlocale(LC_CTYPE, "C");
|
||||
errno = ENODEV;
|
||||
perror("test");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Running that will give you a message with question marks:
|
||||
|
||||
$ LANGUAGE= LANG=de_DE.utf8 ./test
|
||||
test: Kein passendes Ger?t gefunden
|
||||
|
||||
In the long term we should probably see about getting that
|
||||
vsnprintf bug in glibc fixed, and audit our code so it won't
|
||||
fall apart under a non-C locale.
|
||||
|
||||
Then we could simply set LC_CTYPE from the environment, which would
|
||||
make things like the external perror(3) messages work.
|
||||
|
||||
See t/t0203-gettext-setlocale-sanity.sh's "gettext.c" tests for
|
||||
regression tests.
|
||||
|
||||
1. http://sourceware.org/bugzilla/show_bug.cgi?id=6530
|
||||
2. E.g. "Content-Type: text/plain; charset=UTF-8\n" in po/is.po
|
||||
*/
|
||||
setlocale(LC_CTYPE, "");
|
||||
charset = locale_charset();
|
||||
bind_textdomain_codeset(domain, charset);
|
||||
setlocale(LC_CTYPE, "C");
|
||||
}
|
||||
|
||||
void git_setup_gettext(void)
|
||||
{
|
||||
const char *podir = getenv("GIT_TEXTDOMAINDIR");
|
||||
|
||||
if (!podir)
|
||||
podir = GIT_LOCALE_PATH;
|
||||
bindtextdomain("git", podir);
|
||||
setlocale(LC_MESSAGES, "");
|
||||
init_gettext_charset("git");
|
||||
textdomain("git");
|
||||
}
|
||||
#endif
|
||||
|
25
gettext.h
25
gettext.h
@ -13,8 +13,29 @@
|
||||
#error "namespace conflict: '_' or 'Q_' is pre-defined?"
|
||||
#endif
|
||||
|
||||
#ifndef NO_GETTEXT
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# ifdef gettext
|
||||
# undef gettext
|
||||
# endif
|
||||
# define gettext(s) (s)
|
||||
# ifdef ngettext
|
||||
# undef ngettext
|
||||
# endif
|
||||
# define ngettext(s, p, n) ((n == 1) ? (s) : (p))
|
||||
#endif
|
||||
|
||||
#define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
|
||||
|
||||
#ifndef NO_GETTEXT
|
||||
extern void git_setup_gettext(void);
|
||||
#else
|
||||
static inline void git_setup_gettext(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GETTEXT_POISON
|
||||
extern int use_gettext_poison(void);
|
||||
#else
|
||||
@ -23,7 +44,7 @@ extern int use_gettext_poison(void);
|
||||
|
||||
static inline FORMAT_PRESERVING(1) const char *_(const char *msgid)
|
||||
{
|
||||
return use_gettext_poison() ? "# GETTEXT POISON #" : msgid;
|
||||
return use_gettext_poison() ? "# GETTEXT POISON #" : gettext(msgid);
|
||||
}
|
||||
|
||||
static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
|
||||
@ -31,7 +52,7 @@ const char *Q_(const char *msgid, const char *plu, unsigned long n)
|
||||
{
|
||||
if (use_gettext_poison())
|
||||
return "# GETTEXT POISON #";
|
||||
return n == 1 ? msgid : plu;
|
||||
return ngettext(msgid, plu, n);
|
||||
}
|
||||
|
||||
/* Mark msgid for translation but do not translate it. */
|
||||
|
@ -2,17 +2,59 @@
|
||||
#
|
||||
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
|
||||
#
|
||||
# This is a skeleton no-op implementation of gettext for Git. It'll be
|
||||
# replaced by something that uses gettext.sh in a future patch series.
|
||||
# This is Git's interface to gettext.sh. See po/README for usage
|
||||
# instructions.
|
||||
|
||||
# Export the TEXTDOMAIN* data that we need for Git
|
||||
TEXTDOMAIN=git
|
||||
export TEXTDOMAIN
|
||||
if test -z "$GIT_TEXTDOMAINDIR"
|
||||
then
|
||||
TEXTDOMAINDIR="@@LOCALEDIR@@"
|
||||
else
|
||||
TEXTDOMAINDIR="$GIT_TEXTDOMAINDIR"
|
||||
fi
|
||||
export TEXTDOMAINDIR
|
||||
|
||||
if test -z "$GIT_GETTEXT_POISON"
|
||||
then
|
||||
gettext () {
|
||||
printf "%s" "$1"
|
||||
if test -z "$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS" && type gettext.sh >/dev/null 2>&1
|
||||
then
|
||||
# This is GNU libintl's gettext.sh, we don't need to do anything
|
||||
# else than setting up the environment and loading gettext.sh
|
||||
GIT_INTERNAL_GETTEXT_SH_SCHEME=gnu
|
||||
export GIT_INTERNAL_GETTEXT_SH_SCHEME
|
||||
|
||||
# Try to use libintl's gettext.sh, or fall back to English if we
|
||||
# can't.
|
||||
. gettext.sh
|
||||
|
||||
elif test -z "$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS" && test "$(gettext -h 2>&1)" = "-h"
|
||||
then
|
||||
# We don't have gettext.sh, but there's a gettext binary in our
|
||||
# path. This is probably Solaris or something like it which has a
|
||||
# gettext implementation that isn't GNU libintl.
|
||||
GIT_INTERNAL_GETTEXT_SH_SCHEME=solaris
|
||||
export GIT_INTERNAL_GETTEXT_SH_SCHEME
|
||||
|
||||
# Solaris has a gettext(1) but no eval_gettext(1)
|
||||
eval_gettext () {
|
||||
gettext "$1" | (
|
||||
export PATH $(git sh-i18n--envsubst --variables "$1");
|
||||
git sh-i18n--envsubst "$1"
|
||||
)
|
||||
}
|
||||
|
||||
gettextln() {
|
||||
printf "%s\n" "$1"
|
||||
else
|
||||
# Since gettext.sh isn't available we'll have to define our own
|
||||
# dummy pass-through functions.
|
||||
|
||||
# Tell our tests that we don't have the real gettext.sh
|
||||
GIT_INTERNAL_GETTEXT_SH_SCHEME=fallthrough
|
||||
export GIT_INTERNAL_GETTEXT_SH_SCHEME
|
||||
|
||||
gettext () {
|
||||
printf "%s" "$1"
|
||||
}
|
||||
|
||||
eval_gettext () {
|
||||
@ -21,28 +63,30 @@ then
|
||||
git sh-i18n--envsubst "$1"
|
||||
)
|
||||
}
|
||||
|
||||
eval_gettextln () {
|
||||
printf "%s\n" "$1" | (
|
||||
export PATH $(git sh-i18n--envsubst --variables "$1");
|
||||
git sh-i18n--envsubst "$1"
|
||||
)
|
||||
}
|
||||
fi
|
||||
else
|
||||
# Emit garbage under GETTEXT_POISON=YesPlease. Unlike the C tests
|
||||
# this relies on an environment variable
|
||||
|
||||
GIT_INTERNAL_GETTEXT_SH_SCHEME=poison
|
||||
export GIT_INTERNAL_GETTEXT_SH_SCHEME
|
||||
|
||||
gettext () {
|
||||
printf "%s" "# GETTEXT POISON #"
|
||||
}
|
||||
|
||||
gettextln () {
|
||||
printf "%s\n" "# GETTEXT POISON #"
|
||||
}
|
||||
|
||||
eval_gettext () {
|
||||
printf "%s" "# GETTEXT POISON #"
|
||||
}
|
||||
|
||||
eval_gettextln () {
|
||||
printf "%s\n" "# GETTEXT POISON #"
|
||||
}
|
||||
fi
|
||||
|
||||
# Git-specific wrapper functions
|
||||
gettextln () {
|
||||
gettext "$1"
|
||||
echo
|
||||
}
|
||||
|
||||
eval_gettextln () {
|
||||
eval_gettext "$1"
|
||||
echo
|
||||
}
|
||||
|
2
git.c
2
git.c
@ -538,6 +538,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:
|
||||
*
|
||||
|
@ -545,6 +545,8 @@ int main(int argc, char **argv)
|
||||
char *cmd_arg = NULL;
|
||||
int i;
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
set_die_routine(die_webcgi);
|
||||
|
||||
|
@ -22,6 +22,8 @@ int main(int argc, const char **argv)
|
||||
int get_verbosely = 0;
|
||||
int get_recover = 0;
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
while (arg < argc && argv[arg][0] == '-') {
|
||||
|
@ -1748,6 +1748,8 @@ int main(int argc, char **argv)
|
||||
int new_refs;
|
||||
struct ref *ref, *local_refs;
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
repo = xcalloc(sizeof(*repo), 1);
|
||||
|
@ -1538,6 +1538,8 @@ int main(int argc, char **argv)
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
if (argc != 1)
|
||||
usage(imap_send_usage);
|
||||
|
||||
|
89
perl/Git/I18N.pm
Normal file
89
perl/Git/I18N.pm
Normal file
@ -0,0 +1,89 @@
|
||||
package Git::I18N;
|
||||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Exporter 'import';
|
||||
|
||||
our @EXPORT = qw(__);
|
||||
our @EXPORT_OK = @EXPORT;
|
||||
|
||||
sub __bootstrap_locale_messages {
|
||||
our $TEXTDOMAIN = 'git';
|
||||
our $TEXTDOMAINDIR = $ENV{GIT_TEXTDOMAINDIR} || '++LOCALEDIR++';
|
||||
|
||||
require POSIX;
|
||||
POSIX->import(qw(setlocale));
|
||||
# Non-core prerequisite module
|
||||
require Locale::Messages;
|
||||
Locale::Messages->import(qw(:locale_h :libintl_h));
|
||||
|
||||
setlocale(LC_MESSAGES(), '');
|
||||
setlocale(LC_CTYPE(), '');
|
||||
textdomain($TEXTDOMAIN);
|
||||
bindtextdomain($TEXTDOMAIN => $TEXTDOMAINDIR);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
BEGIN
|
||||
{
|
||||
# Used by our test script to see if it should test fallbacks or
|
||||
# not.
|
||||
our $__HAS_LIBRARY = 1;
|
||||
|
||||
local $@;
|
||||
eval {
|
||||
__bootstrap_locale_messages();
|
||||
*__ = \&Locale::Messages::gettext;
|
||||
1;
|
||||
} or do {
|
||||
# Tell test.pl that we couldn't load the gettext library.
|
||||
$Git::I18N::__HAS_LIBRARY = 0;
|
||||
|
||||
# Just a fall-through no-op
|
||||
*__ = sub ($) { $_[0] };
|
||||
};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Git::I18N - Perl interface to Git's Gettext localizations
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Git::I18N;
|
||||
|
||||
print __("Welcome to Git!\n");
|
||||
|
||||
printf __("The following error occured: %s\n"), $error;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Git's internal Perl interface to gettext via L<Locale::Messages>. If
|
||||
L<Locale::Messages> can't be loaded (it's not a core module) we
|
||||
provide stub passthrough fallbacks.
|
||||
|
||||
This is a distilled interface to gettext, see C<info '(gettext)Perl'>
|
||||
for the full interface. This module implements only a small part of
|
||||
it.
|
||||
|
||||
=head1 FUNCTIONS
|
||||
|
||||
=head2 __($)
|
||||
|
||||
L<Locale::Messages>'s gettext function if all goes well, otherwise our
|
||||
passthrough fallback function.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2010 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>
|
||||
|
||||
=cut
|
@ -5,6 +5,7 @@ makfile:=perl.mak
|
||||
|
||||
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
|
||||
prefix_SQ = $(subst ','\'',$(prefix))
|
||||
localedir_SQ = $(subst ','\'',$(localedir))
|
||||
|
||||
ifndef V
|
||||
QUIET = @
|
||||
@ -38,7 +39,7 @@ $(makfile): ../GIT-CFLAGS Makefile
|
||||
echo ' echo $(instdir_SQ)' >> $@
|
||||
else
|
||||
$(makfile): Makefile.PL ../GIT-CFLAGS
|
||||
$(PERL_PATH) $< PREFIX='$(prefix_SQ)' INSTALL_BASE=''
|
||||
$(PERL_PATH) $< PREFIX='$(prefix_SQ)' INSTALL_BASE='' --localedir='$(localedir_SQ)'
|
||||
endif
|
||||
|
||||
# this is just added comfort for calling make directly in perl dir
|
||||
|
@ -1,4 +1,12 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
use ExtUtils::MakeMaker;
|
||||
use Getopt::Long;
|
||||
|
||||
# Sanity: die at first unknown option
|
||||
Getopt::Long::Configure qw/ pass_through /;
|
||||
|
||||
GetOptions("localedir=s" => \my $localedir);
|
||||
|
||||
sub MY::postamble {
|
||||
return <<'MAKE_FRAG';
|
||||
@ -16,7 +24,10 @@ endif
|
||||
MAKE_FRAG
|
||||
}
|
||||
|
||||
my %pm = ('Git.pm' => '$(INST_LIBDIR)/Git.pm');
|
||||
my %pm = (
|
||||
'Git.pm' => '$(INST_LIBDIR)/Git.pm',
|
||||
'Git/I18N.pm' => '$(INST_LIBDIR)/Git/I18N.pm',
|
||||
);
|
||||
|
||||
# We come with our own bundled Error.pm. It's not in the set of default
|
||||
# Perl modules so install it if it's not available on the system yet.
|
||||
@ -33,6 +44,7 @@ WriteMakefile(
|
||||
NAME => 'Git',
|
||||
VERSION_FROM => 'Git.pm',
|
||||
PM => \%pm,
|
||||
PM_FILTER => qq[\$(PERL) -pe "s<\\Q++LOCALEDIR++\\E><$localedir>"],
|
||||
MAKEFILE => 'perl.mak',
|
||||
INSTALLSITEMAN3DIR => '$(SITEPREFIX)/share/man/man3'
|
||||
);
|
||||
|
1
po/.gitignore
vendored
1
po/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/git.pot
|
||||
/build
|
||||
|
229
po/README
Normal file
229
po/README
Normal file
@ -0,0 +1,229 @@
|
||||
Core GIT Translations
|
||||
=====================
|
||||
|
||||
This directory holds the translations for the core of Git. This
|
||||
document describes how to add to and maintain these translations, and
|
||||
how to mark source strings for translation.
|
||||
|
||||
|
||||
Generating a .pot file
|
||||
----------------------
|
||||
|
||||
The po/git.pot file contains a message catalog extracted from Git's
|
||||
sources. You need to generate it to add new translations with
|
||||
msginit(1), or update existing ones with msgmerge(1).
|
||||
|
||||
Since the file can be automatically generated it's not checked into
|
||||
git.git. To generate it do, at the top-level:
|
||||
|
||||
make pot
|
||||
|
||||
|
||||
Initializing a .po file
|
||||
-----------------------
|
||||
|
||||
To add a new translation first generate git.pot (see above) and then
|
||||
in the po/ directory do:
|
||||
|
||||
msginit --locale=XX
|
||||
|
||||
Where XX is your locale, e.g. "is", "de" or "pt_BR".
|
||||
|
||||
Then edit the automatically generated copyright info in your new XX.po
|
||||
to be correct, e.g. for Icelandic:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-# Icelandic translations for PACKAGE package.
|
||||
-# Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
-# This file is distributed under the same license as the PACKAGE package.
|
||||
+# Icelandic translations for Git.
|
||||
+# Copyright (C) 2010 Ævar Arnfjörð Bjarmason <avarab@gmail.com>
|
||||
+# This file is distributed under the same license as the Git package.
|
||||
# Ævar Arnfjörð Bjarmason <avarab@gmail.com>, 2010.
|
||||
|
||||
And change references to PACKAGE VERSION in the PO Header Entry to
|
||||
just "Git":
|
||||
|
||||
perl -pi -e 's/(?<="Project-Id-Version: )PACKAGE VERSION/Git/' XX.po
|
||||
|
||||
|
||||
Updating a .po file
|
||||
-------------------
|
||||
|
||||
If there's an existing *.po file for your language but you need to
|
||||
update the translation you first need to generate git.pot (see above)
|
||||
and then in the po/ directory do:
|
||||
|
||||
msgmerge --add-location --backup=off -U XX.po git.pot
|
||||
|
||||
Where XX.po is the file you want to update.
|
||||
|
||||
Testing your changes
|
||||
--------------------
|
||||
|
||||
Before you submit your changes go back to the top-level and do:
|
||||
|
||||
make
|
||||
|
||||
On systems with GNU gettext (i.e. not Solaris) this will compile your
|
||||
changed PO file with `msgfmt --check`, the --check option flags many
|
||||
common errors, e.g. missing printf format strings, or translated
|
||||
messages that deviate from the originals in whether they begin/end
|
||||
with a newline or not.
|
||||
|
||||
|
||||
Marking strings for translation
|
||||
-------------------------------
|
||||
|
||||
Before strings can be translated they first have to be marked for
|
||||
translation.
|
||||
|
||||
Git uses an internationalization interface that wraps the system's
|
||||
gettext library, so most of the advice in your gettext documentation
|
||||
(on GNU systems `info gettext` in a terminal) applies.
|
||||
|
||||
General advice:
|
||||
|
||||
- Don't mark everything for translation, only strings which will be
|
||||
read by humans (the porcelain interface) should be translated.
|
||||
|
||||
The output from Git's plumbing utilities will primarily be read by
|
||||
programs and would break scripts under non-C locales if it was
|
||||
translated. Plumbing strings should not be translated, since
|
||||
they're part of Git's API.
|
||||
|
||||
- Adjust the strings so that they're easy to translate. Most of the
|
||||
advice in `info '(gettext)Preparing Strings'` applies here.
|
||||
|
||||
- If something is unclear or ambiguous you can use a "TRANSLATORS"
|
||||
comment to tell the translators what to make of it. These will be
|
||||
extracted by xgettext(1) and put in the po/*.po files, e.g. from
|
||||
git-am.sh:
|
||||
|
||||
# TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
|
||||
# in your translation. The program will only accept English
|
||||
# input at this point.
|
||||
gettext "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
|
||||
|
||||
Or in C, from builtin/revert.c:
|
||||
|
||||
/* TRANSLATORS: %s will be "revert" or "cherry-pick" */
|
||||
die(_("%s: Unable to write new index file"), action_name(opts));
|
||||
|
||||
We provide wrappers for C, Shell and Perl programs. Here's how they're
|
||||
used:
|
||||
|
||||
C:
|
||||
|
||||
- Include builtin.h at the top, it'll pull in in gettext.h, which
|
||||
defines the gettext interface. Consult with the list if you need to
|
||||
use gettext.h directly.
|
||||
|
||||
- The C interface is a subset of the normal GNU gettext
|
||||
interface. We currently export these functions:
|
||||
|
||||
- _()
|
||||
|
||||
Mark and translate a string. E.g.:
|
||||
|
||||
printf(_("HEAD is now at %s"), hex);
|
||||
|
||||
- Q_()
|
||||
|
||||
Mark and translate a plural string. E.g.:
|
||||
|
||||
printf(Q_("%d commit", "%d commits", number_of_commits));
|
||||
|
||||
This is just a wrapper for the ngettext() function.
|
||||
|
||||
- N_()
|
||||
|
||||
A no-op pass-through macro for marking strings inside static
|
||||
initializations, e.g.:
|
||||
|
||||
static const char *reset_type_names[] = {
|
||||
N_("mixed"), N_("soft"), N_("hard"), N_("merge"), N_("keep"), NULL
|
||||
};
|
||||
|
||||
And then, later:
|
||||
|
||||
die(_("%s reset is not allowed in a bare repository"),
|
||||
_(reset_type_names[reset_type]));
|
||||
|
||||
Here _() couldn't have statically determined what the translation
|
||||
string will be, but since it was already marked for translation
|
||||
with N_() the look-up in the message catalog will succeed.
|
||||
|
||||
Shell:
|
||||
|
||||
- The Git gettext shell interface is just a wrapper for
|
||||
gettext.sh. Import it right after git-sh-setup like this:
|
||||
|
||||
. git-sh-setup
|
||||
. git-sh-i18n
|
||||
|
||||
And then use the gettext or eval_gettext functions:
|
||||
|
||||
# For constant interface messages:
|
||||
gettext "A message for the user"; echo
|
||||
|
||||
# To interpolate variables:
|
||||
details="oh noes"
|
||||
eval_gettext "An error occured: \$details"; echo
|
||||
|
||||
In addition we have wrappers for messages that end with a trailing
|
||||
newline. I.e. you could write the above as:
|
||||
|
||||
# For constant interface messages:
|
||||
gettextln "A message for the user"
|
||||
|
||||
# To interpolate variables:
|
||||
details="oh noes"
|
||||
eval_gettextln "An error occured: \$details"
|
||||
|
||||
More documentation about the interface is available in the GNU info
|
||||
page: `info '(gettext)sh'`. Looking at git-am.sh (the first shell
|
||||
command to be translated) for examples is also useful:
|
||||
|
||||
git log --reverse -p --grep=i18n git-am.sh
|
||||
|
||||
Perl:
|
||||
|
||||
- The Git::I18N module provides a limited subset of the
|
||||
Locale::Messages functionality, e.g.:
|
||||
|
||||
use Git::I18N;
|
||||
print __("Welcome to Git!\n");
|
||||
printf __("The following error occured: %s\n"), $error;
|
||||
|
||||
Run `perldoc perl/Git/I18N.pm` for more info.
|
||||
|
||||
|
||||
Testing marked strings
|
||||
----------------------
|
||||
|
||||
Even if you've correctly marked porcelain strings for translation
|
||||
something in the test suite might still depend on the US English
|
||||
version of the strings, e.g. to grep some error message or other
|
||||
output.
|
||||
|
||||
To smoke out issues like these Git can be compiled with gettext poison
|
||||
support, at the top-level:
|
||||
|
||||
make GETTEXT_POISON=YesPlease
|
||||
|
||||
That'll give you a git which emits gibberish on every call to
|
||||
gettext. It's obviously not meant to be installed, but you should run
|
||||
the test suite with it:
|
||||
|
||||
cd t && prove -j 9 ./t[0-9]*.sh
|
||||
|
||||
If tests break with it you should inspect them manually and see if
|
||||
what you're translating is sane, i.e. that you're not translating
|
||||
plumbing output.
|
||||
|
||||
If not you should replace calls to grep with test_i18ngrep, or
|
||||
test_cmp calls with test_i18ncmp. If that's not enough you can skip
|
||||
the whole test by making it depend on the C_LOCALE_OUTPUT
|
||||
prerequisite. See existing test files with this prerequisite for
|
||||
examples.
|
93
po/is.po
Normal file
93
po/is.po
Normal file
@ -0,0 +1,93 @@
|
||||
# Icelandic translations for Git.
|
||||
# Copyright (C) 2010 Ævar Arnfjörð Bjarmason <avarab@gmail.com>
|
||||
# This file is distributed under the same license as the Git package.
|
||||
# Ævar Arnfjörð Bjarmason <avarab@gmail.com>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Git\n"
|
||||
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
|
||||
"POT-Creation-Date: 2010-09-20 14:44+0000\n"
|
||||
"PO-Revision-Date: 2010-06-05 19:06 +0000\n"
|
||||
"Last-Translator: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n"
|
||||
"Language-Team: Git Mailing List <git@vger.kernel.org>\n"
|
||||
"Language: is\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.c:5
|
||||
msgid "See 'git help COMMAND' for more information on a specific command."
|
||||
msgstr "Sjá 'git help SKIPUN' til að sjá hjálp fyrir tiltekna skipun."
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.c:10
|
||||
msgid "TEST: A C test string"
|
||||
msgstr "TILRAUN: C tilraunastrengur"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.c:13
|
||||
#, c-format
|
||||
msgid "TEST: A C test string %s"
|
||||
msgstr "TILRAUN: C tilraunastrengur %s"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.c:16
|
||||
#, c-format
|
||||
msgid "TEST: Hello World!"
|
||||
msgstr "TILRAUN: Halló Heimur!"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.c:19
|
||||
#, c-format
|
||||
msgid "TEST: Old English Runes"
|
||||
msgstr "TILRAUN: ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.c:22
|
||||
#, c-format
|
||||
msgid "TEST: ‘single’ and “double” quotes"
|
||||
msgstr "TILRAUN: ‚einfaldar‘ og „tvöfaldar“ gæsalappir"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.sh:8
|
||||
msgid "TEST: A Shell test string"
|
||||
msgstr "TILRAUN: Skeljartilraunastrengur"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.sh:11
|
||||
#, sh-format
|
||||
msgid "TEST: A Shell test $variable"
|
||||
msgstr "TILRAUN: Skeljartilraunastrengur með breytunni $variable"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.perl:8
|
||||
msgid "TEST: A Perl test string"
|
||||
msgstr "TILRAUN: Perl tilraunastrengur"
|
||||
|
||||
#. TRANSLATORS: This is a test. You don't need to translate it.
|
||||
#: t/t0200/test.perl:11
|
||||
#, perl-format
|
||||
msgid "TEST: A Perl test variable %s"
|
||||
msgstr "TILRAUN: Perl tilraunastrengur með breytunni %s"
|
||||
|
||||
#. TRANSLATORS: The first '%s' is either "Reinitialized
|
||||
#. existing" or "Initialized empty", the second " shared" or
|
||||
#. "", and the last '%s%s' is the verbatim directory name.
|
||||
#: builtin/init-db.c:355
|
||||
#, c-format
|
||||
msgid "%s%s Git repository in %s%s\n"
|
||||
msgstr "%s%s Git lind í %s%s\n"
|
||||
|
||||
#: builtin/init-db.c:356
|
||||
msgid "Reinitialized existing"
|
||||
msgstr "Endurgerði"
|
||||
|
||||
#: builtin/init-db.c:356
|
||||
msgid "Initialized empty"
|
||||
msgstr "Bjó til tóma"
|
||||
|
||||
#: builtin/init-db.c:357
|
||||
msgid " shared"
|
||||
msgstr " sameiginlega"
|
2
shell.c
2
shell.c
@ -137,6 +137,8 @@ int main(int argc, char **argv)
|
||||
int devnull_fd;
|
||||
int count;
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
/*
|
||||
|
@ -11,6 +11,8 @@ int main(int argc, char **argv)
|
||||
unsigned int version;
|
||||
static unsigned int top_index[256];
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
if (argc != 1)
|
||||
usage(show_index_usage);
|
||||
if (fread(top_index, 2 * 4, 1, stdin) != 1)
|
||||
|
55
t/lib-gettext.sh
Normal file
55
t/lib-gettext.sh
Normal file
@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
|
||||
#
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
GIT_TEXTDOMAINDIR="$GIT_BUILD_DIR/po/build/locale"
|
||||
GIT_PO_PATH="$GIT_BUILD_DIR/po"
|
||||
export GIT_TEXTDOMAINDIR GIT_PO_PATH
|
||||
|
||||
. "$GIT_BUILD_DIR"/git-sh-i18n
|
||||
|
||||
if test_have_prereq GETTEXT && ! test_have_prereq GETTEXT_POISON
|
||||
then
|
||||
# is_IS.UTF-8 on Solaris and FreeBSD, is_IS.utf8 on Debian
|
||||
is_IS_locale=$(locale -a | sed -n '/^is_IS\.[uU][tT][fF]-*8$/{
|
||||
p
|
||||
q
|
||||
}')
|
||||
# is_IS.ISO8859-1 on Solaris and FreeBSD, is_IS.iso88591 on Debian
|
||||
is_IS_iso_locale=$(locale -a | sed -n '/^is_IS\.[iI][sS][oO]8859-*1$/{
|
||||
p
|
||||
q
|
||||
}')
|
||||
|
||||
# Export them as an environment variable so the t0202/test.pl Perl
|
||||
# test can use it too
|
||||
export is_IS_locale is_IS_iso_locale
|
||||
|
||||
if test -n "$is_IS_locale" &&
|
||||
test $GIT_INTERNAL_GETTEXT_SH_SCHEME != "fallthrough"
|
||||
then
|
||||
# Some of the tests need the reference Icelandic locale
|
||||
test_set_prereq GETTEXT_LOCALE
|
||||
|
||||
# Exporting for t0202/test.pl
|
||||
GETTEXT_LOCALE=1
|
||||
export GETTEXT_LOCALE
|
||||
say "# lib-gettext: Found '$is_IS_locale' as an is_IS UTF-8 locale"
|
||||
else
|
||||
say "# lib-gettext: No is_IS UTF-8 locale available"
|
||||
fi
|
||||
|
||||
if test -n "$is_IS_iso_locale" &&
|
||||
test $GIT_INTERNAL_GETTEXT_SH_SCHEME != "fallthrough"
|
||||
then
|
||||
# Some of the tests need the reference Icelandic locale
|
||||
test_set_prereq GETTEXT_ISO_LOCALE
|
||||
|
||||
say "# lib-gettext: Found '$is_IS_iso_locale' as an is_IS ISO-8859-1 locale"
|
||||
else
|
||||
say "# lib-gettext: No is_IS ISO-8859-1 locale available"
|
||||
fi
|
||||
fi
|
108
t/t0200-gettext-basic.sh
Executable file
108
t/t0200-gettext-basic.sh
Executable file
@ -0,0 +1,108 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
|
||||
#
|
||||
|
||||
test_description='Gettext support for Git'
|
||||
|
||||
. ./lib-gettext.sh
|
||||
|
||||
test_expect_success "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" '
|
||||
test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME"
|
||||
'
|
||||
|
||||
test_expect_success 'sanity: $TEXTDOMAIN is git' '
|
||||
test $TEXTDOMAIN = "git"
|
||||
'
|
||||
|
||||
test_expect_success 'xgettext sanity: Perl _() strings are not extracted' '
|
||||
! grep "A Perl string xgettext will not get" "$GIT_PO_PATH"/is.po
|
||||
'
|
||||
|
||||
test_expect_success 'xgettext sanity: Comment extraction with --add-comments' '
|
||||
grep "TRANSLATORS: This is a test" "$TEST_DIRECTORY"/t0200/* | wc -l >expect &&
|
||||
grep "TRANSLATORS: This is a test" "$GIT_PO_PATH"/is.po | wc -l >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'xgettext sanity: Comment extraction with --add-comments stops at statements' '
|
||||
! grep "This is a phony" "$GIT_PO_PATH"/is.po &&
|
||||
! grep "the above comment" "$GIT_PO_PATH"/is.po
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT 'sanity: $TEXTDOMAINDIR exists without NO_GETTEXT=YesPlease' '
|
||||
test -d "$TEXTDOMAINDIR" &&
|
||||
test "$TEXTDOMAINDIR" = "$GIT_TEXTDOMAINDIR"
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT 'sanity: Icelandic locale was compiled' '
|
||||
test -f "$TEXTDOMAINDIR/is/LC_MESSAGES/git.mo"
|
||||
'
|
||||
|
||||
# TODO: When we have more locales, generalize this to test them
|
||||
# all. Maybe we'll need a dir->locale map for that.
|
||||
test_expect_success GETTEXT_LOCALE 'sanity: gettext("") metadata is OK' '
|
||||
# Return value may be non-zero
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "" >zero-expect &&
|
||||
grep "Project-Id-Version: Git" zero-expect &&
|
||||
grep "Git Mailing List <git@vger.kernel.org>" zero-expect &&
|
||||
grep "Content-Type: text/plain; charset=UTF-8" zero-expect &&
|
||||
grep "Content-Transfer-Encoding: 8bit" zero-expect
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'sanity: gettext(unknown) is passed through' '
|
||||
printf "This is not a translation string" >expect &&
|
||||
gettext "This is not a translation string" >actual &&
|
||||
eval_gettext "This is not a translation string" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
# xgettext from C
|
||||
test_expect_success GETTEXT_LOCALE 'xgettext: C extraction of _() and N_() strings' '
|
||||
printf "TILRAUN: C tilraunastrengur" >expect &&
|
||||
printf "\n" >>expect &&
|
||||
printf "Sjá '\''git help SKIPUN'\'' til að sjá hjálp fyrir tiltekna skipun." >>expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A C test string" >actual &&
|
||||
printf "\n" >>actual &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "See '\''git help COMMAND'\'' for more information on a specific command." >>actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'xgettext: C extraction with %s' '
|
||||
printf "TILRAUN: C tilraunastrengur %%s" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A C test string %s" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
# xgettext from Shell
|
||||
test_expect_success GETTEXT_LOCALE 'xgettext: Shell extraction' '
|
||||
printf "TILRAUN: Skeljartilraunastrengur" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Shell test string" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'xgettext: Shell extraction with $variable' '
|
||||
printf "TILRAUN: Skeljartilraunastrengur með breytunni a var i able" >x-expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" variable="a var i able" eval_gettext "TEST: A Shell test \$variable" >x-actual &&
|
||||
test_cmp x-expect x-actual
|
||||
'
|
||||
|
||||
# xgettext from Perl
|
||||
test_expect_success GETTEXT_LOCALE 'xgettext: Perl extraction' '
|
||||
printf "TILRAUN: Perl tilraunastrengur" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Perl test string" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'xgettext: Perl extraction with %s' '
|
||||
printf "TILRAUN: Perl tilraunastrengur með breytunni %%s" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Perl test variable %s" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'sanity: Some gettext("") data for real locale' '
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "" >real-locale &&
|
||||
test -s real-locale
|
||||
'
|
||||
|
||||
test_done
|
23
t/t0200/test.c
Normal file
23
t/t0200/test.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* This is a phony C program that's only here to test xgettext message extraction */
|
||||
|
||||
const char help[] =
|
||||
/* TRANSLATORS: This is a test. You don't need to translate it. */
|
||||
N_("See 'git help COMMAND' for more information on a specific command.");
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* TRANSLATORS: This is a test. You don't need to translate it. */
|
||||
puts(_("TEST: A C test string"));
|
||||
|
||||
/* TRANSLATORS: This is a test. You don't need to translate it. */
|
||||
printf(_("TEST: A C test string %s"), "variable");
|
||||
|
||||
/* TRANSLATORS: This is a test. You don't need to translate it. */
|
||||
printf(_("TEST: Hello World!"));
|
||||
|
||||
/* TRANSLATORS: This is a test. You don't need to translate it. */
|
||||
printf(_("TEST: Old English Runes"));
|
||||
|
||||
/* TRANSLATORS: This is a test. You don't need to translate it. */
|
||||
printf(_("TEST: ‘single’ and “double” quotes"));
|
||||
}
|
14
t/t0200/test.perl
Normal file
14
t/t0200/test.perl
Normal file
@ -0,0 +1,14 @@
|
||||
# This is a phony Perl program that's only here to test xgettext
|
||||
# message extraction
|
||||
|
||||
# so the above comment won't be folded into the next one by xgettext
|
||||
1;
|
||||
|
||||
# TRANSLATORS: This is a test. You don't need to translate it.
|
||||
print __("TEST: A Perl test string");
|
||||
|
||||
# TRANSLATORS: This is a test. You don't need to translate it.
|
||||
printf __("TEST: A Perl test variable %s"), "moo";
|
||||
|
||||
# TRANSLATORS: If you see this, Git has a bug
|
||||
print _"TEST: A Perl string xgettext will not get";
|
14
t/t0200/test.sh
Normal file
14
t/t0200/test.sh
Normal file
@ -0,0 +1,14 @@
|
||||
# This is a phony Shell program that's only here to test xgettext
|
||||
# message extraction
|
||||
|
||||
# so the above comment won't be folded into the next one by xgettext
|
||||
echo
|
||||
|
||||
# TRANSLATORS: This is a test. You don't need to translate it.
|
||||
gettext "TEST: A Shell test string"
|
||||
|
||||
# TRANSLATORS: This is a test. You don't need to translate it.
|
||||
eval_gettext "TEST: A Shell test \$variable"
|
||||
|
||||
# TRANSLATORS: If you see this, Git has a bug
|
||||
_("TEST: A Shell string xgettext won't get")
|
@ -5,8 +5,24 @@
|
||||
|
||||
test_description='Gettext Shell fallbacks'
|
||||
|
||||
. ./test-lib.sh
|
||||
. "$GIT_BUILD_DIR"/git-sh-i18n
|
||||
GIT_INTERNAL_GETTEXT_TEST_FALLBACKS=YesPlease
|
||||
export GIT_INTERNAL_GETTEXT_TEST_FALLBACKS
|
||||
|
||||
. ./lib-gettext.sh
|
||||
|
||||
test_expect_success "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" '
|
||||
test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME"
|
||||
'
|
||||
|
||||
test_expect_success 'sanity: $GIT_INTERNAL_GETTEXT_TEST_FALLBACKS is set' '
|
||||
test -n "$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS"
|
||||
'
|
||||
|
||||
test_expect_success C_LOCALE_OUTPUT 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is fallthrough' '
|
||||
echo fallthrough >expect &&
|
||||
echo $GIT_INTERNAL_GETTEXT_SH_SCHEME >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'gettext: our gettext() fallback has pass-through semantics' '
|
||||
printf "test" >expect &&
|
||||
|
27
t/t0202-gettext-perl.sh
Executable file
27
t/t0202-gettext-perl.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
|
||||
#
|
||||
|
||||
test_description='Perl gettext interface (Git::I18N)'
|
||||
|
||||
. ./lib-gettext.sh
|
||||
|
||||
if ! test_have_prereq PERL; then
|
||||
skip_all='skipping perl interface tests, perl not available'
|
||||
test_done
|
||||
fi
|
||||
|
||||
"$PERL_PATH" -MTest::More -e 0 2>/dev/null || {
|
||||
skip_all="Perl Test::More unavailable, skipping test"
|
||||
test_done
|
||||
}
|
||||
|
||||
# The external test will outputs its own plan
|
||||
test_external_has_tap=1
|
||||
|
||||
test_external_without_stderr \
|
||||
'Perl Git::I18N API' \
|
||||
"$PERL_PATH" "$TEST_DIRECTORY"/t0202/test.pl
|
||||
|
||||
test_done
|
110
t/t0202/test.pl
Normal file
110
t/t0202/test.pl
Normal file
@ -0,0 +1,110 @@
|
||||
#!/usr/bin/perl
|
||||
use 5.008;
|
||||
use lib (split(/:/, $ENV{GITPERLLIB}));
|
||||
use strict;
|
||||
use warnings;
|
||||
use POSIX qw(:locale_h);
|
||||
use Test::More tests => 8;
|
||||
use Git::I18N;
|
||||
|
||||
my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;
|
||||
|
||||
ok(1, "Testing Git::I18N with " .
|
||||
($has_gettext_library
|
||||
? (defined $Locale::Messages::VERSION
|
||||
? "Locale::Messages version $Locale::Messages::VERSION"
|
||||
# Versions of Locale::Messages before 1.17 didn't have a
|
||||
# $VERSION variable.
|
||||
: "Locale::Messages version <1.17")
|
||||
: "NO Perl gettext library"));
|
||||
ok(1, "Git::I18N is located at $INC{'Git/I18N.pm'}");
|
||||
|
||||
{
|
||||
my $exports = @Git::I18N::EXPORT;
|
||||
ok($exports, "sanity: Git::I18N has $exports export(s)");
|
||||
}
|
||||
is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, "sanity: Git::I18N exports everything by default");
|
||||
|
||||
# prototypes
|
||||
{
|
||||
# Add prototypes here when modifying the public interface to add
|
||||
# more gettext wrapper functions.
|
||||
my %prototypes = (qw(
|
||||
__ $
|
||||
));
|
||||
while (my ($sub, $proto) = each %prototypes) {
|
||||
is(prototype(\&{"Git::I18N::$sub"}), $proto, "sanity: $sub has a $proto prototype");
|
||||
}
|
||||
}
|
||||
|
||||
# Test basic passthrough in the C locale
|
||||
{
|
||||
local $ENV{LANGUAGE} = 'C';
|
||||
local $ENV{LC_ALL} = 'C';
|
||||
local $ENV{LANG} = 'C';
|
||||
|
||||
my ($got, $expect) = (('TEST: A Perl test string') x 2);
|
||||
|
||||
is(__($got), $expect, "Passing a string through __() in the C locale works");
|
||||
}
|
||||
|
||||
# Test a basic message on different locales
|
||||
SKIP: {
|
||||
unless ($ENV{GETTEXT_LOCALE}) {
|
||||
# Can't reliably test __() with a non-C locales because the
|
||||
# required locales may not be installed on the system.
|
||||
#
|
||||
# We test for these anyway as part of the shell
|
||||
# tests. Skipping these here will eliminate failures on odd
|
||||
# platforms with incomplete locale data.
|
||||
|
||||
skip "GETTEXT_LOCALE must be set by lib-gettext.sh for exhaustive Git::I18N tests", 2;
|
||||
}
|
||||
|
||||
# The is_IS UTF-8 locale passed from lib-gettext.sh
|
||||
my $is_IS_locale = $ENV{is_IS_locale};
|
||||
|
||||
my $test = sub {
|
||||
my ($got, $expect, $msg, $locale) = @_;
|
||||
# Maybe this system doesn't have the locale we're trying to
|
||||
# test.
|
||||
my $locale_ok = setlocale(LC_ALL, $locale);
|
||||
is(__($got), $expect, "$msg a gettext library + <$locale> locale <$got> turns into <$expect>");
|
||||
};
|
||||
|
||||
my $env_C = sub {
|
||||
$ENV{LANGUAGE} = 'C';
|
||||
$ENV{LC_ALL} = 'C';
|
||||
};
|
||||
|
||||
my $env_is = sub {
|
||||
$ENV{LANGUAGE} = 'is';
|
||||
$ENV{LC_ALL} = $is_IS_locale;
|
||||
};
|
||||
|
||||
# Translation's the same as the original
|
||||
my ($got, $expect) = (('TEST: A Perl test string') x 2);
|
||||
|
||||
if ($has_gettext_library) {
|
||||
{
|
||||
local %ENV; $env_C->();
|
||||
$test->($got, $expect, "With", 'C');
|
||||
}
|
||||
|
||||
{
|
||||
my ($got, $expect) = ($got, 'TILRAUN: Perl tilraunastrengur');
|
||||
local %ENV; $env_is->();
|
||||
$test->($got, $expect, "With", $is_IS_locale);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
local %ENV; $env_C->();
|
||||
$test->($got, $expect, "Without", 'C');
|
||||
}
|
||||
|
||||
{
|
||||
local %ENV; $env_is->();
|
||||
$test->($got, $expect, "Without", 'is');
|
||||
}
|
||||
}
|
||||
}
|
26
t/t0203-gettext-setlocale-sanity.sh
Executable file
26
t/t0203-gettext-setlocale-sanity.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
|
||||
#
|
||||
|
||||
test_description="The Git C functions aren't broken by setlocale(3)"
|
||||
|
||||
. ./lib-gettext.sh
|
||||
|
||||
test_expect_success 'git show a ISO-8859-1 commit under C locale' '
|
||||
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
|
||||
test_commit "iso-c-commit" iso-under-c &&
|
||||
git show >out 2>err &&
|
||||
! test -s err &&
|
||||
grep -q "iso-c-commit" out
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'git show a ISO-8859-1 commit under a UTF-8 locale' '
|
||||
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
|
||||
test_commit "iso-utf8-commit" iso-under-utf8 &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" git show >out 2>err &&
|
||||
! test -s err &&
|
||||
grep -q "iso-utf8-commit" out
|
||||
'
|
||||
|
||||
test_done
|
78
t/t0204-gettext-reencode-sanity.sh
Executable file
78
t/t0204-gettext-reencode-sanity.sh
Executable file
@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
|
||||
#
|
||||
|
||||
test_description="Gettext reencoding of our *.po/*.mo files works"
|
||||
|
||||
. ./lib-gettext.sh
|
||||
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'gettext: Emitting UTF-8 from our UTF-8 *.mo files / Icelandic' '
|
||||
printf "TILRAUN: Halló Heimur!" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: Hello World!" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'gettext: Emitting UTF-8 from our UTF-8 *.mo files / Runes' '
|
||||
printf "TILRAUN: ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: Old English Runes" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_ISO_LOCALE 'gettext: Emitting ISO-8859-1 from our UTF-8 *.mo files / Icelandic' '
|
||||
printf "TILRAUN: Halló Heimur!" | iconv -f UTF-8 -t ISO8859-1 >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "TEST: Hello World!" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_ISO_LOCALE 'gettext: Emitting ISO-8859-1 from our UTF-8 *.mo files / Runes' '
|
||||
LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "TEST: Old English Runes" >runes &&
|
||||
|
||||
if grep "^TEST: Old English Runes$" runes
|
||||
then
|
||||
say "Your system can not handle this complexity and returns the string as-is"
|
||||
else
|
||||
# Both Solaris and GNU libintl will return this stream of
|
||||
# question marks, so it is s probably portable enough
|
||||
printf "TILRAUN: ?? ???? ??? ?? ???? ?? ??? ????? ??????????? ??? ?? ????" >runes-expect &&
|
||||
test_cmp runes-expect runes
|
||||
fi
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'gettext: Fetching a UTF-8 msgid -> UTF-8' '
|
||||
printf "TILRAUN: ‚einfaldar‘ og „tvöfaldar“ gæsalappir" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: ‘single’ and “double” quotes" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
# How these quotes get transliterated depends on the gettext implementation:
|
||||
#
|
||||
# Debian: ,einfaldar' og ,,tvöfaldar" [GNU libintl]
|
||||
# FreeBSD: `einfaldar` og "tvöfaldar" [GNU libintl]
|
||||
# Solaris: ?einfaldar? og ?tvöfaldar? [Solaris libintl]
|
||||
#
|
||||
# Just make sure the contents are transliterated, and don't use grep -q
|
||||
# so that these differences are emitted under --verbose for curious
|
||||
# eyes.
|
||||
test_expect_success GETTEXT_ISO_LOCALE 'gettext: Fetching a UTF-8 msgid -> ISO-8859-1' '
|
||||
LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "TEST: ‘single’ and “double” quotes" >actual &&
|
||||
grep "einfaldar" actual &&
|
||||
grep "$(echo tvöfaldar | iconv -f UTF-8 -t ISO8859-1)" actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_LOCALE 'gettext.c: git init UTF-8 -> UTF-8' '
|
||||
printf "Bjó til tóma Git lind" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_locale" git init repo >actual &&
|
||||
test_when_finished "rm -rf repo" &&
|
||||
grep "^$(cat expect) " actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_ISO_LOCALE 'gettext.c: git init UTF-8 -> ISO-8859-1' '
|
||||
printf "Bjó til tóma Git lind" >expect &&
|
||||
LANGUAGE=is LC_ALL="$is_IS_iso_locale" git init repo >actual &&
|
||||
test_when_finished "rm -rf repo" &&
|
||||
grep "^$(cat expect | iconv -f UTF-8 -t ISO8859-1) " actual
|
||||
'
|
||||
|
||||
test_done
|
36
t/t0205-gettext-poison.sh
Executable file
36
t/t0205-gettext-poison.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
|
||||
#
|
||||
|
||||
test_description='Gettext Shell poison'
|
||||
|
||||
. ./lib-gettext.sh
|
||||
|
||||
test_expect_success GETTEXT_POISON "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" '
|
||||
test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME"
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_POISON 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is poison' '
|
||||
test "$GIT_INTERNAL_GETTEXT_SH_SCHEME" = "poison"
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_POISON 'gettext: our gettext() fallback has poison semantics' '
|
||||
printf "# GETTEXT POISON #" >expect &&
|
||||
gettext "test" >actual &&
|
||||
test_cmp expect actual &&
|
||||
printf "# GETTEXT POISON #" >expect &&
|
||||
gettext "test more words" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success GETTEXT_POISON 'eval_gettext: our eval_gettext() fallback has poison semantics' '
|
||||
printf "# GETTEXT POISON #" >expect &&
|
||||
eval_gettext "test" >actual &&
|
||||
test_cmp expect actual &&
|
||||
printf "# GETTEXT POISON #" >expect &&
|
||||
eval_gettext "test more words" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
@ -44,6 +44,7 @@ export LANG LC_ALL PAGER TERM TZ
|
||||
EDITOR=:
|
||||
unset VISUAL
|
||||
unset EMAIL
|
||||
unset LANGUAGE
|
||||
unset $(perl -e '
|
||||
my @env = keys %ENV;
|
||||
my $ok = join("|", qw(
|
||||
@ -1118,12 +1119,14 @@ esac
|
||||
test -z "$NO_PERL" && test_set_prereq PERL
|
||||
test -z "$NO_PYTHON" && test_set_prereq PYTHON
|
||||
test -n "$USE_LIBPCRE" && test_set_prereq LIBPCRE
|
||||
test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
|
||||
|
||||
# Can we rely on git's output in the C locale?
|
||||
if test -n "$GETTEXT_POISON"
|
||||
then
|
||||
GIT_GETTEXT_POISON=YesPlease
|
||||
export GIT_GETTEXT_POISON
|
||||
test_set_prereq GETTEXT_POISON
|
||||
else
|
||||
test_set_prereq C_LOCALE_OUTPUT
|
||||
fi
|
||||
|
@ -784,6 +784,8 @@ int main(int argc, char **argv)
|
||||
int i;
|
||||
int strict = 0;
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
packet_trace_identity("upload-pack");
|
||||
git_extract_argv0_path(argv[0]);
|
||||
read_replace_refs = 0;
|
||||
|
@ -15,7 +15,8 @@ else
|
||||
export GIT_TEMPLATE_DIR
|
||||
fi
|
||||
GITPERLLIB='@@BUILD_DIR@@/perl/blib/lib'
|
||||
GIT_TEXTDOMAINDIR='@@BUILD_DIR@@/po/build/locale'
|
||||
PATH='@@BUILD_DIR@@/bin-wrappers:'"$PATH"
|
||||
export GIT_EXEC_PATH GITPERLLIB PATH
|
||||
export GIT_EXEC_PATH GITPERLLIB PATH GIT_TEXTDOMAINDIR
|
||||
|
||||
exec "${GIT_EXEC_PATH}/@@PROG@@" "$@"
|
||||
|
Loading…
Reference in New Issue
Block a user