mirror of https://github.com/halo-dev/halo
Simplify ThemeLocaleContextResolver (#6651)
#### What type of PR is this? /kind improvement /area theme /milestone 2.20.x #### What this PR does / why we need it: This PR simplifies ThemeLocaleContextResolver by removing unused attributes. In another PR <https://github.com/halo-dev/halo/pull/6647>, fixed locale resolution for query parameter `language`. This PR fixes locale resolution for cookie `language` as well. Please see the results below: ```bash http https://www.halo.run/ Cookie:language=zh-CN -p h HTTP/1.1 200 OK Content-Language: und ``` ```bash http http://localhost:8090 Cookie:language=zh-CN -p h HTTP/1.1 200 OK Content-Language: zh-CN ``` #### Does this PR introduce a user-facing change? ```release-note None ```pull/6656/head^2
parent
25eec1ec4f
commit
8ab8a440b6
|
@ -1,15 +1,15 @@
|
||||||
package run.halo.app.theme;
|
package run.halo.app.theme;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.function.Function;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.context.i18n.LocaleContext;
|
import org.springframework.context.i18n.LocaleContext;
|
||||||
import org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext;
|
import org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext;
|
||||||
import org.springframework.http.HttpCookie;
|
import org.springframework.http.HttpCookie;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||||
|
@ -22,71 +22,45 @@ import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component(WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)
|
@Component(WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)
|
||||||
public class ThemeLocaleContextResolver extends AcceptHeaderLocaleContextResolver {
|
public class ThemeLocaleContextResolver extends AcceptHeaderLocaleContextResolver {
|
||||||
public static final String TIME_ZONE_REQUEST_ATTRIBUTE_NAME =
|
|
||||||
ThemeLocaleContextResolver.class.getName() + ".TIME_ZONE";
|
|
||||||
public static final String LOCALE_REQUEST_ATTRIBUTE_NAME =
|
|
||||||
ThemeLocaleContextResolver.class.getName() + ".LOCALE";
|
|
||||||
|
|
||||||
public static final String DEFAULT_PARAMETER_NAME = "language";
|
public static final String LANGUAGE_PARAMETER_NAME = "language";
|
||||||
|
|
||||||
|
public static final String LANGUAGE_COOKIE_NAME = LANGUAGE_PARAMETER_NAME;
|
||||||
|
|
||||||
public static final String TIME_ZONE_COOKIE_NAME = "time_zone";
|
public static final String TIME_ZONE_COOKIE_NAME = "time_zone";
|
||||||
|
|
||||||
private final Function<ServerWebExchange, TimeZone> defaultTimeZoneFunction =
|
|
||||||
exchange -> getDefaultTimeZone();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public LocaleContext resolveLocaleContext(@NonNull ServerWebExchange exchange) {
|
public LocaleContext resolveLocaleContext(@NonNull ServerWebExchange exchange) {
|
||||||
parseLocaleCookieIfNecessary(exchange);
|
var request = exchange.getRequest();
|
||||||
|
var locale = getLocaleFromQueryParameter(request)
|
||||||
|
.or(() -> getLocaleFromCookie(request))
|
||||||
|
.orElseGet(() -> super.resolveLocaleContext(exchange).getLocale());
|
||||||
|
|
||||||
Locale locale = getLocale(exchange);
|
var timeZone = getTimeZoneFromCookie(request)
|
||||||
|
.orElseGet(TimeZone::getDefault);
|
||||||
|
|
||||||
return new SimpleTimeZoneAwareLocaleContext(locale,
|
return new SimpleTimeZoneAwareLocaleContext(locale, timeZone);
|
||||||
exchange.getAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private Optional<Locale> getLocaleFromCookie(ServerHttpRequest request) {
|
||||||
private Locale getLocale(ServerWebExchange exchange) {
|
return Optional.ofNullable(request.getCookies().getFirst(LANGUAGE_COOKIE_NAME))
|
||||||
String language = exchange.getRequest().getQueryParams()
|
.map(HttpCookie::getValue)
|
||||||
.getFirst(DEFAULT_PARAMETER_NAME);
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.map(Locale::forLanguageTag);
|
||||||
Locale locale;
|
|
||||||
if (StringUtils.isNotBlank(language)) {
|
|
||||||
locale = Locale.forLanguageTag(language);
|
|
||||||
} else if (exchange.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) != null) {
|
|
||||||
locale = exchange.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
|
|
||||||
} else {
|
|
||||||
locale = super.resolveLocaleContext(exchange).getLocale();
|
|
||||||
}
|
|
||||||
return locale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeZone getDefaultTimeZone() {
|
private Optional<Locale> getLocaleFromQueryParameter(ServerHttpRequest request) {
|
||||||
return TimeZone.getDefault();
|
return Optional.ofNullable(request.getQueryParams().getFirst(LANGUAGE_PARAMETER_NAME))
|
||||||
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.map(Locale::forLanguageTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseLocaleCookieIfNecessary(ServerWebExchange exchange) {
|
private Optional<TimeZone> getTimeZoneFromCookie(ServerHttpRequest request) {
|
||||||
if (exchange.getAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME) == null) {
|
return Optional.ofNullable(request.getCookies().getFirst(TIME_ZONE_COOKIE_NAME))
|
||||||
TimeZone timeZone = null;
|
.map(HttpCookie::getValue)
|
||||||
HttpCookie cookie = exchange.getRequest()
|
.filter(StringUtils::isNotBlank)
|
||||||
.getCookies()
|
.map(TimeZone::getTimeZone);
|
||||||
.getFirst(TIME_ZONE_COOKIE_NAME);
|
|
||||||
if (cookie != null) {
|
|
||||||
String value = cookie.getValue();
|
|
||||||
timeZone = TimeZone.getTimeZone(value);
|
|
||||||
}
|
|
||||||
exchange.getAttributes().put(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
|
|
||||||
(timeZone != null ? timeZone : this.defaultTimeZoneFunction.apply(exchange)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exchange.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) == null) {
|
|
||||||
HttpCookie cookie = exchange.getRequest()
|
|
||||||
.getCookies()
|
|
||||||
.getFirst(DEFAULT_PARAMETER_NAME);
|
|
||||||
if (cookie != null) {
|
|
||||||
String value = cookie.getValue();
|
|
||||||
exchange.getAttributes()
|
|
||||||
.put(LOCALE_REQUEST_ATTRIBUTE_NAME, new Locale(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import static java.util.Locale.KOREA;
|
||||||
import static java.util.Locale.UK;
|
import static java.util.Locale.UK;
|
||||||
import static java.util.Locale.US;
|
import static java.util.Locale.US;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static run.halo.app.theme.ThemeLocaleContextResolver.DEFAULT_PARAMETER_NAME;
|
import static run.halo.app.theme.ThemeLocaleContextResolver.LANGUAGE_COOKIE_NAME;
|
||||||
import static run.halo.app.theme.ThemeLocaleContextResolver.TIME_ZONE_COOKIE_NAME;
|
import static run.halo.app.theme.ThemeLocaleContextResolver.TIME_ZONE_COOKIE_NAME;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -187,7 +187,7 @@ class ThemeLocaleContextResolverTest {
|
||||||
return MockServerWebExchange.from(
|
return MockServerWebExchange.from(
|
||||||
MockServerHttpRequest.get("").acceptLanguageAsLocales(locales)
|
MockServerHttpRequest.get("").acceptLanguageAsLocales(locales)
|
||||||
.cookie(new HttpCookie(TIME_ZONE_COOKIE_NAME, "America/Adak"))
|
.cookie(new HttpCookie(TIME_ZONE_COOKIE_NAME, "America/Adak"))
|
||||||
.cookie(new HttpCookie(DEFAULT_PARAMETER_NAME, "en")));
|
.cookie(new HttpCookie(LANGUAGE_COOKIE_NAME, "en")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServerWebExchange exchangeForParam(String language) {
|
private ServerWebExchange exchangeForParam(String language) {
|
||||||
|
|
Loading…
Reference in New Issue