Add support for building internationalized translations.

A new directory install/po has been added which contains all
the translations for all files in IPA.

The build has been agumented to build these files. Also the
autogen.sh script was mostly replaced by autoreconf, the preferred
method. The old autogen.sh sript also had some serious bugs in the
way it compared versions which caused it to run old versions of some
of the tools, using standared autoreconf is much better.
This commit is contained in:
John Dennis 2010-02-09 13:14:25 -05:00 committed by Rob Crittenden
parent 0ce253fae4
commit 4461a74403
8 changed files with 991 additions and 205 deletions

View File

@ -1,208 +1,14 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
set -e
PACKAGE=freeipa
LIBTOOLIZE=${LIBTOOLIZE-libtoolize}
LIBTOOLIZE_FLAGS="--copy --force"
AUTOHEADER=${AUTOHEADER-autoheader}
AUTOMAKE_FLAGS="--add-missing --gnu"
AUTOCONF=${AUTOCONF-autoconf}
# automake 1.8 requires autoconf 2.58
# automake 1.7 requires autoconf 2.54
automake_min_vers=1.7
aclocal_min_vers=$automake_min_vers
autoconf_min_vers=2.54
libtoolize_min_vers=1.4
# The awk-based string->number conversion we use needs a C locale to work
# as expected. Setting LC_ALL overrides whether the user set LC_ALL,
# LC_NUMERIC, or LANG.
LC_ALL=C
ARGV0=$0
# Allow invocation from a separate build directory; in that case, we change
# to the source directory to run the auto*, then change back before running configure
#srcdir=`dirname $ARGV0`
#test -z "$srcdir" && srcdir=.
srcdir="."
#ORIGDIR=`pwd`
#cd $srcdir
# Usage:
# compare_versions MIN_VERSION ACTUAL_VERSION
# returns true if ACTUAL_VERSION >= MIN_VERSION
compare_versions() {
ch_min_version=$1
ch_actual_version=$2
ch_status=0
IFS="${IFS= }"; ch_save_IFS="$IFS"; IFS="."
set $ch_actual_version
for ch_min in $ch_min_version; do
ch_cur=`echo $1 | sed 's/[^0-9].*$//'`; shift # remove letter suffixes
if [ -z "$ch_min" ]; then break; fi
if [ -z "$ch_cur" ]; then ch_status=1; break; fi
if [ $ch_cur -gt $ch_min ]; then break; fi
if [ $ch_cur -lt $ch_min ]; then ch_status=1; break; fi
done
IFS="$ch_save_IFS"
return $ch_status
}
if ($AUTOCONF --version) < /dev/null > /dev/null 2>&1 ; then
if ($AUTOCONF --version | head -n 1 | awk 'NR==1 { if( $(NF) >= '$autoconf_min_vers') \
exit 1; exit 0; }');
then
echo "$ARGV0: ERROR: \`$AUTOCONF' is too old."
$AUTOCONF --version
echo " (version $autoconf_min_vers or newer is required)"
DIE="yes"
# automake demands these files exist when run in gnu mode which is the default,
# automake can be run in foreign mode to avoid failing on the absence of these
# files, but unfortunately there is no way to pass the --foreign flag to
# automake when run from autoreconf.
for f in NEWS README AUTHORS ChangeLog; do
if [ ! -e $f ]; then
touch $f
fi
else
echo $AUTOCONF: command not found
echo
echo "$ARGV0: ERROR: You must have \`autoconf' installed to compile $PACKAGE."
echo " (version $autoconf_min_vers or newer is required)"
DIE="yes"
fi
done
#
# Hunt for an appropriate version of automake and aclocal; we can't
# assume that 'automake' is necessarily the most recent installed version
#
# We check automake first to allow it to be a newer version than we know about.
#
if test x"$AUTOMAKE" = x || test x"$ACLOCAL" = x ; then
am_ver=""
for ver in "" "-1.9" "-1.8" "-1.7" ; do
am="automake$ver"
if ($am --version) < /dev/null > /dev/null 2>&1 ; then
if ($am --version | head -n 1 | awk 'NR==1 { if( $(NF) >= '$automake_min_vers') \
exit 1; exit 0; }'); then : ; else
am_ver=$ver
break;
fi
fi
done
AUTOMAKE=${AUTOMAKE-automake$am_ver}
ACLOCAL=${ACLOCAL-aclocal$am_ver}
fi
#
# Now repeat the tests with the copies we decided upon and error out if they
# aren't sufficiently new.
#
if ($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 ; then
automake_actual_version=`$AUTOMAKE --version | head -n 1 | \
sed 's/^.*[ ]\([0-9.]*[a-z]*\).*$/\1/'`
if ! compare_versions $automake_min_vers $automake_actual_version; then
echo "$ARGV0: ERROR: \`$AUTOMAKE' is too old."
$AUTOMAKE --version
echo " (version $automake_min_vers or newer is required)"
DIE="yes"
fi
if ($ACLOCAL --version) < /dev/null > /dev/null 2>&1; then
aclocal_actual_version=`$ACLOCAL --version | head -n 1 | \
sed 's/^.*[ ]\([0-9.]*[a-z]*\).*$/\1/'`
if ! compare_versions $aclocal_min_vers $aclocal_actual_version; then
echo "$ARGV0: ERROR: \`$ACLOCAL' is too old."
$ACLOCAL --version
echo " (version $aclocal_min_vers or newer is required)"
DIE="yes"
fi
else
echo $ACLOCAL: command not found
echo
echo "$ARGV0: ERROR: Missing \`$ACLOCAL'"
echo " The version of $AUTOMAKE installed doesn't appear recent enough."
DIE="yes"
fi
else
echo $AUTOMAKE: command not found
echo
echo "$ARGV0: ERROR: You must have \`automake' installed to compile $PACKAGE."
echo " (version $automake_min_vers or newer is required)"
DIE="yes"
fi
if ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 ; then
if ($LIBTOOLIZE --version | awk 'NR==1 { if( $4 >= '$libtoolize_min_vers') \
exit 1; exit 0; }');
then
echo "$ARGV0: ERROR: \`$LIBTOOLIZE' is too old."
echo " (version $libtoolize_min_vers or newer is required)"
DIE="yes"
fi
else
echo $LIBTOOLIZE: command not found
echo
echo "$ARGV0: ERROR: You must have \`libtoolize' installed to compile $PACKAGE."
echo " (version $libtoolize_min_vers or newer is required)"
DIE="yes"
fi
if test -z "$ACLOCAL_FLAGS"; then
acdir=`$ACLOCAL --print-ac-dir`
if [ ! -f $acdir/pkg.m4 ]; then
echo "$ARGV0: Error: Could not find pkg-config macros."
echo " (Looked in $acdir/pkg.m4)"
echo " If pkg.m4 is available in /another/directory, please set"
echo " ACLOCAL_FLAGS=\"-I /another/directory\""
echo " Otherwise, please install pkg-config."
echo ""
echo "pkg-config is available from:"
echo "http://www.freedesktop.org/software/pkgconfig/"
DIE=yes
fi
fi
if test "X$DIE" != X; then
exit 1
fi
if test -z "$*"; then
echo "$ARGV0: Note: \`./configure' will be run with no arguments."
echo " If you wish to pass any to it, please specify them on the"
echo " \`$0' command line."
echo
fi
do_cmd() {
echo "$ARGV0: running \`$@'"
$@
}
# I don't want a tool telling me what files I need to have
remauto=0
if [ ! -e AUTHORS ]; then
touch AUTHORS ChangeLog NEWS README
remauto=1
fi
do_cmd $LIBTOOLIZE $LIBTOOLIZE_FLAGS
do_cmd $ACLOCAL $ACLOCAL_FLAGS
do_cmd $AUTOHEADER
do_cmd $AUTOMAKE $AUTOMAKE_FLAGS
do_cmd $AUTOCONF
if [ $remauto -eq 1 ]; then
rm -f AUTHORS ChangeLog NEWS README
fi
#cd $ORIGDIR || exit 1
rm -f config.cache
do_cmd $srcdir/configure --cache-file=config.cache --disable-static --enable-maintainer-mode --enable-gtk-doc ${1+"$@"} && echo "Now type \`make' to compile" || exit 1
autoreconf -i
./configure ${1+"$@"}

View File

@ -11,6 +11,7 @@ SUBDIRS = \
share \
tools \
updates \
po \
$(NULL)
install-exec-local:

View File

@ -19,6 +19,35 @@ AM_MAINTAINER_MODE
AC_SUBST(VERSION)
AC_PROG_MKDIR_P
AC_PATH_PROG(XGETTEXT, xgettext, [no])
if test "x$XGETTEXT" = "xno"; then
AC_MSG_ERROR([xgettext not found, install gettext])
fi
AC_PATH_PROG(MSGFMT, msgfmt, [no])
if test "x$MSGFMT" = "xno"; then
AC_MSG_ERROR([msgfmt not found, install gettext])
fi
AC_PATH_PROG(MSGINIT, msginit, [no])
if test "x$MSGINIT" = "xno"; then
AC_MSG_ERROR([msginit not found, install gettext])
fi
AC_PATH_PROG(MSGMERGE, msgmerge, [no])
if test "x$MSGMERGE" = "xno"; then
AC_MSG_ERROR([msgmerge not found, install gettext])
fi
AC_ARG_WITH([gettext_domain],
[AS_HELP_STRING([--with-gettext-domain=name],
[set the name of the i18n message catalog])],
[],
[with_gettext_domain=ipa])
AC_SUBST(GETTEXT_DOMAIN, $with_gettext_domain)
dnl ---------------------------------------------------------------------------
dnl - Set the data install directory since we don't use pkgdatadir
dnl ---------------------------------------------------------------------------
@ -39,6 +68,7 @@ AC_CONFIG_FILES([
tools/Makefile
tools/man/Makefile
updates/Makefile
po/Makefile
])
AC_OUTPUT

0
install/po/LINGUAS Normal file
View File

217
install/po/Makefile.in Normal file
View File

@ -0,0 +1,217 @@
prefix = @prefix@
exec_prefix = ${prefix}
datarootdir = ${prefix}/share
datadir = ${datarootdir}
localedir = ${datarootdir}/locale
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL@ -m 644
MKDIR_P = @MKDIR_P@
XGETTEXT = @XGETTEXT@
MSGFMT = @MSGFMT@
MSGINIT = @MSGINIT@
MSGMERGE = @MSGMERGE@
DOMAIN = @GETTEXT_DOMAIN@
MSGMERGE_UPDATE = $(MSGMERGE) --update
COPYRIGHT_HOLDER = Red Hat
PACKAGE_NAME = $(DOMAIN)
PACKAGE_BUGREPORT = https://hosted.fedoraproject.org/projects/freeipa/newticket
XGETTEXT_OPTIONS = \
--add-comments="TRANSLATORS:" \
--copyright-holder="$(COPYRIGHT_HOLDER)" \
--package-name="$(PACKAGE_NAME)" \
--msgid-bugs-address="$(PACKAGE_BUGREPORT)"
languages = $(shell sed 's/\#.*//' LINGUAS)
po_files = $(patsubst %, %.po, $(languages))
mo_files = $(patsubst %.po, %.mo, $(po_files))
PYTHON_POTFILES = \
../../ipa \
../../lite-server.py \
../../ipapython/config.py \
../../ipapython/sysrestore.py \
../../ipapython/ipasslfile.py \
../../ipapython/__init__.py \
../../ipapython/ipautil.py \
../../ipapython/certdb.py \
../../ipapython/ipavalidate.py \
../../ipapython/dnsclient.py \
../../ipapython/dogtag.py \
../../ipapython/nsslib.py \
../../ipapython/entity.py \
../../install/tools/ipa-replica-manage \
../../install/tools/ipa-server-certinstall \
../../install/tools/ipa-replica-install \
../../install/tools/ipa-nis-manage \
../../install/tools/ipa-upgradeconfig \
../../install/tools/ipa-replica-prepare \
../../install/tools/ipa-compat-manage \
../../install/tools/ipa-server-install \
../../install/tools/ipa-ldap-updater \
../../install/migration/migration.py \
../../ipalib/config.py \
../../ipalib/parameters.py \
../../ipalib/request.py \
../../ipalib/output.py \
../../ipalib/__init__.py \
../../ipalib/backend.py \
../../ipalib/pkcs10.py \
../../ipalib/x509.py \
../../ipalib/plugable.py \
../../ipalib/constants.py \
../../ipalib/aci.py \
../../ipalib/base.py \
../../ipalib/ipauuid.py \
../../ipalib/crud.py \
../../ipalib/cli.py \
../../ipalib/text.py \
../../ipalib/compat.py \
../../ipalib/frontend.py \
../../ipalib/rpc.py \
../../ipalib/errors.py \
../../ipalib/encoder.py \
../../ipalib/util.py \
../../ipalib/plugins/config.py \
../../ipalib/plugins/rolegroup.py \
../../ipalib/plugins/host.py \
../../ipalib/plugins/group.py \
../../ipalib/plugins/migration.py \
../../ipalib/plugins/xmlclient.py \
../../ipalib/plugins/service.py \
../../ipalib/plugins/passwd.py \
../../ipalib/plugins/__init__.py \
../../ipalib/plugins/virtual.py \
../../ipalib/plugins/hbac.py \
../../ipalib/plugins/cert.py \
../../ipalib/plugins/baseldap.py \
../../ipalib/plugins/aci.py \
../../ipalib/plugins/kerberos.py \
../../ipalib/plugins/krbtpolicy.py \
../../ipalib/plugins/dns.py \
../../ipalib/plugins/automount.py \
../../ipalib/plugins/netgroup.py \
../../ipalib/plugins/misc.py \
../../ipalib/plugins/user.py \
../../ipalib/plugins/taskgroup.py \
../../ipalib/plugins/hostgroup.py \
../../ipalib/plugins/pwpolicy.py \
../../ipaserver/__init__.py \
../../ipaserver/servercore.py \
../../ipaserver/ipautil.py \
../../ipaserver/rpcserver.py \
../../ipaserver/conn.py \
../../ipaserver/ipaldap.py \
../../ipaserver/install/installutils.py \
../../ipaserver/install/service.py \
../../ipaserver/install/ldapupdate.py \
../../ipaserver/install/__init__.py \
../../ipaserver/install/cainstance.py \
../../ipaserver/install/ntpinstance.py \
../../ipaserver/install/bindinstance.py \
../../ipaserver/install/krbinstance.py \
../../ipaserver/install/certs.py \
../../ipaserver/install/dsinstance.py \
../../ipaserver/install/replication.py \
../../ipaserver/install/httpinstance.py \
../../ipaserver/plugins/ldap2.py \
../../ipaserver/plugins/rabase.py \
../../ipaserver/plugins/selfsign.py \
../../ipaserver/plugins/__init__.py \
../../ipaserver/plugins/join.py \
../../ipaserver/plugins/ldapapi.py \
../../ipaserver/plugins/xmlserver.py \
../../ipaserver/plugins/dogtag.py \
../../contrib/RHEL4/ipachangeconf.py \
../../ipawebui/engine.py \
../../ipawebui/__init__.py \
../../ipawebui/widgets.py \
../../ipawebui/controllers.py \
../../ipa-client/ipaclient/ntpconf.py \
../../ipa-client/ipaclient/__init__.py \
../../ipa-client/ipaclient/ipachangeconf.py \
../../ipa-client/ipaclient/ipadiscovery.py \
../../ipa-client/ipa-install/ipa-client-install
C_POTFILES = \
../../daemons/ipa-kpasswd/ipa_kpasswd.c \
../../daemons/ipa-slapi-plugins/ipa-enrollment/ipa_enrollment.c \
../../daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof.c \
../../daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof.h \
../../daemons/ipa-slapi-plugins/ipa-memberof/ipa-memberof_config.c \
../../daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c \
../../daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync-config.c \
../../daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync.c \
../../daemons/ipa-slapi-plugins/ipa-winsync/ipa-winsync.h \
../../ipa-client/config.c \
../../ipa-client/ipa-getkeytab.c \
../../ipa-client/ipa-join.c \
../../ipa-client/ipa-rmkeytab.c
POTFILES = $(PYTHON_POTFILES) $(C_POTFILES)
.SUFFIXES:
.SUFFIXES: .po .mo
all: $(po_files)
@
SUFFIXES = .po .mo
.po.mo:
@echo Creating $@; \
$(MSGFMT) -c -o t-$@ $< && mv t-$@ $@
$(po_files): $(DOMAIN).pot
@if [ ! -f @a ]; then \
echo Creating nonexistent $@, you should add this file to your SCM repository; \
$(MSGINIT) --locale en_US --no-translator -i $(DOMAIN).pot -o $@; \
fi; \
$(MSGMERGE) $@ -o $@ $(DOMAIN).pot
create-po: $(DOMAIN).pot
@for po_file in $(po_files); do \
if [ ! -e $$po_file ]; then \
echo Creating nonexistent $$po_file, you should add this file to your SCM repository; \
$(MSGINIT) --locale en_US --no-translator -i $(DOMAIN).pot -o $$po_file; \
fi; \
done
$(DOMAIN).pot: $(POTFILES)
$(MAKE) update-pot
update-po: update-pot
$(MAKE) all
update-pot:
rm -f $(DOMAIN).pot.update
$(XGETTEXT) $(XGETTEXT_OPTIONS) \
--output $(DOMAIN).pot.update \
--language="python" \
$(PYTHON_POTFILES) \
&& \
$(XGETTEXT) $(XGETTEXT_OPTIONS) \
--output $(DOMAIN).pot.update \
--join-existing \
--language="c" \
$(C_POTFILES) \
&& \
mv $(DOMAIN).pot.update $(DOMAIN).pot
install: $(mo_files)
@for lang in $(languages); do \
dstdir=$(DESTDIR)$(localedir)/$$lang/LC_MESSAGES; \
$(MKDIR_P) $$dstdir; \
$(INSTALL) $$lang.mo $$dstdir/$(DOMAIN).mo; \
done
mostlyclean:
rm -f *.mo
clean: mostlyclean
distclean: clean
rm -f Makefile

123
install/po/README Normal file
View File

@ -0,0 +1,123 @@
Q: I've added a new source file, how do I make sure it's strings get translated?
A: Edit Makefile.in and add the source file to the appropriate *_POTFILES list.
Then run "make update-po".
Q: How do I pick up new strings to translate from the source files after the
source have been modified?
A: make update-po
This regenerates the pot template file by scanning all the source files.
Then the new strings are merged into each .po file from the new pot file.
Q: How do I just regenerate the pot template file without regenerating all the
.po files?
A: make update-pot
Q: How do I add a new language for translation?
A: Edit the LINGUAS file and add the new language. Then run "make create-po".
This will generate a new .po file for each language which doesn't have one
yet. Be sure to add the new .po file(s) to the source code repository.
Q: What files must be under source code control?
A: The files Makefile.in, LINGUAS control the build, they must be in the SCM.
The *.pot and *.po files are used by translators, they must be in SCM so the
translator can checkout out a .po files, add the translations, and then check
the .po file back in.
Be careful, .po files may be automatically updated when the source files
change (or the .pot changes, usually the .pot file changes only as a result
of rescanning the source files). This mean a .po file might be automatically
updated while a translator has the file out for editing, all the caveats
about SCM merging apply.
Q: Which are automatically generated and thus do not need to be in SCM?
A: The *.mo files are automatically generated on demand from their corresponding
.po file.
Q: What role does the .pot file play?
A: The .pot file is called a template file. It is generated by scanning all the
source files (e.g. *.py *.c *.h) in the project using xgettext. xgettext
locates every translatable string (e.g. strings marked with _()) and adds
that string along with metadata about it's location to the .pot file. Thus
the .pot file is a collection of every translatable string in the project. If
you edit a source file and add a translatable string you will have to
regenerate the .pot file in order to pick up the new string.
Q: What is the relationship between a .po file and the .pot file?
A: A .po file contains the translations for particular language. It derives from
the .pot file. When the .pot file is updated with new strings to translate
each .po will merge the new strings in. The .po file is where translators
work providing translations for their language. Thus it's important the .po
not be recreated from scratch and is kept in SCM, otherwise the translators
work will be lost.
Let's use an example for French, it's .po file will be fr.po.
1) Developer creates main.c with one translatable sting _("Begin").
2) Produce the .pot file by running xgettext on main.c
3) .pot file contains one msgid, "Begin"
4) fr.po is created from the .pot file, it also contains one msgid, "Begin"
5) Translator edits fr.po and provide the French translation of "Begin".
6) Developer adds new translatable sting _("End") to main.c
7) Generate a new .pot file by running xgettext on main.c
8) .pot file contains two msgid's, "Begin", and "End"
9) fr.po is missing the new msgid in the .pot file, so the .pot is merged
into fr.po by running msgmerge. This copies into fr.po the new "End" msgid
but preserves the existing translations in fr.po (e.g. "Begin"). The fr.po
will now have 2 msgid's one which is translated already (e.g. "Begin") and
one that untranslated (e.g. "End").
10) Sometime later the French translator comes back to see if he/she needs to
add more translations to fr.po. They see there is a missing translation,
they check fr.po out from SCM, add the missing translation, and then
check fr.po back into SCM.
This means at any given moment the set of .po files will have varying degrees
of translation completeness. Because the .po files are merged when the source
code files are updated existing translations are not lost. It also means a
.po file which was fully translated may need new translations after a .pot
update. It is permissible to have incomplete translations in a message
catalog, at run time if a translation for a particular string is available in
the message catalog the user will be presented with the string in their
language. However if the string is not yet translated in the .po file then
they just get the original string (typically in English).
Q: What are .mo files?
A: .mo files are the content of a .po file but in "machine" format for fast
run time access (mo = Machine Object, po = Portable Object). .mo files are
what gets installed along with the package. Think of a .po as a source file
which is compiled into a object file for run time use.
Q: Why don't we use gettexize and autopoint?
A: Because the framework they produce is too limited. Specifically there is no
way to pass the source language to xgettext when it scans a file. xgettext
only knows how to automatically determine the language from the source files
extension. However we have many files without extensions, thus we have to
group all Python (et. al.) files together and run xgettext on every file *we*
know to Python (because xgettext can't figure this out itself if there is no
file extension). There is another added benefit of avoiding gettextize and
autopoint, simplicity. Managing translations is complex and hard enough as it
is, gettextize and autopoint adds another whole layer of complexity which
just further obscures things.
Q: Who created the awful mess and who do I ask when things don't work as I
expect or I have further questions?
A: John Dennis <jdennis@redhat.com>

