CL-L10N Manual

Table of Contents


Next: , Up: (dir)

CL-L10N: CL Localization Package

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:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. The names of the authors and contributors may not be used to endorse or promote products derived from this software without specific prior written permission.

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.


Next: , Previous: Top, Up: Top

1 Introduction

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.

1.1 Supported Implementations


Next: , Previous: Introduction, Up: Top

2 Getting Started

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)

2.1 Downloading

2.2 Installing

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.


Next: , Previous: Getting Started, Up: Top

3 API

3.1 Variables

— Variable: *locale*

The default locale which will be used.

— Variable: *locale-path*

The default pathname where locale definition files can be found.

— Variable: *locales*

A hash table containing loaded locales keyed on locale name.

— Variable: *float-digits*

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.

3.2 Functions

— Function: locale-name locale

Returns the name of locale.

— Function: locale name &key (use-cache t) (errorp t)

Loads the locale designated by the locale-designator name which is expected to be found in *locale-path*. If use-cache is nil 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 type locale-error will be signalled.

— Function: locale-value locale category-name key

Returns the value of key in cagetory category-name found in the locale locale.

— Function: load-all-locales &optional (path *locale-path*)

Load all locales found in pathname path.

— Function: print-number number &key (stream *standard-output) no-ts no-dp locale *locale*

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.

— Function: format-number stream arg no-dp no-ts &optional (locale *locale*)

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`
          
     

— Function: print-money value &key (stream *standard-output) use-int-sym no-ts (locale *locale*)

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 default locale-currency-symbol

— Function: format-money stream arg use-int-sym no-ts &optional (locale *locale*)

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`
          
     

— Function: print-time ut &key show-date show-time (stream *standard-output) (locale *locale) fmt time-zone

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).

— function: format-time stream ut show-date show-time &optional (locale *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 or locale-t-fmt if locale-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'
     

— Function: format stream fmt-string &rest args

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`
     

— Macro: formatter fmt-string

Formatter is another unexported symbol in the cl-l10n package Shadow importing formatter gives support for the new format control directives.

— Function: parse-number num-string &optional (locale *locale*)

Parses the string num-string into a number using locale.

— Function: parse-time time-string &key (start 0) (end (length time-string)) (error-on-mismatch nil) (patterns *default-date-time-patterns*) (default-seconds nil) (default-minutes nil) (default-hours nil) (default-day nil) (default-month nil) (default-year nil) (default-zone nil) (default-weekday nil) (locale *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.

3.3 Classes

— Class: locale

Class Precedence: standard-object The class representing a loaded locale.

— Class: category

Class Precedence: standard-object The class representing a loaded category within a locale.

3.4 Conditions

— Condition: locale-error

Class Precedence: error

Root CL-L10N condition which will be signalled when an exceptional situation occurs.

— Condition: parser-error

Class Precedence: error Error which is signalled when an error occurs when parsing numbers or time strings.


Next: , Previous: API, Up: Top

4 I18N

4.1 Internationalisation

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))
     

4.2 API

— Generic: add-resource bundle from to locale-name

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_")
     

— Macro: add-resources (bundle locale-name) &rest entries

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_")
          
     

— Function: gettext name bundle &optional (*locale* *locale* )

Looks for a mapping for name in bundle. If no mapping is found returns name.


Next: , Previous: I18N, Up: Top

5 Notes

5.1 Locale Designators

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

5.2 The Default Locale

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.

5.3 Time Format Control Characters

The following is a list of each legal control character in a time format string followed by a description of what is does.

5.4 Accessors to Locale Values.

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.

5.5 Known Issues


Next: , Previous: Notes, Up: Top

6 Credits

Thanks To


Previous: Credits, Up: Top

7 Index

7.1 Function Index

7.2 Variable Index