Специфические для локали сообщения в Xerces 2.11.0 (Java)

Я хочу использовать специфичные для локали сообщения об ошибках с моими 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 не вариант.

Любая помощь приветствуется!


person Philip Helger    schedule 30.08.2013    source источник


Ответы (3)


Не максимальная переносимость, но работает, так как парсер в 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

person Holger    schedule 11.09.2013
comment
Спасибо - это было именно то, что я искал! - person Philip Helger; 12.09.2013
comment
Примечание. Если вы хотите принудительно отображать сообщения проверки на английском языке, вам может потребоваться ввести пустой объект Locale. Это связано с тем, что JRE не включает XMLMessage_en.properties и, таким образом, пытается использовать набор языковых стандартов по умолчанию (в моем случае немецкий или французский), который отлично разрешается для включенных пакетов. Используя пустую локаль, вы заставляете механизм ResourceBundle просто попробовать базовое имя (которое в JRE содержит свойства на английском языке). - person beat; 20.02.2017
comment
Небольшое примечание, потому что я наткнулся на аналогичную проблему при использовании проверки XSD: если у вас есть экземпляр Validator, вы можете использовать validator.setProperty("http://apache.org/xml/properties/locale", Locale.FRANCE); - но будьте осторожны, если у вас есть локаль с языком en, но локаль по умолчанию не на английском языке - используйте Locale.ROOT для принудительного применения английских сообщений! - person Philip Helger; 26.01.2018
comment
@PhilipHelger Спасибо за заметку, она очень полезна. Чтобы принудительно использовать английский язык для неанглоязычных пользователей, мы должны использовать Locale.ROOT. - person h2o2; 15.04.2021

Возможность установить/получить 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 {...}
    //...

}
person upx1988    schedule 09.04.2015

Я думаю, вам стоит попробовать использовать

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

or

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");
         }

Это указывает на то, что если файл пакета ресурсов объявлен в соответствии с локалью, элемент управления должен иметь возможность выбрать другой файл ресурсов с сообщением об ошибке на другом языке.

person Gyanendra Dwivedi    schedule 08.09.2013
comment
Я думал об использовании XMLMessageFormatter, но в приведенном примере они используют некоторый XMLSchemaValidatorComponentManager для получения и обновления XMLMessageFormatter (которого у меня нет). Должен быть способ сделать это со стандартной настройкой DocumentBuilder.... - person Philip Helger; 08.09.2013
comment
Извините, мой плохой .. Я поставил неправильную ссылку .. Обновил правильную. Надеюсь это поможет. - person Gyanendra Dwivedi; 08.09.2013
comment
Спасибо за обновление ссылки. Поэтому мне кажется, что я не могу установить локаль напрямую. Итак, как я могу установить XMLMessageFormatter? Какое свойство использовать? Хотя это решение не является оптимальным, поскольку оно привязывается к Xerces..... - person Philip Helger; 09.09.2013
comment
Я думаю, вам нужно использовать метод formatMessage() здесь. Я мог бы предложить одну вещь: если вы хотите иметь метод установки, вам следует подумать о создании дочернего класса с методом установки для локали и вашего собственного метода форматирования, который вызывал бы родительский super.formatMessage(), передавая информацию о локали, установленную через установщик метод. - person Gyanendra Dwivedi; 10.09.2013
comment
Но это полностью противоречит фабричной концепции JAXP - должен быть простой способ просто установить локаль (или средство форматирования сообщений) в DocumentBuilder или DocumentBuilderFactory. - person Philip Helger; 10.09.2013
comment
Параметр formatMessage() имеет возможность отправлять Locale. Это только то, как вы хотите пройти его. Если вы хотите получить локаль из системы (например, java.util.ResourceBundle.getLocale()) и отправить ее в качестве параметра в formatMessage(), все должно быть настроено. - person Gyanendra Dwivedi; 10.09.2013
comment
Хорошо, и как мне установить XMLMessageFormatter? - person Philip Helger; 10.09.2013