Source

j18n / src / main / clojure / j18n / core.clj

The default branch has multiple heads

Full commit
(ns ^{:doc
  "Provide some Clojure sugar for internationalisation using the usual
  Java infrastructure of ResourceBundles."
      :author "Meikel Brandmeyer <m@kotka.de>"}
  j18n.core
  (:import
    java.util.ResourceBundle))

(def ^{:private true} bundles (atom {}))

(defmacro defbundle
  "Creates a new bundle with given name. Attaches the Var to the metadata
  of the namespace. If several bundles are defined in one namespace, the
  last one wins as “the official bundle” for that namespace."
  ([bundle-name] `(defbundle ~bundle-name (name (ns-name *ns*))))
  ([bundle-name package]
   `(do
      (declare ~bundle-name)
      (alter-meta! *ns* assoc ::bundle (symbol (name (ns-name *ns*)) ~(name bundle-name)))
      (swap! @#'bundles assoc (var ~bundle-name) ~package)
      (var ~bundle-name))))

(defn init-bundles!
  "Initialise all bundles defined with defbundle. This should only be called
  once during application startup and initialisation."
  []
  (doseq [[v p] @bundles]
    (alter-var-root v (constantly (ResourceBundle/getBundle p)))))

(defn translate*
  "Translate the given message in the given bundle. This is basically a
  wrapper around ResourceBundle/getString."
  [^String message ^ResourceBundle bundle]
  (.getString bundle message))

(defmacro translate
  "Translate the given message. Message may be a qualified or non-qualified
  keyword or a String. The message is looked up in the given bundle. If no
  bundle is given, the official bundle of the namespace of the qualified
  keyword will be used. If the keyword is not qualified or the message key
  is given as String, the official bundle of the current namespace will be
  used."
  ([message]
   (let [bundle (if (keyword? message)
                  (if-let [nspace (namespace message)]
                    (::bundle (meta (the-ns (symbol nspace))))
                    (::bundle (meta *ns*)))
                  (::bundle (meta *ns*)))]
     `(translate ~message ~bundle)))
  ([message bundle]
   `(translate* ~(if (keyword? message) (name message) message) ~bundle)))