java - 从 messageSource 读取 unicode 给 Java 5 带来了问题

标签 java unicode utf-8 internationalization character-encoding

我用属性文件(例如:messages_en_US.properties、messages_de_DE.properties)制作了一个支持 i18n 的 Spring(2.5.6) webapplication。

这个 .properties 文件带有 uni-codes。例如:

busy = Besch\u00E4ftigt

当从 messageSource 中读取 busy 关键字时,会给出以下结果:

...
private static ReloadableResourceBundleMessageSource messageSource;

    /**
     * Gets a message from the resources (.properties) defined in the applicationContext.xml
     *
     * @param input string to hook up
     * @return the the message hooked up from the resources
     */
    public static String getMessage(String input){
        System.out.println(input); //busy
        System.out.println(messageSource.getDefaultEncoding()); //UTF-8
        System.out.println(messageSource.getMessage(input, null, null)); //Beschu00E4ftigt
        return messageSource.getMessage(input, null, null);
    }
...

所以没有 \

服务器上的文件也是UTF-8:

enter image description here

出现问题的环境:

  • Tomcat 5.5.28(从common/lib 运行jsp-api.jarservlet-api.jar)
  • JDK 1.5.0_22
  • JSTL 1.1.2(从应用lib读取)

  • Tomcat 6.0.32(从 lib 运行 jsp-api.jarservlet-api.jar)

  • JDK 1.5.0_22
  • JSTL 1.1.2(从应用程序 lib 读取)

解决问题的环境(一模一样的分布): - Tomcat 6.0.32(从 lib 运行 jsp-api.jarservlet-api.jar ) - JDK 1.6.0_13 - JSTL 1.1.2(从应用程序lib中读取)

如果您需要更多信息,请告诉我。不要说我需要更新我的 JDK,因为这是不可能的。

更新applicationContext.xml中的绑定(bind)messageSource

<b:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <b:property name="defaultEncoding" value="UTF-8"/>
    <b:property name="fallbackToSystemLocale" value="false" />
    <b:property name="basenames">
        <b:list>
            <b:value>classpath:messages</b:value>
            <b:value>/public/custom/i18n/portalmessages</b:value>
        </b:list>
    </b:property>    
    <b:property name="cacheSeconds" value="1"/>
</b:bean>

更新 2:将资源属性文件放在类路径中并使用类加载器:

URLClassLoader cl = (URLClassLoader) IOUtils.class.getClassLoader();
InputStream resourceAsStream = cl.getResourceAsStream("messages_de_DE.properties");
Properties prop = new Properties();
prop.load(resourceAsStream);
System.out.println("From classpath --> " + prop.get("busy")); //Beschäftigt
System.out.println("From i18n folder --> " + I18nFunctions.getMessage("busy")); //Beschu00E4ftigt

最佳答案

我查看了 DefaultPropertiesPersister 的源代码(它被 ReloadableResourceBundleMessageSource 内部使用)。

如果指定了 defaultEncoding,属性将从 Reader 中逐行手动加载,而不是使用传统的 Properties.load() 方法。

在将键/值对添加到 Properties 对象之前,unescape() 方法在 String 上调用

protected String unescape(String str) {
    StringBuffer outBuffer = new StringBuffer(str.length());
    for (int index = 0; index < str.length();) {
        char c = str.charAt(index++);
        if (c == '\\') {
            c = str.charAt(index++);
            if (c == 't') {
                c = '\t';
            }
            else if (c == 'r') {
                c = '\r';
            }
            else if (c == 'n') {
                c = '\n';
            }
            else if (c == 'f') {
                c = '\f';
            }
        }
        outBuffer.append(c);
    }
    return outBuffer.toString();
}

这是 \ 字符被删除的地方。

如果你创建一个 DefaultPropertiesPersister 的子类,如下所示

package com.something;

import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.util.DefaultPropertiesPersister;

public class MyPropertiesPersister extends DefaultPropertiesPersister {
    protected String unescape(String str)
    {
        return StringEscapeUtils.unescapeJava(str);
    }    
}

像这样在你的spring配置中设置它:

<b:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <b:property name="defaultEncoding" value="UTF-8"/>
    <b:property name="fallbackToSystemLocale" value="false" />
    <b:property name="basenames">
        <b:list>
            <b:value>classpath:messages</b:value>
            <b:value>/public/custom/i18n/portalmessages</b:value>
        </b:list>
    </b:property>    
    <b:property name="cacheSeconds" value="1"/>
    <b:property name="propertiesPersister">
        <b:bean class="com.something.MyPropertiesPersister"/>
    </b:property>
</b:bean>

它会工作.. 可能需要进一步的 jiggery-pokery 才能准确获得您想要的与其他编码等相关的内容:)

关于java - 从 messageSource 读取 unicode 给 Java 5 带来了问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5340183/

相关文章:

java - 可以将 New Relic 与 GAE/J 一起使用吗?

java - Spring Boot 多项目 Maven 应用程序上下文错误

perl - 如何在 Perl 中找到 Unicode 字符串的长度?

python - 只能访问 Python unicode 字典中列表的最后一个元素

utf-8 - 为什么 grep 命令对 UTF-16 LE 编码的文本文件不起作用?

java - 在测试期间排除 Spring Boot 中的 ApplicationListener @Component

java - 黑莓通知消息问题

unicode - 为什么有些字符在Python的IDLE中无法输入?

c# - UTF8编码不加字节序标记

node.js - 如何通过nodejs以正确的编码保存pdf