ICU Accept Language API Proposal

"Steven R. Loomis" <[email protected]> Fri, 8 Oct 2004 18:35:52 -0700
Newsgroups gmane.comp.lib.icu.general
Message-ID <[email protected]>
Jitterbug #3591  [   
http://www.jtcsv.com/cgibin/icu-bugs/others?id=3591  ]
Date:     8  October 2004
Expires:  13 October 2004

------------------------
Motivation / Background:

These APIs provide a function to negotiate the best locale to use for 
an operation, given a user's list of acceptable locales, and the 
application's list of available locales.

One of the intended uses of this API is with the HTTP Accept-Language: 
field, see:
  http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4

Here is another article which describes some of the cautions about 
using accept-language:
  http://www.w3.org/International/questions/qa-accept-lang-locales

------------------------
Theory of operation:

Two input lists are passed to the function:

1. The "Accept List" is from the user/client preference, for example, 
from the HTTP request header.  It is ordered in decreasing order of 
preference.
2. The "Available List" is from the application, for example, from the 
list of installed locales. It is not ordered.


  In the best-case situation, the earliest (preferred) locale from the 
Accept list is matched to an exact match in the available list. In this 
situation, a 'Valid' locale is returned.

  Before failing completely, the ICU API will attempt a fallback from 
the Accept list.   Note that this differs from the HTTP specification, 
and is noted appropriately in the return values of the API as a 
'Fallback'.

  To illustrate the fallback behavior, consider the following examples.
An input accept list of "de_LX, ja"  behaves like "de_LX, ja, (de)", 
with "de" being fallback behavior, only if the other two locales were 
not found. Similarly, an input accept list of "de_LX_FOO, de_CH_BAR, 
ja_JP" behaves like "de_LX_FOO, de_CH_BAR, ja_JP, (de_LX, de_CH, de, 
ja)".  The Fallback locales are considered in descending order of 
length, following the requested locales.
   The HTTP specification says that de_LX should not match de. As well, 
HTTP spec says that 'de' in the accept-list should match 'de_LX'. 
However, we assume that application and ICU locale bundles are 
well-formed, so that if there is a 'de_LX' there will be 'de' and we 
will match it.  Therefore, we will not match an accept-locale of 'de' 
to an available locale of 'de_LX'.



  Two versions of the API are provided for C and Java.  One is passed 
the Accept-Language field from HTTP (as a single string), and the other 
an array of Locales.  Note that the numeric weights of the 
Accept-Language are only used to order the accept list items, their 
values are otherwise unimportant.

C
-

typedef enum {
         ULOC_ACCEPT_VALID = 0,  /* An exact match was found. */
         ULOC_ACCEPT_FALLBACK = 1    /* A fallback was found, for 
example, Accept list contained 'ja_JP'
				   which matched available locale 'ja'. */
} UAcceptResult;


/**
  * @param httpAcceptLanguage - "Accept-Language:" header as per HTTP.
  * @param availableLocales - owned by caller.
  * @returns installed locale, or NULL on error. Note, result is valid 
only
  * until availableLocales enumeration is destroyed. (result is owned by 
the
  * UEnumeration.)
  */
const char*
uloc_acceptLanguageFromHTTP(const char *httpAcceptLanguage,
                           UEnumeration* availableLocales,
                           UAcceptResult *outResult,
                           UErrorCode *status);

const char*
uloc_acceptLanguage(const char *acceptList[],
                           UEnumeration* availableLocales,
                           UAcceptResult *outResult,
                           UErrorCode *status);


JAVA
----

static public final int         ACCEPT_VALID = 0;  /* An exact match 
was found. */
static public final int         ACCEPT_FALLBACK = 1    /* A fallback 
was found, for example, Accept list contained 'ja_JP' which matched 
available locale 'ja'. */

/**
  * @param httpAcceptLanguage - "Accept-Language:" header as per HTTP.
  * @param availableLocales - owned by caller.
  * @returns an installed locale (from the availableLocales list)
  */
static
ULocale   ULocale.acceptLanguageFromHTTP(String httpAcceptLanguage,
                      StringEnumeration availableLocales,
                      int outResult[]);

static
ULocale   ULocale.acceptLanguage(ULocale acceptArray[],
                      StringEnumeration availableLocales,
                      int outResult[]);