gettext-clj ( gtclj
) is a library that allows developers quickly and easily internationalize their Clojure, ClojureScript and ClojureDart projects.
Using standard GNU gettext utilities gtclj
extracts translatable strings from .clj
, .cljc
, .cljx
, .cljs
and .cljd
files into Portable Object ( po
, pot
) files. The po
file format is widely supported by translation software, and many programming languages. Translated po
files are parsed by gtclj
into compact, Clojure friendly JSON.
- pure Clojure (no external dependencies)
- simple
map
data format - plural support for 121 languages (derrived from Unicode CLDR data)
- context support to allow for multiple translations of the same message (ui elements, homonyms, gender etc.)
- e.g.
{{"Queue" "File d'attente"} "tab" {"Queue" "File"}}
- e.g.
- fallback to a language other than english with a simple
merge
- e.g.
(merge (json/read-str (slurp "be-nl.json")) (json/read-str (slurp "be-fr.json")))
- e.g.
None. gtclj
is a pure Clojure project, with no external dependencies.
git clone https://github.com/TiLogic/gettext-clj
cd gettext-clj
# Extract po files (locales are optional)
bash cli/gtclj -p -s path/to/clj/project/dir -o path/to/output/dir fr_CA fr_FR de_DE
# Parse to JSON
bash cli/gtclj -j -s path/to/po/files -o path/to/output/dir
;; deps.edn
{:paths ["src"]
:deps {,,,
tilogic/gettext-clj
{:git/url "https://github.com/TiLogic/gettext-clj.git"
:sha "fcf8f3b8b2937e8a93576041ef98b623bf3de96d"}}}
(ns my.namespace
(:require
[clojure.data.json :as json]
[tilogic.gettext-clj :as gt]))
(def data (atom nil))
(def fr-ca {"Hello, world!" "Salut, monde!"
"What a beautiful cat!" ["Quel beau chat!" "Quels beaux chats!"]
"Duck!" "Baisser la tête!"
"She found a bat in her basement." ["Elle a trouvé un bâton de baseball dans son sous-sol." "Elle a trouvé des bâtons de baseball dans son sous-sol."]
"bird" {"Duck!" "Canard!"}
"mammal" {"She found a bat in her basement." ["Elle a trouvé une chauve-souris dans son sous-sol." "Elle a trouvé %s chauves-souris dans son sous-sol."]}})
(gt/add-locale data :jp (json/read-str (slurp "assets/jp.json")))
(gt/add-locale data :fr-ca fr-ca)
(gt/set-locale data :fr-ca)
(def gettext (gt/gettext-fn data))
(def ngettext (gt/gettext-fn data))
(def pgettext (gt/gettext-fn data))
(def npgettext (gt/gettext-fn data))
(gettext "Hello, world!") ;; => "Salut, monde!"
(ngettext "What a beautiful cat!" "What beautiful cats!" 17) ;; => "Quels beaux chats!"
(pgettext "bird" "Duck!") ;; => "Canard!"
(format (npgettext "mammal"
"She found a bat in her basement."
"She found %s bats in her basement."
2) 2) ;; => "Elle a trouvé 2 chauves-souris dans son sous-sol."
(pgettext "bird" "Duck!" :jp) ;; => "鴨!"
{"msgid" "msgstr"
"a message" "a translated message"
"msgid (plural)" ["msgstr[0]" "msgstr[1]" "msgstr[n]"]
"a plural message" ["plural translation 0" "plural translation 1" "plural translation n"]
"context" {"message" "translated message"}}
No (and yes!). There are many fine internationalization libraries1, but (currently) none of them work with ClojureDart — hence, the existence of gettext-clj
.
gettext
's .po
file format is widely used by translation software, and can be easily converted to other formats if required.
No. The gtclj
library uses a Clojure map
as as its data format. String extraction and po
file parsing are optional.
ClojureDart does not currently support edn
.
clj -X:test
clj -M:test-cljs
sh test/cljd/run.sh
bash test/cli/run.sh