2012-04-13 99 views
1

我有一个可以生成大量文档的系统。其内容在ResourceBundles中定义。如何在ICU4J中的MessageFormat中自定义货币格式

我想定制MessageFormat打印货币值的方式。有时我希望它显示没有小数位的货币(但并非总是)。

这应该按预期工作,但它不是:

System.err.println(
    com.ibm.icu.text.MessageFormat.format(
     "{0,number,\u00A4#}", 
     new com.ibm.icu.util.CurrencyAmount(1, 
     com.ibm.icu.util.Currency.getInstance("USD")))); 

不幸的是它打印出:

US$1,00 

请问您使用自定义格式为货币资源包“属性”文件的人?

我不想改变系统范围。

顺便说一下,这对java.text.MessageFormat工作正常。

+0

你为什么不能使用JDK版本的任何原因呢?顺便说一句:有什么具体的原因,你为什么不能使用'NumberFormat.getCurrencyInstance(locale)'? – 2012-04-13 17:53:45

+0

为什么我想要使用ICU有两个原因。首先,我们的应用程序需要在不同的语言环境中打印某些货币(这在JDK版本中不可能)(货币必须与当前语言环境无关),其次是ICU具有拼写格式,并且必须在不同的语言环境中打印。我不想使用'NumberFormat.getCurrencyInstance(locale)',因为我的所有消息都在ResourceBundles中。 – Marti 2012-04-15 13:53:31

回答

1

好的,我再次读你的问题。 我真的不知道你为什么要砍掉美分(在美国,它在韩国或日本是合理的,因为它们根本不使用它们)。
无论如何,我不认为这是一个好主意,只是截止美分,但如果你想这样做,它就像使用NumberFormat与setMaximumIntegerDigits(int)一样简单。

顺便说一句,我仍然不知道我知道为什么通过使用资源包,你不能使用NumberFormat。 您仍然可以调用格式化在MessageFormat.format()

NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(Locale.US); 
currencyFormatter.setMaximumFractionDigits(0); 
System.err.println(MessageFormat.format("Some amount: {0}.", 
     currencyFormatter.format(1d))); 

预见它打印出:

一些金额:$ 1。

如果您需要保留货币,我建议您使用setCurrency(Currency)方法保留本地格式 - 无论如何您都要在Internalization标签中询问这个问题。


编辑:包括有关的MessageFormat能力的信息

如果需要使用自定义货币格式的语言环境,你实际上需要实例的MessageFormat类(普通静态MessageFormat.format(String, Object...)不会在Web应用程序的工作因为它使用Java 7默认的语言环境 - Locale.getDefault(Locale.Category.FORMAT),如果你愿意的话)。

所以,你真正想要的是写一个辅助方法(很抱歉,没有奖金),这将类似于此(内存,不好意思):

public static String format(String pattern, Locale locale, Object... args) { 
    final String emptyPattern = ""; 
    final FieldPosition zero = new FieldPosition(0); 
    MessageFormat fmt = new MessageFormat(emptyPattern, locale); 
    StringBuffer buf = new StringBuffer(); // I just love it... 

    fmt.applyPattern(pattern); 
    fmt.format(args, buf, zero); 

    return buf.toString(); 
} 

出于性能考虑,你可能会想到创建StringBuffer一次,然后始终清理它,但我会为自己留下优化。
您还需要修改模式的一点,我会在瞬间解释:

String pattern = "{1}{0,number,\u00A4#}"; 

您将需要通过量和货币符号和留给译者在何处放置符号以及如何一个Locale的格式值(不要忘记给属性文件添加注释!)。

+0

感谢您的快速帮助。我没有足够描述我的问题。在我们的系统中,我们生成了大量需要符合正式指导方针的文件。有些金额需要与美分没有任何区别(例如,波兰的正式方式是在美分部分增加2个数字,但我们需要削减它们),但在其他情况下,我们坚持提供金钱的标准方式。因此,在系统范围的格式化程序上设置小数位不是一个选项。在Java中为从ResourceBundles获取的单个消息创建不同的格式化程序将会很麻烦。 – Marti 2012-04-16 08:21:51

+0

让我来解释为什么你的解决方案不能首先工作:[http://icu-project.org/apiref/icu4j/com/ibm/icu/util/CurrencyAmount.html] CurrencyAmount不是从Number派生的,因此普通的toString( )将在格式化过程中被调用。它不适合你。现在,看看我的编辑:) – 2012-04-17 07:22:29