Skip to content

Latest commit

 

History

History
125 lines (93 loc) · 4.81 KB

README.MD

File metadata and controls

125 lines (93 loc) · 4.81 KB

ocsigen-i18n

I18n made easy for web sites written with eliom

ocsigen-i18n-generator

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

ocsigen-i18n-rewriter

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 become MyI18n.foo ()
  • [%i18n MyI18n.S.bar ~x:[%i18n S.foo]] will become MyI18n.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.

Affixing the module names

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.

Installation

opam pin add ocsigen-i18n https://github.com/besport/ocsigen-i18n.git
opem install ocsigen-i18n

How to

Templating system

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 display x as a string.
  • {{x?a||b}} defines an optional boolean value ?x. If x is true then a will be displayed. If it is false (which is the default), then b is chosen.

Using the templates

[%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]].

Notes about the templates

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.