#!/bin/bash # # Based upon Debian's locale-gen, fetched from glibc_2.3.6-7.diff.gz # unset POSIXLY_CORRECT IFS umask 0022 argv0=${0##*/} source /etc/init.d/functions.sh || { echo "${argv0}: Could not source /etc/init.d/functions.sh!" 1>&2 exit 1 } show_usage() { cat <<-EOF Usage: ${HILITE}${argv0}${NORMAL} ${GOOD}[options]${NORMAL} -- ${GOOD}[localedef options]${NORMAL} Generate locales based upon the config file /etc/locale.gen. ${HILITE}Options:${NORMAL} ${GOOD}-k, --keep${NORMAL} Don't nuke existing locales ${GOOD}-d, --destdir ${NORMAL} Use locale data in specified DESTDIR tree ${GOOD}-c, --config ${NORMAL} Use specified config instead of default locale.gen ${GOOD}-l, --list${NORMAL} List all the locales to be generated ${GOOD}-a, --ask${NORMAL} Ask before generating each locale ${GOOD}-u, --update${NORMAL} Only generate locales that are missing ${GOOD}-q, --quiet${NORMAL} Only show errors ${GOOD}-V, --version${NORMAL} Meaningless version information ${GOOD}-h, --help${NORMAL} Show this help cruft ${HILITE}Localedef Options:${NORMAL} By default, ${GOOD}${LOCALEDEF_OPTS}${NORMAL} is passed to localedef. For more info, see the ${HILITE}locale-gen${NORMAL}(1) and ${HILITE}locale.gen${NORMAL}(8) manpages. EOF [[ -z $@ ]] && exit 0 echo "" eerror "Unknown option '$1'" exit 1 } show_version() { local cvsver="$Header: /var/cvsroot/gentoo/src/patchsets/glibc/extra/locale/locale-gen,v 1.8 2006/04/25 01:17:03 vapier Exp $" cvsver=${cvsver##*locale-gen-} echo "locale-gen-${cvsver%%,v *}" exit 0 } LOCALEDEF_OPTS="--no-archive -c" KEEP="" DESTDIR="" CONFIG="" JUST_LIST="" ASK="" UPDATE="" QUIET=0 while [[ -n $1 ]] ; do case $1 in -k|--keep|--keep-existing) KEEP=$1;; -d|--destdir) shift; DESTDIR=$1;; -c|--config) shift; CONFIG=$1;; -l|--list) JUST_LIST=$1;; -a|--ask) ASK=$1;; -u|--update) UPDATE=$1;; -q|--quiet) ((++QUIET));; -V|--version) show_version;; -h|--help) show_usage;; --) shift; LOCALEDEF_OPTS=$*; break;; *) show_usage $1;; esac shift done KEEP=${KEEP:-${UPDATE:-${JUST_LIST}}} ROOT=${ROOT:-/} [[ ${ROOT} != */ ]] && ROOT="${ROOT}/" if [[ -n ${DESTDIR} ]] && [[ ${ROOT} != "/" ]] ; then eerror "DESTDIR and ROOT are mutually exclusive options" exit 1 fi if [[ ${ROOT} != "/" ]] ; then einfo "Using locale.gen from ROOT ${ROOT}etc/" fi if [[ -n ${DESTDIR} ]] ; then einfo "Building locales in DESTDIR ${DESTDIR}" else DESTDIR=${ROOT} fi # XXX: should fix this ... if [[ ${DESTDIR} != "/" || ${ROOT} != "/" ]] ; then eerror "Sorry, but DESTDIR/ROOT support is incomplete at this time." exit 0 fi LOCALEGEN=${CONFIG:-${ROOT}etc/locale.gen} LOCALES=${DESTDIR}usr/share/i18n/locales CHARMAPS=${DESTDIR}usr/share/i18n/charmaps SUPPORTED=${DESTDIR}usr/share/i18n/SUPPORTED ALIAS=${DESTDIR}usr/share/locale/locale.alias # Extract the location of the locale dir on the fly as `localedef --help` has: # locale path : /usr/lib64/locale:/usr/share/i18n LOCALEDIR=${DESTDIR}$(localedef --help | sed -n -e '/locale path/{s|.* : ||;s|:.*||;p}') if [[ ${QUIET} -eq 0 ]] && [[ -z ${JUST_LIST} ]] && \ [[ -e ${ROOT}etc/locales.build ]] then ewarn "You should upgrade your /etc/locales.build to /etc/locale.gen" ewarn "and then remove /etc/locales.build when you're done.\n" fi locales_to_generate="" if [[ -e ${LOCALEGEN} ]] ; then locales_to_generate=$(sed \ -e 's:#.*::' \ -e '/^[[:space:]]*$/d' \ "${LOCALEGEN}") fi if [[ -z ${locales_to_generate} ]] ; then # Maybe they have /etc/locales.build setup still ... if [[ ${LOCALEGEN} == */etc/locale.gen ]] ; then LOCALEGEN=${LOCALEGEN/%locale.gen/locales.build} locales_to_generate=$(sed \ -e 's:#.*::' \ -e '/^[[:space:]]*$/d' \ -e 's:/: :g' \ "${LOCALEGEN}") if [[ -n ${locales_to_generate} ]] && \ [[ ${QUIET} -eq 0 ]] && [[ -z ${JUST_LIST} ]] then ewarn "Automatically importing locales from /etc/locales.build ..." ewarn "You really should do this yourself ...\n" fi fi if [[ -z ${locales_to_generate} ]] ; then [[ ${QUIET} -eq 0 ]] && [[ -z ${JUST_LIST} ]] && \ ewarn "No locales found" exit 0 fi fi mkdir -p "${LOCALEDIR}" if [[ -z ${KEEP} ]] ; then # Remove all old locale dir and locale-archive before generating new # locale data. rm -rf "${LOCALEDIR}"/* || true fi # Transform the name in locales.gen to the name used when storing # the locale data in /usr/lib/locale/ ... this normalize algo is # taken out of the glibc localedef source code ... normalize() { if [[ $1 == *.* ]] ; then local ret=$(echo ${1##*.} | tr '[[:upper:]]' '[[:lower:]]') echo ${1%%.*}.${ret//-} else echo $1 fi } # These funky sed's are based on the stuff in glibc's localedata/Makefile # Basically we want to rewrite the display like so: # .[@extra stuff after the @ in the locale] # en_US ISO-8859-1 -> en_US.ISO-8859-1 # en_US.UTF-8 UTF-8 -> en_US.UTF-8 # de_DE@euro ISO-8859-15 -> de_DE.ISO-8859-15@euro locales_disp=$(echo "${locales_to_generate}" | sed \ -e '/\@/s:\([^\@ ]*\)\([^ ]*\) \(.*\):\1.\3\2:' \ -e '/[^\@]/s:\([^. ]*\)\([^ ]*\) \(.*\):\1.\3:') eval declare -a locales_disp=(${locales_disp}) eval declare -a locales_to_generate=(${locales_to_generate}) total=$((${#locales_to_generate[*]}/2)) [[ ${QUIET} -eq 0 ]] && [[ -z ${JUST_LIST} ]] && \ einfo "Generating ${total} locales (this might take a while)" ret=0 cnt=0 if [[ -n ${UPDATE} ]] ; then # normalize newlines into spaces existing_locales=" $(echo $(locale -a)) " fi lidx=0 while [[ -n ${locales_to_generate[${lidx}]} ]] ; do ((++cnt)) locale=${locales_to_generate[$((lidx++))]} charmap=${locales_to_generate[$((lidx++))]} # XXX: if we wanted to, we could check existence of # ${LOCALES}/${locale} and ${CHARMAPS}/${charmap} # this would fail for things like "en_US.UTF8", but # in that case we could fall back to checking the # SUPPORTED file ... then again, the localedef # below will abort nicely for us ... if [[ -z ${locale} || -z ${charmap} ]] ; then eerror "Bad entry in locale.gen: '${locale} ${charmap}'; skipping" continue fi disp=${locales_disp[$((cnt-1))]} if [[ -n ${UPDATE} ]] && \ [[ ${existing_locales} == *" $(normalize ${locale}) "* ]] then [[ ${QUIET} -eq 0 ]] && einfo " (${cnt}/${total}) Skipping ${disp}" continue fi # If the locale is like 'en_US.UTF8', then we really want 'en_US' if [[ -f ${LOCALES}/${locale} ]] ; then input=${locale} else input=${locale%%.*} fi if [[ -z ${JUST_LIST} ]] ; then if [[ -n ${ASK} ]] ; then einfon " (${cnt}/${total}) Generate ${disp} ? (Y/n) " read user_answer [[ ${user_answer} == [nN]* ]] && continue elif [[ ${QUIET} -eq 0 ]] ; then ebegin " (${cnt}/${total}) Generating ${disp}" fi localedef ${LOCALEDEF_OPTS} \ -i "${input}" \ -f "${charmap}" \ -A "${ALIAS}" \ "${locale}" my_ret=$? ((ret+=my_ret)) [[ -z ${ASK} ]] && [[ ${QUIET} -eq 0 ]] && eend ${my_ret} else echo "${disp}" fi done [[ ${QUIET} -eq 0 ]] && [[ -z ${JUST_LIST} ]] && \ einfo "Generation complete" exit ${ret}