是否可以在同一个 MessageFormat 中使用多个 Locales?
It it possible to have multiple Locales in one same MessageFormat?
我有以下 JSON 示例:
{
"value": 946.2,
"description": "O valor é R$ 946,20."
}
我需要使用 MessageFormat 来 JUnit 测试这个 JSON 示例,但是我得到了一个无效值,因为我的区域设置不是英语。如果我将语言环境更改为英语而不是巴西葡萄牙语,我会收到无效描述,因为货币值以英语显示。
这是我的代码:
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Locale;
Locale.setDefault(Locale.ENGLISH);
System.out.println(MessageFormat.format("""
'{'
"value": {0},
"description": "O valor é {0,number,currency}."
'}'
""", new BigDecimal(946.2)));
如何设置值或描述的格式以获得上面显示的 JSON?
好的,没问题!但是:
Locale.setDefault
严苛! (为了测试它可以容忍....但我不想查找那个错误..)
- (我“不喜欢”
MessageFormat
...它在内部使用 StringBuffer
(性能杀手和内存转储先生)。)
只要你能处理好“复杂性”,就可以做到:
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.Locale;
public class MainSimple {
// Brazilian Locale:
private static final Locale LOCALE_PT_BR = new Locale.Builder().
setLanguage("pt").
setRegion("BR").
build();
// US number format:
private static final NumberFormat DEFAULT_NUMBER_FMT = NumberFormat.getNumberInstance(Locale.US);
public static void main(String[] args) {
// MessageFormat instance, with format (with 2! parameters) and Locale:
MessageFormat mainFmt = new MessageFormat("""
'{'
"value": {0},
"description": "O valor é {1,number,currency}. <-- trick 1 "
'}'
""", LOCALE_PT_BR);
final BigDecimal num = new BigDecimal(946.2);
// trick 2:
Object[] params = {DEFAULT_NUMBER_FMT.format(num), num};
// do it:
System.out.println(mainFmt.format(params));
}
}
大纲:
- 常数:
- 巴西(外部格式)语言环境。
- US/Standard 自定义(非巴西)formatting/this 特定数字的(内部)数字格式。
MessageFormat
has a constructor with locale parameter! (我们使用那个,并称它为外部format/locale(mainFmt
))
- Int 格式我们“稍微耍点儿花招”并使用 2 个参数:
{0}
和 {1,number,currency}
- 我们的技巧是:将第一个参数作为(美国格式的数字)
String
传递,第二个作为有。 (Object[] params = {DEFAULT_NUMBER_FMT.format(num), num}
)
- 最终格式化(&打印出来)。
打印:
{
"value": 946.2,
"description": "O valor é R$ 946,20."
}
这是一个 String.format
解决方案,有两个内部(本地化、自定义)NumberFormat
三层:
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;
public class OtherMain {
private static final Locale LOCALE_PT_BR = new Locale.Builder().
setLanguage("pt").
setRegion("BR").
build();
private static final NumberFormat DEFAULT_NUMBER_FMT
= NumberFormat.getNumberInstance(Locale.US);
private static final NumberFormat MY_SPECIAL_NUMBER_FMT
= NumberFormat.getCurrencyInstance(LOCALE_PT_BR);
static {
// this disables "thousands sperarator", we can adjust DEFAULT_NUMBER_FMT as well...
MY_SPECIAL_NUMBER_FMT.setGroupingUsed(false);
}
public static void main(String[] args) {
final BigDecimal num = new BigDecimal(99946.2);
System.out.format("""
{
"value": %s,
"description": "O valor é %s."
}
""",
DEFAULT_NUMBER_FMT.format(num),
MY_SPECIAL_NUMBER_FMT.format(num)
);
}
}
打印:
{
"value": 99,946.2,
"description": "O valor é R$ 99946,20."
}
我有以下 JSON 示例:
{
"value": 946.2,
"description": "O valor é R$ 946,20."
}
我需要使用 MessageFormat 来 JUnit 测试这个 JSON 示例,但是我得到了一个无效值,因为我的区域设置不是英语。如果我将语言环境更改为英语而不是巴西葡萄牙语,我会收到无效描述,因为货币值以英语显示。
这是我的代码:
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Locale;
Locale.setDefault(Locale.ENGLISH);
System.out.println(MessageFormat.format("""
'{'
"value": {0},
"description": "O valor é {0,number,currency}."
'}'
""", new BigDecimal(946.2)));
如何设置值或描述的格式以获得上面显示的 JSON?
好的,没问题!但是:
Locale.setDefault
严苛! (为了测试它可以容忍....但我不想查找那个错误..)- (我“不喜欢”
MessageFormat
...它在内部使用StringBuffer
(性能杀手和内存转储先生)。)
只要你能处理好“复杂性”,就可以做到:
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.Locale;
public class MainSimple {
// Brazilian Locale:
private static final Locale LOCALE_PT_BR = new Locale.Builder().
setLanguage("pt").
setRegion("BR").
build();
// US number format:
private static final NumberFormat DEFAULT_NUMBER_FMT = NumberFormat.getNumberInstance(Locale.US);
public static void main(String[] args) {
// MessageFormat instance, with format (with 2! parameters) and Locale:
MessageFormat mainFmt = new MessageFormat("""
'{'
"value": {0},
"description": "O valor é {1,number,currency}. <-- trick 1 "
'}'
""", LOCALE_PT_BR);
final BigDecimal num = new BigDecimal(946.2);
// trick 2:
Object[] params = {DEFAULT_NUMBER_FMT.format(num), num};
// do it:
System.out.println(mainFmt.format(params));
}
}
大纲:
- 常数:
- 巴西(外部格式)语言环境。
- US/Standard 自定义(非巴西)formatting/this 特定数字的(内部)数字格式。
MessageFormat
has a constructor with locale parameter! (我们使用那个,并称它为外部format/locale(mainFmt
))- Int 格式我们“稍微耍点儿花招”并使用 2 个参数:
{0}
和{1,number,currency}
- 我们的技巧是:将第一个参数作为(美国格式的数字)
String
传递,第二个作为有。 (Object[] params = {DEFAULT_NUMBER_FMT.format(num), num}
) - 最终格式化(&打印出来)。
打印:
{
"value": 946.2,
"description": "O valor é R$ 946,20."
}
这是一个 String.format
解决方案,有两个内部(本地化、自定义)NumberFormat
三层:
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;
public class OtherMain {
private static final Locale LOCALE_PT_BR = new Locale.Builder().
setLanguage("pt").
setRegion("BR").
build();
private static final NumberFormat DEFAULT_NUMBER_FMT
= NumberFormat.getNumberInstance(Locale.US);
private static final NumberFormat MY_SPECIAL_NUMBER_FMT
= NumberFormat.getCurrencyInstance(LOCALE_PT_BR);
static {
// this disables "thousands sperarator", we can adjust DEFAULT_NUMBER_FMT as well...
MY_SPECIAL_NUMBER_FMT.setGroupingUsed(false);
}
public static void main(String[] args) {
final BigDecimal num = new BigDecimal(99946.2);
System.out.format("""
{
"value": %s,
"description": "O valor é %s."
}
""",
DEFAULT_NUMBER_FMT.format(num),
MY_SPECIAL_NUMBER_FMT.format(num)
);
}
}
打印:
{
"value": 99,946.2,
"description": "O valor é R$ 99946,20."
}