[PATCH] i18n/l10n pam_winbind. (updated for v3-3 and higher)

boyang boyang at suse.de
Fri Oct 31 08:10:16 GMT 2008


tested with master, work as expected. Thanks!
boyang wrote:
> Hi, everybody:
>       here is the patch for v3-3-test, v3-devel, master, Please review it.
>       I have tested v3-3-test, v3-devel with gdm, su, passwd, and it
> worked as expected.  For master, I am not sure whether it is a Makefile
> problem or I misused the compile system. When built samba3, some
> binaries ended with 4 were produced, I guess they are for samba4. Why?
>       And I cannot use "make install" to install all files for samba3
> because of the error "No rule to make xxxxx4, needed by installbin",@@. 
> I compiled master with the following steps: 1. ./configure; 2. make; 3.
> make install(failed). Thanks for helping me on this. :-)
>       Here is the major changes:
>       1. add configuration option to set locale directory;
>       2. To make pam_winbind find the correct path to .mo files, define
> the LOCALEDIR; I didn't link it against dynconfig.c but against a new
> file localedir.c because link against dynconfig.c will cause it linking
> to param/loadparam.c(because of lp_XXX()), which is too expensive. many
> unused variables and functions will be linked into pam_winbind, which is
> a waste of memory and disk too.
>       3. add target <installmo> in makefile to install .mo files;
>       4. add one directory locale/ in source/ to hold .po files, For
> example, .po for pam_winbind goes into source[3]/locale/pam_winbind/.
>       Thanks in advance!
> Best
>        Regards
> BoYang
> 30th, Oct
>   
> ------------------------------------------------------------------------
>
> commit 8666b84021dbb0a263d9758c1528d93307a66822
> Author: boyang <boyang at desktop.boyang.novell.com>
> Date:   Thu Oct 30 17:53:52 2008 +0800
>
>     i18n/l10n pam_winbind
>
> diff --git a/source3/Makefile.in b/source3/Makefile.in
> index ac9770d..05353bf 100644
> --- a/source3/Makefile.in
> +++ b/source3/Makefile.in
> @@ -139,6 +139,9 @@ PRIVATE_DIR = $(PRIVATEDIR)
>  # This is where SWAT images and help files go
>  SWATDIR = @swatdir@
>  
> +# This is where locale(mo) files go
> +LOCALEDIR= @localedir@
> +
>  # the directory where lock files go
>  LOCKDIR = @lockdir@
>  
> @@ -172,7 +175,8 @@ PATH_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" \
>  	-DCONFIGDIR=\"$(CONFIGDIR)\" \
>  	-DCODEPAGEDIR=\"$(CODEPAGEDIR)\" \
>  	-DCACHEDIR=\"$(CACHEDIR)\" \
> -	-DSTATEDIR=\"$(STATEDIR)\"
> +	-DSTATEDIR=\"$(STATEDIR)\" \
> +	-DLOCALEDIR=\"$(LOCALEDIR)\"
>  
>  # Note that all executable programs now provide for an optional executable suffix.
>  
> @@ -797,7 +801,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
>  	     $(LIBADS_OBJ) $(POPT_LIB_OBJ) \
>  	     $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(LDB_OBJ) 
>  
> -PAM_WINBIND_OBJ = nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \
> +PAM_WINBIND_OBJ = nsswitch/pam_winbind.o localedir.o $(WBCOMMON_OBJ) \
>  		  $(LIBREPLACE_OBJ) @BUILD_INIPARSER@
>  
>  LIBSMBCLIENT_OBJ0 = \
> @@ -1304,6 +1308,13 @@ dynconfig.o: dynconfig.c Makefile
>  		echo "$(COMPILE_CC_PATH)" 1>&2;\
>  		$(COMPILE_CC_PATH) >/dev/null 2>&1
>  
> +localedir.o: localedir.c Makefile
> +	@echo Compiling $*.c
> +	@$(COMPILE_CC_PATH) && exit 0;\
> +		echo "The following command failed:" 1>&2;\
> +		echo "$(COMPILE_CC_PATH)" 1>&2;\
> +		$(COMPILE_CC_PATH) >/dev/null 2>&1
> +		
>  lib/pidfile.o: lib/pidfile.c
>  	@echo Compiling $*.c
>  	@$(COMPILE_CC_PATH) && exit 0;\
> @@ -2546,7 +2557,7 @@ bin/test_lp_load at EXEEXT@: $(BINARY_PREREQS) $(TEST_LP_LOAD_OBJ) @BUILD_POPT@ @LI
>  
>  install:: installservers installbin @INSTALL_CIFSMOUNT@ @INSTALL_CIFSUPCALL@ installman \
>  		installscripts installdat installmodules @SWAT_INSTALL_TARGETS@ \
> -		@INSTALL_PAM_MODULES@ installlibs
> +		@INSTALL_PAM_MODULES@ installlibs installmo
>  
>  install-everything:: install installmodules
>  
> @@ -2559,7 +2570,7 @@ install-everything:: install installmodules
>  # is not used
>  
>  installdirs::
> -	@$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR) $(CODEPAGEDIR) $(MODULESDIR)
> +	@$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR) $(CODEPAGEDIR) $(MODULESDIR) $(LOCALEDIR)
>  
>  installservers:: all installdirs
>  	@$(SHELL) script/installbin.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(SBINDIR) $(SBIN_PROGS)
> @@ -2625,6 +2636,9 @@ revert::
>  installman:: installdirs
>  	@$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@"
>  
> +installmo:: all installdirs
> +	@$(SHELL) $(srcdir)/script/installmo.sh $(DESTDIR) $(LOCALEDIR) $(srcdir)
> +
>  .PHONY: showlayout
>  
>  showlayout::
> @@ -2644,8 +2658,11 @@ showlayout::
>  	@echo "  codepagedir: $(CODEPAGEDIR)"
>  
>  
> -uninstall:: uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ @UNINSTALL_CIFSUPCALL@ uninstallscripts uninstalldat uninstallswat uninstallmodules uninstalllibs @UNINSTALL_PAM_MODULES@
> +uninstall:: uninstallmo uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ @UNINSTALL_CIFSUPCALL@ uninstallscripts uninstalldat uninstallswat uninstallmodules uninstalllibs @UNINSTALL_PAM_MODULES@
>  
> +uninstallmo::
> +	@$(SHELL) $(srcdir)/script/uninstallmo.sh $(DESTDIR) $(LOCALEDIR) $(srcdir)
> +       
>  uninstallman::
>  	@$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) C
>  
> @@ -2689,7 +2706,7 @@ uninstallpammodules::
>  	done
>  
>  # Toplevel clean files
> -TOPFILES=dynconfig.o
> +TOPFILES=dynconfig.o localedir.o
>  
>  cleanlibs::
>  	-rm -f ../lib/*/*.o ../lib/*/*/*.o \
> diff --git a/source3/configure.in b/source3/configure.in
> index cd84934..eaf2807 100644
> --- a/source3/configure.in
> +++ b/source3/configure.in
> @@ -662,7 +662,7 @@ AUTH_LIBS="${AUTH_LIBS} ${CRYPT_LIBS}"
>  
>  AC_CHECK_HEADERS(aio.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h)
>  AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h memory.h alloca.h)
> -AC_CHECK_HEADERS(limits.h float.h pthread.h)
> +AC_CHECK_HEADERS(limits.h float.h pthread.h libintl.h)
>  AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
>  AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
>  AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h)
> @@ -1055,6 +1055,7 @@ AC_CHECK_FUNCS(memalign posix_memalign hstrerror)
>  AC_CHECK_HEADERS(sys/mman.h)
>  # setbuffer, shmget, shm_open are needed for smbtorture
>  AC_CHECK_FUNCS(setbuffer shmget shm_open)
> +AC_CHECK_FUNCS(gettext dgettext)
>  
>  # Find a method of generating a stack trace
>  AC_CHECK_HEADERS(execinfo.h libexc.h libunwind.h)
> diff --git a/source3/include/localedir.h b/source3/include/localedir.h
> new file mode 100644
> index 0000000..2a291d3
> --- /dev/null
> +++ b/source3/include/localedir.h
> @@ -0,0 +1,6 @@
> +#ifndef __LOCALEDIR_H__
> +#define __LOCALEDIR_H__
> +
> +extern const char *dyn_LOCALEDIR;
> +
> +#endif
> diff --git a/source3/locale/pam_winbind/genmsg b/source3/locale/pam_winbind/genmsg
> new file mode 100644
> index 0000000..5aa258a
> --- /dev/null
> +++ b/source3/locale/pam_winbind/genmsg
> @@ -0,0 +1,25 @@
> +#!/bin/sh
> +
> +FILES="../../nsswitch/pam_winbind.c ../../nsswitch/pam_winbind.h"
> +LANGS="af ar bg bn bs ca cs cy da de el en_GB en_US es et fi fr gl gu he hi hr hu id it ja ka km ko lo lt mk mr nb nl pa pl pt_BR pt ro ru si sk sl sr sv ta th tr uk vi wa xh zh_CN zh_TW zu"
> +
> +XGETTEXT=xgettext
> +MSGMERGE=msgmerge
> +
> +WIDTH=256
> +
> +$XGETTEXT --default-domain="pam_winbind" \
> +	--add-comments \
> +	--keyword=_ --keyword=N_ \
> +	--width=${WIDTH} \
> +	${FILES}
> +
> +for lang in ${LANGS}; do
> +	echo -n $lang
> +	touch ${lang}.po
> +	mv ${lang}.po ${lang}.po.old
> +	${MSGMERGE} --width=${WIDTH} ${lang}.po.old pam_winbind.po -o ${lang}.po
> +	rm -fr ${lang}.po.old
> +done
> +
> +rm -fr pam_winbind.po
> diff --git a/source3/localedir.c b/source3/localedir.c
> new file mode 100644
> index 0000000..20f6921
> --- /dev/null
> +++ b/source3/localedir.c
> @@ -0,0 +1,3 @@
> +#include "localedir.h"
> +
> +const char *dyn_LOCALEDIR = LOCALEDIR;
> diff --git a/source3/m4/check_path.m4 b/source3/m4/check_path.m4
> index 9c99468..f61ed7c 100644
> --- a/source3/m4/check_path.m4
> +++ b/source3/m4/check_path.m4
> @@ -30,6 +30,7 @@ swatdir="\${prefix}/swat"
>  codepagedir="\${MODULESDIR}"
>  statedir="\${LOCKDIR}"
>  cachedir="\${LOCKDIR}"
> +localedir="\${prefix}/share/locale"
>  
>  AC_ARG_WITH(fhs,
>  [AS_HELP_STRING([--with-fhs],[Use FHS-compliant paths (default=no)])],
> @@ -242,6 +243,23 @@ AC_ARG_WITH(mandir,
>      ;;
>    esac])
>  
> +################################################
> +# set locale directory location
> +AC_ARG_WITH(localedir,
> +[  --with-localedir=DIR    Where to put po files ($ac_default_prefix/share/locale)],
> +[ case "$withval" in
> +  yes|no)
> +    #
> +    # Just in case anybody does it
> +    #
> +    AC_MSG_WARN([--with-localedir called without argument - will use default])
> +  ;;
> +  *)
> +  localedir="$withval"
> +  ;;
> +  esac])
> +			
> +
>  AC_SUBST(configdir)
>  AC_SUBST(lockdir)
>  AC_SUBST(piddir)
> @@ -258,6 +276,7 @@ AC_SUBST(cachedir)
>  AC_SUBST(rootsbindir)
>  AC_SUBST(pammodulesdir)
>  AC_SUBST(modulesdir)
> +AC_SUBST(localedir)
>  
>  #################################################
>  # set prefix for 'make test'
> diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c
> index 1c92725..cfbc4b0 100644
> --- a/source3/nsswitch/pam_winbind.c
> +++ b/source3/nsswitch/pam_winbind.c
> @@ -147,6 +147,21 @@ static const char *_pam_error_code_str(int err)
>  
>  #define MAX_PASSWD_TRIES	3
>  
> +#ifdef HAVE_GETTEXT
> +static char initialized = 0;
> +
> +static inline void textdomain_init(void);
> +static inline void textdomain_init(void)
> +{
> +	if (!initialized) {
> +		bindtextdomain(MODULE_NAME, dyn_LOCALEDIR);
> +		initialized = 1;
> +	}
> +	return;
> +}
> +#endif
> +
> +
>  /*
>   * Work around the pam API that has functions with void ** as parameters
>   * These lead to strict aliasing warnings with gcc.
> @@ -515,6 +530,10 @@ static int _pam_winbind_init_context(pam_handle_t *pamh,
>  {
>  	struct pwb_context *r = NULL;
>  
> +	#ifdef HAVE_GETTEXT
> +	textdomain_init();
> +	#endif
> +
>  	r = TALLOC_ZERO_P(NULL, struct pwb_context);
>  	if (!r) {
>  		return PAM_BUF_ERR;
> @@ -557,44 +576,44 @@ static const struct ntstatus_errors {
>  	const char *error_string;
>  } ntstatus_errors[] = {
>  	{"NT_STATUS_OK",
> -		"Success"},
> +		N_("Success")},
>  	{"NT_STATUS_BACKUP_CONTROLLER",
> -		"No primary Domain Controler available"},
> +		N_("No primary Domain Controler available")},
>  	{"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
> -		"No domain controllers found"},
> +		N_("No domain controllers found")},
>  	{"NT_STATUS_NO_LOGON_SERVERS",
> -		"No logon servers"},
> +		N_("No logon servers")},
>  	{"NT_STATUS_PWD_TOO_SHORT",
> -		"Password too short"},
> +		N_("Password too short")},
>  	{"NT_STATUS_PWD_TOO_RECENT",
> -		"The password of this user is too recent to change"},
> +		N_("The password of this user is too recent to change")},
>  	{"NT_STATUS_PWD_HISTORY_CONFLICT",
> -		"Password is already in password history"},
> +		N_("Password is already in password history")},
>  	{"NT_STATUS_PASSWORD_EXPIRED",
> -		"Your password has expired"},
> +		N_("Your password has expired")},
>  	{"NT_STATUS_PASSWORD_MUST_CHANGE",
> -		"You need to change your password now"},
> +		N_("You need to change your password now")},
>  	{"NT_STATUS_INVALID_WORKSTATION",
> -		"You are not allowed to logon from this workstation"},
> +		N_("You are not allowed to logon from this workstation")},
>  	{"NT_STATUS_INVALID_LOGON_HOURS",
> -		"You are not allowed to logon at this time"},
> +		N_("You are not allowed to logon at this time")},
>  	{"NT_STATUS_ACCOUNT_EXPIRED",
>  		"Your account has expired. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_ACCOUNT_DISABLED",
>  		"Your account is disabled. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_ACCOUNT_LOCKED_OUT",
>  		"Your account has been locked. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_ACCESS_DENIED",
> -		"Access is denied"},
> +		N_("Access is denied")},
>  	{NULL, NULL}
>  };
>  
> @@ -604,7 +623,7 @@ static const char *_get_ntstatus_error_string(const char *nt_status_string)
>  	for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) {
>  		if (!strcasecmp(ntstatus_errors[i].ntstatus_string,
>  				nt_status_string)) {
> -			return ntstatus_errors[i].error_string;
> +			return _(ntstatus_errors[i].error_string);
>  		}
>  	}
>  	return NULL;
> @@ -832,14 +851,14 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
>  
>  	if (days == 0) {
>  		_make_remark(ctx, PAM_TEXT_INFO,
> -			     "Your password expires today");
> +			     _("Your password expires today"));
>  		return true;
>  	}
>  
>  	if (days > 0 && days < warn_pwd_expire) {
>  		_make_remark_format(ctx, PAM_TEXT_INFO,
> -				    "Your password will expire in %d %s",
> -				    days, (days > 1) ? "days":"day");
> +				    _("Your password will expire in %d %s"),
> +				    days, (days > 1) ? _("days"):_("day"));
>  		return true;
>  	}
>  
> @@ -1231,9 +1250,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
>  	if (PAM_WB_GRACE_LOGON(info3_user_flgs)) {
>  
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Grace login. "
> -			     "Please change your password as soon you're "
> -			     "online again");
> +			     _("Grace login. "
> +			       "Please change your password as soon you're "
> +			       "online again"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s logged on using grace logon\n",
>  			       username);
> @@ -1241,9 +1260,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
>  	} else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) {
>  
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Domain Controller unreachable, "
> -			     "using cached credentials instead. "
> -			     "Network resources may be unavailable");
> +			     _("Domain Controller unreachable, "
> +			       "using cached credentials instead. "
> +			       "Network resources may be unavailable"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s logged on using cached credentials\n",
>  			       username);
> @@ -1266,10 +1285,10 @@ static void _pam_warn_krb5_failure(struct pwb_context *ctx,
>  {
>  	if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) {
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Failed to establish your Kerberos Ticket cache "
> -			     "due time differences\n"
> -			     "with the domain controller.  "
> -			     "Please verify the system time.\n");
> +			     _("Failed to establish your Kerberos Ticket cache "
> +			       "due time differences\n"
> +			       "with the domain controller.  "
> +			       "Please verify the system time.\n"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s: Clock skew when getting Krb5 TGT\n",
>  			       username);
> @@ -1334,7 +1353,7 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
>  		goto failed;
>  	}
>  
> -	str = talloc_asprintf(ctx, "Your password ");
> +	str = talloc_asprintf(ctx, _("Your password "));
>  	if (!str) {
>  		goto failed;
>  	}
> @@ -1350,8 +1369,8 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
>  
>  	if (i->password_history > 0) {
>  		str = talloc_asprintf_append(str,
> -			       "cannot repeat any of your previous %d "
> -			       "passwords; ",
> +			       _("cannot repeat any of your previous %d "
> +			        "passwords; "),
>  			       i->password_history);
>  		if (!str) {
>  			goto failed;
> @@ -1360,19 +1379,19 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
>  
>  	if (i->password_properties & WBC_DOMAIN_PASSWORD_COMPLEX) {
>  		str = talloc_asprintf_append(str,
> -			       "must contain capitals, numerals "
> -			       "or punctuation; "
> -			       "and cannot contain your account "
> -			       "or full name; ");
> +			       _("must contain capitals, numerals "
> +			         "or punctuation; "
> +			         "and cannot contain your account "
> +			         "or full name; "));
>  		if (!str) {
>  			goto failed;
>  		}
>  	}
>  
>  	str = talloc_asprintf_append(str,
> -		       "Please type a different password. "
> -		       "Type a password which meets these requirements in "
> -		       "both text boxes.");
> +		       _("Please type a different password. "
> +		         "Type a password which meets these requirements in "
> +		         "both text boxes."));
>  	if (!str) {
>  		goto failed;
>  	}
> @@ -1851,8 +1870,8 @@ static int winbind_chauthtok_request(struct pwb_context *ctx,
>  				break;
>  			case WBC_PWD_CHANGE_REJECT_COMPLEXITY:
>  				_make_remark(ctx, PAM_ERROR_MSG,
> -					     "Password does not meet "
> -					     "complexity requirements");
> +					     _("Password does not meet "
> +					       "complexity requirements"));
>  				break;
>  			default:
>  				_pam_log_debug(ctx, LOG_DEBUG,
> @@ -2485,7 +2504,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
>  	}
>  
>  	retval = _winbind_read_password(ctx, ctx->ctrl, NULL,
> -					"Password: ", NULL,
> +					_("Password: "), NULL,
>  					&password);
>  
>  	if (retval != PAM_SUCCESS) {
> @@ -2893,7 +2912,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  
>  		/* instruct user what is happening */
>  
> -#define greeting "Changing password for"
> +#define greeting _("Changing password for")
>  		Announce = talloc_asprintf(ctx, "%s %s", greeting, user);
>  		if (!Announce) {
>  			_pam_log(ctx, LOG_CRIT,
> @@ -2906,7 +2925,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  		lctrl = ctx->ctrl | WINBIND__OLD_PASSWORD;
>  		ret = _winbind_read_password(ctx, lctrl,
>  						Announce,
> -						"(current) NT password: ",
> +						_("(current) NT password: "),
>  						NULL,
>  						(const char **) &pass_old);
>  		TALLOC_FREE(Announce);
> @@ -2976,8 +2995,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  
>  			ret = _winbind_read_password(ctx, lctrl,
>  						     NULL,
> -						     "Enter new NT password: ",
> -						     "Retype new NT password: ",
> +						     _("Enter new NT password: "),
> +						     _("Retype new NT password: "),
>  						     (const char **)&pass_new);
>  
>  			if (ret != PAM_SUCCESS) {
> diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h
> index cb6f450..2d7005a 100644
> --- a/source3/nsswitch/pam_winbind.h
> +++ b/source3/nsswitch/pam_winbind.h
> @@ -9,6 +9,7 @@
>  #include "system/time.h"
>  #include <talloc.h>
>  #include "libwbclient/wbclient.h"
> +#include "localedir.h"
>  
>  #define MODULE_NAME "pam_winbind"
>  #define PAM_SM_AUTH
> @@ -22,6 +23,10 @@
>  
>  #include <iniparser.h>
>  
> +#ifdef HAVE_LIBINTL_H
> +#include <libintl.h>
> +#endif
> +
>  #ifndef LINUX
>  
>  /* Solaris always uses dynamic pam modules */
> @@ -105,8 +110,22 @@ do {                             \
>   * here is the string to inform the user that the new passwords they
>   * typed were not the same.
>   */
> + 
> +#if 0
> +#ifndef LOCALEDIR
> +#define LOCALEDIR "/usr/share/locale"
> +#endif
> +#endif
> +
> +#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
> +#define _(string) dgettext(MODULE_NAME, string)
> +#else
> +#define _(string) string
> +#endif
> +
> +#define N_(string) string
>  
> -#define MISTYPED_PASS "Sorry, passwords do not match"
> +#define MISTYPED_PASS _("Sorry, passwords do not match")
>  
>  #define on(x, y) (x & y)
>  #define off(x, y) (!(x & y))
> diff --git a/source3/script/installmo.sh b/source3/script/installmo.sh
> new file mode 100644
> index 0000000..0581853
> --- /dev/null
> +++ b/source3/script/installmo.sh
> @@ -0,0 +1,83 @@
> +#!/bin/sh
> +
> +DESTDIR=$1
> +LOCALEDIR=`echo $2 | sed 's/\/\//\//g'`
> +SRCDIR=$3/
> +MSGFMT=msgfmt
> +
> +case $0 in
> +	*uninstall*)
> +		if test ! -d "$DESTDIR/$LOCALEDIR"; then
> +			echo "Directory $DESTDIR/$LOCALEDIR doesn't exist!"
> +			echo "Do a \"make installmo\" or \"make install\" first."
> +			exit 1
> +		fi
> +		mode='uninstall'
> +	;;
> +	*)
> +		mode='install'
> +	;;
> +esac
> +
> +for dir in $SRCDIR/locale/*; do
> +	MODULE=`basename $dir`
> +	for f in $SRCDIR/locale/$MODULE/*.po; do
> +		BASE=`basename $f`
> +		LANGUAGE=`echo $BASE | sed 's/\.po//g'`
> +		FNAME="$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/$MODULE.mo"
> +		if test ! -d "$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/"; then
> +			mkdir -p "$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/"
> +		fi
> +		if test "$mode" = 'install'; then
> +			echo "Installing $f as $FNAME"
> +			touch "$FNAME"
> +			$MSGFMT "$f" -f -o "$FNAME"
> +			if test ! -f "$FNAME"; then
> +				echo "Cannot install $FNAME. Does $USER have privileges?"
> +				exit 1
> +			fi
> +			chmod 0644 "$FNAME"
> +		elif test "$mode" = 'uninstall'; then
> +			echo "removing $FNAME"
> +			rm -f "$FNAME"
> +			if test -f "$FNAME"; then
> +				echo "Cannot remove $FNAME. Does $USER have privileges?"
> +				exit 1
> +			fi
> +		else
> +			echo "Unknown mode $mode. script called as $0."
> +			exit 1
> +		fi
> +	done
> +	if test "$mode" = 'install'; then
> +		cat << EOF
> +==============================================================
> +MO files for $MODULE are installed. 
> +==============================================================
> +EOF
> +	else
> +		cat << EOF
> +==============================================================
> +MO files for $MODULE are removed.
> +==============================================================
> +EOF
> +	fi
> +done
> +
> +if test "$mode" = 'install'; then
> +	cat << EOF
> +==============================================================
> +All MO files for Samba are installed. You can use "make uninstall"
> +or "make uninstallmo" to remove them.
> +==============================================================
> +EOF
> +else
> +	cat << EOF
> +==============================================================
> +All MO files for Samba are removed. you can use "make install"
> +or "make installmo" to install them.
> +==============================================================
> +EOF
> +fi
> +
> +exit 0
> diff --git a/source3/script/uninstallmo.sh b/source3/script/uninstallmo.sh
> new file mode 100644
> index 0000000..1a2cb68
> --- /dev/null
> +++ b/source3/script/uninstallmo.sh
> @@ -0,0 +1 @@
> +installmo.sh
> \ No newline at end of file
>   
> ------------------------------------------------------------------------
>
> commit 95ee8c16a23f309aa736d97d4d1471f3d9ec0598
> Author: boyang <boyang at desktop.boyang.novell.com>
> Date:   Thu Oct 30 13:02:41 2008 +0800
>
>     i18n/l10n pam_winbind
>
> diff --git a/source/Makefile.in b/source/Makefile.in
> index e6f99f0..235adef 100644
> --- a/source/Makefile.in
> +++ b/source/Makefile.in
> @@ -137,6 +137,9 @@ PRIVATE_DIR = $(PRIVATEDIR)
>  # This is where SWAT images and help files go
>  SWATDIR = @swatdir@
>  
> +# This is where locale(mo) files go
> +LOCALEDIR= @localedir@
> +
>  # the directory where lock files go
>  LOCKDIR = @lockdir@
>  
> @@ -174,7 +177,8 @@ PATH_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" \
>  	-DCONFIGDIR=\"$(CONFIGDIR)\" \
>  	-DCODEPAGEDIR=\"$(CODEPAGEDIR)\" \
>  	-DCACHEDIR=\"$(CACHEDIR)\" \
> -	-DSTATEDIR=\"$(STATEDIR)\"
> +	-DSTATEDIR=\"$(STATEDIR)\" \
> +	-DLOCALEDIR=\"$(LOCALEDIR)\"
>  
>  # Note that all executable programs now provide for an optional executable suffix.
>  
> @@ -777,7 +781,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
>  	     $(LIBADS_OBJ) $(POPT_LIB_OBJ) \
>  	     $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(LDB_OBJ) 
>  
> -PAM_WINBIND_OBJ = nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \
> +PAM_WINBIND_OBJ = nsswitch/pam_winbind.o localedir.o $(WBCOMMON_OBJ) \
>  		  $(LIBREPLACE_OBJ) @BUILD_INIPARSER@
>  
>  LIBSMBCLIENT_OBJ0 = \
> @@ -1272,6 +1276,13 @@ dynconfig.o: dynconfig.c Makefile
>  		echo "$(COMPILE_CC_PATH)" 1>&2;\
>  		$(COMPILE_CC_PATH) >/dev/null 2>&1
>  
> +localedir.o: localedir.c Makefile
> +	@echo Compiling $*.c
> +	@$(COMPILE_CC_PATH) && exit 0;\
> +		echo "The following command failed:" 1>&2;\
> +		echo "$(COMPILE_CC_PATH)" 1>&2;\
> +		$(COMPILE_CC_PATH) >/dev/null 2>&1
> +		
>  lib/pidfile.o: lib/pidfile.c
>  	@echo Compiling $*.c
>  	@$(COMPILE_CC_PATH) && exit 0;\
> @@ -2500,7 +2511,7 @@ bin/rpc_open_tcp at EXEEXT@: $(BINARY_PREREQS) $(RPC_OPEN_TCP_OBJ) @LIBTALLOC_SHARE
>  
>  install:: installservers installbin @INSTALL_CIFSMOUNT@ @INSTALL_CIFSUPCALL@ installman \
>  		installscripts installdat installmodules @SWAT_INSTALL_TARGETS@ \
> -		@INSTALL_PAM_MODULES@ installlibs
> +		@INSTALL_PAM_MODULES@ installlibs installmo
>  
>  install-everything:: install installmodules
>  
> @@ -2513,7 +2524,7 @@ install-everything:: install installmodules
>  # is not used
>  
>  installdirs::
> -	@$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR) $(CODEPAGEDIR) $(MODULESDIR)
> +	@$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR) $(CODEPAGEDIR) $(MODULESDIR) $(LOCALEDIR)
>  
>  installservers:: all installdirs
>  	@$(SHELL) script/installbin.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(SBINDIR) $(SBIN_PROGS)
> @@ -2579,6 +2590,9 @@ revert::
>  installman:: installdirs
>  	@$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@"
>  
> +installmo:: all installdirs
> +	@$(SHELL) $(srcdir)/script/installmo.sh $(DESTDIR) $(LOCALEDIR) $(srcdir)
> +
>  .PHONY: showlayout
>  
>  showlayout::
> @@ -2598,8 +2612,11 @@ showlayout::
>  	@echo "  codepagedir: $(CODEPAGEDIR)"
>  
>  
> -uninstall:: uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ @UNINSTALL_CIFSUPCALL@ uninstallscripts uninstalldat uninstallswat uninstallmodules uninstalllibs @UNINSTALL_PAM_MODULES@
> +uninstall:: uninstallmo uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ @UNINSTALL_CIFSUPCALL@ uninstallscripts uninstalldat uninstallswat uninstallmodules uninstalllibs @UNINSTALL_PAM_MODULES@
>  
> +uninstallmo::
> +	@$(SHELL) $(srcdir)/script/uninstallmo.sh $(DESTDIR) $(LOCALEDIR) $(srcdir)
> +       
>  uninstallman::
>  	@$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) C
>  
> @@ -2643,7 +2660,7 @@ uninstallpammodules::
>  	done
>  
>  # Toplevel clean files
> -TOPFILES=dynconfig.o
> +TOPFILES=dynconfig.o localedir.o
>  
>  clean:: cleanlibs
>  	-rm -f include/build_env.h
> diff --git a/source/configure.in b/source/configure.in
> index 83eef75..6db7ac7 100644
> --- a/source/configure.in
> +++ b/source/configure.in
> @@ -662,7 +662,7 @@ LIBS="${LIBS} ${LIBDL} ${LIBREPLACE_NETWORK_LIBS}"
>  
>  AC_CHECK_HEADERS(aio.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h)
>  AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h memory.h alloca.h)
> -AC_CHECK_HEADERS(limits.h float.h pthread.h)
> +AC_CHECK_HEADERS(limits.h float.h pthread.h libintl.h)
>  AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
>  AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
>  AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h)
> @@ -1055,6 +1055,7 @@ AC_CHECK_FUNCS(memalign posix_memalign hstrerror)
>  AC_CHECK_HEADERS(sys/mman.h)
>  # setbuffer, shmget, shm_open are needed for smbtorture
>  AC_CHECK_FUNCS(setbuffer shmget shm_open)
> +AC_CHECK_FUNCS(gettext dgettext)
>  
>  # Find a method of generating a stack trace
>  AC_CHECK_HEADERS(execinfo.h libexc.h libunwind.h)
> diff --git a/source/include/localedir.h b/source/include/localedir.h
> new file mode 100644
> index 0000000..2a291d3
> --- /dev/null
> +++ b/source/include/localedir.h
> @@ -0,0 +1,6 @@
> +#ifndef __LOCALEDIR_H__
> +#define __LOCALEDIR_H__
> +
> +extern const char *dyn_LOCALEDIR;
> +
> +#endif
> diff --git a/source/locale/pam_winbind/genmsg b/source/locale/pam_winbind/genmsg
> new file mode 100755
> index 0000000..5aa258a
> --- /dev/null
> +++ b/source/locale/pam_winbind/genmsg
> @@ -0,0 +1,25 @@
> +#!/bin/sh
> +
> +FILES="../../nsswitch/pam_winbind.c ../../nsswitch/pam_winbind.h"
> +LANGS="af ar bg bn bs ca cs cy da de el en_GB en_US es et fi fr gl gu he hi hr hu id it ja ka km ko lo lt mk mr nb nl pa pl pt_BR pt ro ru si sk sl sr sv ta th tr uk vi wa xh zh_CN zh_TW zu"
> +
> +XGETTEXT=xgettext
> +MSGMERGE=msgmerge
> +
> +WIDTH=256
> +
> +$XGETTEXT --default-domain="pam_winbind" \
> +	--add-comments \
> +	--keyword=_ --keyword=N_ \
> +	--width=${WIDTH} \
> +	${FILES}
> +
> +for lang in ${LANGS}; do
> +	echo -n $lang
> +	touch ${lang}.po
> +	mv ${lang}.po ${lang}.po.old
> +	${MSGMERGE} --width=${WIDTH} ${lang}.po.old pam_winbind.po -o ${lang}.po
> +	rm -fr ${lang}.po.old
> +done
> +
> +rm -fr pam_winbind.po
> diff --git a/source/localedir.c b/source/localedir.c
> new file mode 100644
> index 0000000..20f6921
> --- /dev/null
> +++ b/source/localedir.c
> @@ -0,0 +1,3 @@
> +#include "localedir.h"
> +
> +const char *dyn_LOCALEDIR = LOCALEDIR;
> diff --git a/source/m4/check_path.m4 b/source/m4/check_path.m4
> index 7aa8c21..77e571b 100644
> --- a/source/m4/check_path.m4
> +++ b/source/m4/check_path.m4
> @@ -29,6 +29,7 @@ swatdir="\${prefix}/swat"
>  codepagedir="\${MODULESDIR}"
>  statedir="\${LOCKDIR}"
>  cachedir="\${LOCKDIR}"
> +localedir="\${prefix}/share/locale"
>  
>  AC_ARG_WITH(fhs,
>  [AS_HELP_STRING([--with-fhs],[Use FHS-compliant paths (default=no)])],
> @@ -224,6 +225,23 @@ AC_ARG_WITH(mandir,
>      ;;
>    esac])
>  
> +################################################
> +# set locale directory location
> +AC_ARG_WITH(localedir,
> +[  --with-localedir=DIR    Where to put po files ($ac_default_prefix/share/locale)],
> +[ case "$withval" in
> +  yes|no)
> +    #
> +    # Just in case anybody does it
> +    #
> +    AC_MSG_WARN([--with-localedir called without argument - will use default])
> +  ;;
> +  *)
> +  localedir="$withval"
> +  ;;
> +  esac])
> +			
> +
>  AC_SUBST(configdir)
>  AC_SUBST(lockdir)
>  AC_SUBST(piddir)
> @@ -239,6 +257,7 @@ AC_SUBST(cachedir)
>  AC_SUBST(rootsbindir)
>  AC_SUBST(pammodulesdir)
>  AC_SUBST(modulesdir)
> +AC_SUBST(localedir)
>  
>  #################################################
>  # set prefix for 'make test'
> diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
> index 5593114..1cee296 100644
> --- a/source/nsswitch/pam_winbind.c
> +++ b/source/nsswitch/pam_winbind.c
> @@ -111,6 +111,21 @@ static const char *_pam_error_code_str(int err)
>  
>  #define MAX_PASSWD_TRIES	3
>  
> +#ifdef HAVE_GETTEXT
> +static char initialized = 0;
> +
> +static inline void textdomain_init(void);
> +static inline void textdomain_init(void)
> +{
> +	if (!initialized) {
> +		bindtextdomain(MODULE_NAME, dyn_LOCALEDIR);
> +		initialized = 1;
> +	}
> +	return;
> +}
> +#endif
> +
> +
>  /*
>   * Work around the pam API that has functions with void ** as parameters
>   * These lead to strict aliasing warnings with gcc.
> @@ -469,6 +484,10 @@ static int _pam_winbind_init_context(pam_handle_t *pamh,
>  {
>  	struct pwb_context *r = NULL;
>  
> +	#ifdef HAVE_GETTEXT
> +	textdomain_init();
> +	#endif
> +
>  	r = (struct pwb_context *)malloc(sizeof(struct pwb_context));
>  	if (!r) {
>  		return PAM_BUF_ERR;
> @@ -511,44 +530,44 @@ static const struct ntstatus_errors {
>  	const char *error_string;
>  } ntstatus_errors[] = {
>  	{"NT_STATUS_OK",
> -		"Success"},
> +		N_("Success")},
>  	{"NT_STATUS_BACKUP_CONTROLLER",
> -		"No primary Domain Controler available"},
> +		N_("No primary Domain Controler available")},
>  	{"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
> -		"No domain controllers found"},
> +		N_("No domain controllers found")},
>  	{"NT_STATUS_NO_LOGON_SERVERS",
> -		"No logon servers"},
> +		N_("No logon servers")},
>  	{"NT_STATUS_PWD_TOO_SHORT",
> -		"Password too short"},
> +		N_("Password too short")},
>  	{"NT_STATUS_PWD_TOO_RECENT",
> -		"The password of this user is too recent to change"},
> +		N_("The password of this user is too recent to change")},
>  	{"NT_STATUS_PWD_HISTORY_CONFLICT",
> -		"Password is already in password history"},
> +		N_("Password is already in password history")},
>  	{"NT_STATUS_PASSWORD_EXPIRED",
> -		"Your password has expired"},
> +		N_("Your password has expired")},
>  	{"NT_STATUS_PASSWORD_MUST_CHANGE",
> -		"You need to change your password now"},
> +		N_("You need to change your password now")},
>  	{"NT_STATUS_INVALID_WORKSTATION",
> -		"You are not allowed to logon from this workstation"},
> +		N_("You are not allowed to logon from this workstation")},
>  	{"NT_STATUS_INVALID_LOGON_HOURS",
> -		"You are not allowed to logon at this time"},
> +		N_("You are not allowed to logon at this time")},
>  	{"NT_STATUS_ACCOUNT_EXPIRED",
>  		"Your account has expired. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_ACCOUNT_DISABLED",
>  		"Your account is disabled. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_ACCOUNT_LOCKED_OUT",
>  		"Your account has been locked. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_ACCESS_DENIED",
> -		"Access is denied"},
> +		N_("Access is denied")},
>  	{NULL, NULL}
>  };
>  
> @@ -558,7 +577,7 @@ static const char *_get_ntstatus_error_string(const char *nt_status_string)
>  	for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) {
>  		if (!strcasecmp(ntstatus_errors[i].ntstatus_string,
>  				nt_status_string)) {
> -			return ntstatus_errors[i].error_string;
> +			return _(ntstatus_errors[i].error_string);
>  		}
>  	}
>  	return NULL;
> @@ -823,14 +842,14 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
>  
>  	if (days == 0) {
>  		_make_remark(ctx, PAM_TEXT_INFO,
> -			     "Your password expires today");
> +			     _("Your password expires today"));
>  		return true;
>  	}
>  
>  	if (days > 0 && days < warn_pwd_expire) {
>  		_make_remark_format(ctx, PAM_TEXT_INFO,
> -				    "Your password will expire in %d %s",
> -				    days, (days > 1) ? "days":"day");
> +				    _("Your password will expire in %d %s"),
> +				    days, (days > 1) ? _("days"):_("day"));
>  		return true;
>  	}
>  
> @@ -1171,9 +1190,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
>  	if (PAM_WB_GRACE_LOGON(info3_user_flgs)) {
>  
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Grace login. "
> -			     "Please change your password as soon you're "
> -			     "online again");
> +			     _("Grace login. "
> +			       "Please change your password as soon you're "
> +			       "online again"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s logged on using grace logon\n",
>  			       username);
> @@ -1181,9 +1200,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
>  	} else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) {
>  
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Domain Controller unreachable, "
> -			     "using cached credentials instead. "
> -			     "Network resources may be unavailable");
> +			     _("Domain Controller unreachable, "
> +			       "using cached credentials instead. "
> +			       "Network resources may be unavailable"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s logged on using cached credentials\n",
>  			       username);
> @@ -1206,10 +1225,10 @@ static void _pam_warn_krb5_failure(struct pwb_context *ctx,
>  {
>  	if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) {
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Failed to establish your Kerberos Ticket cache "
> -			     "due time differences\n"
> -			     "with the domain controller.  "
> -			     "Please verify the system time.\n");
> +			     _("Failed to establish your Kerberos Ticket cache "
> +			       "due time differences\n"
> +			       "with the domain controller.  "
> +			       "Please verify the system time.\n"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s: Clock skew when getting Krb5 TGT\n",
>  			       username);
> @@ -1236,14 +1255,14 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo
>  
>  	memset(str, '\0', str_size);
>  
> -	offset = snprintf(str, str_size, "Your password ");
> +	offset = snprintf(str, str_size, _("Your password "));
>  	if (offset == -1) {
>  		goto failed;
>  	}
>  
>  	if (response->data.auth.policy.min_length_password > 0) {
>  		ret = snprintf(str+offset, str_size-offset,
> -			       "must be at least %d characters; ",
> +			       _("must be at least %d characters; "),
>  			       response->data.auth.policy.min_length_password);
>  		if (ret == -1) {
>  			goto failed;
> @@ -1253,8 +1272,8 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo
>  
>  	if (response->data.auth.policy.password_history > 0) {
>  		ret = snprintf(str+offset, str_size-offset,
> -			       "cannot repeat any of your previous %d "
> -			       "passwords; ",
> +			       _("cannot repeat any of your previous %d "
> +			         "passwords; "),
>  			       response->data.auth.policy.password_history);
>  		if (ret == -1) {
>  			goto failed;
> @@ -1265,10 +1284,10 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo
>  	if (response->data.auth.policy.password_properties &
>  	    DOMAIN_PASSWORD_COMPLEX) {
>  		ret = snprintf(str+offset, str_size-offset,
> -			       "must contain capitals, numerals "
> -			       "or punctuation; "
> -			       "and cannot contain your account "
> -			       "or full name; ");
> +			       _("must contain capitals, numerals "
> +			         "or punctuation; "
> +			         "and cannot contain your account "
> +			         "or full name; "));
>  		if (ret == -1) {
>  			goto failed;
>  		}
> @@ -1276,9 +1295,9 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo
>  	}
>  
>  	ret = snprintf(str+offset, str_size-offset,
> -		       "Please type a different password. "
> -		       "Type a password which meets these requirements in "
> -		       "both text boxes.");
> +		       _("Please type a different password. "
> +		         "Type a password which meets these requirements in "
> +		         "both text boxes."));
>  	if (ret == -1) {
>  		goto failed;
>  	}
> @@ -1578,8 +1597,8 @@ static int winbind_chauthtok_request(struct pwb_context *ctx,
>  				break;
>  			case SAMR_REJECT_COMPLEXITY:
>  				_make_remark(ctx, PAM_ERROR_MSG,
> -					     "Password does not meet "
> -					     "complexity requirements");
> +					     _("Password does not meet "
> +					       "complexity requirements"));
>  				break;
>  			default:
>  				_pam_log_debug(ctx, LOG_DEBUG,
> @@ -1953,7 +1972,7 @@ static char winbind_get_separator(struct pwb_context *ctx)
>  
>  	ZERO_STRUCT(request);
>  	ZERO_STRUCT(response);
> -
> +	
>  	if (pam_winbind_request_log(ctx, WINBINDD_INFO,
>  				    &request, &response, NULL)) {
>  		return '\0';
> @@ -2092,7 +2111,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
>  	}
>  
>  	retval = _winbind_read_password(ctx, ctx->ctrl, NULL,
> -					"Password: ", NULL,
> +					_("Password: "), NULL,
>  					&password);
>  
>  	if (retval != PAM_SUCCESS) {
> @@ -2567,7 +2586,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  		time_t pwdlastset_prelim = 0;
>  
>  		/* instruct user what is happening */
> -#define greeting "Changing password for "
> +#define greeting _("Changing password for ")
>  		Announce = (char *) malloc(sizeof(greeting) + strlen(user));
>  		if (Announce == NULL) {
>  			_pam_log(ctx, LOG_CRIT,
> @@ -2582,7 +2601,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  		lctrl = ctx->ctrl | WINBIND__OLD_PASSWORD;
>  		ret = _winbind_read_password(ctx, lctrl,
>  						Announce,
> -						"(current) NT password: ",
> +						_("(current) NT password: "),
>  						NULL,
>  						(const char **) &pass_old);
>  		if (ret != PAM_SUCCESS) {
> @@ -2650,8 +2669,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  
>  			ret = _winbind_read_password(ctx, lctrl,
>  						     NULL,
> -						     "Enter new NT password: ",
> -						     "Retype new NT password: ",
> +						     _("Enter new NT password: "),
> +						     _("Retype new NT password: "),
>  						     (const char **)&pass_new);
>  
>  			if (ret != PAM_SUCCESS) {
> diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h
> index c8c1910..7db8718 100644
> --- a/source/nsswitch/pam_winbind.h
> +++ b/source/nsswitch/pam_winbind.h
> @@ -7,6 +7,7 @@
>  #include "lib/replace/replace.h"
>  #include "system/syslog.h"
>  #include "system/time.h"
> +#include "localedir.h"
>  
>  #define MODULE_NAME "pam_winbind"
>  #define PAM_SM_AUTH
> @@ -20,6 +21,10 @@
>  
>  #include <iniparser.h>
>  
> +#ifdef HAVE_LIBINTL_H
> +#include <libintl.h>
> +#endif
> +
>  #ifndef LINUX
>  
>  /* Solaris always uses dynamic pam modules */
> @@ -102,8 +107,22 @@ do {                             \
>   * here is the string to inform the user that the new passwords they
>   * typed were not the same.
>   */
> + 
> +#if 0
> +#ifndef LOCALEDIR
> +#define LOCALEDIR "/usr/share/locale"
> +#endif
> +#endif
> +
> +#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
> +#define _(string) dgettext(MODULE_NAME, string)
> +#else
> +#define _(string) string
> +#endif
> +
> +#define N_(string) string
>  
> -#define MISTYPED_PASS "Sorry, passwords do not match"
> +#define MISTYPED_PASS _("Sorry, passwords do not match")
>  
>  #define on(x, y) (x & y)
>  #define off(x, y) (!(x & y))
> diff --git a/source/script/installmo.sh b/source/script/installmo.sh
> new file mode 100644
> index 0000000..0581853
> --- /dev/null
> +++ b/source/script/installmo.sh
> @@ -0,0 +1,83 @@
> +#!/bin/sh
> +
> +DESTDIR=$1
> +LOCALEDIR=`echo $2 | sed 's/\/\//\//g'`
> +SRCDIR=$3/
> +MSGFMT=msgfmt
> +
> +case $0 in
> +	*uninstall*)
> +		if test ! -d "$DESTDIR/$LOCALEDIR"; then
> +			echo "Directory $DESTDIR/$LOCALEDIR doesn't exist!"
> +			echo "Do a \"make installmo\" or \"make install\" first."
> +			exit 1
> +		fi
> +		mode='uninstall'
> +	;;
> +	*)
> +		mode='install'
> +	;;
> +esac
> +
> +for dir in $SRCDIR/locale/*; do
> +	MODULE=`basename $dir`
> +	for f in $SRCDIR/locale/$MODULE/*.po; do
> +		BASE=`basename $f`
> +		LANGUAGE=`echo $BASE | sed 's/\.po//g'`
> +		FNAME="$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/$MODULE.mo"
> +		if test ! -d "$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/"; then
> +			mkdir -p "$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/"
> +		fi
> +		if test "$mode" = 'install'; then
> +			echo "Installing $f as $FNAME"
> +			touch "$FNAME"
> +			$MSGFMT "$f" -f -o "$FNAME"
> +			if test ! -f "$FNAME"; then
> +				echo "Cannot install $FNAME. Does $USER have privileges?"
> +				exit 1
> +			fi
> +			chmod 0644 "$FNAME"
> +		elif test "$mode" = 'uninstall'; then
> +			echo "removing $FNAME"
> +			rm -f "$FNAME"
> +			if test -f "$FNAME"; then
> +				echo "Cannot remove $FNAME. Does $USER have privileges?"
> +				exit 1
> +			fi
> +		else
> +			echo "Unknown mode $mode. script called as $0."
> +			exit 1
> +		fi
> +	done
> +	if test "$mode" = 'install'; then
> +		cat << EOF
> +==============================================================
> +MO files for $MODULE are installed. 
> +==============================================================
> +EOF
> +	else
> +		cat << EOF
> +==============================================================
> +MO files for $MODULE are removed.
> +==============================================================
> +EOF
> +	fi
> +done
> +
> +if test "$mode" = 'install'; then
> +	cat << EOF
> +==============================================================
> +All MO files for Samba are installed. You can use "make uninstall"
> +or "make uninstallmo" to remove them.
> +==============================================================
> +EOF
> +else
> +	cat << EOF
> +==============================================================
> +All MO files for Samba are removed. you can use "make install"
> +or "make installmo" to install them.
> +==============================================================
> +EOF
> +fi
> +
> +exit 0
> diff --git a/source/script/uninstallmo.sh b/source/script/uninstallmo.sh
> new file mode 120000
> index 0000000..1a2cb68
> --- /dev/null
> +++ b/source/script/uninstallmo.sh
> @@ -0,0 +1 @@
> +installmo.sh
> \ No newline at end of file
>   
> ------------------------------------------------------------------------
>
> commit 46e5ab0479818193cf51835456ed3f3efecc9a4f
> Author: boyang <boyang at desktop.boyang.novell.com>
> Date:   Thu Oct 30 14:11:13 2008 +0800
>
>     i18n/l10n pam_winbind
>
> diff --git a/source/Makefile.in b/source/Makefile.in
> index b67cfe8..e52346e 100644
> --- a/source/Makefile.in
> +++ b/source/Makefile.in
> @@ -137,6 +137,9 @@ PRIVATE_DIR = $(PRIVATEDIR)
>  # This is where SWAT images and help files go
>  SWATDIR = @swatdir@
>  
> +# This is where locale(mo) files go
> +LOCALEDIR= @localedir@
> +
>  # the directory where lock files go
>  LOCKDIR = @lockdir@
>  
> @@ -174,7 +177,8 @@ PATH_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" \
>  	-DCONFIGDIR=\"$(CONFIGDIR)\" \
>  	-DCODEPAGEDIR=\"$(CODEPAGEDIR)\" \
>  	-DCACHEDIR=\"$(CACHEDIR)\" \
> -	-DSTATEDIR=\"$(STATEDIR)\"
> +	-DSTATEDIR=\"$(STATEDIR)\" \
> +	-DLOCALEDIR=\"$(LOCALEDIR)\"
>  
>  # Note that all executable programs now provide for an optional executable suffix.
>  
> @@ -775,7 +779,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
>  	     $(LIBADS_OBJ) $(POPT_LIB_OBJ) \
>  	     $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(LDB_OBJ) 
>  
> -PAM_WINBIND_OBJ = nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \
> +PAM_WINBIND_OBJ = nsswitch/pam_winbind.o localedir.o $(WBCOMMON_OBJ) \
>  		  $(LIBREPLACE_OBJ) @BUILD_INIPARSER@
>  
>  LIBSMBCLIENT_OBJ0 = \
> @@ -1256,6 +1260,13 @@ dynconfig.o: dynconfig.c Makefile
>  		echo "$(COMPILE_CC_PATH)" 1>&2;\
>  		$(COMPILE_CC_PATH) >/dev/null 2>&1
>  
> +localedir.o: localedir.c Makefile
> +	@echo Compiling $*.c
> +	@$(COMPILE_CC_PATH) && exit 0;\
> +		echo "The following command failed:" 1>&2;\
> +		echo "$(COMPILE_CC_PATH)" 1>&2;\
> +		$(COMPILE_CC_PATH) >/dev/null 2>&1
> +		
>  lib/pidfile.o: lib/pidfile.c
>  	@echo Compiling $*.c
>  	@$(COMPILE_CC_PATH) && exit 0;\
> @@ -2463,7 +2474,7 @@ bin/rpc_open_tcp at EXEEXT@: $(BINARY_PREREQS) $(RPC_OPEN_TCP_OBJ) @LIBTALLOC_SHARE
>  
>  install:: installservers installbin @INSTALL_CIFSMOUNT@ @INSTALL_CIFSUPCALL@ installman \
>  		installscripts installdat installmodules @SWAT_INSTALL_TARGETS@ \
> -		@INSTALL_PAM_MODULES@ installlibs
> +		@INSTALL_PAM_MODULES@ installlibs installmo
>  
>  install-everything:: install installmodules
>  
> @@ -2476,7 +2487,7 @@ install-everything:: install installmodules
>  # is not used
>  
>  installdirs::
> -	@$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR) $(CODEPAGEDIR) $(MODULESDIR)
> +	@$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR) $(CODEPAGEDIR) $(MODULESDIR) $(LOCALEDIR)
>  
>  installservers:: all installdirs
>  	@$(SHELL) script/installbin.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(SBINDIR) $(SBIN_PROGS)
> @@ -2540,6 +2551,9 @@ revert::
>  installman:: installdirs
>  	@$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@"
>  
> +installmo:: all installdirs
> +	@$(SHELL) $(srcdir)/script/installmo.sh $(DESTDIR) $(LOCALEDIR) $(srcdir)
> +
>  .PHONY: showlayout
>  
>  showlayout::
> @@ -2559,8 +2573,11 @@ showlayout::
>  	@echo "  codepagedir: $(CODEPAGEDIR)"
>  
>  
> -uninstall:: uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ @UNINSTALL_CIFSUPCALL@ uninstallscripts uninstalldat uninstallswat uninstallmodules uninstalllibs @UNINSTALL_PAM_MODULES@
> +uninstall:: uninstallmo uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ @UNINSTALL_CIFSUPCALL@ uninstallscripts uninstalldat uninstallswat uninstallmodules uninstalllibs @UNINSTALL_PAM_MODULES@
>  
> +uninstallmo::
> +	@$(SHELL) $(srcdir)/script/uninstallmo.sh $(DESTDIR) $(LOCALEDIR) $(srcdir)
> +       
>  uninstallman::
>  	@$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) C
>  
> @@ -2604,7 +2621,7 @@ uninstallpammodules::
>  	done
>  
>  # Toplevel clean files
> -TOPFILES=dynconfig.o
> +TOPFILES=dynconfig.o localedir.o
>  
>  clean:: cleanlibs
>  	-rm -f include/build_env.h
> diff --git a/source/configure.in b/source/configure.in
> index f813e87..7d8a882 100644
> --- a/source/configure.in
> +++ b/source/configure.in
> @@ -662,7 +662,7 @@ LIBS="${LIBS} ${LIBDL} ${LIBREPLACE_NETWORK_LIBS}"
>  
>  AC_CHECK_HEADERS(aio.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h)
>  AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h memory.h alloca.h)
> -AC_CHECK_HEADERS(limits.h float.h pthread.h)
> +AC_CHECK_HEADERS(limits.h float.h pthread.h libintl.h)
>  AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
>  AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
>  AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h)
> @@ -1040,6 +1040,7 @@ AC_CHECK_FUNCS(memalign posix_memalign hstrerror)
>  AC_CHECK_HEADERS(sys/mman.h)
>  # setbuffer, shmget, shm_open are needed for smbtorture
>  AC_CHECK_FUNCS(setbuffer shmget shm_open)
> +AC_CHECK_FUNCS(gettext dgettext)
>  
>  # Find a method of generating a stack trace
>  AC_CHECK_HEADERS(execinfo.h libexc.h libunwind.h)
> diff --git a/source/include/localedir.h b/source/include/localedir.h
> new file mode 100644
> index 0000000..2a291d3
> --- /dev/null
> +++ b/source/include/localedir.h
> @@ -0,0 +1,6 @@
> +#ifndef __LOCALEDIR_H__
> +#define __LOCALEDIR_H__
> +
> +extern const char *dyn_LOCALEDIR;
> +
> +#endif
> diff --git a/source/locale/pam_winbind/genmsg b/source/locale/pam_winbind/genmsg
> new file mode 100644
> index 0000000..5aa258a
> --- /dev/null
> +++ b/source/locale/pam_winbind/genmsg
> @@ -0,0 +1,25 @@
> +#!/bin/sh
> +
> +FILES="../../nsswitch/pam_winbind.c ../../nsswitch/pam_winbind.h"
> +LANGS="af ar bg bn bs ca cs cy da de el en_GB en_US es et fi fr gl gu he hi hr hu id it ja ka km ko lo lt mk mr nb nl pa pl pt_BR pt ro ru si sk sl sr sv ta th tr uk vi wa xh zh_CN zh_TW zu"
> +
> +XGETTEXT=xgettext
> +MSGMERGE=msgmerge
> +
> +WIDTH=256
> +
> +$XGETTEXT --default-domain="pam_winbind" \
> +	--add-comments \
> +	--keyword=_ --keyword=N_ \
> +	--width=${WIDTH} \
> +	${FILES}
> +
> +for lang in ${LANGS}; do
> +	echo -n $lang
> +	touch ${lang}.po
> +	mv ${lang}.po ${lang}.po.old
> +	${MSGMERGE} --width=${WIDTH} ${lang}.po.old pam_winbind.po -o ${lang}.po
> +	rm -fr ${lang}.po.old
> +done
> +
> +rm -fr pam_winbind.po
> diff --git a/source/localedir.c b/source/localedir.c
> new file mode 100644
> index 0000000..20f6921
> --- /dev/null
> +++ b/source/localedir.c
> @@ -0,0 +1,3 @@
> +#include "localedir.h"
> +
> +const char *dyn_LOCALEDIR = LOCALEDIR;
> diff --git a/source/m4/check_path.m4 b/source/m4/check_path.m4
> index 7aa8c21..77e571b 100644
> --- a/source/m4/check_path.m4
> +++ b/source/m4/check_path.m4
> @@ -29,6 +29,7 @@ swatdir="\${prefix}/swat"
>  codepagedir="\${MODULESDIR}"
>  statedir="\${LOCKDIR}"
>  cachedir="\${LOCKDIR}"
> +localedir="\${prefix}/share/locale"
>  
>  AC_ARG_WITH(fhs,
>  [AS_HELP_STRING([--with-fhs],[Use FHS-compliant paths (default=no)])],
> @@ -224,6 +225,23 @@ AC_ARG_WITH(mandir,
>      ;;
>    esac])
>  
> +################################################
> +# set locale directory location
> +AC_ARG_WITH(localedir,
> +[  --with-localedir=DIR    Where to put po files ($ac_default_prefix/share/locale)],
> +[ case "$withval" in
> +  yes|no)
> +    #
> +    # Just in case anybody does it
> +    #
> +    AC_MSG_WARN([--with-localedir called without argument - will use default])
> +  ;;
> +  *)
> +  localedir="$withval"
> +  ;;
> +  esac])
> +			
> +
>  AC_SUBST(configdir)
>  AC_SUBST(lockdir)
>  AC_SUBST(piddir)
> @@ -239,6 +257,7 @@ AC_SUBST(cachedir)
>  AC_SUBST(rootsbindir)
>  AC_SUBST(pammodulesdir)
>  AC_SUBST(modulesdir)
> +AC_SUBST(localedir)
>  
>  #################################################
>  # set prefix for 'make test'
> diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
> index c28c5d2..a000b03 100644
> --- a/source/nsswitch/pam_winbind.c
> +++ b/source/nsswitch/pam_winbind.c
> @@ -103,6 +103,21 @@ static const char *_pam_error_code_str(int err)
>  
>  #define MAX_PASSWD_TRIES	3
>  
> +#ifdef HAVE_GETTEXT
> +static char initialized = 0;
> +
> +static inline void textdomain_init(void);
> +static inline void textdomain_init(void)
> +{
> +	if (!initialized) {
> +		bindtextdomain(MODULE_NAME, dyn_LOCALEDIR);
> +		initialized = 1;
> +	}
> +	return;
> +}
> +#endif
> +
> +
>  /*
>   * Work around the pam API that has functions with void ** as parameters
>   * These lead to strict aliasing warnings with gcc.
> @@ -461,6 +476,10 @@ static int _pam_winbind_init_context(pam_handle_t *pamh,
>  {
>  	struct pwb_context *r = NULL;
>  
> +	#ifdef HAVE_GETTEXT
> +	textdomain_init();
> +	#endif
> +
>  	r = (struct pwb_context *)malloc(sizeof(struct pwb_context));
>  	if (!r) {
>  		return PAM_BUF_ERR;
> @@ -503,44 +522,44 @@ static const struct ntstatus_errors {
>  	const char *error_string;
>  } ntstatus_errors[] = {
>  	{"NT_STATUS_OK",
> -		"Success"},
> +		N_("Success")},
>  	{"NT_STATUS_BACKUP_CONTROLLER",
> -		"No primary Domain Controler available"},
> +		N_("No primary Domain Controler available")},
>  	{"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
> -		"No domain controllers found"},
> +		N_("No domain controllers found")},
>  	{"NT_STATUS_NO_LOGON_SERVERS",
> -		"No logon servers"},
> +		N_("No logon servers")},
>  	{"NT_STATUS_PWD_TOO_SHORT",
> -		"Password too short"},
> +		N_("Password too short")},
>  	{"NT_STATUS_PWD_TOO_RECENT",
> -		"The password of this user is too recent to change"},
> +		N_("The password of this user is too recent to change")},
>  	{"NT_STATUS_PWD_HISTORY_CONFLICT",
> -		"Password is already in password history"},
> +		N_("Password is already in password history")},
>  	{"NT_STATUS_PASSWORD_EXPIRED",
> -		"Your password has expired"},
> +		N_("Your password has expired")},
>  	{"NT_STATUS_PASSWORD_MUST_CHANGE",
> -		"You need to change your password now"},
> +		N_("You need to change your password now")},
>  	{"NT_STATUS_INVALID_WORKSTATION",
> -		"You are not allowed to logon from this workstation"},
> +		N_("You are not allowed to logon from this workstation")},
>  	{"NT_STATUS_INVALID_LOGON_HOURS",
> -		"You are not allowed to logon at this time"},
> +		N_("You are not allowed to logon at this time")},
>  	{"NT_STATUS_ACCOUNT_EXPIRED",
>  		"Your account has expired. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_ACCOUNT_DISABLED",
>  		"Your account is disabled. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_ACCOUNT_LOCKED_OUT",
>  		"Your account has been locked. "
> -		"Please contact your System administrator"}, /* SCNR */
> +		N_("Please contact your System administrator")}, /* SCNR */
>  	{"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
> -		"Invalid Trust Account"},
> +		N_("Invalid Trust Account")},
>  	{"NT_STATUS_ACCESS_DENIED",
> -		"Access is denied"},
> +		N_("Access is denied")},
>  	{NULL, NULL}
>  };
>  
> @@ -550,7 +569,7 @@ static const char *_get_ntstatus_error_string(const char *nt_status_string)
>  	for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) {
>  		if (!strcasecmp(ntstatus_errors[i].ntstatus_string,
>  				nt_status_string)) {
> -			return ntstatus_errors[i].error_string;
> +			return _(ntstatus_errors[i].error_string);
>  		}
>  	}
>  	return NULL;
> @@ -815,14 +834,14 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
>  
>  	if (days == 0) {
>  		_make_remark(ctx, PAM_TEXT_INFO,
> -			     "Your password expires today");
> +			     _("Your password expires today"));
>  		return true;
>  	}
>  
>  	if (days > 0 && days < warn_pwd_expire) {
>  		_make_remark_format(ctx, PAM_TEXT_INFO,
> -				    "Your password will expire in %d %s",
> -				    days, (days > 1) ? "days":"day");
> +				    _("Your password will expire in %d %s"),
> +				    days, (days > 1) ? _("days"):_("day"));
>  		return true;
>  	}
>  
> @@ -1163,9 +1182,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
>  	if (PAM_WB_GRACE_LOGON(info3_user_flgs)) {
>  
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Grace login. "
> -			     "Please change your password as soon you're "
> -			     "online again");
> +			     _("Grace login. "
> +			       "Please change your password as soon you're "
> +			       "online again"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s logged on using grace logon\n",
>  			       username);
> @@ -1173,9 +1192,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
>  	} else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) {
>  
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Domain Controller unreachable, "
> -			     "using cached credentials instead. "
> -			     "Network resources may be unavailable");
> +			     _("Domain Controller unreachable, "
> +			       "using cached credentials instead. "
> +			       "Network resources may be unavailable"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s logged on using cached credentials\n",
>  			       username);
> @@ -1198,10 +1217,10 @@ static void _pam_warn_krb5_failure(struct pwb_context *ctx,
>  {
>  	if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) {
>  		_make_remark(ctx, PAM_ERROR_MSG,
> -			     "Failed to establish your Kerberos Ticket cache "
> -			     "due time differences\n"
> -			     "with the domain controller.  "
> -			     "Please verify the system time.\n");
> +			     _("Failed to establish your Kerberos Ticket cache "
> +			       "due time differences\n"
> +			       "with the domain controller.  "
> +			       "Please verify the system time.\n"));
>  		_pam_log_debug(ctx, LOG_DEBUG,
>  			       "User %s: Clock skew when getting Krb5 TGT\n",
>  			       username);
> @@ -1228,14 +1247,14 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo
>  
>  	memset(str, '\0', str_size);
>  
> -	offset = snprintf(str, str_size, "Your password ");
> +	offset = snprintf(str, str_size, _("Your password "));
>  	if (offset == -1) {
>  		goto failed;
>  	}
>  
>  	if (response->data.auth.policy.min_length_password > 0) {
>  		ret = snprintf(str+offset, str_size-offset,
> -			       "must be at least %d characters; ",
> +			       _("must be at least %d characters; "),
>  			       response->data.auth.policy.min_length_password);
>  		if (ret == -1) {
>  			goto failed;
> @@ -1245,8 +1264,8 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo
>  
>  	if (response->data.auth.policy.password_history > 0) {
>  		ret = snprintf(str+offset, str_size-offset,
> -			       "cannot repeat any of your previous %d "
> -			       "passwords; ",
> +			       _("cannot repeat any of your previous %d "
> +			         "passwords; "),
>  			       response->data.auth.policy.password_history);
>  		if (ret == -1) {
>  			goto failed;
> @@ -1257,10 +1276,10 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo
>  	if (response->data.auth.policy.password_properties &
>  	    DOMAIN_PASSWORD_COMPLEX) {
>  		ret = snprintf(str+offset, str_size-offset,
> -			       "must contain capitals, numerals "
> -			       "or punctuation; "
> -			       "and cannot contain your account "
> -			       "or full name; ");
> +			       _("must contain capitals, numerals "
> +			         "or punctuation; "
> +			         "and cannot contain your account "
> +			         "or full name; "));
>  		if (ret == -1) {
>  			goto failed;
>  		}
> @@ -1268,9 +1287,9 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo
>  	}
>  
>  	ret = snprintf(str+offset, str_size-offset,
> -		       "Please type a different password. "
> -		       "Type a password which meets these requirements in "
> -		       "both text boxes.");
> +		       _("Please type a different password. "
> +		         "Type a password which meets these requirements in "
> +		         "both text boxes."));
>  	if (ret == -1) {
>  		goto failed;
>  	}
> @@ -1570,8 +1589,8 @@ static int winbind_chauthtok_request(struct pwb_context *ctx,
>  				break;
>  			case SAMR_REJECT_COMPLEXITY:
>  				_make_remark(ctx, PAM_ERROR_MSG,
> -					     "Password does not meet "
> -					     "complexity requirements");
> +					     _("Password does not meet "
> +					       "complexity requirements"));
>  				break;
>  			default:
>  				_pam_log_debug(ctx, LOG_DEBUG,
> @@ -1945,7 +1964,7 @@ static char winbind_get_separator(struct pwb_context *ctx)
>  
>  	ZERO_STRUCT(request);
>  	ZERO_STRUCT(response);
> -
> +	
>  	if (pam_winbind_request_log(ctx, WINBINDD_INFO,
>  				    &request, &response, NULL)) {
>  		return '\0';
> @@ -2084,7 +2103,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
>  	}
>  
>  	retval = _winbind_read_password(ctx, ctx->ctrl, NULL,
> -					"Password: ", NULL,
> +					_("Password: "), NULL,
>  					&password);
>  
>  	if (retval != PAM_SUCCESS) {
> @@ -2552,7 +2571,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  		time_t pwdlastset_prelim = 0;
>  
>  		/* instruct user what is happening */
> -#define greeting "Changing password for "
> +#define greeting _("Changing password for ")
>  		Announce = (char *) malloc(sizeof(greeting) + strlen(user));
>  		if (Announce == NULL) {
>  			_pam_log(ctx, LOG_CRIT,
> @@ -2567,7 +2586,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  		lctrl = ctx->ctrl | WINBIND__OLD_PASSWORD;
>  		ret = _winbind_read_password(ctx, lctrl,
>  						Announce,
> -						"(current) NT password: ",
> +						_("(current) NT password: "),
>  						NULL,
>  						(const char **) &pass_old);
>  		if (ret != PAM_SUCCESS) {
> @@ -2635,8 +2654,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
>  
>  			ret = _winbind_read_password(ctx, lctrl,
>  						     NULL,
> -						     "Enter new NT password: ",
> -						     "Retype new NT password: ",
> +						     _("Enter new NT password: "),
> +						     _("Retype new NT password: "),
>  						     (const char **)&pass_new);
>  
>  			if (ret != PAM_SUCCESS) {
> diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h
> index c8c1910..7db8718 100644
> --- a/source/nsswitch/pam_winbind.h
> +++ b/source/nsswitch/pam_winbind.h
> @@ -7,6 +7,7 @@
>  #include "lib/replace/replace.h"
>  #include "system/syslog.h"
>  #include "system/time.h"
> +#include "localedir.h"
>  
>  #define MODULE_NAME "pam_winbind"
>  #define PAM_SM_AUTH
> @@ -20,6 +21,10 @@
>  
>  #include <iniparser.h>
>  
> +#ifdef HAVE_LIBINTL_H
> +#include <libintl.h>
> +#endif
> +
>  #ifndef LINUX
>  
>  /* Solaris always uses dynamic pam modules */
> @@ -102,8 +107,22 @@ do {                             \
>   * here is the string to inform the user that the new passwords they
>   * typed were not the same.
>   */
> + 
> +#if 0
> +#ifndef LOCALEDIR
> +#define LOCALEDIR "/usr/share/locale"
> +#endif
> +#endif
> +
> +#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
> +#define _(string) dgettext(MODULE_NAME, string)
> +#else
> +#define _(string) string
> +#endif
> +
> +#define N_(string) string
>  
> -#define MISTYPED_PASS "Sorry, passwords do not match"
> +#define MISTYPED_PASS _("Sorry, passwords do not match")
>  
>  #define on(x, y) (x & y)
>  #define off(x, y) (!(x & y))
> diff --git a/source/script/installmo.sh b/source/script/installmo.sh
> new file mode 100644
> index 0000000..0581853
> --- /dev/null
> +++ b/source/script/installmo.sh
> @@ -0,0 +1,83 @@
> +#!/bin/sh
> +
> +DESTDIR=$1
> +LOCALEDIR=`echo $2 | sed 's/\/\//\//g'`
> +SRCDIR=$3/
> +MSGFMT=msgfmt
> +
> +case $0 in
> +	*uninstall*)
> +		if test ! -d "$DESTDIR/$LOCALEDIR"; then
> +			echo "Directory $DESTDIR/$LOCALEDIR doesn't exist!"
> +			echo "Do a \"make installmo\" or \"make install\" first."
> +			exit 1
> +		fi
> +		mode='uninstall'
> +	;;
> +	*)
> +		mode='install'
> +	;;
> +esac
> +
> +for dir in $SRCDIR/locale/*; do
> +	MODULE=`basename $dir`
> +	for f in $SRCDIR/locale/$MODULE/*.po; do
> +		BASE=`basename $f`
> +		LANGUAGE=`echo $BASE | sed 's/\.po//g'`
> +		FNAME="$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/$MODULE.mo"
> +		if test ! -d "$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/"; then
> +			mkdir -p "$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/"
> +		fi
> +		if test "$mode" = 'install'; then
> +			echo "Installing $f as $FNAME"
> +			touch "$FNAME"
> +			$MSGFMT "$f" -f -o "$FNAME"
> +			if test ! -f "$FNAME"; then
> +				echo "Cannot install $FNAME. Does $USER have privileges?"
> +				exit 1
> +			fi
> +			chmod 0644 "$FNAME"
> +		elif test "$mode" = 'uninstall'; then
> +			echo "removing $FNAME"
> +			rm -f "$FNAME"
> +			if test -f "$FNAME"; then
> +				echo "Cannot remove $FNAME. Does $USER have privileges?"
> +				exit 1
> +			fi
> +		else
> +			echo "Unknown mode $mode. script called as $0."
> +			exit 1
> +		fi
> +	done
> +	if test "$mode" = 'install'; then
> +		cat << EOF
> +==============================================================
> +MO files for $MODULE are installed. 
> +==============================================================
> +EOF
> +	else
> +		cat << EOF
> +==============================================================
> +MO files for $MODULE are removed.
> +==============================================================
> +EOF
> +	fi
> +done
> +
> +if test "$mode" = 'install'; then
> +	cat << EOF
> +==============================================================
> +All MO files for Samba are installed. You can use "make uninstall"
> +or "make uninstallmo" to remove them.
> +==============================================================
> +EOF
> +else
> +	cat << EOF
> +==============================================================
> +All MO files for Samba are removed. you can use "make install"
> +or "make installmo" to install them.
> +==============================================================
> +EOF
> +fi
> +
> +exit 0
> diff --git a/source/script/uninstallmo.sh b/source/script/uninstallmo.sh
> new file mode 120000
> index 0000000..1a2cb68
> --- /dev/null
> +++ b/source/script/uninstallmo.sh
> @@ -0,0 +1 @@
> +installmo.sh
> \ No newline at end of file
>   

-------------- next part --------------
A non-text attachment was scrubbed...
Name: boyang.vcf
Type: text/x-vcard
Size: 187 bytes
Desc: not available
Url : http://lists.samba.org/archive/samba-technical/attachments/20081031/37557fa4/boyang.vcf


More information about the samba-technical mailing list