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
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?
Remplacez toutes les occurrences de "_"
Par "-"
Dans la chaîne locale lorsque vous recevez le paramètre et laissez la logique n'attend que "-"
.
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).