* Pike:: Pike
* GCC-source:: GNU Compiler Collection sources
+sh - Shell Script
+
+* Preparing Shell Scripts:: Preparing Shell Scripts for Internationalization
+* gettext.sh:: Contents of @code{gettext.sh}
+* gettext Invocation:: Invoking the @code{gettext} program
+* ngettext Invocation:: Invoking the @code{ngettext} program
+* envsubst Invocation:: Invoking the @code{envsubst} program
+* eval_gettext Invocation:: Invoking the @code{eval_gettext} function
+* eval_ngettext Invocation:: Invoking the @code{eval_ngettext} function
+
+Perl
+
+* General Problems:: General Problems Parsing Perl Code
+* Default Keywords:: Which Keywords Will xgettext Look For?
+* Special Keywords:: How to Extract Hash Keys
+* Quote-like Expressions:: What are Strings And Quote-like Expressions?
+* Interpolation I:: Invalid String Interpolation
+* Interpolation II:: Valid String Interpolation
+* Parentheses:: When To Use Parentheses
+* Long Lines:: How To Grok with Long Lines
+* Perl Pitfalls:: Bugs, Pitfalls, and Things That Do Not Work
+
Internationalizable Data
* POT:: POT - Portable Object Template
@c Java 1200 *
@c PHP 1051 *
@c Python 613 *
-@c Unix Shell 357
+@c Unix Shell 357 *
@c Tcl 266 *
@c SQL 174
@c JavaScript 118
@code{"abc"}, @code{'abc'}, @code{abc}
@item gettext shorthand
-@code{"`gettext "abc"`"}
+@code{"`gettext \"abc\"`"}
@item gettext/ngettext functions
@pindex gettext
@pindex ngettext
@code{gettext}, @code{ngettext} programs
+@*@code{eval_gettext}, @code{eval_ngettext} shell functions
@item textdomain
@vindex TEXTDOMAIN@r{, environment variable}
automatic
@item Prerequisite
----
+@code{. gettext.sh}
@item Use or emulate GNU gettext
use
@item Extractor
----
+@code{xgettext}
@item Formatting with positions
---
@item Portability
----
+fully portable
@item po-mode marking
---
@end table
-@node bash, Python, sh, List of Programming Languages
-@subsection bash - Bourne-Again Shell Script
-@cindex bash
+@menu
+* Preparing Shell Scripts:: Preparing Shell Scripts for Internationalization
+* gettext.sh:: Contents of @code{gettext.sh}
+* gettext Invocation:: Invoking the @code{gettext} program
+* ngettext Invocation:: Invoking the @code{ngettext} program
+* envsubst Invocation:: Invoking the @code{envsubst} program
+* eval_gettext Invocation:: Invoking the @code{eval_gettext} function
+* eval_ngettext Invocation:: Invoking the @code{eval_ngettext} function
+@end menu
-@table @asis
-@item RPMs
-bash 2.0 or newer, gettext
+@node Preparing Shell Scripts, gettext.sh, sh, sh
+@subsubsection Preparing Shell Scripts for Internationalization
+@cindex preparing shell scripts for translation
-@item File extension
-@code{sh}
+Preparing a shell script for internationalization is conceptually similar
+to the steps described in @ref{Sources}. The concrete steps for shell
+scripts are as follows.
-@item String syntax
-@code{"abc"}, @code{'abc'}, @code{abc}
+@enumerate
+@item
+Insert the line
-@item gettext shorthand
-@code{$"abc"}
+@smallexample
+. gettext.sh
+@end smallexample
-@item gettext/ngettext functions
-@pindex gettext
-@pindex ngettext
-@code{gettext}, @code{ngettext} programs
+near the top of the script. @code{gettext.sh} is a shell function library
+that provides the functions
+@code{eval_gettext} (see @ref{eval_gettext Invocation}) and
+@code{eval_ngettext} (see @ref{eval_ngettext Invocation}).
+You have to ensure that @code{gettext.sh} can be found in the @code{PATH}.
-@item textdomain
-@vindex TEXTDOMAIN@r{, environment variable}
-environment variable @code{TEXTDOMAIN}
+@item
+Set and export the @code{TEXTDOMAIN} and @code{TEXTDOMAINDIR} environment
+variables. Usually @code{TEXTDOMAIN} is the package or program name, and
+@code{TEXTDOMAINDIR} is the absolute pathname corresponding to
+@code{$prefix/share/locale}, where @code{$prefix} is the installation location.
-@item bindtextdomain
-@vindex TEXTDOMAINDIR@r{, environment variable}
-environment variable @code{TEXTDOMAINDIR}
+@smallexample
+TEXTDOMAIN=@@PACKAGE@@
+export TEXTDOMAIN
+TEXTDOMAINDIR=@@LOCALEDIR@@
+export TEXTDOMAINDIR
+@end smallexample
-@item setlocale
-automatic
+@item
+Prepare the strings for translation, as described in @ref{Preparing Strings}.
-@item Prerequisite
----
+@item
+Simplify translatable strings so that they don't contain command substitution
+(@code{"`...`"} or @code{"$(...)"}), variable access with defaulting (like
+@code{$@{@var{variable}-@var{default}@}}), access to positional arguments
+(like @code{$0}, @code{$1}, ...) or highly volatile shell variables (like
+@code{$?}). This can always be done through simple local code restructuring.
+For example,
-@item Use or emulate GNU gettext
-use
+@smallexample
+echo "Usage: $0 [OPTION] FILE..."
+@end smallexample
-@item Extractor
-@code{bash --dump-po-strings}
+becomes
-@item Formatting with positions
----
+@smallexample
+program_name=$0
+echo "Usage: $program_name [OPTION] FILE..."
+@end smallexample
-@item Portability
----
+Similarly,
-@item po-mode marking
----
-@end table
+@smallexample
+echo "Remaining files: `ls | wc -l`"
+@end smallexample
+
+becomes
+
+@smallexample
+filecount="`ls | wc -l`"
+echo "Remaining files: $filecount"
+@end smallexample
+
+@item
+For each translatable string, change the output command @samp{echo} or
+@samp{$echo} to @samp{gettext} (if the string contains no references to
+shell variables) or to @samp{eval_gettext} (if it refers to shell variables),
+followed by a no-argument @samp{echo} command (to account for the terminating
+newline). Similarly, for cases with plural handling, replace a conditional
+@samp{echo} command with an invocation of @samp{ngettext} or
+@samp{eval_ngettext}, followed by a no-argument @samp{echo} command.
+@end enumerate
+
+@node gettext.sh, gettext Invocation, Preparing Shell Scripts, sh
+@subsubsection Contents of @code{gettext.sh}
+
+@code{gettext.sh}, contained in the run-time package of GNU gettext, provides
+the following:
+
+@itemize @bullet
+@item $echo
+The variable @code{echo} is set to a command that outputs its first argument
+and a newline, without interpreting backslashes in the argument string.
+
+@item eval_gettext
+See @ref{eval_gettext Invocation}.
+
+@item eval_ngettext
+See @ref{eval_ngettext Invocation}.
+@end itemize
+
+@node gettext Invocation, ngettext Invocation, gettext.sh, sh
+@subsubsection Invoking the @code{gettext} program
+
+@include rt-gettext.texi
+
+@node ngettext Invocation, envsubst Invocation, gettext Invocation, sh
+@subsubsection Invoking the @code{ngettext} program
+
+@include rt-ngettext.texi
+
+@node envsubst Invocation, eval_gettext Invocation, ngettext Invocation, sh
+@subsubsection Invoking the @code{envsubst} program
+
+@include rt-envsubst.texi
+
+@node eval_gettext Invocation, eval_ngettext Invocation, envsubst Invocation, sh
+@subsubsection Invoking the @code{eval_gettext} function
+
+@cindex @code{eval_gettext} function, usage
+@example
+eval_gettext @var{msgid}
+@end example
+
+@cindex lookup message translation
+This function outputs the native language translation of a textual message,
+performing dollar-substitution on the result. Note that only shell variables
+mentioned in @var{msgid} will be dollar-substituted in the result.
+
+@node eval_ngettext Invocation, , eval_gettext Invocation, sh
+@subsubsection Invoking the @code{eval_ngettext} function
+
+@cindex @code{eval_ngettext} function, usage
+@example
+eval_ngettext @var{msgid} @var{msgid-plural} @var{count}
+@end example
+
+@cindex lookup plural message translation
+This function outputs the native language translation of a textual message
+whose grammatical form depends on a number, performing dollar-substitution
+on the result. Note that only shell variables mentioned in @var{msgid} or
+@var{msgid-plural} will be dollar-substituted in the result.
+
+@node bash, Python, sh, List of Programming Languages
+@subsection bash - Bourne-Again Shell Script
+@cindex bash
+
+GNU @code{bash} 2.0 or newer has a special shorthand for translating a
+string and substituting variable values in it: @code{$"msgid"}. But
+the use of this construct is @strong{discouraged}, due to the security
+holes it opens and due to its portability problems.
+
+The security holes of @code{$"..."} come from the fact that after looking up
+the translation of the string, @code{bash} processes it like it processes
+any double-quoted string: dollar and backquote processing, like @samp{eval}
+does.
+
+@enumerate
+@item
+In a locale whose encoding is one of BIG5, BIG5-HKSCS, GBK, GB18030, SHIFT_JIS,
+JOHAB, some double-byte characters have a second byte whose value is
+@code{0x60}. For example, the byte sequence @code{\xe0\x60} is a single
+character in these locales. Many versions of @code{bash} (all versions
+up to bash-2.05, and newer versions on platforms without @code{mbsrtowcs()}
+function) don't know about character boundaries and see a backquote character
+where there is only a particular Chinese character. Thus it can start
+executing part of the translation as a command list. This situation can occur
+even without the translator being aware of it: if the translator provides
+translations in the UTF-8 encoding, it is the @code{gettext()} function which
+will, during its conversion from the translator's encoding to the user's
+locale's encoding, produce the dangerous @code{\x60} bytes.
+
+@item
+A translator could - voluntarily or inadvertantly - use backquotes
+@code{"`...`"} or dollar-parentheses @code{"$(...)"} in her translations.
+The enclosed strings would be executed as command lists by the shell.
+@end enumerate
+
+The portability problem is that @code{bash} must be built with
+internationalization support; this is normally not the case on systems
+that don't have the @code{gettext()} function in libc.
@node Python, Common Lisp, bash, List of Programming Languages
@subsection Python
worst probably being its imperfectness.
@menu
-* General Problems:: General Problems Parsing Perl Code
-* Default Keywords:: Which Keywords Will xgettext Look For?
-* Special Keywords:: How to Extract Hash Keys
-* Quote-like Expressions:: What are Strings And Quote-like Expressions?
-* Interpolation I:: Invalid String Interpolation
-* Interpolation II:: Valid String Interpolation
-* Parentheses:: When To Use Parentheses
-* Long Lines:: How To Grok with Long Lines
-* Perl Pitfalls:: Bugs, Pitfalls, and Things That Do Not Work
+* General Problems:: General Problems Parsing Perl Code
+* Default Keywords:: Which Keywords Will xgettext Look For?
+* Special Keywords:: How to Extract Hash Keys
+* Quote-like Expressions:: What are Strings And Quote-like Expressions?
+* Interpolation I:: Invalid String Interpolation
+* Interpolation II:: Valid String Interpolation
+* Parentheses:: When To Use Parentheses
+* Long Lines:: How To Grok with Long Lines
+* Perl Pitfalls:: Bugs, Pitfalls, and Things That Do Not Work
@end menu
@node General Problems, Default Keywords, , Perl