Skip to content

Simplify default locale/timezone resolution in cookie/session locale resolvers #27609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,12 +22,16 @@
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.lang.Nullable;

/**
* Extension of {@link LocaleResolver}, adding support for a rich locale context
* (potentially including locale and time zone information).
*
* <p>Also provides pre-implemented versions of {@link #resolveLocale} and {@link #setLocale},
* delegating to {@link #resolveLocaleContext} and {@link #setLocaleContext}.
*
* @author Juergen Hoeller
* @since 4.0
* @see org.springframework.context.i18n.LocaleContext
Expand Down Expand Up @@ -73,4 +77,15 @@ public interface LocaleContextResolver extends LocaleResolver {
void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,
@Nullable LocaleContext localeContext);

@Override
default Locale resolveLocale(HttpServletRequest request) {
Locale locale = resolveLocaleContext(request).getLocale();
return (locale != null ? locale : request.getLocale());
}

@Override
default void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) {
setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,23 +16,15 @@

package org.springframework.web.servlet.i18n;

import java.util.Locale;
import java.util.TimeZone;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.LocaleContextResolver;

/**
* Abstract base class for {@link LocaleContextResolver} implementations.
* Provides support for a default locale and a default time zone.
*
* <p>Also provides pre-implemented versions of {@link #resolveLocale} and {@link #setLocale},
* delegating to {@link #resolveLocaleContext} and {@link #setLocaleContext}.
*
* @author Juergen Hoeller
* @since 4.0
* @see #setDefaultLocale
Expand All @@ -59,16 +51,4 @@ public TimeZone getDefaultTimeZone() {
return this.defaultTimeZone;
}


@Override
public Locale resolveLocale(HttpServletRequest request) {
Locale locale = resolveLocaleContext(request).getLocale();
return (locale != null ? locale : request.getLocale());
}

@Override
public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) {
setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,21 +33,18 @@
* specified in the "accept-language" header of the HTTP request (that is,
* the locale sent by the client browser, normally that of the client's OS).
*
* <p>Note: Does not support {@code setLocale}, since the accept header
* <p>Note: Does not support {@code setLocale}, since the "accept-header"
* can only be changed through changing the client's locale settings.
*
* @author Juergen Hoeller
* @author Rossen Stoyanchev
* @since 27.02.2003
* @see jakarta.servlet.http.HttpServletRequest#getLocale()
*/
public class AcceptHeaderLocaleResolver implements LocaleResolver {
public class AcceptHeaderLocaleResolver extends AbstractLocaleResolver {

private final List<Locale> supportedLocales = new ArrayList<>(4);

@Nullable
private Locale defaultLocale;


/**
* Configure supported locales to check against the requested locales
Expand All @@ -69,29 +66,6 @@ public List<Locale> getSupportedLocales() {
return this.supportedLocales;
}

/**
* Configure a fixed default locale to fall back on if the request does not
* have an "Accept-Language" header.
* <p>By default this is not set in which case when there is no "Accept-Language"
* header, the default locale for the server is used as defined in
* {@link HttpServletRequest#getLocale()}.
* @param defaultLocale the default locale to use
* @since 4.3
*/
public void setDefaultLocale(@Nullable Locale defaultLocale) {
this.defaultLocale = defaultLocale;
}

/**
* The configured default locale, if any.
* <p>This method may be overridden in subclasses.
* @since 4.3
*/
@Nullable
public Locale getDefaultLocale() {
return this.defaultLocale;
}


@Override
public Locale resolveLocale(HttpServletRequest request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.util.Locale;
import java.util.TimeZone;
import java.util.function.Function;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -50,6 +51,7 @@
*
* @author Juergen Hoeller
* @author Jean-Pierre Pawlak
* @author Vedran Pavic
* @since 27.02.2003
* @see #setDefaultLocale
* @see #setDefaultTimeZone
Expand Down Expand Up @@ -94,6 +96,15 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
@Nullable
private TimeZone defaultTimeZone;

private Function<HttpServletRequest, Locale> defaultLocaleFunction = request -> {
Locale defaultLocale = getDefaultLocale();
if (defaultLocale == null) {
defaultLocale = request.getLocale();
}
return defaultLocale;
};

private Function<HttpServletRequest, TimeZone> defaultTimeZoneFunction = request -> getDefaultTimeZone();

/**
* Create a new instance of the {@link CookieLocaleResolver} class
Expand Down Expand Up @@ -137,8 +148,8 @@ public boolean isLanguageTagCompliant() {
* @since 5.1.7
* @see #setDefaultLocale
* @see #setDefaultTimeZone
* @see #determineDefaultLocale
* @see #determineDefaultTimeZone
* @see #setDefaultLocaleFunction(Function)
* @see #setDefaultTimeZoneFunction(Function)
*/
public void setRejectInvalidCookies(boolean rejectInvalidCookies) {
this.rejectInvalidCookies = rejectInvalidCookies;
Expand Down Expand Up @@ -186,6 +197,35 @@ protected TimeZone getDefaultTimeZone() {
return this.defaultTimeZone;
}

/**
* Set the function used to determine the default locale for the given request,
* called if no {@link Locale} session attribute has been found.
* <p>The default implementation returns the specified default locale,
* if any, else falls back to the request's accept-header locale.
* @param defaultLocaleFunction the function used to determine the default locale
* @since 6.0
* @see #setDefaultLocale
* @see jakarta.servlet.http.HttpServletRequest#getLocale()
*/
public void setDefaultLocaleFunction(Function<HttpServletRequest, Locale> defaultLocaleFunction) {
Assert.notNull(defaultLocaleFunction, "defaultLocaleFunction must not be null");
this.defaultLocaleFunction = defaultLocaleFunction;
}

/**
* Set the function used to determine the default time zone for the given request,
* called if no {@link TimeZone} session attribute has been found.
* <p>The default implementation returns the specified default time zone,
* if any, or {@code null} otherwise.
* @param defaultTimeZoneFunction the function used to determine the default time zone
* @since 6.0
* @see #setDefaultTimeZone
*/
public void setDefaultTimeZoneFunction(Function<HttpServletRequest, TimeZone> defaultTimeZoneFunction) {
Assert.notNull(defaultTimeZoneFunction, "defaultTimeZoneFunction must not be null");
this.defaultTimeZoneFunction = defaultTimeZoneFunction;
}


@Override
public Locale resolveLocale(HttpServletRequest request) {
Expand Down Expand Up @@ -260,9 +300,9 @@ private void parseLocaleCookieIfNecessary(HttpServletRequest request) {
}

request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
(locale != null ? locale : determineDefaultLocale(request)));
(locale != null ? locale : this.defaultLocaleFunction.apply(request)));
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
(timeZone != null ? timeZone : determineDefaultTimeZone(request)));
(timeZone != null ? timeZone : this.defaultTimeZoneFunction.apply(request)));
}
}

