I18n made easy for web sites written with eliom
usage: ocsigen-i18n-generator [options] [< input] [> output]
--languages Comma-separated languages (e.g. en,fr-fr, or Foo.Fr,Foo.Us if using external types). Must be ordered as in source TSV file.
--default-language Set the default language (default is the first one in --languages).
--input-file TSV file containing keys and translations. If option is omited or set to -, read on stdin.
--ouput-file File TSV file containing keys and translations. If option is omitted or set to -, write on stdout.
--external-type Values passed to --languages option come from a predefined type (do not generate the type nor from/to string functions).
--primary Generated file is secondary and depends on given primary file.
-help Display this list of options
--help Display this list of options
The ppx supports two general forms of constructions:
- I18n entries in the 'default' file
- I18n entries in a given module
You can use ocsigen-i18n-generator
to generate multiple .eliom files
from different TSV files. One of those will be the "default" one.
Use the -ppx 'ocsigen-i18n-rewriter DEFAULT'
where DEFAULT
is the name of the module generated with ocsigen-i18n-generator
you wish to use as a default for all extension expressions
(basename of the output file)
This will call the right function turning
[%i18n foo]
into DEFAULT.foo ()
,
[%i18n S.bar ~x:"foo"]
into DEFAULT.S.bar ~x:"foo" ()]
and so on...
To specify a different module from the default one, you can do so using expressions such as these:
[%i18n MyI18n.foo]
will becomeMyI18n.foo ()
[%i18n MyI18n.S.bar ~x:[%i18n S.foo]]
will becomeMyI18n.S.bar ~x:(DEFAULT.S.foo ()) ()
Because the rewriter infers your module from the module-path of your expression,
it needs to make the assumption that a module named S
will always be
the one generated by ocsigen-i18n-generator
for strings.
Do not name your i18n file s.tsv
. It won't be compatible.
Because the ppx already forces you to i18n
in the expression,
and because most projects will want to keep sane files with i18n
in their names,
it would be likely to end up with expressions like [%i18n I18n_a.entry]
.
This is redundant and heavy. So, if you like, you can auto-prefix and auto-suffix your module names.
Calling the rewriter with -ppx 'ocsigen-i18n-rewriter --prefix Pr_ --suffix _i18n DEFAULT'
will prefix and suffix all custom modules (i.e. not the DEFAULT
one) with Pr_
and _i18n
.
As such, [%i18n Feature.foo]
will become Pr_Feature_i18n.foo ()
,
allowing for clearer and more readable expressions.
The prefix must begin with a capital letter, to make it a legit module name start.
If you use these options, note that your file will need to account for the capital in the middle part.
[%i18n Module.entry]
still needs Module
to be a module name.
opam pin add ocsigen-i18n https://github.com/besport/ocsigen-i18n.git
opem install ocsigen-i18n
Define your translations into a tsv file. The first column is the key to use (i.e. the name of the OCaml variable to use in your code). The next columns are the translation for each language you want to use.
foo This is a simple key. Ceci est une clé toute simple.
bar I am {{x}}. Je suis {{x}}.
baz There {{{c?are||is}}} apple{{{c?s||}}} here! Il y a {{{c?des||une}}} pomme{{{c?s||}}} ici !
bu I am {{x %s}} ({{n %d}}). Je suis {{x %s}} ({{n %d}}).
{{x}}
defines a variable labeled~x
{{x %d}}
defines a variable labeled~x
, and the%d
format is used to displayx
as a string.{{x?a||b}}
defines an optional boolean value?x
. Ifx
istrue
thena
will be displayed. If it isfalse
(which is the default), thenb
is chosen.
[%i18n foo]
[%i18n bar ~x:[%i18n a_human]]
[%i18n bar ~x:[ pcdata "Jean-Michel ("
; pcdata @@ string_of_int id
; pcdata ")" ] ]
[%i18n baz]
[%i18n baz ~c:(nb > 1)]
[%i18n bu ~x:"Jean-Michel" ~n:id ]
This will generate an HTML fragment (a list of elements). If you want a string
instead of a list of elements, prefix the variable name by S.
, e.g.
[%i18n S.bar ~s:[%i18n S.a_human]]
.
A conditional value {{{c?if_true||if_false}}}
will generate a function
taking an optional parameter ?(c=false)
to define if if_true
or if_false
needs to be printed.
Languages does not need to use the same labeled variables. The compiler will generate a function taking all the parameters it can detect when parsing the template.
Variable name used twice refers to the same argument.