首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使西班牙字符正确显示使用速度模板?

如何使西班牙字符正确显示使用速度模板?
EN

Stack Overflow用户
提问于 2015-06-17 16:59:26
回答 1查看 1.6K关注 0票数 3

我使用速成和消息资源包来生成html页面。当我指定墨西哥作为我的区域设置时,我的消息-es_MX.properties将被处理为消息资源的源。这正是我所期望的。但是,字符(áéíóúü果真)没有正确显示。

我的邮件属性:

代码语言:javascript
复制
customer.greeting=áéíóúüñ¿¡

对于我的第一次尝试,我有以下几点:

  • 生成页面中的header:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  • 速度特性包含:
    • 输入编码=utf-8
    • 输出.编码=utf-8

  • html编码:UTF-8
  • messages_es_MX.properties编码:ISO-8859-1

输出到${customer.greeting}的html

代码语言:javascript
复制
�������

然后我意识到属性文件的编码是不正确的;它也应该是UTF-8。

第二次尝试:

  • 生成页面中的html标题:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    • 速度特性包含:
      • 输入编码=utf-8
      • 输出.编码=utf-8

  • html编码:UTF-8
  • messages_es_MX.properties编码:UTF-8

输出到html:

代码语言:javascript
复制
áéíóúüñ¿¡

对如何让这件事起作用有什么建议吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-18 22:26:21

事实证明,这比我想象的要复杂得多,但这是个解决办法。在开始之前,确保所有html和属性文件都用UTF-8编码.所有的速度配置也都参考了UTF-8。不应提及ISO-8859-1。

根本的问题是,默认情况下,ResourceBundle假定属性文件是ISO-8859-1编码的。可以覆盖这一点,但需要一段自定义代码。

而不是打电话

代码语言:javascript
复制
ResourceBundle bundle = ResourceBundle.getBundle("messages", MEXICO);

我需要为自定义控件实现添加一个参数:

代码语言:javascript
复制
ResourceBundle bundle = ResourceBundle.getBundle("messages", MEXICO, new UTF8Control());

UTF8Control类如下所示:

代码语言:javascript
复制
package test;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.ResourceBundle.Control;

public class UTF8Control extends Control {

    public ResourceBundle newBundle(String baseName, Locale locale,
            String format, ClassLoader loader, boolean reload)
            throws IllegalAccessException, InstantiationException, IOException {

        // The below is a copy of the default implementation.
        String bundleName = toBundleName(baseName, locale);
        String resourceName = toResourceName(bundleName, "properties");
        ResourceBundle bundle = null;
        InputStream stream = null;
        if (reload) {
            URL url = loader.getResource(resourceName);
            if (url != null) {
                URLConnection connection = url.openConnection();
                if (connection != null) {
                    connection.setUseCaches(false);
                    stream = connection.getInputStream();
                }
            }
        } else {
            stream = loader.getResourceAsStream(resourceName);
        }
        if (stream != null) {
            try {
                // Only this line is changed to make it to read properties files
                // as UTF-8.
                bundle = new PropertyResourceBundle(new InputStreamReader(
                        stream, "UTF-8"));
            } finally {
                stream.close();
            }
        }
        return bundle;
    }

}

归功于@BalusC,他最初发布了this related answer

第一部分解决了。但是仍然存在一个问题,因为我使用的是VelocityTools,我可以在ResourceTool的源代码中看到它调用ResourceBundle.getBundle(...)而不传递任何控制实现。这意味着它将使用ISO-8859-1,我没有办法通过我的UTF8Control.

除非我重写ResourceTool类的方法以获得包:

代码语言:javascript
复制
package test;

import java.util.Locale;
import java.util.ResourceBundle;

import org.apache.velocity.tools.ConversionUtils;
import org.apache.velocity.tools.generic.ResourceTool;

public class UTF8ResourceTool extends ResourceTool {

    /**
     * Retrieves the {@link ResourceBundle} for the specified baseName and
     * locale, if such exists, using UTF-8 encoding. If the baseName or locale is null or if the
     * locale argument cannot be converted to a {@link Locale}, then this will
     * return null.
     */
    protected ResourceBundle getBundle(String baseName, Object loc) {
        Locale locale = (loc == null) ? getLocale() : toLocale(loc);
        if (baseName == null || locale == null) {
            return null;
        }
        return ResourceBundle.getBundle(baseName, locale, new UTF8Control());
    }

    /* Copied here from parent class because it's private there */
    private Locale toLocale(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Locale) {
            return (Locale) obj;
        }
        String s = String.valueOf(obj);
        return ConversionUtils.toLocale(s);
    }

}

在我的UTF8ResourceTool类中,我只覆盖一个方法getBundle (我必须逐字地从父类复制一个私有方法)。在获取资源包时,重写的方法将UTFControl作为第三个参数传递,以便我们可以使用UTF-8编码来提取资源。

现在剩下的唯一的事情是更新我的速度配置,这样我就可以引用我的自定义UTF8ResourceTool,而不是速度工具的ResourceTool

代码语言:javascript
复制
        EasyFactoryConfiguration config = new EasyFactoryConfiguration();
    config.toolbox(Scope.APPLICATION).tool("msg", UTF8ResourceTool.class)
            .property("bundles", "messages/messages").property("locale", locale)
            .tool("date", DateTool.class).tool("number", NumberTool.class)
            .tool("string", StringTool.class).tool("esc", EscapeTool.class)
            .tool("base64", Base64Tool.class);

把所有这些放在一起,我的${customer.greeting}的html输出是:

代码语言:javascript
复制
áéíóúüñ¿¡
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30897865

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档