CMUCL commit: src/docs/cmu-user (cmu-user.tex extensions.tex)

Raymond Toy rtoy at common-lisp.net
Sat Apr 3 04:21:00 CEST 2010


    Date: Friday, April 2, 2010 @ 22:21:00
  Author: rtoy
    Path: /project/cmucl/cvsroot/src/docs/cmu-user

Modified: cmu-user.tex extensions.tex

extensions.tex:
o Add some documentation for localization support
o Fix a few places where words were run together in the pdf output. 

cmu-user.tex:
o Update date and version.


----------------+
 cmu-user.tex   |    2 
 extensions.tex |  196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 194 insertions(+), 4 deletions(-)


Index: src/docs/cmu-user/cmu-user.tex
diff -u src/docs/cmu-user/cmu-user.tex:1.41 src/docs/cmu-user/cmu-user.tex:1.42
--- src/docs/cmu-user/cmu-user.tex:1.41	Wed Sep  9 11:51:27 2009
+++ src/docs/cmu-user/cmu-user.tex	Fri Apr  2 22:20:59 2010
@@ -47,7 +47,7 @@
 \newcommand{\keywords}{lisp, Common Lisp, manual, compiler, programming
 language implementation, programming environment}
 
-\date{Sep 2009 \\ Release 20a}
+\date{Apr 2009 \\ Snapshot 2010-04}
 
 
 \begin{document}
Index: src/docs/cmu-user/extensions.tex
diff -u src/docs/cmu-user/extensions.tex:1.42 src/docs/cmu-user/extensions.tex:1.43
--- src/docs/cmu-user/extensions.tex:1.42	Wed Dec 30 11:39:46 2009
+++ src/docs/cmu-user/extensions.tex	Fri Apr  2 22:20:59 2010
@@ -2470,7 +2470,7 @@
 \code{(setf fdefinition)} will set the primary function in the
 innermost fwrapper.
 
-\begin{defmac}{fwrappers:}{define-fwrapper}{name lambda-list \ampbody body}
+\begin{defmac}{fwrappers:}{define-fwrapper}{name lambda-list \ampbody{} body}
   This macro is like \code{defun}, but defines a function named
   \var{name} that can be used as an fwrapper definition.
   
@@ -2552,8 +2552,8 @@
   undefined function.
 \end{defun}
 
-\begin{defmac}{fwrappers:}{do-fwrappers}{(var fdefn \ampoptional
-  result) \ampbody body}
+\begin{defmac}{fwrappers:}{do-fwrappers}{(var fdefn \ampoptional{}
+  result) \ampbody{} body}
   Evaluate \var{body} with \var{var} bound to consecutive fwrappers of
   \var{fdefn}.  Return \var{result} at the end.  Note that \var{fdefn}
   must be an \code{fdefn} object.  You can use
@@ -2763,3 +2763,193 @@
   :case :common to :case :local.  This merged name will be probed with
   both a .lisp and .fasl extensions, calling \code{LOAD} if it exists.
 \end{defun}
