【问题标题】:Locale specific messages in Xerces 2.11.0 (Java)Xerces 2.11.0 (Java) 中特定于语言环境的消息
【发布时间】:2013-08-30 11:18:56
【问题描述】:

我想在我的 JAXP 和 Xerces2 中使用特定于语言环境的错误消息。默认情况下,只有英文消息可用。

第一步是检索消息文件并将它们放入包“org/apache/xerces/impl/msg/” - 完成。通过使用Locale.setDefault (Locale.GERMANY) 会显示德语消息,因此可以正常工作。

但我希望消息在每个实例的基础上进行不同的本地化。所以一个解析器应该返回英文消息,另一个解析器应该返回德语消息。

我用来创建 SAX2 解析器的代码是:

org.xml.sax.XMLReader ret = XMLReaderFactory.createXMLReader ();

对于 DOM,我使用 DocumentBuilder 喜欢这样(非常简化):

    final DocumentBuilderFactory aDocumentBuilderFactory = DocumentBuilderFactory.newInstance ();
    final DocumentBuilder aDocBuilder = aDocBuilderFactory.newDocumentBuilder ();
    final Document doc = aDocumentBuilder.parse (aInputSource);

我发现了类似 org.apache.xerces.impl.XMLErrorReporter 类的东西,它有一个 setLocale(Locale) 方法,但我没有找到获取/设置它的方法。

顺便说一句,切换到 SAX1 不是一种选择。

感谢任何帮助!

【问题讨论】:

    标签: java localization xerces xerces2-j


    【解决方案1】:

    不是最大的可移植性,但它的工作原理是在 99% 的情况下解析器是 apache 解析器。

    final DocumentBuilderFactory aDocBuilderFactory = DocumentBuilderFactory.newInstance();
    aDocBuilderFactory.setAttribute("http://apache.org/xml/properties/locale", Locale.FRANCE);
    final DocumentBuilder aDocBuilder = aDocBuilderFactory.newDocumentBuilder();
    final Document doc = aDocBuilder.parse (aInputSource);
    

    对于SAXParser saxParser,只需致电saxParser.setProperty("http://apache.org/xml/properties/locale", Locale.FRANCE);

    哦,忘记官方出处了: http://xerces.apache.org/xerces2-j/properties.html

    【讨论】:

    • 谢谢 - 这正是我想要的!
    • 注意:如果您想强制使用英文验证消息,您可能需要输入一个空的 Locale 对象。这是因为 JRE 不包含 XMLMessage_en.properties,因此会尝试默认的语言环境集(在我的情况下为德语或法语),它可以很好地解析到包含的包。使用空的 Locale 可以强制 ResourceBundle 机制只尝试基本名称(在 JRE 中包含英文属性)。
    • 小记,因为我在使用 XSD 验证时偶然发现了一个类似的问题:如果您有一个 Validator 实例,您可以使用 validator.setProperty("http://apache.org/xml/properties/locale", Locale.FRANCE); - 但请注意,如果您的语言环境使用“en”语言但非英语默认语言环境 - 使用 Locale.ROOT 强制执行英语消息!
    • @PhilipHelger 感谢您的留言,这很有帮助。要强制非英语用户使用英语,我们必须使用 Locale.ROOT。
    【解决方案2】:

    设置/获取MessageFormatter的可能性:

    Validator validator = schema.newValidator();      
    XMLErrorReporter property = (XMLErrorReporter) validator.getProperty("http://apache.org/xml/properties/internal/error-reporter");
    MessageFormatter messageFormatter = property.getMessageFormatter("http://www.w3.org/TR/xml-schema-1");
    property.putMessageFormatter(MyMessageFormatter.SCHEMA_DOMAIN, new MyMessageFormatter());
    
    
    public class MyMessageFormatter implements MessageFormatter {
        public static final String SCHEMA_DOMAIN = "http://www.w3.org/TR/xml-schema-1";
        //...
        public String formatMessage(Locale locale, String key, Object[] arguments)
                throws MissingResourceException {...}
        //...
    
    }
    

    【讨论】:

      【解决方案3】:

      我认为你应该尝试使用

      com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter 
      

      如果您正在编写自定义验证,请尝试调用其 formatMessage(...) 方法,您可以在其中提供语言环境名称作为参数。

      apache 库本身提供了一个相同的示例。见http://cr.openjdk.java.net/~coffeys/openJDK.7u21.sync/webrev/jaxp/src/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter_zh_CN.java-.html

      http://www.docjar.com/html/api/com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter.java.html

      另一种方法可能是您可以覆盖 formatMessage() 方法以您自己的方式实现它。请看下面这个方法的实现代码:

       public String More ...formatMessage(Locale locale, String key, Object[] arguments)
               throws MissingResourceException {
                if (fResourceBundle == null || locale != fLocale) {
                   if (locale != null) {
                       fResourceBundle = PropertyResourceBundle.getBundle("com.sun.org.apache.xerces.internal.impl.msg.XMLMessages", locale);
                       // memorize the most-recent locale
                       fLocale = locale;
                   }
                   if (fResourceBundle == null)
                       fResourceBundle = PropertyResourceBundle.getBundle("com.sun.org.apache.xerces.internal.impl.msg.XMLMessages");
               }
      

      这表明,如果根据语言环境声明资源包文件,则控件应该能够选择具有不同语言的错误消息的不同资源文件。

      【讨论】:

      • 我正在考虑使用 XMLMessageFormatter,但在提供的示例中,他们使用一些 XMLSchemaValidatorComponentManager 来获取和更新 XMLMessageFormatter(我没有)。必须有一种方法可以使用标准 DocumentBuilder 设置......
      • 对不起,我的错..我放错了链接..已经更新了正确的链接。希望这会有所帮助。
      • 感谢您更新链接。所以在我看来,我不能直接设置语言环境。那么如何设置 XMLMessageFormatter 呢?使用哪个属性?尽管这个解决方案不是最优的,因为它绑定到 Xerces.....
      • 我猜,你需要在这里使用 formatMessage() 方法。我可以建议的一件事是,如果您希望有一个 setter 方法,您应该考虑创建一个子类,该子类使用 setter 方法设置语言环境和您自己的格式方法,该方法将调用父级的 super.formatMessage() 通过 setter 传递语言环境信息集方法。
      • 但这完全干扰了 JAXP 的工厂概念 - 必须有一种“简单”的方式来“简单地”将语言环境(或消息格式化程序)设置为 DocumentBuilder 或 DocumentBuilderFactory
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-18
      • 2018-11-27
      • 1970-01-01
      • 2014-01-18
      • 2011-05-10
      • 2011-03-26
      • 1970-01-01
      相关资源
      最近更新 更多