Skip to content

Commit 356c5fc

Browse files
committed
Merge branch 'prefer-locale-param' into dev-2.x
2 parents 11e27ef + 6013f69 commit 356c5fc

File tree

2 files changed

+109
-23
lines changed

2 files changed

+109
-23
lines changed

application/src/main/java/org/opentripplanner/framework/graphql/GraphQLUtils.java

Lines changed: 106 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,60 @@
44
import java.util.Locale;
55
import java.util.Map;
66
import java.util.Optional;
7+
import javax.annotation.Nullable;
78
import org.opentripplanner.framework.i18n.I18NString;
89

10+
/**
11+
* This class should always be used when translating fields or handling locales in GraphQL queries.
12+
*/
913
public class GraphQLUtils {
1014

11-
public static String getTranslation(I18NString input, DataFetchingEnvironment environment) {
15+
/**
16+
* If input is {@code null}, return null. Otherwise, input is translated using a locale from this
17+
* prioritized list:
18+
* <ol>
19+
* <li>
20+
* {@code language} parameter of a queried field.
21+
* </li>
22+
* <li>
23+
* Locale from the DataFetchingEnvironment's local context (for journey planning queries this is {@code locale} parameter).
24+
* </li>
25+
* <li>
26+
* DataFetchingEnvironment's locale which comes from the accept-language header.
27+
* </li>
28+
* <li>
29+
* Default locale.
30+
* </li>
31+
* </ol>
32+
*/
33+
@Nullable
34+
public static String getTranslation(
35+
@Nullable I18NString input,
36+
DataFetchingEnvironment environment
37+
) {
1238
if (input == null) {
1339
return null;
1440
}
1541
return input.toString(getLocale(environment));
1642
}
1743

44+
/**
45+
* Returns locale from this prioritized list:
46+
* <ol>
47+
* <li>
48+
* {@code language} parameter of a queried field.
49+
* </li>
50+
* <li>
51+
* Locale from the DataFetchingEnvironment's local context (for journey planning queries this is {@code locale} parameter).
52+
* </li>
53+
* <li>
54+
* DataFetchingEnvironment's locale which comes from the accept-language header.
55+
* </li>
56+
* <li>
57+
* Default locale.
58+
* </li>
59+
* </ol>
60+
*/
1861
public static Locale getLocale(DataFetchingEnvironment environment) {
1962
var localeString = environment.getArgument("language");
2063
if (localeString != null) {
@@ -24,47 +67,90 @@ public static Locale getLocale(DataFetchingEnvironment environment) {
2467
return getLocaleFromEnvironment(environment);
2568
}
2669

27-
public static Locale getLocale(DataFetchingEnvironment environment, String localeString) {
70+
/**
71+
* Returns locale from this prioritized list:
72+
* <ol>
73+
* <li>
74+
* {@code localeString}.
75+
* </li>
76+
* <li>
77+
* Locale from the DataFetchingEnvironment's local context (for journey planning queries this is {@code locale} parameter).
78+
* </li>
79+
* <li>
80+
* DataFetchingEnvironment's locale which comes from the accept-language header.
81+
* </li>
82+
* <li>
83+
* Default locale.
84+
* </li>
85+
* </ol>
86+
*/
87+
public static Locale getLocale(
88+
DataFetchingEnvironment environment,
89+
@Nullable String localeString
90+
) {
2891
if (localeString != null) {
2992
return Locale.forLanguageTag(localeString);
3093
}
3194

3295
return getLocaleFromEnvironment(environment);
3396
}
3497

35-
public static Locale getLocale(DataFetchingEnvironment environment, Locale locale) {
98+
/**
99+
* Returns locale from this prioritized list:
100+
* <ol>
101+
* <li>
102+
* {@code locale}.
103+
* </li>
104+
* <li>
105+
* Locale from the DataFetchingEnvironment's local context (for journey planning queries this is {@code locale} parameter).
106+
* </li>
107+
* <li>
108+
* DataFetchingEnvironment's locale which comes from the accept-language header.
109+
* </li>
110+
* <li>
111+
* Default locale.
112+
* </li>
113+
* </ol>
114+
*/
115+
public static Locale getLocale(DataFetchingEnvironment environment, @Nullable Locale locale) {
36116
if (locale != null) {
37117
return locale;
38118
}
39119

40120
return getLocaleFromEnvironment(environment);
41121
}
42122

123+
/**
124+
* Returns locale from this prioritized list:
125+
* <ol>
126+
* <li>
127+
* Locale from the DataFetchingEnvironment's local context (for journey planning queries this is {@code locale} parameter).
128+
* </li>
129+
* <li>
130+
* DataFetchingEnvironment's locale which comes from the accept-language header.
131+
* </li>
132+
* <li>
133+
* Default locale.
134+
* </li>
135+
* </ol>
136+
*/
43137
public static Locale getLocaleFromEnvironment(DataFetchingEnvironment environment) {
44138
// This can come from the accept-language header
45-
var userLocale = environment.getLocale();
46-
var defaultLocale = getDefaultLocale(environment);
47-
48-
if (userLocale == null) {
49-
return defaultLocale.orElse(Locale.forLanguageTag("*"));
50-
}
51-
52-
if (defaultLocale.isPresent() && acceptAnyLocale(userLocale)) {
53-
return defaultLocale.get();
54-
}
55-
56-
return userLocale;
139+
var envLocale = environment.getLocale();
140+
// This can come from a locale param
141+
var localContextLocale = getLocalContextLocale(environment);
142+
return localContextLocale.orElse(envLocale);
57143
}
58144

59-
private static Optional<Locale> getDefaultLocale(DataFetchingEnvironment environment) {
145+
/**
146+
* Returns locale from the DataFetchingEnvironment's local context (for journey planning queries
147+
* this is {@code locale} parameter) or empty if none exist.
148+
*/
149+
private static Optional<Locale> getLocalContextLocale(DataFetchingEnvironment environment) {
60150
Map<String, ?> localContext = environment.getLocalContext();
61151
if (localContext == null) {
62152
return Optional.empty();
63153
}
64154
return Optional.ofNullable((Locale) localContext.get("locale"));
65155
}
66-
67-
private static boolean acceptAnyLocale(Locale locale) {
68-
return locale.getLanguage().equals("*");
69-
}
70156
}

application/src/test/java/org/opentripplanner/framework/graphql/GraphQLUtilsTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ void testGetLocaleWithDefinedLocaleArg() {
7979
void testGetLocaleWithEnvLocale() {
8080
var frenchLocale = Locale.FRENCH;
8181
var env = DataFetchingEnvironmentImpl.newDataFetchingEnvironment(executionContext)
82-
.localContext(Map.of("locale", Locale.GERMAN))
83-
.locale(frenchLocale)
82+
.locale(Locale.FRENCH)
8483
.build();
8584

8685
var locale = GraphQLUtils.getLocale(env);
@@ -90,10 +89,11 @@ void testGetLocaleWithEnvLocale() {
9089

9190
@Test
9291
void testGetLocaleWithLocalContextLocale() {
93-
// Should use locale from local context if env locale is not defined
92+
// Should use locale from local context even if env locale is defined
9493

9594
var frenchLocale = Locale.FRENCH;
9695
var envWithNoLocale = DataFetchingEnvironmentImpl.newDataFetchingEnvironment(executionContext)
96+
.locale(Locale.GERMAN)
9797
.localContext(Map.of("locale", Locale.FRENCH))
9898
.build();
9999

0 commit comments

Comments
 (0)