消息格式重新设计

目标

    • 模块化:我们希望能够提供对大多数ICU没有静态依赖的格式。

      • 我们应该在ICU4C公共库中提供简单的格式支持,只需使用字符串替换和“选择”格式,作为基本的格式API,并用于Locale Display Names和使用“{0}{1}”等CLDR模式进行项目排序的类似程序。

      • 我们应该具有数字支持的格式,添加对“数字”、“选项”和“复数”参数类型的支持。

      • 最后,全力支持。

    • 线程化:重要的对象和方法应该是线程安全的,以便可以缓存和并发使用对象。

    • 性能:如果在不记住上下文的情况下,用参数格式化字符串的速度相当快,那就更好了。应该可以通过缓存来提高速度,但一次性使用应该可以。

      • 例如,应用choice/multiple/select格式不应该需要重新解析它们所选择的消息片段。

    • 可扩展性:目前,MessageFormat和Choice/Plural/SelectFormat之间的交互是硬编码的,并且依赖于RTTI。应该可以在不修改核心格式化类的情况下添加另一个这样的参数格式化程序。

思想

消息类

由取代icu设计2011-02-08 00:59:ICU4J API*pre*-提案:MessagePattern类

的分析器 基本MessageFormat语法和容器,用于解析的消息表示。它将解析整个消息字符串,删除它识别的语法(引号和大括号,一些空格),并构建一个简单的数据结构以实现高效使用。

    • setAutoQuoteApostrope(布尔模式)

    • 解析(CharSequence消息[,UErrorCode])

    • 是一种可冻结的--一旦冻结,便可缓存且线程安全

    • String getParsedString()--语法已删除,仅可用于索引

    • int countIndexes()

    • int getIndex(int i)

    • (可能是像int findEndOfArgument(int startIndex)这样的助手)

指标设计:(为便于处理而设计)

    • 索引将是位字段,其中位24..0表示解析字符串中的实际索引。(这将解析消息字符串的长度“限制”为0x1ffffff。)索引按升序存储。

    • 位26..25:

      • 0:参数名称/编号的开头

      • 1:参数类型的开头

      • 2:参数开始样式(模式)

      • 3:论点结束

      • 问题:我们需要允许不使用参数语法的嵌套{fragments},并将它们与参数区分开来。

      • 在解析器不知道子格式语法细节的情况下,解析器如何区分复数形式的{fragment}并从{argument}中选择格式?解析器是否必须限制为只带出'{}并注意{}在何处具有嵌套级别,但不预处理参数编号/名称/类型?

    • 位30..27:嵌套级别0..15,每{增加一次,每}减少一次。

    • 位31:符号位,未设置。

已分析的消息字符串:

    • 删除了引号(撇号),但引用它们的地方除外。文本始终是文字。

    • 删除了语法(未引用)大括号。参数是通过索引找到的。

    • 参数编号被预处理并存储为UChar 0..0x3f。(这将数字索引参数的数量“限制”为64个。)

    • 参数名称将被修剪并检查[:ID_START:][:ID_CONTINUE:]*语法。

    • 参数类型将被修剪。

例子:

原始消息字符串:“{0}'{}'追逐{1,select,female{her}other{his}}尾巴。”

解析的消息字符串:“The \u0000{}chased\u0001选择女性她另一个他的尾巴。

索引:1+开始+4,1+结束+5,1+开始+16,1+类型+17,1+样式+23,2+开始+31,2+结束+34,2+开始+41,2+结尾+44,1+结束+44

格式化程序类

格式化程序有一个消息并对其进行格式化,途中调用参数格式化程序。递归消除了MessageFormat-Choice/Plural/Select RTTI魔法。

设计选择:

    1. 我们可以提供格式化程序子类他们知道参数格式化程序的级别(简单/带数字/全部)。它可以通过编写额外的子类进行定制。

    2. 赞成:这很容易实现。

    3. 反对:您必须使用支持消息中参数类型的格式化程序。

    4. 缺点:(次要)需要编写Formatter子类来支持新的参数类型。(可能很少有用户会提供超出ICU提供的参数格式化程序。)

    5. 我们可以使用注册:向参数格式化程序工厂注册参数类型。工厂将获取语言环境、类型和样式,并返回参数格式化程序。

    6. Pro:注册后,相同的Formatter类将能够处理所有注册的参数类型。

    7. 反对:我们什么时候用C++注册?我们会要求用户调用几个函数中的一个来注册一些参数格式化程序包吗?

    8. 反对:参数格式化程序访问将通过同步注册表缓存getter进行。

公共格式化程序API:(不是线程安全的;使其不可变似乎有局限性,或者似乎需要一个worker对象)

    • 格式设置工具(区域设置区域设置[,UErrorCode])

    • aliasMessage(消息消息)--使用消息,但不获取其所有权

    • ?parseMessageString(CharSequence[,UErrorCode])--方便吗?

    • (format()方法将是非静态的,将参数设置到Formatter对象中,该对象可能也会像MessageFormat一样缓存特定的参数格式化程序)

    • 格式(可附加dest、Object…args)

    • 格式(可附加dest,Map namedArgs)

受保护的格式化程序API(如果我们使用子类):

    • 对象getArgument(int argNumber)

    • 对象getArgument(字符串argName)

    • 格式(可追加dest,消息消息,int styleStart/*使用msg.getIndex(styleStart)*/,int argNumber,String argType)

    • 格式(可追加dest,消息消息,int styleStart/*使用消息.getIndex(styleStart)*/,字符串argName,字符串argType)

    • format(Appendable dest,Message msg,int msgStringStart,int msgStringLimit)-用于从选择中进行递归调用,并使用公共format()方法中的(0,msg.getParsedString().length())进行调用

    • format(Appendable dest、Message msg、int nestedIndex)--用于复数形式的递归调用/select

数字格式

NumberFormat应该对小整数进行优化。它可以缓存一个限制值,以便对低于限制的数字进行简单快速的格式化。例如,如果NumberFormat使用BMP上某个位置的十进制数字,则标准分组的限制可以是1000(对于-1000<intValue<1000),如果不使用分组分隔符,则限制可以更大。格式化一个小于最小值的整数应该使用非常快的代码。

可设置格式

在C++中,我们必须将Formattable移动到公共库中。(在Java中,参数作为Object传入。)检查我们是否可以在不拖动格式化代码的情况下这样做。

相关票据

马克写道:

我认为我们还应该修复一些语法项,作为其中的一部分,如下所示:

我认为以下工作已经完成。

http://bugs.icu-project.org/trac/tickt/2322

http://bugs.icu-project.org/trac/tickt/4569

http://bugs.icu-project.org/trac/tickt/4510//如果calendar关键字在语言环境中?

我应该继续把上面的内容添加到文档的一个部分吗?