Liking cljdoc? Tell your friends :D

internationalisation

A Clojure library designed to provide simple interationalisation of user-facing messages.

Usage

To use this library in your project, add the following leiningen dependency:

[org.clojars.simon_brooke/internationalisation "1.0.4"]

To use it in your namespace, require:

[scot.weft.i18n.core :refer [get-message get-messages]]

There is only two functions you may need to use:

get-messages

(get-messages accept-language-header resource-path default-locale)

Return the most acceptable messages collection we have given this accept-language-header.

  • accept-language-header should be a string representing the value of an RFC 2616 Accept-Language header;
  • resource-path should be a string representing the fully-qualified path name of the directory in which message files are stored;
  • default-locale should be a string representing a locale specifier to use if no acceptable locale can be identified.

For example:

(get-messages "en-GB;q=0.9, fr-FR" "i18n" "en-GB")

Returns a map of message keys to strings.

See RFC 2616.

NOTE THAT get-messages is memoized resulting in faster response when called repeatedly with similar arguments.

get-message

A wrapper around get-messages to resolve a single, particular message.

(get-message token)

(get-message token accept-language-header)

(get-message token accept-language-header resource-path default-locale)

where

  • token is the Clojure keyword which identifies the particular message you want to retrieve;

and all the other arguments are as defined above.

For example:

(get-message :pipe)

(get-message :pipe "en-GB;q=0.9, fr-FR")

(get-message :pipe "de-DE" "i18n" "ru")

So how does this work? When one calls (get-message token accept-language-header), how does it know where to find resources? The answer is that there is a *config* map, with (currently) two significant keys:

  • :resource-path, whose value should be a string representation of the default path within the resources space on which translation files will be sought. Initialised to i18n.
  • :default-language, the language tag for the language to use when no otherwise suitable language can be identified. Initialised to the default language of the runtime session, so this may well be different on your machine from someone elses running identical software.

Thus

(binding [*config* {:resource-path "language-files"
                    :default-language "en-CA"}]
    (get-message :pipe "en-GB;q=0.9, fr-FR"))

and

(get-message :pipe "en-GB;q=0.9, fr-FR" "language-files" "en-CA")

are effectively the same.

The intelligent reader will note that if one calls

(get-message :pipe)

there's no mechanism to set the accept-header. This is true. The expected use case for this arity of the function is in desktop applications where the locale of the local machine will always be the correct locale to use. The two-argument arity of the function is intended for web applications, where different clients may have different linguistic needs.

NOTE THAT get-message is also memoized, and for the same reason.

The translation files

Obviously, this only works if you provide files with translations of your interesting strings. These files should contain Clojure maps, and the file names should be the locale string for which the file is relevent followed by the extension ".edn". All the translation files should be in the same directory.

In this project you will find two very simple example files, which should give you the idea:

en-GB.edn

;;;; This is a British English translation file.

{:pipe "This is not a pipe"}

fr-FR.edn

;;;; This is a French translation file.

{:pipe "Ceci n'est pas une pipe."}

Documentation

Documentation can be found here. It may be generated by running

lein codox

Future direction

It's likely that in future configuration will be extended

  1. To read per-language keys/messages from CSV files;
  2. To read per-language keys/messages from database tables;
  3. potentially, to read per-language keys/messages from other sources.

Pull requests implementing any of these things will be welcomed.

Deprecated features

There are still two dynamic configuration variables, *default-language* and *resource-path*, but these are now superceded by the *config* map, which is extensible. Consequently, if you are using these configuration variables in production, you should bind *config* to nil.

License

Copyright © 2017 Simon Brooke

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

Can you improve this documentation? These fine people already did:
simon & Simon Brooke
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close