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