web-dev-qa-db-fra.com

Analyser à la fois en_us et en-nous en tant que locale in Java

J'écris une API (en utilisant Java) qui prend des paramètres. Nous voulons que les clients puissent spécifier "EN-US" ou "EN_US", car ils semblent tous deux être largement utilisés dans toutes les langues.

J'ai traversé ces liens

  1. Comment obtenir la locale à partir de la représentation de chaîne en Java
  2. EN_US ou EN-US, lequel devriez-vous utiliser
  3. Documentation Locale Java

Documentation Java (source 3 d'en haut) States "Les valeurs de variante bien formées ont la sous -tag de formulaire ((" _ "|" - ') subtag) * Où subtag = [0-9] [0-9a-za-z] { 3} | [0-9A-ZA-Z] {5,8}. (Remarque: BCP 47 utilise uniquement un trait d'union ('-') en tant que délimiteur, c'est plus clément). "

La façon dont j'ai compris c'est à la fois "_" et "-" sont prises en charge, mais leur code ne supporte que "-". Voir mon test d'unité d'échantillon ci-dessous qui échoue, mais passe si j'utilise "en-nous".

@Test
public void testLocale() {
    Locale locale = Locale.forLanguageTag("en_US");
    assertThat(locale.getLanguage(), equalTo("en"));
}

Y a-t-il des moyens d'analyser un paramètre local des deux formes de chaîne "EN_US" et "EN-US"? Quelle est l'approche recommandée ici?

5
srini

Remplacez toutes les occurrences de "_" Par "-" Dans la chaîne locale lorsque vous recevez le paramètre et laissez la logique n'attend que "-".

2
Tulains Córdova

Plutôt que de remplacer sans compréhension, j'aimerais expliquer pourquoi il semble y avoir deux formes, une sous-traitance et une autre traite avec une autre traite et pourquoi on devrait s'en soucier.

TL; DR Il n'est pas simple comme un seul remplacement de caractère.


1. Spécifications

Il y a plusieurs spécifications en jeu ici:

  • ICU : le [~ # ~ # ~] I [~ # ~] Nternational [~ # ~] c [~ # ~] omponents pour [~ # ~ # ~] u [~ # ~ ~] Nicode qui a une section sur la manière de coder/représenter les locaux (langue, pays, Script, variante, etc.), ce projet est principalement utilisé dans des langues natales telles que C. et ne doit pas être mélangée à des locaux dans un système POSIX.

  • nicode CLDR : Qui offre de manière intéressante une page simple sur le équivalence avec balise de langue . Cette représentation permet à la fois des traits d'union et de soulignement, tout en préférant le trait d'union. Celui-ci est également différent de l'ICU.

  • (BCP 47 / RFC 4646) ⇒ RFC 5646 est à propos de l'étiquette de langue utilisée dans les en-têtes HTTP ( RFC 3282 ) surtout dans Content-Language Et dans Accept-Language ).

La norme dans la bande est donc d'utiliser des balises de langue dans certains en-têtes. afin que cela signifie

  • Si l'application Server s'appuie sur des en-têtes HTTP standard, il doit gérer les balises de langue (gamme de langues plus spécifiquement pour le Accept-Language).

  • Si l'application Server utilise une en-tête personnalisée comme Company-MyApp-Other-Language Alors pas de problème, il est coutume à cet écosystème.

  • Si l'application client utilise des en-têtes HTTP standard, mais en utilisant un mauvais format, alors l'application Server-Server devrait essayer de gérer ceux-ci.


2. Quelques détails de la mise en œuvre

La bonne chose à propos de PHP locale est-ce qu'il gère ICU format et étiquettes de langue.

Cependant, pour Java L'histoire est un peu plus compliquée, car la classe Locale classe est assez ancienne (depuis JDK 1.1 vers 1997) et n'a pas été capable Pour analyser ou formater (toString) à l'une quelconque des normes mentionnées ci-dessus, il a utilisé le soulignement comme séparateur, mais ce n'est pas ICU Conforme. Dans JDK 1.7 vers 2011, forLanguageTag/toLanguageTag a été ajouté pour prendre en charge la norme BCP 47/RFC 4646; les anciennes méthodes ont conservé leur comportement hérité pour la compatibilité en arrière. À cette date (mars 2018) ICU/Le format local CLDR n'est pas pris en charge par les paramètres régionaux de JDK.

En effet, l'approche naïve, travaillant dans la plupart des situations (99,999%) consiste à remplacer les traits de soulignement par des traits d'union. Certains cas rares peuvent apparaître lorsque la chaîne ne contient qu'une extension.

Cependant, cela ne fonctionne pas pour chaque ICU Représentation notamment lorsqu'il y a ICU Mots-clés comme @currency=..., Celles ne peuvent pas être converties via un seul bloc Remplacer.

  • sr_Latn_RS_REVISED@currency=USD
  • en_IE@currency=IEP

Aussi cela ne fonctionnera pas pour Java Clients qui utilisent le toString du Java locale, il est plus susceptible de causer des problèmes pour Certains pays où le script est un élément important pour les paramètres régionaux, par exemple pour la Serbie:

  • Locale.forLanguageTag("sr-Latn-RS").toString()sr_RS_#Latn, cette totring hérité ne peut pas être interprétée comme une balise de langue valide, l'analyseur rejeter complètement le script.

Donc, la manipulation de chaque mauvais comportement possible dans une en-tête standard est délicate, le meilleur serait d'imposer à respecter la RFC de la balise de langue, que le navigateur respecte. Sinon possible, il est préférable d'identifier quelle application est responsable de cette mauvaise conduite et du format utilisé. Cela éviterait de gérer tous les formats possibles.


3. post scriptum

En outre, la partie Javadoc qui est citée dans la question ne s'applique qu'à la variante partie d'un local, non à la langue et au pays

Les valeurs variantes bien formées ont la sous -tag de formulaire (('_' | '-') subtag) * Où subtag = [0-9] [0-9A-ZA-Z] {3} | [0-9A-ZA-Z] {5,8}. (Remarque: BCP 47 utilise uniquement un trait d'union ('-') en tant que délimiteur, c'est plus clément).

13
Brice