Add localization support to com_err
authorGreg Hudson <ghudson@mit.edu>
Fri, 10 Jun 2011 18:17:22 +0000 (18:17 +0000)
committerGreg Hudson <ghudson@mit.edu>
Fri, 10 Jun 2011 18:17:22 +0000 (18:17 +0000)
* 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

12 files changed:
src/aclocal.m4
src/config/post.in
src/config/pre.in
src/po/Makefile.in
src/po/mit-krb5.pot
src/util/Makefile.in
src/util/et/compile_et.1
src/util/et/compile_et.sh
src/util/et/error_message.c
src/util/et/et_c.awk
src/util/gss-kernel-lib/Makefile.in
src/util/support/errors.c

index 390a747fb165bc97739d10ad7a2a03fe734d2c63..57a0a38d9984825a38906ed2f7abc00cbcedef34 100644 (file)
@@ -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,
index 43c218bdff6b9364898827951f81e801c3d94925..c59360059cc9103240708f1d5c5f9b0c311d75ce 100644 (file)
@@ -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)
index 69548babfe2e49a132da73536f7af6a42329f950..a81d150dd48c5cde04b365f903d956ac9919ffe3 100644 (file)
@@ -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
 
index fd71f92b5bcf1df811537591c2bb2db515b02470..9d67f874c31da91bf68346f3c79a4499f27d7f8a 100644 (file)
@@ -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::
index caa907e847cc40da2e635bf700919fa627c4dc42..771249faca37e992873c68e32f0006afceff16b9 100644 (file)
@@ -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 <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
index ba14a605fe3159f904fb62e0e1e88ed1b4b47a46..b6e7af6e21c50df0de86cb6cf38bfc66ad638152 100644 (file)
@@ -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:
index a082bca46c4c7811096402ef606c76f091307210..c9dff781513717a01b228daa738301e84d0bb751 100644 (file)
@@ -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
index adb0be666260e5d5bce87c955db2e537eb546b86..f17ddba7124763c511ddf3abd6055676f33cee75 100755 (executable)
@@ -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"
index 35d58f30681349ae244ed354c4773cc0533e965c..01f2c03cab9ba767ed3338035ce8f3acb4a25bfa 100644 (file)
@@ -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);
 }
 
index cc277f5dcd84e7c60c67ffae890e9b45578a1f71..35d924aa356028ba23bde2c2c0feb892a97ca051 100644 (file)
@@ -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
index c2291f04ba9a6232af6249a3d9e82ed844e17e10..9887740936a14411d12ea63de56bddac8f8a975a 100644 (file)
@@ -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)
index 00cc922ebf2b8e51c40f163ba880e48ef2bb365c..0cd39277d5830669b14a895e720b33f71477cc9f 100644 (file)
@@ -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;