Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit 6afd692

Browse files
committed
Refactor the Request locale API
Following the addition of: - `List<Locale> locales(BiFunction<List<Locale.LanguageRange>, List<Locale>, List<Locale>> filter` - `Locale locale(BiFunction<List<Locale.LanguageRange>, List<Locale>, Locale> filter)` `Locale locale(Iterable<Locale> locales)` and `Locale locale(Locale... locales)` were made redundant by the new two functions. This use case can be implemented in the following way: List<Locale> supportedLocales = ... Locale locale = req.locale((ranges, locales) -> Locale.lookup(ranges, supportedLocales)); `List<Locale> locales()` is just an shorthand for `locales(Locale::filter)`. `Locale locale()` simply returns the first element of `locales` or the default locale as per `app.lang` if there are no matches. This function is expected to be the most used one. Issue jooby-project#273
1 parent 2eca216 commit 6afd692

File tree

6 files changed

+56
-113
lines changed

6 files changed

+56
-113
lines changed
Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.jooby.issues;
22

3+
import java.util.Arrays;
34
import java.util.Locale;
45

56
import org.jooby.test.ServerFeature;
@@ -12,21 +13,52 @@ public class Issue273 extends ServerFeature {
1213

1314
{
1415
use(ConfigFactory.empty()
15-
.withValue("application.lang", ConfigValueFactory.fromAnyRef("en-us")));
16-
17-
get("/273", req -> {
18-
Locale selected = req.locale();
19-
Locale noMatch = req.locale(Locale.forLanguageTag("de-at"));
20-
Locale match = req.locale(Locale.forLanguageTag("fr"));
21-
return selected + ";" + noMatch + ";" + match;
22-
});
16+
.withValue("application.lang",
17+
ConfigValueFactory.fromAnyRef("fr-CA,fr-FR,en,en-CA,en-GB,en-US,de")));
18+
19+
get("/273", req -> req.locale().toLanguageTag());
20+
}
21+
22+
@Test
23+
public void noNegotiation() throws Exception {
24+
request().get("/273")
25+
.expect("fr-CA");
26+
}
27+
28+
@Test
29+
public void exactMatch() throws Exception {
30+
request().get("/273")
31+
.header("Accept-Language", "de")
32+
.expect("de");
33+
34+
request().get("/273")
35+
.header("Accept-Language", "en-GB")
36+
.expect("en-GB");
37+
}
38+
39+
@Test
40+
public void inexactMatch() throws Exception {
41+
request().get("/273")
42+
.header("Accept-Language", "fr")
43+
.expect("fr-CA");
44+
}
45+
46+
@Test
47+
public void noMatch() throws Exception {
48+
request().get("/273")
49+
.header("Accept-Language", "es")
50+
.expect("fr-CA");
51+
52+
request().get("/273")
53+
.header("Accept-Language", "en-AU")
54+
.expect("fr-CA");
2355
}
2456

2557
@Test
2658
public void shouldHanleComplexLocaleExpressions() throws Exception {
2759
request().get("/273")
2860
.header("Accept-Language", "de-DE,de;q=0.8,fr-CA;q=0.7,fr;q=0.5,en-CA;q=0.3,en;q=0.2")
29-
.expect("de_DE;en_US;fr");
61+
.expect("de");
3062
}
3163

3264
}

coverage-report/src/test/java/org/jooby/issues/Issue273b.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,12 @@ public class Issue273b extends ServerFeature {
1616
.withValue("application.lang",
1717
ConfigValueFactory.fromAnyRef("fr-CA,fr-FR,en,en-CA,en-GB,en-US,de")));
1818

19-
get("/locale/def", req -> {
20-
req.locales().forEach(l -> System.out.println(l.getCountry()));
21-
return req.locales();
22-
});
23-
2419
get("/locale/filter", req -> req.locales(Locale::filter));
2520

