如何使用 Velocity 模板正确显示西班牙语字符? [英] How do I get Spanish characters to display properly using a Velocity template?

查看:20
本文介绍了如何使用 Velocity 模板正确显示西班牙语字符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Velocity 和消息资源包来生成 html 页面.当我将墨西哥指定为我的语言环境时,我的 messages-es_MX.properties 被处理为消息资源的源.这正如我所期望的那样.但是字符 (áéíóúüñ¿¡) 显示不正确.

I'm using Velocity and a message resource bundle to generate html pages. When I specify Mexico as my locale, my messages-es_MX.properties gets processed as the source for the message resources. This is as I expect it to be. But the characters (áéíóúüñ¿¡) aren't displayed properly.

我的消息属性:

customer.greeting=áéíóúüñ¿¡

对于我的第一次尝试,我得到了以下内容:

For my first attempt, I've got the following:

  • 生成页面中的html标题:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  • 速度属性包含:
    • input.encoding=utf-8
    • output.encoding=utf-8

    输出到 ${customer.greeting} 的 html:

    Output to html for ${customer.greeting}:

    �������
    

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

    I then realized that the encoding of the properties file isn't correct; it should also be UTF-8.

    第二次尝试:

    • 生成页面中的html标题:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
      • 速度属性包含:
        • input.encoding=utf-8
        • output.encoding=utf-8

        输出到 html:

        áéíóúüñ¿¡
        

        关于如何让它发挥作用的任何建议?

        Any suggestions on how to get this to work?

        推荐答案

        好吧,事实证明这比我想象的要棘手,但这里是解决方案.在开始之前,请确保所有 html 和属性文件都以 UTF-8 编码.并且所有 Velocity 配置也参考 UTF-8.不应引用 ISO-8859-1.

        Well, this turned out to be trickier than I thought it would be, but here's the solution. Before beginning, ensure that all html and properties files are encoded in UTF-8. And that all Velocity configurations reference UTF-8 as well. There should be no references to ISO-8859-1.

        潜在的问题是,默认情况下,ResourceBundle 假定属性文件采用 ISO-8859-1 编码.可以覆盖它,但需要一段自定义代码.

        The underlying problem is that by default, ResourceBundle assumes property files are in ISO-8859-1 encoding. It's possible to override this, but takes a piece of custom code.

        而不是打电话

        ResourceBundle bundle = ResourceBundle.getBundle("messages", MEXICO);
        

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

        I needed to add an argument for a custom Control implementation:

        ResourceBundle bundle = ResourceBundle.getBundle("messages", MEXICO, new UTF8Control());
        

        UTF8Control 类如下所示:

        The UTF8Control class looks like this:

        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回答.

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

        So, part 1 solved. But there's still a problem, because I'm using VelocityTools and I can see in the source code for ResourceTool that it calls ResourceBundle.getBundle(...) without passing in any Control implementation. This means that it's going to use ISO-8859-1, and I have no way to pass in my UTF8Control...

        除非我重写 ResourceTool 类的方法来获取包:

        Unless I override the ResourceTool class's method to get the bundle:

        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编码拉入资源.

        In my UTF8ResourceTool class, I override just one method getBundle (and I had to copy a private method in verbatim from the parent class). The overridden method passes the UTFControl as the third argument when getting the resource bundle, so that we can pull in the resources using UTF-8 encoding.

        现在唯一剩下的就是更新我的 Velocity 配置,以便我引用我的自定义 UTF8ResourceTool 而不是 Velocity Tools 的 ResourceTool:

        The only thing left now is to update my Velocity configuration so that I'm referencing my custom UTF8ResourceTool instead of Velocity Tools' ResourceTool:

                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 输出是:

        Put it all together, and my html output for ${customer.greeting} is:

        áéíóúüñ¿¡
        

        这篇关于如何使用 Velocity 模板正确显示西班牙语字符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