diff --git a/docs/src/main/asciidoc/qute-reference.adoc b/docs/src/main/asciidoc/qute-reference.adoc index 942ecaef36afd..dea89afaf0357 100644 --- a/docs/src/main/asciidoc/qute-reference.adoc +++ b/docs/src/main/asciidoc/qute-reference.adoc @@ -1659,7 +1659,7 @@ public class CustomLocator implements TemplateLocator { === Template Variants Sometimes it's useful to render a specific variant of the template based on the content negotiation. -This can be done by setting a special attribute via `TemplateInstance.setAttribute()`: +This can be done by setting a special attribute via `TemplateInstance.setVariant()`: [source,java] ---- @@ -1672,7 +1672,9 @@ class MyService { ItemManager manager; String renderItems() { - return items.data("items",manager.findItems()).setAttribute(TemplateInstance.SELECTED_VARIANT, new Variant(Locale.getDefault(),"text/html","UTF-8")).render(); + return items.data("items", manager.findItems()) + .setVariant(new Variant(Locale.getDefault(), "text/html", "UTF-8")) + .render(); } } ---- @@ -2829,7 +2831,7 @@ public class MyBean { Template hello; String render() { - return hello.instance().setAttribute("locale", Locale.forLanguageTag("cs")).render(); <1> + return hello.instance().setLocale("cs").render(); <1> } } ---- diff --git a/extensions/qute/runtime/src/main/java/io/quarkus/qute/i18n/MessageBundles.java b/extensions/qute/runtime/src/main/java/io/quarkus/qute/i18n/MessageBundles.java index b460ac5b144d8..6191405d631fc 100644 --- a/extensions/qute/runtime/src/main/java/io/quarkus/qute/i18n/MessageBundles.java +++ b/extensions/qute/runtime/src/main/java/io/quarkus/qute/i18n/MessageBundles.java @@ -28,7 +28,7 @@ public final class MessageBundles { - public static final String ATTRIBUTE_LOCALE = "locale"; + public static final String ATTRIBUTE_LOCALE = TemplateInstance.LOCALE; public static final String DEFAULT_LOCALE = "<>"; private static final Logger LOGGER = Logger.getLogger(MessageBundles.class); diff --git a/independent-projects/qute/core/src/main/java/io/quarkus/qute/TemplateInstance.java b/independent-projects/qute/core/src/main/java/io/quarkus/qute/TemplateInstance.java index 25d496ec4a206..5b5a2f1f9a42a 100644 --- a/independent-projects/qute/core/src/main/java/io/quarkus/qute/TemplateInstance.java +++ b/independent-projects/qute/core/src/main/java/io/quarkus/qute/TemplateInstance.java @@ -1,5 +1,6 @@ package io.quarkus.qute; +import java.util.Locale; import java.util.concurrent.CompletionStage; import java.util.function.Consumer; import java.util.function.Function; @@ -31,6 +32,11 @@ public interface TemplateInstance { */ String SELECTED_VARIANT = "selectedVariant"; + /** + * Attribute key - locale. + */ + String LOCALE = "locale"; + /** * Set the the root data object. Invocation of this method removes any data set previously by * {@link #data(String, Object)} and {@link #computedData(String, Function)}. @@ -70,7 +76,6 @@ default TemplateInstance computedData(String key, Function funct } /** - * * @param key * @param value * @return self @@ -80,7 +85,6 @@ default TemplateInstance setAttribute(String key, Object value) { } /** - * * @param key * @return the attribute or null */ @@ -142,7 +146,6 @@ default CompletionStage consume(Consumer consumer) { } /** - * * @return the timeout * @see TemplateInstance#TIMEOUT */ @@ -151,7 +154,6 @@ default long getTimeout() { } /** - * * @return the original template */ default Template getTemplate() { @@ -159,7 +161,6 @@ default Template getTemplate() { } /** - * * @param id * @return the fragment or {@code null} * @see Template#getFragment(String) @@ -178,6 +179,38 @@ default TemplateInstance onRendered(Runnable action) { throw new UnsupportedOperationException(); } + /** + * Sets the {@code locale} attribute that can be used to localize parts of the template, i.e. to specify the locale for all + * message bundle expressions in the template. + * + * @param locale a language tag + * @return self + */ + default TemplateInstance setLocale(String locale) { + return setAttribute(LOCALE, Locale.forLanguageTag(locale)); + } + + /** + * Sets the {@code locale} attribute that can be used to localize parts of the template, i.e. to specify the locale for all + * message bundle expressions in the template. + * + * @param locale a {@link Locale} instance + * @return self + */ + default TemplateInstance setLocale(Locale locale) { + return setAttribute(LOCALE, locale); + } + + /** + * Sets the variant attribute that can be used to select a specific variant of the template. + * + * @param variant the variant + * @return self + */ + default TemplateInstance setVariant(Variant variant) { + return setAttribute(SELECTED_VARIANT, variant); + } + /** * This component can be used to initialize a template instance, i.e. the data and attributes. * diff --git a/independent-projects/qute/core/src/test/java/io/quarkus/qute/TemplateInstanceTest.java b/independent-projects/qute/core/src/test/java/io/quarkus/qute/TemplateInstanceTest.java index ba675fb3c6fe1..1ee22f343b255 100644 --- a/independent-projects/qute/core/src/test/java/io/quarkus/qute/TemplateInstanceTest.java +++ b/independent-projects/qute/core/src/test/java/io/quarkus/qute/TemplateInstanceTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Test; @@ -64,4 +65,33 @@ public void testComputeData() { assertTrue(fooUsed.get()); assertFalse(barUsed.get()); } + + @Test + public void testLocale() throws Exception { + Engine engine = Engine.builder().addDefaults() + .addValueResolver(ValueResolver.builder() + .applyToName("locale") + .resolveSync(ctx -> ctx.getAttribute(TemplateInstance.LOCALE)) + .build()) + .build(); + Template hello = engine.parse("Hello {locale}!"); + assertEquals("Hello fr!", hello.instance().setLocale(Locale.FRENCH).render()); + } + + @Test + public void testVariant() { + Engine engine = Engine.builder().addDefaults() + .addValueResolver(ValueResolver.builder() + .applyToName("variant") + .resolveSync(ctx -> ctx.getAttribute(TemplateInstance.SELECTED_VARIANT)) + .build()) + .addValueResolver(ValueResolver.builder() + .appliesTo(ctx -> ctx.getBase() instanceof Variant && ctx.getName().equals("contentType")) + .resolveSync(ctx -> ((Variant) ctx.getBase()).getContentType()) + .build()) + .build(); + Template hello = engine.parse("Hello {variant.contentType}!"); + String render = hello.instance().setVariant(Variant.forContentType(Variant.TEXT_HTML)).render(); + assertEquals("Hello text/html!", render); + } }