+
+
+\section{Localization}
+\label{sec:localization}
+
+\cmucl{} support localization where messages can be presented in the
+native language.  This is done in the style of \code{gettext} which
+marks strings that are to be translated and provides the lookup to
+convert the string to the specified language.
+
+All messages from \cmucl{} can be translated but as of this writing,
+the only complete translation is a Pig Latin translation done by
+machine.  There are a few messages translated to Korean.
+
+\subsection{Dictionary}
+\label{sec:localization-dictionary}
+
+
+\begin{defun}{intl:}{setlocale}{\ampoptional{} locale}
+  Sets the locale to the locale specified by \var{locale}.  If
+  \var{locale} is not give or is \nil, the locale is determined by
+  look at the environment variables \code{LANGUAGE}, \code{LC\_ALL},
+  \code{LC\_MESSAGES}, or \code{LANG}.  If none of these are set, the
+  locale is unchanged.
+
+  The default locale is ``C''.
+\end{defun}
+
+\begin{defun}{intl:}{textdomain}{domain}
+  Set the default domain to the domain specified by \var{domain}.
+  Typically,  this only needs to be done at the top of each source
+  file.  This is used to \code{gettext} and \code{ngettext} to set the
+  domain for the message string.
+\end{defun}
+
+\begin{defmac}{intl:}{gettext}{string}
+  Look up the specified string, \var{string}, in the current message
+  domain and return its translation.
+\end{defmac}
+
+\begin{defun}{intl:}{dgettext}{domain string}
+  Look up the specified string, \var{string}, in the message domain,
+  \var{domain}.  The translation is returned.
+
+  When compiled, this also function also records the string so that an
+  appropriate message template file can be created.  (See
+  \code{intl::dump-pot-files}.) 
+\end{defun}
+
+\begin{defmac}{intl:}{ngettext}{singular plural n}
+  Look up the singular or plural form of a message in the default
+  domain.  The singular form is \var{singular}; the plural is
+  \var{plural}.  The number of items is specified by \var{n} in case
+  the correct translation depends on the actual number of items.
+\end{defmac}
+
+\begin{defun}{intl:}{dngettext}{domain singular plural n}
+  Look up the singular or plural form of a message in the specified
+  domain, \var{domain}.  The singular form is \var{singular}; the
+  plural is \var{plural}.  The number of items is specified by \var{n}
+  in case the correct translation depends on the actual number of
+  items.
+
+  When compiled, this also function also records the singular and
+  plural forms so that an appropriate message template file can be
+  created.  (See \code{intl::dump-pot-files}.)
+\end{defun}
+
+\begin{defun}{intl::}{dump-pot-files}{\keys copyright
+    output-directory}
+  Dumps the translatable strings recorded by \code{dgettext} and
+  \code{dngettext}.  The message template file (pot file) is written
+  to a file in the directory specified by \var{output-directory}, and
+  the name of the file is the domain of the string.
+
+  If \var{copyright} is specified, this is placed in the output file
+  as the copyright message.
+\end{defun}
+
+\begin{defvar}{intl:}{locale-directories}
+  This is a list of directory pathnames where the translations can be found.
+\end{defvar}  
+
+Two reader macros are also provided: \code{\_''} and \code{\_N''}.  The
+first is equivalent to wrapping \code{dgettext} around the string.
+The second returns the string, but also records the string.  This is
+needed when we want to record a docstring for translation or any other
+string in a place where a macro or function call would be incorrect.
+
+Also, the standard comment reader is extended to allow translator
+comments to be saved and written to the messages template file so that
+the translator may not need to look at the original source to
+understand the string.  Any comment line that begins with exactly
+\verb|"TRANSLATORS: "| is saved.  This means each translator comment
+must be preceded by this string to be saved; the translator comment
+ends at the end of each line.
+
+
+\subsection{Example Usage}
+\label{sec:localization-usage}
+
+Here is a simple example of how to localize your code.
+
+\begin{example}
+
+(intl:textdomain "example")  
+
+(defun foo (x y)
+  _N"Cool function foo of x and y"
+  (let ((result (bar x y)))
+    (format t _"bar of ~A and ~A = ~A~%" x y result)
+    ;; TRANSLATORS:  Do the right thing here.
+    ;; TRANSLATORS:  Whatever that might be.
+    (format t (intl:ngettext "There is one X"
+                             "There are many Xs"
+                             x))
+    result))
+\end{example}
+
+The call to \code{textdomain} sets the default domain for all
+translatable strings following the call.
+
+When this file is compiled, all of the translatable strings are
+recorded.  This includes the docstring for \code{foo}, the string for
+the first \code{format}, and the string marked by the call to
+\code{intl:ngettext}.
+
+After all of the files have been compiled, we can dump the recorded
+strings.  In this case,
+\begin{example}
+* (intl::dump-pot-files :output-directory "dir/")
+Dumping 3 messages for domain "example"
+NIL
+\end{example}
+will create a file named ``example.pot'' in the directory ``dir/''.
+The contents of this file are:
+\begin{example}
+#@ example
+
+# SOME DESCRIPTIVE TITLE
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION"
+"Report-Msgid-Bugs-To: "
+"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>"
+"Language-Team: LANGUAGE <LL at li.org>"
+"MIME-Version: 1.0"
+"Content-Type: text/plain; charset=UTF-8"
+"Content-Transfer-Encoding: 8bit"
+
+#: /tmp/foo.lisp
+msgid "Cool function foo of x and y"
+msgstr ""
+
+#.  Whatever that might be.
+#: /tmp/foo.lisp
+msgid "bar of ~A and ~A = ~A~%"
+msgstr ""
+
+#: /tmp/foo.lisp
+msgid "There is one X"
+msgid_plural "There are many Xs"
+msgstr[0] ""
+
+\end{example}
+
+To finish the translation, a corresponding ``example.po'' file needs
+to be created with the appropriate translations for the given
+strings.  This file must be placed in some directory that is included
+in \code{intl:*locale-directories*}.
+
+Suppose the translation is done for Korean.  Then the user can set the
+environment variables appropriately or call \code{(intl:setlocale
+  "ko")}.  Note that the external format for the standard streams
+needs to be set up appropriately too.  It is up to the user to set
+this correctly.  Once this is all done, the output from the function
+\code{foo} will now be in Korean instead of English as in the original
+source file.
+
+For further information, we refer the reader to documentation on
+\ifpdf
+\href{http://www.gnu.org/software/gettext/manual/gettext.html}{gettext}.
+\else
+gettext at
+\href{http://www.gnu.org/software/gettext/manual/gettext.html}{\texttt{http://www.gnu.org/software/gettext/manual/gettext.html}}.
+\fi



More information about the cmucl-commit mailing list