[loc-en-dev] -u- extension API - necessary updates?

Yoshito Umaoka y.umaoka at gmail.com
Wed Jun 30 13:30:24 PDT 2010


In the Locale Enhancement repository, we have following proposed APIs 
supporting -u- extension:

In java.util.Locale

public Set<String> getUnicodeLocaleKeys()
public String getUnicodeLocaleType(String key)

In java.util.Locale.Builder

public Builder setUnicodeLocaleKeyword(String key, String type)

Following Unicode locale extension are not in our scope last year.

1. type represented by multiple subtags
2. key without type
3. attribute

For supporting 1, it looks we do not need any changes in the proposal.  
A Unicode locale extension keyword may have type represented by multiple 
subtags. For example, "en-u-vt-0061-0065" is a valid example defined by 
the current LDML specification (See 
http://www.unicode.org/reports/tr35/#Locale_Extension_Key_and_Type_Data).

However, this does not mean that a keyword may have multiple types. In 
this example, 0061 and 0065 are not two different types - instead 
"0061-0065" is a type. Thus, getUnicodeLocaleType("vt") can simply 
return "0061-0065".  To set the type using Builder, 
setUnicodeLocaleKeyword("vt", "0061-0065") is sufficient.

For supporting 2, there is a minor conflict with the current proposal. 
Assume we have a Locale represented by pseudo language tag 
"en-u-aa-bb-ccc". getUnicodeLocaleKeys() will return a set containing 
"aa" and "bb". getUnicodeLocaleType(String key) currently returns null 
when the input key is not available, and it returns non-empty type 
string when the key is available. We could use empty string "" to 
represent typeless keyword - that is, getUnicodeLocaleType("aa") to 
return "" in this example.

The remaining question is the Builder API - 
setUnicodeLocaleKeyword(String key, String type). For now, empty string 
type indicate that the keyword itself is removed from the current state 
and null type throws NPE. We could change the API to use null for 
deletion instead of empty string. For example, if an Builder internally 
represents "en-u-aa-bb-ccc", setUnicodeLocaleKeyword("aa", null) will 
remove the typeless keyword "aa" - and internal representation will be 
changed to "en-u-bb-ccc" after the call. Also, 
setUnicodeLocaleKeyword("dd", "") will append a typeless keyword "dd" to 
the internal state (that is, "en-u-aa-bb-ccc-dd").

Note that setXXX with empty string is removing a field from Builder by 
the current design. If we really want to change the semantics of empty 
string and null in  the API setUnicodeLocaleKeyword, the consistent 
policy should be applied to others (for example, setLanguage(null) to 
remove language field, instead of setLanguage("")).

For supporting 3, we could treat an attribute as keyless keyword. But it 
makes getUnicodeLocaleKeys()/getUnicodeLocaleType(String key) a little 
bit awkward. Technically, we can still design them like that way 
(getUnicodeLocaleKeys() to include an empty string in the return set / 
getUnicodeLocaleType("") to return attribute subtags). I think adding 
extra API dedicated for attribute is cleaner.

public Set<String> getUnicodeLocaleAttributes()

The same idea is applicable to Builder. The API dedicated for 
adding/removing Unicode locale attribute like below may be added:

public Builder addUnicodeLocaleAttribute(String attribute)
public Builder removeUnicodeLocaleAttribute(String attribute)

Another possibility is to multiple attributes as a whole.

public Builder setUnicodeLocaleAttribute(String attributes)

For example, setting attribute "abc" and "def", 
setUnicodeLocaleAttributes("abc-def"). If we go for this approach, we do 
not need "remove" method. A tricky part is that the order of attributes 
does not matter. So, semantically, "abc-def" and "def-abc" are same. We 
do not want to introduce unnecessary variations, we should clearly state 
that the order of attributes are not preserved.


Another question related to this - Set<String> vs. List<String>. 
Currently, getUnicodeLocaleKeys() returns Set<String> (actually, 
unmodifiable set). Semantically, the order of keywords does not matter. 
"u-ca-japanese-cu-jpy" is equivalent to "u-cu-jpy-ca-japanese". But we 
do use canonical order (alphabetical order of keys) when a Locale is 
converted to a language tag. From this point of view, List<String> might 
be more appropriate. This also applies to attributes. If we agree to 
support Unicode locale attributes with dedicated APIs like above, we 
should decide if the collection of attributes should be represented by 
Set or List.


Overall, supporting full specification of Unicode locale extension looks 
not too bad. Some may argue why we add APIs dedicated for things which 
are not yet used. We could defer adding "attribute" APIs - and attribute 
can be only set via Builder.setExtension('u', "...."). But necessary API 
addition is pretty minimal and with these APIs, the design look more 
complete. Therefore, if we are going to include any 'u' extension 
specific APIs, I want to do it completely including attribute support.

-Yoshito






More information about the locale-enhancement-dev mailing list