Add Locale to Charset Mapping for Servlet containers
This commit adds a new configuration key:
spring.http.encoding.mapping.<locale>=<charset>
This allows to specify which default charset should be used for any
given Locale, if none has been provided already in the response itself.
This applies to all supported embedded servlet containers.
Fixes gh-6453
This commit is contained in:
@@ -20,11 +20,15 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.web.HttpEncodingProperties.Type;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.filter.OrderedCharacterEncodingFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.filter.CharacterEncodingFilter;
|
||||
|
||||
/**
|
||||
@@ -32,10 +36,12 @@ import org.springframework.web.filter.CharacterEncodingFilter;
|
||||
* in web applications.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Brian Clozel
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(HttpEncodingProperties.class)
|
||||
@ConditionalOnWebApplication
|
||||
@ConditionalOnClass(CharacterEncodingFilter.class)
|
||||
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
|
||||
public class HttpEncodingAutoConfiguration {
|
||||
@@ -56,4 +62,30 @@ public class HttpEncodingAutoConfiguration {
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
|
||||
return new LocaleCharsetMappingsCustomizer(this.properties);
|
||||
}
|
||||
|
||||
private static class LocaleCharsetMappingsCustomizer implements EmbeddedServletContainerCustomizer, Ordered {
|
||||
|
||||
private final HttpEncodingProperties properties;
|
||||
|
||||
LocaleCharsetMappingsCustomizer(HttpEncodingProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainer container) {
|
||||
if (this.properties.getMapping() != null) {
|
||||
container.setLocaleCharsetMappings(this.properties.getMapping());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.boot.autoconfigure.web;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@@ -24,6 +26,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Configuration properties for http encoding.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Brian Clozel
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.http.encoding")
|
||||
@@ -53,6 +56,11 @@ public class HttpEncodingProperties {
|
||||
*/
|
||||
private Boolean forceResponse;
|
||||
|
||||
/**
|
||||
* Locale to Encoding mapping.
|
||||
*/
|
||||
private Map<Locale, Charset> mapping;
|
||||
|
||||
public Charset getCharset() {
|
||||
return this.charset;
|
||||
}
|
||||
@@ -85,6 +93,14 @@ public class HttpEncodingProperties {
|
||||
this.forceResponse = forceResponse;
|
||||
}
|
||||
|
||||
public Map<Locale, Charset> getMapping() {
|
||||
return this.mapping;
|
||||
}
|
||||
|
||||
public void setMapping(Map<Locale, Charset> mapping) {
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
boolean shouldForce(Type type) {
|
||||
Boolean force = (type == Type.REQUEST ? this.forceRequest : this.forceResponse);
|
||||
if (force == null) {
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.web;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
@@ -27,13 +30,17 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter;
|
||||
import org.springframework.boot.web.filter.OrderedHttpPutFormContentFilter;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.filter.CharacterEncodingFilter;
|
||||
import org.springframework.web.filter.HiddenHttpMethodFilter;
|
||||
|
||||
@@ -49,7 +56,7 @@ public class HttpEncodingAutoConfigurationTests {
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
private AnnotationConfigWebApplicationContext context;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
@@ -135,6 +142,31 @@ public class HttpEncodingAutoConfigurationTests {
|
||||
assertThat(beans.get(1)).isInstanceOf(HiddenHttpMethodFilter.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noLocaleCharsetMapping() {
|
||||
load(EmptyConfiguration.class);
|
||||
Map<String, EmbeddedServletContainerCustomizer> beans =
|
||||
this.context.getBeansOfType(EmbeddedServletContainerCustomizer.class);
|
||||
assertThat(beans.size()).isEqualTo(1);
|
||||
assertThat(this.context.getBean(MockEmbeddedServletContainerFactory.class)
|
||||
.getLocaleCharsetMappings().size()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customLocaleCharsetMappings() {
|
||||
load(EmptyConfiguration.class, "spring.http.encoding.mapping.en:UTF-8",
|
||||
"spring.http.encoding.mapping.fr_FR:UTF-8");
|
||||
Map<String, EmbeddedServletContainerCustomizer> beans =
|
||||
this.context.getBeansOfType(EmbeddedServletContainerCustomizer.class);
|
||||
assertThat(beans.size()).isEqualTo(1);
|
||||
assertThat(this.context.getBean(MockEmbeddedServletContainerFactory.class)
|
||||
.getLocaleCharsetMappings().size()).isEqualTo(2);
|
||||
assertThat(this.context.getBean(MockEmbeddedServletContainerFactory.class)
|
||||
.getLocaleCharsetMappings().get(Locale.ENGLISH)).isEqualTo(Charset.forName("UTF-8"));
|
||||
assertThat(this.context.getBean(MockEmbeddedServletContainerFactory.class)
|
||||
.getLocaleCharsetMappings().get(Locale.FRANCE)).isEqualTo(Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
private void assertCharacterEncodingFilter(CharacterEncodingFilter actual,
|
||||
String encoding, boolean forceRequestEncoding,
|
||||
boolean forceResponseEncoding) {
|
||||
@@ -147,12 +179,14 @@ public class HttpEncodingAutoConfigurationTests {
|
||||
this.context = doLoad(new Class<?>[] { config }, environment);
|
||||
}
|
||||
|
||||
private AnnotationConfigApplicationContext doLoad(Class<?>[] configs,
|
||||
private AnnotationConfigWebApplicationContext doLoad(Class<?>[] configs,
|
||||
String... environment) {
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
|
||||
applicationContext.register(configs);
|
||||
applicationContext.register(HttpEncodingAutoConfiguration.class);
|
||||
applicationContext.register(MinimalWebAutoConfiguration.class,
|
||||
HttpEncodingAutoConfiguration.class);
|
||||
applicationContext.setServletContext(new MockServletContext());
|
||||
applicationContext.refresh();
|
||||
return applicationContext;
|
||||
}
|
||||
@@ -190,4 +224,19 @@ public class HttpEncodingAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class MinimalWebAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public MockEmbeddedServletContainerFactory mockEmbeddedServletContainerFactory() {
|
||||
return new MockEmbeddedServletContainerFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerCustomizerBeanPostProcessor
|
||||
embeddedServletContainerCustomizerBeanPostProcessor() {
|
||||
return new EmbeddedServletContainerCustomizerBeanPostProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,10 +18,14 @@ package org.springframework.boot.context.embedded;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -39,6 +43,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Stephane Nicoll
|
||||
* @author Ivan Sopov
|
||||
* @author Eddú Meléndez
|
||||
* @author Brian Clozel
|
||||
* @see AbstractEmbeddedServletContainerFactory
|
||||
*/
|
||||
public abstract class AbstractConfigurableEmbeddedServletContainer
|
||||
@@ -81,6 +86,8 @@ public abstract class AbstractConfigurableEmbeddedServletContainer
|
||||
|
||||
private String serverHeader;
|
||||
|
||||
private Map<Locale, Charset> localeCharsetMappings = new HashMap<Locale, Charset>();
|
||||
|
||||
/**
|
||||
* Create a new {@link AbstractConfigurableEmbeddedServletContainer} instance.
|
||||
*/
|
||||
@@ -327,6 +334,19 @@ public abstract class AbstractConfigurableEmbeddedServletContainer
|
||||
this.serverHeader = serverHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Locale to Charset mappings.
|
||||
* @return the charset mappings
|
||||
*/
|
||||
public Map<Locale, Charset> getLocaleCharsetMappings() {
|
||||
return this.localeCharsetMappings;
|
||||
}
|
||||
|
||||
public void setLocaleCharsetMappings(Map<Locale, Charset> localeCharsetMappings) {
|
||||
Assert.notNull(localeCharsetMappings, "localeCharsetMappings must not be null");
|
||||
this.localeCharsetMappings = localeCharsetMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that can be used by subclasses wishing to combine the specified
|
||||
* {@link ServletContextInitializer} parameters with those defined in this instance.
|
||||
|
||||
@@ -18,7 +18,10 @@ package org.springframework.boot.context.embedded;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -34,6 +37,7 @@ import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
* @author Eddú Meléndez
|
||||
* @author Brian Clozel
|
||||
* @see EmbeddedServletContainerFactory
|
||||
* @see EmbeddedServletContainerCustomizer
|
||||
*/
|
||||
@@ -174,4 +178,10 @@ public interface ConfigurableEmbeddedServletContainer extends ErrorPageRegistry
|
||||
*/
|
||||
void setServerHeader(String serverHeader);
|
||||
|
||||
/**
|
||||
* Sets the Locale to Charset mappings.
|
||||
* @param localeCharsetMappings the Locale to Charset mappings
|
||||
*/
|
||||
void setLocaleCharsetMappings(Map<Locale, Charset> localeCharsetMappings);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
@@ -354,6 +355,10 @@ public class JettyEmbeddedServletContainerFactory
|
||||
addJspServlet(context);
|
||||
context.addBean(new JasperInitializer(context), true);
|
||||
}
|
||||
for (Locale locale : getLocaleCharsetMappings().keySet()) {
|
||||
context.addLocaleEncoding(locale.toString(),
|
||||
getLocaleCharsetMappings().get(locale).toString());
|
||||
}
|
||||
ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
|
||||
Configuration[] configurations = getWebAppContextConfigurations(context,
|
||||
initializersToUse);
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -193,6 +194,15 @@ public class TomcatEmbeddedServletContainerFactory
|
||||
context.setParentClassLoader(
|
||||
this.resourceLoader != null ? this.resourceLoader.getClassLoader()
|
||||
: ClassUtils.getDefaultClassLoader());
|
||||
// override defaults, see org.apache.catalina.util.CharsetMapperDefault.properties
|
||||
context.addLocaleEncodingMappingParameter(Locale.ENGLISH.toString(),
|
||||
DEFAULT_CHARSET.displayName());
|
||||
context.addLocaleEncodingMappingParameter(Locale.FRENCH.toString(),
|
||||
DEFAULT_CHARSET.displayName());
|
||||
for (Locale locale : getLocaleCharsetMappings().keySet()) {
|
||||
context.addLocaleEncodingMappingParameter(locale.toString(),
|
||||
getLocaleCharsetMappings().get(locale).toString());
|
||||
}
|
||||
try {
|
||||
context.setUseRelativeRedirects(false);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
@@ -382,6 +383,10 @@ public class UndertowEmbeddedServletContainerFactory
|
||||
File dir = getValidSessionStoreDir();
|
||||
deployment.setSessionPersistenceManager(new FileSessionPersistence(dir));
|
||||
}
|
||||
for (Locale locale : getLocaleCharsetMappings().keySet()) {
|
||||
deployment.addLocaleCharsetMapping(locale.toString(),
|
||||
getLocaleCharsetMappings().get(locale).toString());
|
||||
}
|
||||
DeploymentManager manager = Servlets.newContainer().addDeployment(deployment);
|
||||
manager.deploy();
|
||||
SessionManager sessionManager = manager.getDeployment().getSessionManager();
|
||||
|
||||
@@ -38,6 +38,8 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
@@ -870,6 +872,17 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void localeCharsetMappingsAreConfigured() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
Map<Locale, Charset> mappings = new HashMap<Locale, Charset>();
|
||||
mappings.put(Locale.GERMAN, Charset.forName("UTF-8"));
|
||||
factory.setLocaleCharsetMappings(mappings);
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
assertThat(getCharset(Locale.GERMAN).toString()).isEqualTo("UTF-8");
|
||||
assertThat(getCharset(Locale.ITALIAN)).isNull();
|
||||
}
|
||||
|
||||
protected abstract void addConnector(int port,
|
||||
AbstractEmbeddedServletContainerFactory factory);
|
||||
|
||||
@@ -917,6 +930,8 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
return MimeMappings.DEFAULT.getAll();
|
||||
}
|
||||
|
||||
protected abstract Charset getCharset(Locale locale);
|
||||
|
||||
private void addTestTxtFile(AbstractEmbeddedServletContainerFactory factory)
|
||||
throws IOException {
|
||||
FileCopyUtils.copy("test",
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package org.springframework.boot.context.embedded.jetty;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -326,4 +328,11 @@ public class JettyEmbeddedServletContainerFactoryTests
|
||||
return context.getMimeTypes().getMimeMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Charset getCharset(Locale locale) {
|
||||
WebAppContext context = (WebAppContext) ((JettyEmbeddedServletContainer) this.container)
|
||||
.getServer().getHandler();
|
||||
String charsetName = context.getLocaleEncoding(locale);
|
||||
return (charsetName != null) ? Charset.forName(charsetName) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -37,6 +38,7 @@ import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.Wrapper;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.catalina.util.CharsetMapper;
|
||||
import org.apache.catalina.valves.RemoteIpValve;
|
||||
import org.apache.tomcat.util.net.SSLHostConfig;
|
||||
import org.junit.After;
|
||||
@@ -430,6 +432,15 @@ public class TomcatEmbeddedServletContainerFactoryTests
|
||||
new InitialContext().lookup("java:comp/env");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultLocaleCharsetMappingsAreOverriden() throws Exception {
|
||||
TomcatEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
// override defaults, see org.apache.catalina.util.CharsetMapperDefault.properties
|
||||
assertThat(getCharset(Locale.ENGLISH).toString()).isEqualTo("UTF-8");
|
||||
assertThat(getCharset(Locale.FRENCH).toString()).isEqualTo("UTF-8");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Wrapper getJspServlet() {
|
||||
Container context = ((TomcatEmbeddedServletContainer) this.container).getTomcat()
|
||||
@@ -446,6 +457,15 @@ public class TomcatEmbeddedServletContainerFactoryTests
|
||||
"mimeMappings");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Charset getCharset(Locale locale) {
|
||||
Context context = (Context) ((TomcatEmbeddedServletContainer) this.container)
|
||||
.getTomcat().getHost().findChildren()[0];
|
||||
CharsetMapper mapper = ((TomcatEmbeddedContext) context).getCharsetMapper();
|
||||
String charsetName = mapper.getCharset(locale);
|
||||
return (charsetName != null) ? Charset.forName(charsetName) : null;
|
||||
}
|
||||
|
||||
private void assertTimeout(TomcatEmbeddedServletContainerFactory factory,
|
||||
int expected) {
|
||||
Tomcat tomcat = getTomcat(factory);
|
||||
|
||||
@@ -19,9 +19,11 @@ package org.springframework.boot.context.embedded.undertow;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -268,4 +270,11 @@ public class UndertowEmbeddedServletContainerFactoryTests
|
||||
return expectedMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Charset getCharset(Locale locale) {
|
||||
DeploymentInfo info = ((DeploymentManager) ReflectionTestUtils
|
||||
.getField(this.container, "manager")).getDeployment().getDeploymentInfo();
|
||||
String charsetName = info.getLocaleCharsetMapping().get(locale.toString());
|
||||
return (charsetName != null) ? Charset.forName(charsetName) : null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user