605
install/po/ipa.pot Normal file
View File

@ -0,0 +1,605 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Red Hat
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: ipa\n"
"Report-Msgid-Bugs-To: https://hosted.fedoraproject.org/projects/freeipa/"
"newticket\n"
"POT-Creation-Date: 2010-02-09 12:59-0500\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: ../../ipalib/parameters.py:228
msgid "incorrect type"
msgstr ""
#: ../../ipalib/parameters.py:231
msgid "Only one value is allowed"
msgstr ""
#: ../../ipalib/parameters.py:795
msgid "must be True or False"
msgstr ""
#: ../../ipalib/parameters.py:896
msgid "must be an integer"
msgstr ""
#: ../../ipalib/parameters.py:947
#, python-format
msgid "must be at least %(minvalue)d"
msgstr ""
#: ../../ipalib/parameters.py:957
#, python-format
msgid "can be at most %(maxvalue)d"
msgstr ""
#: ../../ipalib/parameters.py:967
msgid "must be a decimal number"
msgstr ""
#: ../../ipalib/parameters.py:989
#, python-format
msgid "must be at least %(minvalue)f"
msgstr ""
#: ../../ipalib/parameters.py:999
#, python-format
msgid "can be at most %(maxvalue)f"
msgstr ""
#: ../../ipalib/parameters.py:1059
#, python-format
msgid "must match pattern \"%(pattern)s\""
msgstr ""
#: ../../ipalib/parameters.py:1077
msgid "must be binary data"
msgstr ""
#: ../../ipalib/parameters.py:1092
#, python-format
msgid "must be at least %(minlength)d bytes"
msgstr ""
#: ../../ipalib/parameters.py:1102
#, python-format
msgid "can be at most %(maxlength)d bytes"
msgstr ""
#: ../../ipalib/parameters.py:1112
#, python-format
msgid "must be exactly %(length)d bytes"
msgstr ""
#: ../../ipalib/parameters.py:1130
msgid "must be Unicode text"
msgstr ""
#: ../../ipalib/parameters.py:1160
#, python-format
msgid "must be at least %(minlength)d characters"
msgstr ""
#: ../../ipalib/parameters.py:1170
#, python-format
msgid "can be at most %(maxlength)d characters"
msgstr ""
#: ../../ipalib/parameters.py:1180
#, python-format
msgid "must be exactly %(length)d characters"
msgstr ""
#: ../../ipalib/parameters.py:1219
#, python-format
msgid "must be one of %(values)r"
msgstr ""
#: ../../ipalib/cli.py:505
#, python-format
msgid "Enter %(label)s again to verify: "
msgstr ""
#: ../../ipalib/cli.py:509
msgid "Passwords do not match!"
msgstr ""
#: ../../ipalib/cli.py:514
msgid "Cancelled."
msgstr ""
#: ../../ipalib/frontend.py:377
msgid "Results are truncated, try a more specific search"
msgstr ""
#: ../../ipalib/errors.py:297
#, python-format
msgid "%(cver)s client incompatible with %(sver)s server at %(server)r"
msgstr ""
#: ../../ipalib/errors.py:315
#, python-format
msgid "unknown error %(code)d from %(server)s: %(error)s"
msgstr ""
#: ../../ipalib/errors.py:331
msgid "an internal error has occurred"
msgstr ""
#: ../../ipalib/errors.py:353
#, python-format
msgid "an internal error has occurred on server at %(server)r"
msgstr ""
#: ../../ipalib/errors.py:369
#, python-format
msgid "unknown command %(name)r"
msgstr ""
#: ../../ipalib/errors.py:386 ../../ipalib/errors.py:411
#, python-format
msgid "error on server %(server)r: %(error)s"
msgstr ""
#: ../../ipalib/errors.py:402
#, python-format
msgid "cannot connect to %(uri)r: %(error)s"
msgstr ""
#: ../../ipalib/errors.py:420
#, python-format
msgid "Invalid JSON-RPC request: %(error)s"
msgstr ""
#: ../../ipalib/errors.py:448
#, python-format
msgid "Kerberos error: %(major)s/%(minor)s"
msgstr ""
#: ../../ipalib/errors.py:465
msgid "did not receive Kerberos credentials"
msgstr ""
#: ../../ipalib/errors.py:481
#, python-format
msgid "Service %(service)r not found in Kerberos database"
msgstr ""
#: ../../ipalib/errors.py:497
msgid "No credentials cache found"
msgstr ""
#: ../../ipalib/errors.py:513
msgid "Ticket expired"
msgstr ""
#: ../../ipalib/errors.py:529
msgid "Credentials cache permissions incorrect"
msgstr ""
#: ../../ipalib/errors.py:545
msgid "Bad format in credentials cache"
msgstr ""
#: ../../ipalib/errors.py:561
msgid "Cannot resolve KDC for requested realm"
msgstr ""
#: ../../ipalib/errors.py:580
#, python-format
msgid "Insufficient access: %(info)s"
msgstr ""
#: ../../ipalib/errors.py:624
#, python-format
msgid "command %(name)r takes no arguments"
msgstr ""
#: ../../ipalib/errors.py:644
#, python-format
msgid "command %(name)r takes at most %(count)d argument"
msgid_plural "command %(name)r takes at most %(count)d arguments"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/errors.py:674
#, python-format
msgid "overlapping arguments and options: %(names)r"
msgstr ""
#: ../../ipalib/errors.py:690
#, python-format
msgid "%(name)r is required"
msgstr ""
#: ../../ipalib/errors.py:706 ../../ipalib/errors.py:722
#, python-format
msgid "invalid %(name)r: %(error)s"
msgstr ""
#: ../../ipalib/errors.py:738
#, python-format
msgid "api has no such namespace: %(name)r"
msgstr ""
#: ../../ipalib/errors.py:747
msgid "Passwords do not match"
msgstr ""
#: ../../ipalib/errors.py:755
msgid "Command not implemented"
msgstr ""
#: ../../ipalib/errors.py:783 ../../ipalib/errors.py:1023
#, python-format
msgid "%(reason)s"
msgstr ""
#: ../../ipalib/errors.py:799
msgid "This entry already exists"
msgstr ""
#: ../../ipalib/errors.py:815
msgid "You must enroll a host in order to create a host service"
msgstr ""
#: ../../ipalib/errors.py:831
#, python-format
msgid ""
"Service principal is not of the form: service/fully-qualified host name: %"
"(reason)s"
msgstr ""
#: ../../ipalib/errors.py:847
msgid ""
"The realm for the principal does not match the realm for this IPA server"
msgstr ""
#: ../../ipalib/errors.py:863
msgid "This command requires root access"
msgstr ""
#: ../../ipalib/errors.py:879
msgid "This is already a posix group"
msgstr ""
#: ../../ipalib/errors.py:895
#, python-format
msgid "Principal is not of the form user@REALM: %(principal)r"
msgstr ""
#: ../../ipalib/errors.py:911
msgid "This entry is already unlocked"
msgstr ""
#: ../../ipalib/errors.py:927
msgid "This entry is already locked"
msgstr ""
#: ../../ipalib/errors.py:943
msgid "This entry has nsAccountLock set, it cannot be locked or unlocked"
msgstr ""
#: ../../ipalib/errors.py:959
msgid "This entry is not a member of the group"
msgstr ""
#: ../../ipalib/errors.py:975
msgid "A group may not be a member of itself"
msgstr ""
#: ../../ipalib/errors.py:991
msgid "This entry is already a member of the group"
msgstr ""
#: ../../ipalib/errors.py:1007
#, python-format
msgid "Base64 decoding failed: %(reason)s"
msgstr ""
#: ../../ipalib/errors.py:1039
msgid "A group may not be added as a member of itself"
msgstr ""
#: ../../ipalib/errors.py:1055
msgid "The default users group cannot be removed"
msgstr ""
#: ../../ipalib/errors.py:1078
#, python-format
msgid "no command nor help topic %(topic)r"
msgstr ""
#: ../../ipalib/errors.py:1102
msgid "change collided with another change"
msgstr ""
#: ../../ipalib/errors.py:1118
msgid "no modifications to be performed"
msgstr ""
#: ../../ipalib/errors.py:1134
#, python-format
msgid "%(desc)s:%(info)s"
msgstr ""
#: ../../ipalib/errors.py:1150
msgid "limits exceeded for this query"
msgstr ""
#: ../../ipalib/errors.py:1165
#, python-format
msgid "%(info)s"
msgstr ""
#: ../../ipalib/errors.py:1190
#, python-format
msgid "Certificate operation cannot be completed: %(error)s"
msgstr ""
#: ../../ipalib/plugins/rolegroup.py:73
#, python-format
msgid "Added rolegroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/rolegroup.py:83
#, python-format
msgid "Deleted rolegroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/rolegroup.py:93
#, python-format
msgid "Modified rolegroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/rolegroup.py:104
#, python-format
msgid "%(count)d rolegroup matched"
msgid_plural "%(count)d rolegroups matched"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/plugins/host.py:149
#, python-format
msgid "Added host \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/host.py:178
#, python-format
msgid "Deleted host \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/host.py:206
#, python-format
msgid "Modified host \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/host.py:255
#, python-format
msgid "%(count)d host matched"
msgid_plural "%(count)d hosts matched"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/plugins/group.py:85
#, python-format
msgid "Added group \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/group.py:108
#, python-format
msgid "Deleted group \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/group.py:134
#, python-format
msgid "Modified group \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/group.py:163
#, python-format
msgid "%(count)d group matched"
msgid_plural "%(count)d groups matched"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/plugins/cert.py:63 ../../ipalib/plugins/cert.py:84
msgid "Unable to decode certificate in entry"
msgstr ""
#: ../../ipalib/plugins/cert.py:106 ../../ipalib/plugins/cert.py:120
#: ../../ipalib/plugins/cert.py:137
msgid "Failure decoding Certificate Signing Request"
msgstr ""
#: ../../ipalib/plugins/cert.py:139
#, python-format
msgid "Failure decoding Certificate Signing Request: %s"
msgstr ""
#: ../../ipalib/plugins/aci.py:109
msgid "type, filter, subtree and targetgroup are mutually exclusive"
msgstr ""
#: ../../ipalib/plugins/aci.py:112
msgid ""
"at least one of: type, filter, subtree, targetgroup, attrs or memberof are "
"required"
msgstr ""
#: ../../ipalib/plugins/aci.py:117
msgid "group and taskgroup are mutually exclusive"
msgstr ""
#: ../../ipalib/plugins/aci.py:119
msgid "One of group or taskgroup is required"
msgstr ""
#: ../../ipalib/plugins/aci.py:140
#, python-format
msgid "Group '%s' does not exist"
msgstr ""
#: ../../ipalib/plugins/aci.py:184
#, python-format
msgid "ACI with name \"%s\" not found"
msgstr ""
#: ../../ipalib/plugins/aci.py:255
#, python-format
msgid "Created ACI \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/aci.py:305
#, python-format
msgid "Deleted ACI \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/aci.py:345
#, python-format
msgid "Modified ACI \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/aci.py:405
#, python-format
msgid "%(count)d ACI matched"
msgid_plural "%(count)d ACIs matched"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/plugins/misc.py:37
#, python-format
msgid "%(count)d variables"
msgstr ""
#: ../../ipalib/plugins/misc.py:96
#, python-format
msgid "%(count)d plugin loaded"
msgid_plural "%(count)d plugins loaded"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/plugins/user.py:139
#, python-format
msgid "Added user \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/user.py:184
#, python-format
msgid "Deleted user \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/user.py:203
#, python-format
msgid "Modified user \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/user.py:214
#, python-format
msgid "%(count)d user matched"
msgid_plural "%(count)d users matched"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/plugins/user.py:234
#, python-format
msgid "Locked user \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/user.py:260
#, python-format
msgid "Unlocked user \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/taskgroup.py:73
#, python-format
msgid "Added taskgroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/taskgroup.py:83
#, python-format
msgid "Deleted taskgroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/taskgroup.py:93
#, python-format
msgid "Modified taskgroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/taskgroup.py:104
#, python-format
msgid "%(count)d taskgroup matched"
msgid_plural "%(count)d taskgroups matched"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/plugins/hostgroup.py:72
#, python-format
msgid "Added hostgroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/hostgroup.py:82
#, python-format
msgid "Deleted hostgroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/hostgroup.py:92
#, python-format
msgid "Modified hostgroup \"%(value)s\""
msgstr ""
#: ../../ipalib/plugins/hostgroup.py:103
#, python-format
msgid "%(count)d hostgroup matched"
msgid_plural "%(count)d hostgroups matched"
msgstr[0] ""
msgstr[1] ""
#: ../../ipalib/plugins/pwpolicy.py:231
msgid "priority cannot be set on global policy"
msgstr ""
#: ../../ipaserver/install/certs.py:571 ../../ipaserver/plugins/dogtag.py:1313
#: ../../ipaserver/plugins/dogtag.py:1398
#: ../../ipaserver/plugins/dogtag.py:1463
#: ../../ipaserver/plugins/dogtag.py:1543
#: ../../ipaserver/plugins/dogtag.py:1602
#, python-format
msgid "Unable to communicate with CMS (%s)"
msgstr ""
#: ../../ipaserver/plugins/selfsign.py:102
#, python-format
msgid ""
"Request subject \"%(request_subject)s\" does not match the form \"%"
"(subject_base)s\""
msgstr ""
#: ../../ipaserver/plugins/selfsign.py:107
#, python-format
msgid "unable to decode csr: %s"
msgstr ""
#: ../../ipaserver/plugins/selfsign.py:128
#: ../../ipaserver/plugins/selfsign.py:143
msgid "file operation"
msgstr ""
#: ../../ipaserver/plugins/selfsign.py:157
msgid "cannot obtain next serial number"
msgstr ""
#: ../../ipaserver/plugins/selfsign.py:192
msgid "certutil failure"
msgstr ""

View File

@ -9,6 +9,7 @@
%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
%global POLICYCOREUTILSVER 1.33.12-1
%global gettext_domain ipa
Name: ipa
Version: __VERSION__
@ -44,6 +45,7 @@ BuildRequires: python-setuptools
BuildRequires: python-krbV
BuildRequires: xmlrpc-c-devel
BuildRequires: libcurl-devel
BuildRequires: gettext
%endif
%description
@ -251,6 +253,8 @@ cd ..
%else
make client-install DESTDIR=%{buildroot}
%endif
%find_lang %{gettext_domain}
%if ! %{ONLY_CLIENT}
# Remove .la files from libtool - we don't want to package
@ -461,7 +465,7 @@ fi
%{_sysconfdir}/bash_completion.d
%endif
%files python
%files python -f %{gettext_domain}.lang
%doc LICENSE README
%defattr(-,root,root,-)
%dir %{python_sitelib}/ipapython