diff --git a/application/src/main/java/run/halo/app/theme/ThemeLocaleContextResolver.java b/application/src/main/java/run/halo/app/theme/ThemeLocaleContextResolver.java index 65d7e2289..9220690a3 100644 --- a/application/src/main/java/run/halo/app/theme/ThemeLocaleContextResolver.java +++ b/application/src/main/java/run/halo/app/theme/ThemeLocaleContextResolver.java @@ -1,15 +1,15 @@ package run.halo.app.theme; import java.util.Locale; +import java.util.Optional; import java.util.TimeZone; -import java.util.function.Function; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.context.i18n.LocaleContext; import org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext; import org.springframework.http.HttpCookie; +import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; @@ -22,71 +22,45 @@ import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver; @Slf4j @Component(WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME) 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"; - private final Function defaultTimeZoneFunction = - exchange -> getDefaultTimeZone(); - @Override @NonNull 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, - exchange.getAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME)); + return new SimpleTimeZoneAwareLocaleContext(locale, timeZone); } - @Nullable - private Locale getLocale(ServerWebExchange exchange) { - String language = exchange.getRequest().getQueryParams() - .getFirst(DEFAULT_PARAMETER_NAME); - - 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 Optional getLocaleFromCookie(ServerHttpRequest request) { + return Optional.ofNullable(request.getCookies().getFirst(LANGUAGE_COOKIE_NAME)) + .map(HttpCookie::getValue) + .filter(StringUtils::isNotBlank) + .map(Locale::forLanguageTag); } - private TimeZone getDefaultTimeZone() { - return TimeZone.getDefault(); + private Optional getLocaleFromQueryParameter(ServerHttpRequest request) { + return Optional.ofNullable(request.getQueryParams().getFirst(LANGUAGE_PARAMETER_NAME)) + .filter(StringUtils::isNotBlank) + .map(Locale::forLanguageTag); } - private void parseLocaleCookieIfNecessary(ServerWebExchange exchange) { - if (exchange.getAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME) == null) { - TimeZone timeZone = null; - HttpCookie cookie = exchange.getRequest() - .getCookies() - .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)); - } - } + private Optional getTimeZoneFromCookie(ServerHttpRequest request) { + return Optional.ofNullable(request.getCookies().getFirst(TIME_ZONE_COOKIE_NAME)) + .map(HttpCookie::getValue) + .filter(StringUtils::isNotBlank) + .map(TimeZone::getTimeZone); } + } diff --git a/application/src/test/java/run/halo/app/theme/ThemeLocaleContextResolverTest.java b/application/src/test/java/run/halo/app/theme/ThemeLocaleContextResolverTest.java index 8662382e4..a1ada782e 100644 --- a/application/src/test/java/run/halo/app/theme/ThemeLocaleContextResolverTest.java +++ b/application/src/test/java/run/halo/app/theme/ThemeLocaleContextResolverTest.java @@ -12,7 +12,7 @@ import static java.util.Locale.KOREA; import static java.util.Locale.UK; import static java.util.Locale.US; 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 java.util.Arrays; @@ -187,7 +187,7 @@ class ThemeLocaleContextResolverTest { return MockServerWebExchange.from( MockServerHttpRequest.get("").acceptLanguageAsLocales(locales) .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) {