Skip to content

Commit 143b9e3

Browse files
authored
fix: I18NProvider.translate return same as Component.translate (#22363)
The I18NProvider.translate should return the same as Component.translate when no provider can be found. Fixes #19516
1 parent ab0687a commit 143b9e3

File tree

3 files changed

+62
-10
lines changed

3 files changed

+62
-10
lines changed

flow-server/src/main/java/com/vaadin/flow/i18n/I18NProvider.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,23 @@
2020
import java.util.List;
2121
import java.util.Locale;
2222
import java.util.Map;
23+
import java.util.Optional;
2324
import java.util.function.Function;
2425
import java.util.stream.Collectors;
2526

27+
import org.slf4j.LoggerFactory;
28+
29+
import com.vaadin.flow.di.Instantiator;
2630
import com.vaadin.flow.internal.LocaleUtil;
31+
import com.vaadin.flow.server.VaadinService;
2732

2833
/**
2934
* I18N provider interface for internationalization usage.
3035
*
3136
* @since 1.0
3237
*/
3338
public interface I18NProvider extends Serializable {
39+
3440
/**
3541
* Get the locales that we have translations for. The first locale should be
3642
* the default locale.
@@ -137,6 +143,9 @@ static String translate(String key, Object... params) {
137143
/**
138144
* Get the translation for key with given locale via {@link I18NProvider}
139145
* instance retrieved from the current VaadinService.
146+
* <p>
147+
* If there is no {@link I18NProvider} available or no translation for the
148+
* {@code key} it returns an exception string e.g. '!{key}!'.
140149
*
141150
* @param locale
142151
* locale to use
@@ -145,13 +154,21 @@ static String translate(String key, Object... params) {
145154
* @param params
146155
* parameters used in translation string
147156
* @return translation for key if found
148-
* @throws IllegalStateException
149-
* thrown if no I18NProvider found from the VaadinService
150157
*/
151158
static String translate(Locale locale, String key, Object... params) {
159+
VaadinService vaadinService = VaadinService.getCurrent();
160+
if (vaadinService == null) {
161+
throw new IllegalStateException(
162+
"I18NProvider is not available as VaadinService is null");
163+
}
164+
Instantiator instantiator = vaadinService.getInstantiator();
165+
if (instantiator == null) {
166+
throw new IllegalStateException(
167+
"I18NProvider is not available as Instantiator is null");
168+
}
169+
152170
return LocaleUtil.getI18NProvider()
153-
.orElseThrow(() -> new IllegalStateException(
154-
"I18NProvider is not available via current VaadinService. VaadinService, Instantiator or I18NProvider is null."))
155-
.getTranslation(key, locale, params);
171+
.map(i18n -> i18n.getTranslation(key, locale, params))
172+
.orElseGet(() -> "!{" + key + "}!");
156173
}
157174
}

flow-server/src/test/java/com/vaadin/flow/i18n/DefaultInstantiatorI18NTest.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,17 @@ protected ClassLoader getClassLoader() {
209209
}
210210

211211
@Test
212-
public void translate_withoutInstantiator_throwsIllegalStateException() {
212+
public void translate_withoutProvider_returnsKey() {
213213
VaadinService service = Mockito.mock(VaadinService.class);
214214
VaadinService.setCurrent(service);
215215

216-
Assert.assertThrows(
217-
"Should throw exception without Instantiator in VaadinService",
218-
IllegalStateException.class,
219-
() -> I18NProvider.translate("foo.bar"));
216+
DefaultInstantiator defaultInstantiator = new DefaultInstantiator(
217+
service);
218+
Mockito.when(service.getInstantiator()).thenReturn(defaultInstantiator);
219+
220+
Assert.assertEquals(
221+
"Should return the key with !{}! to show no translation available",
222+
"!{foo.bar}!", I18NProvider.translate("foo.bar"));
220223
}
221224

222225
@Test

flow-server/src/test/java/com/vaadin/flow/server/I18NProviderTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ public void translate_calls_provider()
9999
"!foo.bar!", I18NProvider.translate("foo.bar"));
100100
}
101101

102+
@Test
103+
public void translate_withoutProvider_returnsKey()
104+
throws ServletException, ServiceException {
105+
initServletAndService(config);
106+
107+
Assert.assertEquals(
108+
"Should return the key with !{}! to show no translation available",
109+
"!{foo.bar}!", I18NProvider.translate("foo.bar"));
110+
}
111+
102112
@Test
103113
public void translate_withoutVaadinService_throwIllegalStateException()
104114
throws ServletException, ServiceException {
@@ -115,6 +125,28 @@ public void translate_withoutVaadinService_throwIllegalStateException()
115125
() -> I18NProvider.translate("foo.bar"));
116126
}
117127

128+
@Test
129+
public void translate_withoutInstantiator_throwIllegalStateException()
130+
throws ServletException, ServiceException {
131+
config.setApplicationOrSystemProperty(InitParameters.I18N_PROVIDER,
132+
TestProvider.class.getName());
133+
134+
initServletAndService(config);
135+
service = new MockVaadinServletService(config) {
136+
@Override
137+
public Instantiator getInstantiator() {
138+
return null;
139+
}
140+
};
141+
142+
VaadinService.setCurrent(service);
143+
144+
Assert.assertThrows(
145+
"Should throw exception without active VaadinService",
146+
IllegalStateException.class,
147+
() -> I18NProvider.translate("foo.bar"));
148+
}
149+
118150
@Before
119151
public void initState()
120152
throws NoSuchFieldException, IllegalAccessException {

0 commit comments

Comments
 (0)