luci-base: add support for plural translations and contexts in Lua api

- Introduce a new luci.template.parser.ntranslate() function which
   takes a count, a singular and a plural translation string as well
   as an optional context argument and returns the appropriate,
   language specific plural translation.

 - Introduce an optional translation context argument in the existing
   luci.template.parser.translate() function

 - Support translation contexts in LuCI template directives.
   Translation messages are split on the first unescaped pipe
   character and the reamining string after the pipe is treated
   as context.

Examples:

 - `string.format(p.ntranslate(n, "1 apple", "%d apples"), n)` will
   return an appropriate plural translation for the given amount.

 - `translate("Load", "The system load")` will return an appropiate
   translation for `Load`, using `The system load` as disambiguation
   context (a `msgctxt` directive in *.po files).

 - Likewise `<%:Load|The system load%>` will translate the word
   `Load` while using the remainder of the string as context.

 - To use pipes in translations strings literally, they must be
   escaped: `<%:Use the "\|" character%>` will translate the literal
   string `Use the "|" character`.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich
2020-01-23 21:53:26 +01:00
parent 6f6f3e84ca
commit 9939fc5a26
10 changed files with 6319 additions and 17 deletions

View File

@@ -124,14 +124,24 @@ sub preprocess_htm($$) {
'=' => '(%s)',
'_' => 'translate([==[%s]==])',
':' => 'translate([==[%s]==])',
'+' => 'include([==[%s]==)',
'+' => 'include([==[%s]==])',
'#' => '--[==[%s]==]',
'' => '%s'
};
# Translate the .htm source into a valid Lua source using bracket quotes
# to avoid the need for complex escaping.
$source =~ s|<%-?([=_:+#]?)(.*?)-?%>|sprintf "]==]; $sub->{$1}; [==[", $2|sge;
$source =~ s!<%-?([=_:+#]?)(.*?)-?%>!
my $t = $1;
my $s = $2;
# Split translation expressions on first non-escaped pipe.
if ($t eq ':' || $t eq '_') {
$s =~ s/^((?:[^\|\\]|\\.)*)\|(.*)$/$1]==],[==[$2/;
}
sprintf "]==]; $sub->{$t}; [==[", $s
!sge;
# Discover expressions like "lng.translate(...)" or "luci.i18n.translate(...)"
# and return them as extra keyword so that xgettext recognizes such expressions