From cb8b1138d6e349a77507f3c561fc7ee2dde5cd7c Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Fri, 10 Jun 2011 18:17:22 +0000 Subject: [PATCH] Add localization support to com_err * Add compile_et arguments --textdomain and --localedir. * Store text domain and localedir at the end of error tables. * error_message() calls dgettext if the table has a text domain. * add_error_table() calls bindtextdomain if the table has a localedir. * Define N_() as no-op in generated source and mark up error messages. * When using system compile_et, test for --textdomain support. * Use --textdomain option when available. * Run xgettext over generated sources in compile_et rule. * Translate com_err results in krb5int_get_error() if com_err won't. ticket: 6918 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24960 dc483132-0cff-0310-8789-dd5450dbe970 --- src/aclocal.m4 | 21 +++++++++++++++++++- src/config/post.in | 2 +- src/config/pre.in | 6 +++++- src/po/Makefile.in | 19 +++++++++++++++++- src/po/mit-krb5.pot | 2 +- src/util/Makefile.in | 1 + src/util/et/compile_et.1 | 18 +++++++++++++++++ src/util/et/compile_et.sh | 30 ++++++++++++++++++++--------- src/util/et/error_message.c | 12 +++++++++++- src/util/et/et_c.awk | 15 ++++++++++++--- src/util/gss-kernel-lib/Makefile.in | 1 + src/util/support/errors.c | 4 ++++ 12 files changed, 113 insertions(+), 18 deletions(-) diff --git a/src/aclocal.m4 b/src/aclocal.m4 index 390a747fb..57a0a38d9 100644 --- a/src/aclocal.m4 +++ b/src/aclocal.m4 @@ -1417,6 +1417,7 @@ AC_ARG_WITH([system-et], AC_HELP_STRING(--with-system-et,use system compile_et and -lcom_err @<:@default: build and install a local version@:>@)) AC_MSG_CHECKING(which version of com_err to use) if test "x$with_system_et" = xyes ; then + # This will be changed to "intlsys" if textdomain support is present. COM_ERR_VERSION=sys AC_MSG_RESULT(system) else @@ -1445,11 +1446,29 @@ EOF ],[ &et_foo_error_table; ],:, [AC_MSG_ERROR(cannot use et_foo_error_table)]) # Anything else we need to test for? - rm -f conf$$e.et conf$$e.c conf$$e.h + rm -f conf$$e.c conf$$e.h krb5_cv_compile_et_useful=yes ]) + AC_CACHE_CHECK(whether compile_et supports --textdomain, + krb5_cv_compile_et_textdomain,[ + krb5_cv_compile_et_textdomain=no + if compile_et --textdomain=xyzw conf$$e.et >/dev/null 2>&1 ; then + if grep -q xyzw conf$$e.c; then + krb5_cv_compile_et_textdomain=yes + fi + fi + rm -f conf$$e.c conf$$e.h + ]) + if test "$krb5_cv_compile_et_textdomain" = yes; then + COM_ERR_VERSION=intlsys + fi + rm -f conf$$e.et fi AC_SUBST(COM_ERR_VERSION) +if test "$COM_ERR_VERSION" = k5 -o "$COM_ERR_VERSION" = intlsys; then + AC_DEFINE(HAVE_COM_ERR_INTL,1, + [Define if com_err has compatible gettext support]) +fi ]) AC_DEFUN([KRB5_AC_CHOOSE_SS],[ AC_ARG_WITH(system-ss, diff --git a/src/config/post.in b/src/config/post.in index 43c218bdf..c59360059 100644 --- a/src/config/post.in +++ b/src/config/post.in @@ -42,7 +42,7 @@ $(BUILDTOP)/.depend-verify-et: depend-verify-et-$(COM_ERR_VERSION) depend-verify-et-k5: @if test -r $(BUILDTOP)/.depend-verify-et; then :; \ else (set -x; touch $(BUILDTOP)/.depend-verify-et); fi -depend-verify-et-sys: +depend-verify-et-sys depend-verify-et-intlsys: @echo 1>&2 error: cannot build dependencies using system et package @exit 1 $(BUILDTOP)/.depend-verify-ss: depend-verify-ss-$(SS_VERSION) diff --git a/src/config/pre.in b/src/config/pre.in index 69548babf..a81d150dd 100644 --- a/src/config/pre.in +++ b/src/config/pre.in @@ -330,6 +330,7 @@ KRB5_DEPLIB = $(TOPLIBD)/libkrb5$(DEPLIBEXT) CRYPTO_DEPLIB = $(TOPLIBD)/libk5crypto$(DEPLIBEXT) COM_ERR_DEPLIB = $(COM_ERR_DEPLIB-@COM_ERR_VERSION@) COM_ERR_DEPLIB-sys = # empty +COM_ERR_DEPLIB-intlsys = # empty COM_ERR_DEPLIB-k5 = $(TOPLIBD)/libcom_err$(DEPLIBEXT) SUPPORT_LIBNAME=krb5support SUPPORT_DEPLIB = $(TOPLIBD)/lib$(SUPPORT_LIBNAME)$(DEPLIBEXT) @@ -356,6 +357,7 @@ KADMCLNT_DEPLIBS = $(KADMCLNT_DEPLIB) $(KADM_COMM_DEPLIBS) COM_ERR_VERSION = @COM_ERR_VERSION@ COM_ERR_DEPS = $(COM_ERR_DEPS-@COM_ERR_VERSION@) COM_ERR_DEPS-sys = +COM_ERR_DEPS-intlsys = COM_ERR_DEPS-k5 = $(BUILDTOP)/include/com_err.h SS_VERSION = @SS_VERSION@ SS_DEPS = $(SS_DEPS-@SS_VERSION@) @@ -421,7 +423,9 @@ PRNG_ALG = @PRNG_ALG@ ### /* these are invoked as $(...) foo.et, which works, but could be better */ COMPILE_ET= $(COMPILE_ET-@COM_ERR_VERSION@) COMPILE_ET-sys= compile_et -COMPILE_ET-k5= $(BUILDTOP)/util/et/compile_et -d $(top_srcdir)/util/et +COMPILE_ET-intlsys= compile_et --textdomain mit-krb5 +COMPILE_ET-k5= $(BUILDTOP)/util/et/compile_et -d $(top_srcdir)/util/et \ + --textdomain mit-krb5 .SUFFIXES: .h .c .et .ct diff --git a/src/po/Makefile.in b/src/po/Makefile.in index fd71f92b5..9d67f874c 100644 --- a/src/po/Makefile.in +++ b/src/po/Makefile.in @@ -6,6 +6,17 @@ DOMAIN=mit-krb5 POTFILE=$(srcdir)/$(DOMAIN).pot XGETTEXT=xgettext --foreign-user --package-name=mit-krb5 \ --package-version=$(VER) --copyright-holder=MIT +ETSRCS= $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.c \ + $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.c \ + $(BUILDTOP)/lib/kadm5/chpass_util_strings.c \ + $(BUILDTOP)/lib/kadm5/kadm_err.c \ + $(BUILDTOP)/lib/kdb/adb_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/k5e1_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/krb5_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/kdb5_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/asn1_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/kv5m_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/krb524_err.c # This is a placeholder until we have an actual translation. CATALOGS=en_US.mo @@ -15,12 +26,18 @@ CATALOGS=en_US.mo all:: $(CATALOGS) -update-po: csrcs +update-po: csrcs check_et_@COM_ERR_VERSION@ $(XGETTEXT) -k_ -kN_ -o $(POTFILE) -f csrcs + $(XGETTEXT) -kN_ -j -o $(POTFILE) $(ETSRCS) csrcs: always find $(top_srcdir) -name "*.c" -print > $@ +check_et_k5 check_et_intlsys: +check_et_sys: + @echo 1>&2 error: cannot update po file with this version of compile_et + @exit 1 + always: install:: diff --git a/src/po/mit-krb5.pot b/src/po/mit-krb5.pot index caa907e84..771249fac 100644 --- a/src/po/mit-krb5.pot +++ b/src/po/mit-krb5.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: mit-krb5 1.10-prerelease\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-06-06 00:34-0400\n" +"POT-Creation-Date: 2011-06-06 12:34-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/src/util/Makefile.in b/src/util/Makefile.in index ba14a605f..b6e7af6e2 100644 --- a/src/util/Makefile.in +++ b/src/util/Makefile.in @@ -12,6 +12,7 @@ BUILDTOP=$(REL).. MAYBE_ET_k5 = et MAYBE_SS_k5 = ss MAYBE_ET_sys = +MAYBE_ET_intlsys = MAYBE_SS_sys = all-recurse: diff --git a/src/util/et/compile_et.1 b/src/util/et/compile_et.1 index a082bca46..c9dff7815 100644 --- a/src/util/et/compile_et.1 +++ b/src/util/et/compile_et.1 @@ -8,6 +8,13 @@ compile_et \- error table compiler .SH SYNOPSIS .B compile_et +[ +.B \-\-textdomain +.I domain +[ +.B \-\-localedir +.I dir +] ] file .SH DESCRIPTION .B Compile_et @@ -62,6 +69,17 @@ the ``.et'' suffix replaced by ``.c'' and ``.h''. A ``#'' in the source file is treated as a comment character, and all remaining text to the end of the source line will be ignored. +If a text domain is provided with the +.B \-\-textdomain +option, error messages will be looked up in the specified domain with +.BR gettext . +If a locale directory is also provided with the +.B \-\-localedir +option, the text domain will be bound to the specified locale +directory with +.B bindtextdomain +when the error table is initialized. + .SH BUGS Since diff --git a/src/util/et/compile_et.sh b/src/util/et/compile_et.sh index adb0be666..f17ddba71 100755 --- a/src/util/et/compile_et.sh +++ b/src/util/et/compile_et.sh @@ -4,21 +4,33 @@ AWK=@AWK@ DIR=@DIR@ -usage="usage: $0 [ -d scriptDir ] inputfile.et" +usage="usage: $0 [ -d scriptDir ] [ --textdomain domain [ --localedir dir ] ]" +usage="$usage inputfile.et" -if [ "$1" = "-d" ]; then - if [ $# -lt 3 ]; then +TEXTDOMAIN= +LOCALEDIR= + +while [ $# -ge 2 ]; do + if [ "$1" = "-d" ]; then + DIR=$2; shift; shift + elif [ "$1" = "--textdomain" ]; then + TEXTDOMAIN=$2; shift; shift + elif [ "$1" = "--localedir" ]; then + LOCALEDIR=$2; shift; shift + else echo $usage 1>&2 ; exit 1 fi - DIR=$2 ; shift ; shift -fi -if [ $# -ne 1 ]; then +done + +# --localedir requires --textdomain. +if [ $# -ne 1 -o \( -n "$LOCALEDIR" -a -z "$TEXTDOMAIN" \) ]; then echo $usage 1>&2 ; exit 1 fi ROOT=`echo $1 | sed -e s/.et$//` -BASE=`echo $ROOT | sed -e 's;.*/;;'` +BASE=`echo "$ROOT" | sed -e 's;.*/;;'` set -ex -$AWK -f ${DIR}/et_h.awk outfile=${BASE}.h $ROOT.et -$AWK -f ${DIR}/et_c.awk outfile=${BASE}.c $ROOT.et +$AWK -f ${DIR}/et_h.awk "outfile=${BASE}.h" "$ROOT.et" +$AWK -f ${DIR}/et_c.awk "outfile=${BASE}.c" "textdomain=$TEXTDOMAIN" \ + "localedir=$LOCALEDIR" "$ROOT.et" diff --git a/src/util/et/error_message.c b/src/util/et/error_message.c index 35d58f306..01f2c03ca 100644 --- a/src/util/et/error_message.c +++ b/src/util/et/error_message.c @@ -185,7 +185,11 @@ found: if (table->n_msgs <= (unsigned int) offset) goto no_table_found; - return table->msgs[offset]; + /* If there's a string at the end of the table, it's a text domain. */ + if (table->msgs[table->n_msgs] != NULL) + return dgettext(table->msgs[table->n_msgs], table->msgs[offset]); + else + return table->msgs[offset]; no_table_found: k5_mutex_unlock(&et_list_lock); @@ -290,6 +294,12 @@ add_error_table(const struct error_table *et) } e->next = et_list; et_list = e; + + /* If there are two strings at the end of the table, they are a text domain + * and locale dir, and we are supposed to call bindtextdomain. */ + if (et->msgs[et->n_msgs] != NULL && et->msgs[et->n_msgs + 1] != NULL) + bindtextdomain(et->msgs[et->n_msgs], et->msgs[et->n_msgs + 1]); + return k5_mutex_unlock(&et_list_lock); } diff --git a/src/util/et/et_c.awk b/src/util/et/et_c.awk index cc277f5dc..35d924aa3 100644 --- a/src/util/et/et_c.awk +++ b/src/util/et/et_c.awk @@ -117,6 +117,8 @@ c2n["_"]=63 print "extern void initialize_" table_name "_error_table (void);" > outfile print "#endif" > outfile print "" > outfile + print "#define N_(x) (x)" > outfile + print "" > outfile print "/* Lclint doesn't handle null annotations on arrays" > outfile print " properly, so we need this typedef in each" > outfile print " generated .c file. */" > outfile @@ -136,7 +138,7 @@ c2n["_"]=63 (continuation == 1) && ($0 ~ /"[ \t]*$/) { # printf "\t\t\"%s,\n", $0 > outfile - printf "\t%s,\n", cont_buf $0 > outfile + printf "\tN_(%s),\n", cont_buf $0 > outfile continuation = 0; } @@ -152,7 +154,7 @@ c2n["_"]=63 text = text FS $i } text=substr(text,2,length(text)-1); - printf "\t%s,\n", text > outfile + printf "\tN_(%s),\n", text > outfile table_item_count++ } @@ -179,7 +181,7 @@ c2n["_"]=63 { if (skipone) { - printf "\t%s,\n", $0 > outfile + printf "\tN_(%s),\n", $0 > outfile } skipone=0 } @@ -188,6 +190,13 @@ END { print "Error table too large!" | "cat 1>&2" exit 1 } + # Put text domain and/or localedir at the end of the list. + if (textdomain) { + printf " \"%s\", /* Text domain */\n", textdomain > outfile + if (localedir) { + printf " \"%s\", /* Locale dir */\n", localedir > outfile + } + } print " 0" > outfile print "};" > outfile print "" > outfile diff --git a/src/util/gss-kernel-lib/Makefile.in b/src/util/gss-kernel-lib/Makefile.in index c2291f04b..988774093 100644 --- a/src/util/gss-kernel-lib/Makefile.in +++ b/src/util/gss-kernel-lib/Makefile.in @@ -81,6 +81,7 @@ HEADERS= \ MAYBE_COMERR_k5 = com_err.h MAYBE_COMERR_sys = +MAYBE_COMERR_intlsys = check-pytests:: t_kgss_user t_kgss_kernel $(RUNPYTEST) $(srcdir)/t_kgss.py $(PYTESTFLAGS) diff --git a/src/util/support/errors.c b/src/util/support/errors.c index 00cc922eb..0cd39277d 100644 --- a/src/util/support/errors.c +++ b/src/util/support/errors.c @@ -172,6 +172,10 @@ krb5int_get_error (struct errinfo *ep, long code) return ep->scratch_buf; } r = fptr(code); +#ifndef HAVE_COM_ERR_INTL + /* Translate com_err results here if libcom_err won't do it. */ + r = _(r); +#endif if (r == NULL) { unlock(); goto format_number; -- 2.26.2