Почему Spring Аргументы MessageSource неправильно заполнены в некоторых локалях?
mailconfirm.mail.body=<html><body><h3 style="margin: 0 0 1em;">Hi, {0}!</h3>\
To confirm your email address click on the confirmation link given bellow. If clicking on the link doesn't work, copy and paste the link in a new browser tab. <br /><br />\
<a href="#" onclick="location.href='http://www.domain.com/confirm_email.html?action=activate&hash={1}'; return false;">http://www.domain.com/confirm_email.html?action=activate&hash={1}</a><br /><br />\
Kind regards,<br />\
Your Something
</body></html>
Это вышеописанное сообщение, используемое для кода ниже.
String country = "AU";
Object[] args = new Object[] { account.getLogin(), confirm.getHash() };
helper.setText(appContext.getMessage("mailconfirm.mail.body", args,
new Locale(country)), true);
Я отлаживал оба аргумента, и оба они имеют правильные значения. При отладке строки appContext.getMessage
я увидел, что параметр {1}
не заполнен правильным значением, однако {0}
is.
Любые идеи, что может быть неправильным? Я подозреваю, что это может быть проблема с локалью.
Ответы
Ответ 1
Проблема решена!
Похоже, проблема заключалась в том, что сообщение mailconfirm.mail.body содержало апостроф где-то после {0} и между {1}. После замены doesn't
на does not
он исправил проблему. Я не знал, что апострофы там нельзя использовать.
Постскриптум Это ошибка или просто моя ошибка и апострофы должны быть экранированы?
mailconfirm.mail.body=<html><body><h3 style="margin: 0 0 1em;">Hi, {0}!</h3>\
To confirm your email address, click on the confirmation link given bellow. If clicking on the link doesn't work, copy and paste the link in a new browser tab. <br /><br />\
<a href="http://www.domain.com/confirm_email.html?action=activate&hash={1}">http://www.domain.com/confirm_email.html?action=activate&hash={1}</a><br /><br />\
Kind regards,<br />\
Your Something
</body></html>
Один doesn't
взял меня около часа, чтобы понять это и нажать на исправление. Хахаха... Отныне я считаю апострофы злыми!
Ответ 2
Spring ResourceBundleMessageSource
(который, я думаю, вы используете) использует MessageFormat
для замены заполнителей ({0}
) внутри сообщений. MessageFormat
требует, чтобы одинарные кавычки ('
) сбрасывались с использованием двух одинарных кавычек (''
) (см. MessageFormat Javadoc).
Однако сообщения по умолчанию, которые не содержат никаких аргументов, не будут анализироваться с помощью MessageFormat
. Таким образом, одиночные кавычки в сообщениях без аргументов не нужно экранировать.
ResourceBundleMessageSource
предоставляет флаг под названием alwaysUseMessageFormat
, который может использоваться, если MessageFormat
должен применяться ко всем сообщениям. Таким образом, одиночная кавычка всегда должна быть экранирована двумя одинарными кавычками.
Подробнее см. в сообщении в блоге.
Ответ 3
Я не могу убедить свою бизнес-команду добавить двойные апоса в требуемые места, а иногда они забывают.
Поэтому я просто переопределил ReloadableResourceBundleMessageSource#loadProperties
как:
если значение содержит, "'"
и "{0"
, затем замените "'"
на "''"
и вставьте в свойства с тем же ключом.