casid / jte

Secure and speedy templates for Java and Kotlin.
https://jte.gg
Apache License 2.0
754 stars 56 forks source link

LocalizationSupport does expand ChoiceFormat place holders #373

Open PeterFokkinga opened 3 weeks ago

PeterFokkinga commented 3 weeks ago

It would be nice if LocalizationSupport not only expands simple place holders like {0} but also the choice format so one can display a text in proper singular or plural form based on a numerical value.

Example input: There {0,choice,0#are no new messages|1#is one new message|1< are {0} new messages} in your inbox.

A possible implementation would be to replace the current regular expression based code with a call to MessageFormat, ie

@SuppressWarnings("unused") // Called by template code
default Content localize(String key, final Object... params) {
    final String value = this.lookup(key);
    return value != null && !value.isEmpty() ? new Content() {
        public void writeTo(TemplateOutput output) {
            output.writeContent(new MessageFormat(value).format(params));
        }
    }
    : null;
}
casid commented 3 weeks ago

Hi @PeterFokkinga!

Thanks for sharing. However, the way you implemented it would make the usage of localize unsafe in HTML contexts.

There is a whole set of tests for localization, providing some examples, like this one.

At work we explicitly opted out of MessageFormat, to have more control over localizations and don't pay the message format performance penalty. For instance, we have custom localize methods for key lookup of one, some, many keys. Replacing the current implementation with MessageFormat is a no-go, as it would break existing user code.

If you want, you could create your own MessageFormatLocalizationSupport and use that. To be safe, you would need to output escape all String parameters received, before passing them down to MessageFormat.