Next: Error handling, Previous: Templates composition, Up: Top [Contents][Index]
| • Syntax | ||
| • Tags | ||
| • Filters | ||
| • Choosing language | ||
| • Backends | ||
| • Translate backend | ||
| • Locale backend | ||
| • Gettext backend | ||
Next: Tags<2>, Up: Internationalization [Contents][Index]
The easiest way to translate a string or variable is to enclose it between {_ and _}:
{_ var _}
{_ "hello" _}
Next: Filters<2>, Previous: Syntax, Up: Internationalization [Contents][Index]
| • trans | ||
Translates a variable or string
Example:
{% trans var %}
{% trans "hello" %}
Next: Choosing language, Previous: Tags<2>, Up: Internationalization [Contents][Index]
| • trans | ||
Up: Filters<2> [Contents][Index]
Translates a variable or string.
For example:
{{ var | trans }}
{{ "my string" | trans }}
Next: Backends, Previous: Filters<2>, Up: Internationalization [Contents][Index]
To choose the language to use, set the *CURRENT-LANGUAGE* variable.
For example:
(let ((djula:*current-language* :es)) (djula:render-template* +translation.html+))
Next: Translate backend, Previous: Choosing language, Up: Internationalization [Contents][Index]
Djula supports several backends for doing translations: cl-locale1, gettext2, translate3.
For translations to work, one of the translation backend systems need to be loaded and configured. Otherwise translate function will signal an error.
The ASDF systems are: djula-gettext, djula-locale and djula-translate.
Please have a look at the demo and the documentation of those packages to figure out how to use them.
Next: Locale backend, Previous: Backends, Up: Internationalization [Contents][Index]
TBD
Next: Gettext backend, Previous: Translate backend, Up: Internationalization [Contents][Index]
TBD
Previous: Locale backend, Up: Internationalization [Contents][Index]
| • Gettext message extraction | ||
| • Gettext utilities | ||
Next: Gettext utilities, Up: Gettext backend [Contents][Index]
For working with gettext library, messages to be translated first need to be extracted from Djula templates, generate a Lisp file with Gettext entries from it, and then extracted again from that file with xgettext library.
Create a Makefile similar to this:
gettext-extract: ## Extract gettext translations from source files
sbcl --eval '(ql:quickload :my-project)' --eval '(djula::xgettext-templates :my-project-package (asdf:system-relative-pathname :my-project "i18n/xgettext.lisp"))' --quit
find src -iname "*.lisp" | xargs xgettext --from-code=UTF-8 --keyword=_ --output=i18n/my-project.pot --sort-output
gettext-edit: ## Edit the extracted gettext translations
msgmerge --update i18n/nb.po i18n/my-project.pot
xdg-open i18n/nb.po
gettext-compile: ## Compile the edited gettext translations
msgfmt --output-file=i18n/nb/LC_MESSAGES/ie.mo i18n/nb.po
gettext-init: ## Initialize gettext translations
msginit --input=i18n/my-project.pot --locale=nb --output=i18n/nb.po
make gettext-extract first uses the Lisp compiler to extract translated strings from templates. That generates a Lisp file that can be used with xgettext command line utility. This Lisp file is basically dead code that should not be loaded into the project, just contains Gettext entries that xgettext utility can understand. Looks like this:
;; THIS FILE IS AUTOGENERATED. DON'T CHANGE BY HAND. USE XGETTEXT-TEMPLATES FUNCTION. (INVOICE-ENGINE::GETTEXT "Activity") (INVOICE-ENGINE::GETTEXT "Address 1") (INVOICE-ENGINE::GETTEXT "Address 2") (INVOICE-ENGINE::GETTEXT "Amount") (INVOICE-ENGINE::GETTEXT "API") (INVOICE-ENGINE::GETTEXT "Balance") (INVOICE-ENGINE::GETTEXT "Close") (INVOICE-ENGINE::GETTEXT "Company") (INVOICE-ENGINE::GETTEXT "Contact person")
Then xgettext can be used to extract the messages from that file.
Previous: Gettext message extraction, Up: Gettext backend [Contents][Index]
Use GETTEXT:PRELOAD-CATALOGS to inspect current gettext settings:
(gettext:preload-catalogs ;; Tell gettext where to find the .mo files #.(asdf:system-relative-pathname :my-project "locale/"))
And that returns Gettext information:
#S(GETTEXT::CATALOG
:KEY ("fr_fr" :LC_MESSAGES "bookshops")
:HEADERS ((:PROJECT-ID-VERSION . "PACKAGE VERSION")
(:REPORT-MSGID-BUGS-TO . "")
(:PO-REVISION-DATE . "YEAR-MO-DA HO:MI +ZONE")
(:LAST-TRANSLATOR . "FULL NAME <EMAIL@ADDRESS>")
(:LANGUAGE-TEAM . "LANGUAGE <LL@li.org>") (:LANGUAGE . "")
(:MIME-VERSION . "1.0")
(:CONTENT-TYPE . "text/plain; charset=CHARSET")
(:CONTENT-TRANSFER-ENCODING . "8bit"))
:NPLURALS 2
:PLURALS-FUNCTION #<FUNCTION (LAMBDA (GETTEXT::N)) {542C149B}>
:MESSAGES (SERAPEUM:DICT
"Login" '("Se connecter")
"Password" '("Mot de passe")
"Please login to continue" '("Veuillez vous identifier pour continuer")
"Results: ~a. Page: ~a/~a~&" '("Resultats: ~a. Page: ~a/~a~&")
"Welcome to OpenBookStore" '("Bienvenue dans OpenBookStore")
) )
Run the following function to reload the translations when developing:
(defun reload-translations () ;; Clear gettext's cache (clrhash gettext::*catalog-cache*) (gettext:preload-catalogs ;; Tell gettext where to find the .mo files #.(asdf:system-relative-pathname :my-project "locale/")))
https://github.com/arielnetworks/cl-locale
https://github.com/copyleft/gettext
https://gitlab.common-lisp.net/dkochmanski/translate
Previous: Gettext message extraction, Up: Gettext backend [Contents][Index]