Copyright © 2004 Sean Ross. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
This software is provided by the authors and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the authors or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
CL-L10N is a portable localization package for Common Lisp which is more or less modelled on the Allegro Common Lisp locale package. It currently supports various accessors (like locale-mon), number printing, money printing and time/date printing.
The CL-L10N Home Page is at http://www.common-lisp.net/project/cl-l10n where one can find details about mailing lists, cvs repositories and various releases.
Enjoy Sean.
CL-L10N uses asdf as it's system definition tool and
is required whenever you load the package.
You will need to download it, or if you have sbcl
(require 'asdf)
(asdf-install:install :cl-l10n)
This will download and install the package for you. Asdf-install will try to verify
that the package signature is correct and that you trust the author. If the key is
not found or the trust level is not sufficient a continuable error will be signalled.
You can choose to ignore the error and continue to install the package.
See the documentation of asdf-install for more details.
The latest cl-l10n release will always be available from cl.net.
Download and untar in an appropriate directory then symlink cl-l10n.asd to a directory on
asdf:*central-registry*
(see the documentation for asdf for details about setting up asdf).
If you feel the need to be on the bleeding edge you can use anonymous CVS access, see the Home Page for more details for accessing the archive. Once downloaded follow the symlink instructions above.
Once downloaded and symlinked you can load CL-L10N at anytime using
(asdf:oos 'asdf:load-op :cl-l10n)
This will compile CL-L10N the first time it is loaded.
Once installed run (asdf:oos 'asdf:test-op :cl-l10n)
to test
the package. If any tests fail please send an email to one of the
mailing lists.
An integer value which determines the number of digits after the decimal point when all said digits are zero. This variable only has an effect when printing numbers as monetary printing gets this value from the locale.
Loads the locale designated by the locale-designator name which is expected to be found in
*locale-path*
. If use-cache isnil
the locale will be forcibly reloaded from path otherwise the cached locale will be returned. If the locale cannot be found and errorp is not nil an error of typelocale-error
will be signalled.
Returns the value of key in cagetory category-name found in the
locale
locale.
Load all locales found in pathname path.
Prints number using locale locale. If no-ts is not nil no thousand seperators will be used when printing number. If no-dp is not nil the decimal seperator will be suppressed if number is not an integer.
format-number is intended to be used as an argument to the ~/ / format directive. Example (assuming *locale* is en_ZA)
(format t "~:/cl-l10n:format-number/" 1002932) prints `1,002,932`
Prints value as a monetary value using locale locale. If no-ts is not nil no thousand seperators will be used when printing number. If use-int-sym is not nil
locale-int-curr-symbol
will be used instead of the defaultlocale-currency-symbol
Prints value as a monetary value using locale locale. format-money is intended to be used as the function to the ~/ / format directive Examples.
(format t "~/cl-l10n:format-money/" 188232.2322) prints `R188,232.23` ;; and (format t "~:/cl-l10n:format-money/" 188232.2322) prints `ZAR 188,232.23`
Prints the
universal-time
ut as a locale specific time to stream. Equivalent to(format-time stream ut show-date show-time locale fmt time-zone)
.
Prints the
universal-time
ut as a locale specific time to stream. The format of the time printed is controlled by show-time and show-date.
show-time and show-date are not nil
locale-d-t-fmt
show-time and show-date are nil
locale-t-fmt-ampm
orlocale-t-fmt
iflocale-t-fmt-ampm
has no apparent value.show-time is not nil and show-date is nil
- locale-t-fmt
show-date is not nil and show-time is nil
- locale-d-fmt
If fmt is not nil then show-date and show-time are ignored and fmt is used as the format control string. See the Notes Section for the defined control characters which can be used.
Examples (assuming *locale* is “en_ZA” and a CL -2 Time Zone)
(format t "~:/cl-l10n:format-time/" 3192624000) prints `03/03/01' (format t "~@/cl-l10n:format-time/" 3192624000) prints `18:00:00' (format t "~:@/cl-l10n:format-time/" 3192624000) prints `Sat 03 Mar 2001 18:00:00 +0200' (format t "~v,v/cl-l10n:format-time/" "fr_FR" "%A" 3192624000) prints `samedi' (format t "~,v/cl-l10n:format-time/" "%A" 3192624000) prints `Saturday' ; The Time Zone can be overriden with an extra v argument (format t "~v,v,v/cl-l10n:format-time/" "en_ZA" "%A" -8 3192624000) print `Sunday'
Format is an unexported symbol in the cl-l10n package. It's use is to make formatting of dates, times, numbers and monetary values simpler. Shadow importing
cl-l10::format
into your package gives you a few new format directives. The new directives are ~U : Time and Date (universal-time), ~N : Numbers and ~M : Monetary values. All other format directives are unchanged and work as normal. These new directives are drop in replacements for the ~/cl-l10n:format-?/ calls.;; These examples assume an en_ZA locale and a CL -2 Time Zone (in-package :cl-user) (shadowing-import 'cl-l10n::format) (format t "~:U" 3192624000) prints `03/03/2001' (format t "~,vU" "%A" 3192624000) prints `Saturday' (format t "~:N" 3192624000) prints `3,192,624,000' (format t "~:M" 3192624000) prints `ZAR 3,192,624,000.00`
Formatter is another unexported symbol in the cl-l10n package Shadow importing formatter gives support for the new format control directives.
Parses the string num-string into a number using locale.
Tries very hard to make sense out of the argument time-string using locale and returns a single integer representing the universal time if successful. If not, it returns nil. If the :error-on-mismatch keyword is true, parse-time will signal an error instead of returning nil. Default values for each part of the time/date can be specified by the appropriate :default- keyword. These keywords can be given a numeric value or the keyword :current to set them to the current value. The default-default values are 00:00:00 on the current date, current time-zone.
Example, what date does the string “02/03/05” specify? parse-time will use the current locale or the locale-designator passed to it to determine the correct format for dates. In America (en_US) this date is the 3rd of February 2005, with an South African English (en_ZA) locale this date is the 2nd of March 2005 and with a Swedish locale (sv_SE) it's the 5th of March 2002.
Note. This is not my work but was done by Jim Healy and is a part of the CMUCL project, which has been modified to handle differt locales.
Class Precedence:
standard-object
The class representing a loaded category within a locale.
Class Precedence:
error
Root CL-L10N condition which will be signalled when an exceptional situation occurs.
Class Precedence:
error
Error which is signalled when an error occurs when parsing numbers or time strings.
CL-L10N supports internationalised strings through the use of bundles. The process is currently extremely basic, and is bound to change in the future, but is flexible and does what is expected of it.
First you define a bundle using make-instance
.
(defvar *my-bundle* (make-instance 'bundle))
Then you add resources to your bundle using either add-resource
or add-resources
.
(add-resources (bundle "af_") "showtime" "Dankie, die tyd is ~:@/cl-l10n:format-time/~%") ;; an empty string as the locale matcher becomes the default (add-resources (bundle "") "showtime" "Thanks, the time is ~:@/cl-l10n:format-time/~%")
Then by using gettext
you can lookup locale specific strings.
(defun timey () (format t (gettext "showtime" bundle) 3310880446)) (timey) ;; with locale en_ZA prints `Thanks, the time is Wed 01 Dec 2004 11:00:46 +0200` (let ((*locale* (locale "af_ZA"))) (timey)) prints `Dankie, di tyd is Wo 01 Des 2004 11:00:46 +0200`
A useful trick is to define either a macro or reader macro wrapping gettext for your specific bundle eg.
(set-dispatch-macro-character #\# #\" #'(lambda (s c1 c2) (declare (ignore c2)) (unread-char c1 s) `(cl-l10n:gettext ,(read s) bundle))) ;; or this (defmacro _ (text) `(cl-l10n:gettext ,text bundle))
which would change the timey
function to
(defun timey () (format t #"showtime" 3310880446)) ;; or (defun timey () (format t (_ "showtime") 3310880446))
Adds an entry to bundle for locale-name mapping from to to. The locale-name does not have to be a full name like “en_US” but can be a partial match like “en_”. Adding mappings for these two locale-names will result in the mapping for “en_US” being used when the locale is “en_US” and the mapping for “en_” being used when using any other english locale. Adding a mapping for an empty locale-name will become the default.
;; Add mapping for welcome for Afrikaans languages. (add-resource *my-bundle* "welcome" "welkom" "af_")
Utility macro to group large amounts of entries into a single logical block for a locale.
(add-resources (bundle "af_") "hello" "hallo" "goodbye" "totsiens" "yes" "ja" "no "nee") == (add-resource bundle "hello" "hallo" "af_") (add-resource bundle "goodbye" "totsiens" "af_") (add-resource bundle "yes" "ja" "af_") (add-resource bundle "no" "nee" "af_")
Looks for a mapping for name in bundle. If no mapping is found returns name.
The locale argument to the various locale accessors and to the print functions is a locale designator. A locale designator is one of three things
(locale name)
The default locale is found by looking at various environment variables. If the CL_LOCALE environment variable is set then this locale is loaded. Failing that the locale designated by the environment variable LC_CTYPE is loaded. If these two have failed then the POSIX locale is loaded as the default.
The following is a list of each legal control character in a time format string followed by a description of what is does.
There are a number of accessor functions to the various locale attributes defined. The functions are named by replacing underscores with hypens and prepending locale- to the name. The following is each defined accessor function in the format Category, Keyword and the accessor function for it.
locale-int-curr-symbol
locale-currency-symbol
locale-mon-decimal-point
locale-mon-thousands-sep
locale-mon-grouping
locale-positive-sign
locale-negative-sign
locale-int-frac-digits
locale-frac-digits
locale-p-cs-precedes
locale-p-sep-by-space
locale-n-cs-precedes
locale-n-sep-by-space
locale-p-sign-posn
locale-n-sign-posn
locale-decimal-point
locale-thousands-sep
locale-grouping
locale-abday
locale-day
locale-abmon
locale-mon
locale-d-t-fmt
locale-d-fmt
locale-t-fmt
locale-am-pm
locale-t-fmt-ampm
locale-date-fmt
locale-yesexpr
locale-noexpr
locale-height
locale-width
locale-name-fmt
locale-name-gen
locale-name-mr
locale-name-mrs
locale-name-miss
locale-name-ms
locale-postal-fmt
locale-tel-int-fmt
locale-measurement
Thanks To
add-resource
: I18Nadd-resources
: I18Nformat
: APIformat-money
: APIformat-number
: APIformat-time
: APIformatter
: APIgettext
: I18Nload-all-locales
: APIlocale
: APIlocale-name
: APIlocale-value
: APIparse-number
: APIparse-time
: APIprint-money
: APIprint-number
: APIprint-time
: API