I use a very simple solution, I specify Vala as the language for xgettext. It is close enough to Scala in terms of escaping literals and function call syntax. It is not a rigorous solution, but in my practice it has worked well enough for me.
I have a Po
class holding the message catalog, and allowing me to perform the translations via a couple of simple methods:
def t(singular: String): String = lookupSingular(None, singular)
def tf(singular: String, parameters: Any*): String = format(t(singular), Array(parameters: _*))
def tc(ctx: String, singular: String): String = lookupSingular(Some(ctx), singular)
def tcf(ctx: String, singular: String, parameters: Any*): String = format(lookupSingular(Some(ctx), singular), Array(parameters: _*))
def tn(singular: String, plural: String, n: Long): String = lookupPlural(None, singular, plural, n)
def tcn(ctx: String, singular: String, plural: String, n: Long): String = lookupPlural(Some(ctx), singular, plural, n)
t
stands for Translate, f
for Formatted (has parameters), c
for Context (meaning the gettext context, and additional information to the messages distinguishing it from other messages with the same text), n
stands for plural with N specified. You can make up your own names.
These methods acts both as a means of performing a translation, and as a marker for xgettext to extract the .pot
files from the source code.
I use those like this:
new JMenuItem(po.t("Copy to clipboard"))
new JButton(po.tc("errorDialog", "Copy to clipboard"))
po.tf("Camera {0}", number),
etc.
With this setup, I run xgettext like this:
xgettext \
--package-name="xxx" \
-ktc:1c,2 \
-ktcf:1c,2 \
-ktnc:1c,2,3 \
-ktf \
-kt \
-ktn:1,2 \
-o "output.po" \
$(find "DIRECTORY" -name *.scala) 2>&1 | grep -v "extension 'scala' is unknown; will try C"
The important part is the -k
parameters, that maps custom xgettext keywords directly to names of my methods. This way, xgettext can be configured to use custom keywords.
Scala's triple quotes are not supported, though. xgettext warns about "unterminated literal" when encountering them, but progresses anyway.
IIRC, even the -c
command line parameter can be made to work to support comments about the translated message, that can be very useful for the translators.
A couple of more observations from practice that do not directly answer the original question:
- If I was implementing this again, the methods
t
, tc
, ... would not return directly a translated String, but some LocalizableMessage
encapsulating the original string and expansion parameters, that could be translated later lazily via an appropriate catalog.
- I don't use the methods
tn
(gettext way of handling plurals). I recommend using the more general ICU messsage expansion libraries or something similar.