From e6d42c892a119fccf76ee5fa6f8d7fd62fedd350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gasterst=C3=A4dt?= <157380642+antagoony@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:00:14 +0100 Subject: [PATCH 1/5] add documentation about localized transformers --- cucumber-java/README.md | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/cucumber-java/README.md b/cucumber-java/README.md index 90094e7446..0d0048346d 100644 --- a/cucumber-java/README.md +++ b/cucumber-java/README.md @@ -329,6 +329,55 @@ public class DataTableStepDefinitions { } ``` +### Localized Transformers + +Combining the [Before hook](#before--after) and the Scenario's language offers custom transformation that respects the +language of the feature file. For example, localized features about summer solstice may provide the date "21 kesäkuuta +2025" (Finnish) or "21 juin 2025" (French). Parsing these dates requires an according `DateTimeFormatter`, either within +a default transformer method or within a named type. + + ```java +package com.example.app; + +import io.cucumber.java.Before; +import io.cucumber.java.DefaultParameterTransformer; +import io.cucumber.java.ParameterType; +import io.cucumber.java.Scenario; + +import java.lang.reflect.Type; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +public class TransformerDefinitions { + + private DateTimeFormatter formatter; + + @Before + public void updateFormatter(final Scenario scenario) { + String language = scenario.getLanguage(); + Locale locale = new Locale.Builder().setLanguage(language).build(); + formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy").withLocale(locale); + } + + @DefaultParameterTransformer + public Object transform(final String value, final Type type) + throws Exception { + if (LocalDate.class.equals(type)) { + return LocalDate.parse(value.toString(), formatter); + } else { + throw new UnsupportedOperationException("Can't transform '" + value + "' to " + type); + } + } + + @ParameterType(name = "date", value = "\\d{1,2} \\w+ \\d{4}") + public LocalDate parseLocalDate(String value) { + return LocalDate.parse(value, formatter); + } + +} +``` + ### Empty Cells Data tables in Gherkin cannot represent null or an empty string unambiguously. Cucumber will interpret empty cells as From 8e11e9a23cfabda8582cf13dca75f19c7a96bcfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gasterst=C3=A4dt?= <157380642+antagoony@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:55:04 +0100 Subject: [PATCH 2/5] reduce section content --- cucumber-java/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cucumber-java/README.md b/cucumber-java/README.md index 0d0048346d..a963925cb1 100644 --- a/cucumber-java/README.md +++ b/cucumber-java/README.md @@ -331,10 +331,9 @@ public class DataTableStepDefinitions { ### Localized Transformers -Combining the [Before hook](#before--after) and the Scenario's language offers custom transformation that respects the -language of the feature file. For example, localized features about summer solstice may provide the date "21 kesäkuuta -2025" (Finnish) or "21 juin 2025" (French). Parsing these dates requires an according `DateTimeFormatter`, either within -a default transformer method or within a named type. +To transform a value localized to the language of the feature file combine the [Before hook](#before--after) and the +scenario's language. For example, localized features about summer solstice may provide the date "21 kesäkuuta 2025" +(Finnish) or "21 juin 2025" (French). Parsing these dates requires a `DateTimeFormatter` with a locale. ```java package com.example.app; From 02da4a7bf975756b84e6b29d4a94f9530fd9aefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gasterst=C3=A4dt?= <157380642+antagoony@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:57:47 +0100 Subject: [PATCH 3/5] split @ParameterType and @Default*Transformer example --- cucumber-java/README.md | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/cucumber-java/README.md b/cucumber-java/README.md index a963925cb1..744a18aa42 100644 --- a/cucumber-java/README.md +++ b/cucumber-java/README.md @@ -339,11 +339,9 @@ scenario's language. For example, localized features about summer solstice may p package com.example.app; import io.cucumber.java.Before; -import io.cucumber.java.DefaultParameterTransformer; import io.cucumber.java.ParameterType; import io.cucumber.java.Scenario; -import java.lang.reflect.Type; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Locale; @@ -359,16 +357,6 @@ public class TransformerDefinitions { formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy").withLocale(locale); } - @DefaultParameterTransformer - public Object transform(final String value, final Type type) - throws Exception { - if (LocalDate.class.equals(type)) { - return LocalDate.parse(value.toString(), formatter); - } else { - throw new UnsupportedOperationException("Can't transform '" + value + "' to " + type); - } - } - @ParameterType(name = "date", value = "\\d{1,2} \\w+ \\d{4}") public LocalDate parseLocalDate(String value) { return LocalDate.parse(value, formatter); @@ -377,6 +365,21 @@ public class TransformerDefinitions { } ``` +Similar, the example `ObjectMapper` of the [aforementioned default transformers](#default-transformers) can be localized +before each scenario. + +```java + [...] + @Before + public void updateObjectMapper(final Scenario scenario) { + String language = scenario.getLanguage(); + Locale locale = new Locale.Builder().setLanguage(language).build(); + objectMapper.setLocale(locale); + } + [...] +``` + + ### Empty Cells Data tables in Gherkin cannot represent null or an empty string unambiguously. Cucumber will interpret empty cells as From 8030fd11dd444b339a69188c1b09824bc150274b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gasterst=C3=A4dt?= <157380642+antagoony@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:03:40 +0100 Subject: [PATCH 4/5] use method name as the parameter type name (for consistency) --- cucumber-java/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cucumber-java/README.md b/cucumber-java/README.md index 744a18aa42..2eb5374124 100644 --- a/cucumber-java/README.md +++ b/cucumber-java/README.md @@ -357,8 +357,8 @@ public class TransformerDefinitions { formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy").withLocale(locale); } - @ParameterType(name = "date", value = "\\d{1,2} \\w+ \\d{4}") - public LocalDate parseLocalDate(String value) { + @ParameterType(value = "\\d{1,2} \\w+ \\d{4}") + public LocalDate localizedDate(String value) { return LocalDate.parse(value, formatter); } From 6c179866a8b02bc3ae13592310e0a7411d834ea3 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Wed, 3 Dec 2025 19:36:43 +0100 Subject: [PATCH 5/5] Update cucumber-java/README.md --- cucumber-java/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cucumber-java/README.md b/cucumber-java/README.md index 2eb5374124..72805c2442 100644 --- a/cucumber-java/README.md +++ b/cucumber-java/README.md @@ -365,7 +365,7 @@ public class TransformerDefinitions { } ``` -Similar, the example `ObjectMapper` of the [aforementioned default transformers](#default-transformers) can be localized +Similarly, the example `ObjectMapper` of the [aforementioned default transformers](#default-transformers) can be localized before each scenario. ```java