背景
專案中使用Spring的ReloadableResourceBundleMessageSource這個類來實現多語言,有一次字串裡包含引號'
時,解析時出了問題,一起來看一下吧
例子
resources下包含三個語言檔案
分別是:
bundle_zh_CN.properties
hello=你好嗎?{0}
bundle_zh_TW.properties
hello=你好嗎?{0}
bundle_en.properties
hello=how are you ? {0}
測試類:
public class Main {
public static void main(String[] args) throws UnsupportedEncodingException {
System.out.println(getMessage("hello", new Object[] {"輝"}, Locale.CHINA));
System.out.println(getMessage("hello", new Object[] {"輝"}, Locale.TRADITIONAL_CHINESE));
System.out.println(getMessage("hello", new Object[] {"hui"}, Locale.ENGLISH));
}
public static String getMessage(String code, Object[] args, Locale locale) {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
messageSource.setBasename("bundle");
messageSource.setCacheSeconds(1800);
return messageSource.getMessage(code, args, locale);
}
}
輸出:
你好嗎?輝
你好嗎?輝
how are you ? hui
可以看出沒什麼問題
如果含有引號'
改成:
bundle_zh_CN.properties
hello=你好'嗎?{0}
bundle_zh_TW.properties
hello=你好'嗎?{0}
bundle_en.properties
hello=how are' you ? {0}
輸出結果:
你好嗎?{0}
你好嗎?{0}
how are you ? {0}
可以看出如果含有引號',引數不起作用,而且引號'也沒顯示出來
原因
MessageFormat messageFormat = resolveCode(code, locale);
if (messageFormat != null) {
synchronized (messageFormat) {
return messageFormat.format(argsToUse);
}
}
追蹤原始碼,底層是由Java底層的MessageFormat來實現的
API中解釋如下:
Within a String, a pair of single quotes can be used to quote any arbitrary characters except single quotes.
For example, pattern string "'{0}'" represents string "{0}", not a FormatElement.
A single quote itself must be represented by doubled single quotes '' throughout a String.
For example, pattern string "'{''}'" is interpreted as a sequence of '{ (start of quoting and a left curly brace), '' (a single quote), and }' (a right curly brace and end of quoting), not '{' and '}' (quoted left and right curly braces): representing string "{'}", not "{}".
Any unmatched quote is treated as closed at the end of the given pattern. For example, pattern string "'{0}" is treated as pattern "'{0}'".
大概意思就是:
- 兩個單引號裡面的值保持不變,不會被格式化
- 如果想輸出單引號,使用兩個單引號'' 來輸出單引號'
- 如果只有一個單引號,那麼單引號後面的值就原封不動的輸出來,即不會被格式化
修改
改成:
bundle_zh_CN.properties
hello=你好''嗎?{0}
bundle_zh_TW.properties
hello=你好''嗎?{0}
bundle_en.properties
hello=how are'' you ? {0}
輸出結果:
你好'嗎?輝
你好'嗎?輝
how are' you ? hui
還有一點需要注意的就是:在沒有引數的情況下,如果想輸出引號,那就用一個引號即可,如下:
bundle_zh_CN.properties
hello=你好'嗎?
bundle_zh_TW.properties
hello=你好'嗎?
bundle_en.properties
hello=how are' you ?
public static void main(String[] args) throws UnsupportedEncodingException {
System.out.println(getMessage("hello", null, Locale.CHINA));
System.out.println(getMessage("hello", null, Locale.TRADITIONAL_CHINESE));
System.out.println(getMessage("hello", null, Locale.ENGLISH));
}
輸出:
你好'嗎?
你好'嗎?
how are' you ?