Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write multilingual applications in Clojure?

I'm trying to figure out how to create a Compojure-based web-site with multilingual support. Is there any solutions like i18n or something like that?

like image 284
jarik Avatar asked Dec 18 '10 16:12

jarik


4 Answers

The easiest way is to replace all your localized strings with a function calls like:

(i18n lang "help")

And implement that function to read localized string from a .properties file determined by lang parameter.

For that you don't need any libraries. It's a simple function.

To avoid reading files all the time you could read them in memory during your applications start with a def into a map named loaded-property-files where, lang is the key and the value is a map of message keys and appropriate localized messages.

This can be done like this:

(defn load-property-files [langs]
  (let [default (into {} (read-properties "locale.properties"))]
      (apply merge 
       (for [lang langs] 
        (assoc {} lang
         (merge default 
          (into {} (read-properties (str "locale_" lang ".properties")))))))))

(def loaded-property-files 
      (load-property-files ["en" "es" "de"]))

If file loading performance is not a problem, but you'd like to be able to change the files more easily during runtime, just change the def to a function.

The function read-properties (originally from old clojure.contrib) looks like this:

(defn read-properties
  "Read properties from file-able."
  ([fileable]
   (into {} (map #(vector (keyword (key %)) (val %))
    (try
      (with-open [f (java.io.FileInputStream. (new java.io.File fileable))]
        (doto (new java.util.Properties)
          (.load f)))
    (catch java.io.FileNotFoundException e {})))))
  ([fileable defaults] (merge (read-properties fileable) defaults)))

The localization string from default file would be used whenever that key isn't found in the specified map, i.e. new string that has just been added, and no one translated it in Spanish yet, would be shown in language from default locale.properties

Then your i18n function looks like this:

(defn i18n [lang code]
  ((loaded-property-files lang) code))
like image 100
Goran Jovic Avatar answered Nov 13 '22 15:11

Goran Jovic


There is a new i18n library: https://github.com/ptaoussanis/tower with this rationale:

Tower is an attempt to present a simple, idiomatic internationalization and localization story for Clojure. It wraps standard Java functionality where possible, but it isn't afraid to step away from Java conventions when there's a good reason to.

like image 33
jneira Avatar answered Nov 13 '22 13:11

jneira


I created clji18n for this, but I had to switch to other project before completing it. It's "almost" usable, you can give it a try.

like image 5
Sebastián Galkin Avatar answered Nov 13 '22 14:11

Sebastián Galkin


kotarak's j18n (note that there is another j18n library for Java but they are different ones) seems good.

https://bitbucket.org/kotarak/j18n

like image 4
omasanori Avatar answered Nov 13 '22 14:11

omasanori