26-
get("/locale/lookup",
27-
req -> Optional.ofNullable(req.locale((range, locales) -> Locale.lookup(range, locales)))
21+
get("/locale/lookup", req -> Optional.ofNullable(req.locale(Locale::lookup))
2822
.map(Locale::toString).orElse(""));
2923
}
3024

31-
@Test
32-
public void deflocales() throws Exception {
33-
request().get("/locale/def")
34-
.expect("[fr_CA, fr_FR, fr_FX, en, en_CA, en_GB, en_US, de]");
35-
}
36-
3725
@Test
3826
public void filter() throws Exception {
3927
request().get("/locale/filter")

jooby/src/main/java/org/jooby/Request.java

Lines changed: 14 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,6 @@ public Locale locale() {
194194
return req.locale();
195195
}
196196

197-
@Override
198-
public Locale locale(final Iterable<Locale> locales) {
199-
return req.locale(locales);
200-
}
201-
202197
@Override
203198
public Locale locale(final BiFunction<List<LanguageRange>, List<Locale>, Locale> filter) {
204199
return req.locale(filter);
@@ -210,11 +205,6 @@ public List<Locale> locales(
210205
return req.locales(filter);
211206
}
212207

213-
@Override
214-
public Locale locale(final Locale... locales) {
215-
return req.locale(locales);
216-
}
217-
218208
@Override
219209
public List<Locale> locales() {
220210
return req.locales();
@@ -645,12 +635,13 @@ default <T> T require(final TypeLiteral<T> type) {
645635
Charset charset();
646636

647637
/**
648-
* Get the content of the <code>Accept-Language</code> header. If the request doens't specify
649-
* such header, this method return the global locale: <code>application.lang</code>.
638+
* Get a list of locale that best matches the current request as per {@link Locale::filter}.
650639
*
651-
* @return List of locale.
640+
* @return A list of matching locales.
652641
*/
653-
List<Locale> locales();
642+
default List<Locale> locales() {
643+
return locales(Locale::filter);
644+
}
654645

655646
/**
656647
* Get a list of locale that best matches the current request.
@@ -671,7 +662,7 @@ default <T> T require(final TypeLiteral<T> type) {
671662
List<Locale> locales(BiFunction<List<Locale.LanguageRange>, List<Locale>, List<Locale>> filter);
672663

673664
/**
674-
* Get a list of locale that best matches the current request.
665+
* Get a locale that best matches the current request.
675666
*
676667
* The first filter argument is the value of <code>Accept-Language</code> as
677668
* {@link Locale.LanguageRange} and filter while the second argument is a list of supported
@@ -684,42 +675,21 @@ default <T> T require(final TypeLiteral<T> type) {
684675
* req.locale(Locale::lookup)
685676
* }</pre>
686677
*
687-
* @return A list of matching locales.
678+
* @return A matching locale.
688679
*/
689680
Locale locale(BiFunction<List<Locale.LanguageRange>, List<Locale>, Locale> filter);
690681

691682
/**
692-
* Get the content of the <code>Accept-Language</code> header. If the request doens't specify
693-
* such header, this method return the global locale: <code>application.lang</code>.
683+
* Get a locale that best matches the current request or the default locale as specified
684+
* in <code>application.lang</code>.
694685
*
695-
* @return A locale.
686+
* @return A matching locale.
696687
*/
697688
default Locale locale() {
698-
return locales().get(0);
699-
}
700-
701-
/**
702-
* Select a locale in the provided <code>collection</code> based on the content of the
703-
* <code>Accept-Language</code> header using the lookup algorithm of RFC4647. If the request
704-
* doens't specify such header, this method return the global locale:
705-
* <code>application.lang</code>.
706-
*
707-
* @param locales Locales to test for.
708-
* @return A locale.
709-
*/
710-
Locale locale(Iterable<Locale> locales);
711-
712-
/**
713-
* Select a locale in the provided <code>collection</code> based on the content of the
714-
* <code>Accept-Language</code> header using the lookup algorithm of RFC4647. If the request
715-
* doens't specify such header, this method return the global locale:
716-
* <code>application.lang</code>.
717-
*
718-
* @param locales Locales to test for.
719-
* @return A locale.
720-
*/
721-
default Locale locale(final Locale... locales) {
722-
return locale(Arrays.asList(locales));
689+
return locale((ranges, locales) ->
690+
Locale.filter(ranges, locales).stream()
691+
.findFirst()
692+
.orElse(locales.get(0)));
723693
}
724694

725695
/**

jooby/src/main/java/org/jooby/internal/RequestImpl.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,6 @@ public long length() {
274274
.orElse(-1L);
275275
}
276276

277-
@Override
278-
public List<Locale> locales() {
279-
return lang.map(LocaleUtils::parse).orElse(locales);
280-
}
281-
282277
@Override
283278
public List<Locale> locales(
284279
final BiFunction<List<Locale.LanguageRange>, List<Locale>, List<Locale>> filter) {
@@ -292,14 +287,6 @@ public Locale locale(final BiFunction<List<LanguageRange>, List<Locale>, Locale>
292287
.orElseGet(() -> filter.apply(ImmutableList.of(), locales));
293288
}
294289

295-
@Override
296-
public Locale locale(final Iterable<Locale> locales) {
297-
return lang.map(h -> {
298-
Collection<Locale> clocale = ImmutableList.<Locale> copyOf(locales);
299-
return Locale.lookup(LocaleUtils.range(h), clocale);
300-
}).orElse(this.locales.get(0));
301-
}
302-
303290
@Override
304291
public String ip() {
305292
return req.ip();

jooby/src/test/java/org/jooby/RequestForwardingTest.java

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -410,30 +410,6 @@ public void localesFilter() throws Exception {
410410
});
411411
}
412412

413-
@Test
414-
public void bestLocale() throws Exception {
415-
new MockUnit(Request.class)
416-
.expect(unit -> {
417-
Request req = unit.get(Request.class);
418-
expect(req.locale(Locale.CANADA)).andReturn(Locale.getDefault());
419-
})
420-
.run(unit -> {
421-
assertEquals(Locale.getDefault(),
422-
new Request.Forwarding(unit.get(Request.class)).locale(Locale.CANADA));
423-
});
424-
425-
new MockUnit(Request.class)
426-
.expect(unit -> {
427-
Request req = unit.get(Request.class);
428-
expect(req.locale(Arrays.asList(Locale.CANADA))).andReturn(Locale.getDefault());
429-
})
430-
.run(unit -> {
431-
assertEquals(Locale.getDefault(),
432-
new Request.Forwarding(unit.get(Request.class))
433-
.locale(Arrays.asList(Locale.CANADA)));
434-
});
435-
}
436-
437413
@Test
438414
public void ip() throws Exception {
439415
new MockUnit(Request.class)

jooby/src/test/java/org/jooby/RequestTest.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,6 @@ public Locale locale() {
9797
throw new UnsupportedOperationException();
9898
}
9999

100-
@Override
101-
public Locale locale(final Iterable<Locale> locales) {
102-
throw new UnsupportedOperationException();
103-
}
104-
105100
@Override
106101
public List<Locale> locales(
107102
final BiFunction<List<LanguageRange>, List<Locale>, List<Locale>> filter) {
@@ -113,11 +108,6 @@ public Locale locale(final BiFunction<List<LanguageRange>, List<Locale>, Locale>
113108
throw new UnsupportedOperationException();
114109
}
115110

116-
@Override
117-
public Locale locale(final Locale... locales) {
118-
throw new UnsupportedOperationException();
119-
}
120-
121111
@Override
122112
public List<Locale> locales() {
123113
throw new UnsupportedOperationException();

0 commit comments

Comments
 (0)