Expand Down Expand Up @@ -291,9 +331,9 @@ public void setLocaleContext(HttpServletRequest request, @Nullable HttpServletRe
removeCookie(response);
}
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
(locale != null ? locale : determineDefaultLocale(request)));
(locale != null ? locale : this.defaultLocaleFunction.apply(request)));
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
(timeZone != null ? timeZone : determineDefaultTimeZone(request)));
(timeZone != null ? timeZone : this.defaultTimeZoneFunction.apply(request)));
}


Expand Down Expand Up @@ -334,13 +374,11 @@ protected String toLocaleValue(Locale locale) {
* @return the default locale (never {@code null})
* @see #setDefaultLocale
* @see jakarta.servlet.http.HttpServletRequest#getLocale()
* @deprecated as of 6.0, in favor of {@link #setDefaultLocaleFunction(Function)}
*/
@Deprecated
protected Locale determineDefaultLocale(HttpServletRequest request) {
Locale defaultLocale = getDefaultLocale();
if (defaultLocale == null) {
defaultLocale = request.getLocale();
}
return defaultLocale;
return this.defaultLocaleFunction.apply(request);
}

/**
Expand All @@ -351,10 +389,12 @@ protected Locale determineDefaultLocale(HttpServletRequest request) {
* @param request the request to resolve the time zone for
* @return the default time zone (or {@code null} if none defined)
* @see #setDefaultTimeZone
* @deprecated as of 6.0, in favor of {@link #setDefaultTimeZoneFunction(Function)}
*/
@Deprecated
@Nullable
protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {
return getDefaultTimeZone();
return this.defaultTimeZoneFunction.apply(request);
}

}
Loading