2017-04-17 1 views
2

J'ai essayé d'obtenir Java pour convertir des nombres en fonction de leurs lieux. à travers this post qui Came a contribué de façon considérable depuis la compréhension avant cela, je l'avais mis au point des méthodes propres à convertir des nombres à lieux spécifiques (comme par d'autres discussions de confusion sur ce sujet)java Locale.Builder setExtension (Locale.UNICODE_LOCALE_EXTENSION

donc, en supposant que j'ai:

Locale arabicLocale = new Locale.Builder().setLanguage("ar").setRegion("SA") 
.setExtension(Locale.UNICODE_LOCALE_EXTENSION, "nu-arab").build(); 

Locale thaiLocale = new Locale.Builder().setLanguage("th").setRegion("TH") 
.setExtension(Locale.UNICODE_LOCALE_EXTENSION, "nu-thai").build(); 

Locale hinduLocale = new Locale.Builder().setLanguage("hi").setRegion("IN") 
.setExtension(Locale.UNICODE_LOCALE_EXTENSION, "nu-hindu").build(); 

DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(arabicLocale); 
NumberFormat numberFormat = NumberFormat.getNumberInstance(arabicLocale); 
println" Arabic ${numberFormat.format(123.22)}" 

dfs = DecimalFormatSymbols.getInstance(thaiLocale); 
numberFormat = NumberFormat.getNumberInstance(thaiLocale); 
println" Thai ${numberFormat.format(123.22)}" 

dfs = DecimalFormatSymbols.getInstance(hinduLocale); 
numberFormat = NumberFormat.getNumberInstance(hinduLocale); 
println" Hindu ${numberFormat.format(123.22)}" 

Ceci produit la sortie suivante

Arabic ١٢٣٫٢٢ 
Thai ๑๒๓.๒๒ 
Hindu १२३.२२ 

Le but de cet article était d'essayer d'identifier comment je peux chercher ou obtenir le code lui-même pour pointer vers la droite Locale.UNICODE_LOCALE_EXTENSION puisque le truc th et hindou était juste deviner le travail de ma fin et j'ai de la difficulté à comprendre peut faire la même chose pour l'hébreu chinois japonais. Bien que je pense que le chinois et le japonais utilisent probablement le système de numérotation arabe, je peux me tromper sur ce point.

Quoi qu'il en soit toute aide/conseils sur la façon dont je peux soit la capture automatique ce bit de données ou de normes comme dans une page qui a toutes les définitions que je peux faire un ENUM sur serait d'une grande aide

J'étais creuser plus profondément dans LocaleExtensions

static { 
     CALENDAR_JAPANESE = new LocaleExtensions("u-ca-japanese", Character.valueOf('u'), UnicodeLocaleExtension.CA_JAPANESE); 
     NUMBER_THAI = new LocaleExtensions("u-nu-thai", Character.valueOf('u'), UnicodeLocaleExtension.NU_THAI); 
    } 

cela fait donc maintenant plus de sens nu-language = nombre ca-language = calendrier

Mais lors de l'exécution:

Locale japLocale = new Locale.Builder().setLanguage("ja").setRegion("JP") 
        .setExtension(Locale.UNICODE_LOCALE_EXTENSION, "nu-japanese").build(); 

Je reçois des nombres en anglais.

Selon question initiale, le lien https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry

Pour Hebrew

Type: language 
Subtag: he 
Description: Hebrew 
Added: 2005-10-16 
Suppress-Script: Hebr 

Mais en essayant ci-dessous:

Locale hebrewLocale = new Locale.Builder().setLanguage("he").setRegion("IL") 
        .setExtension(Locale.UNICODE_LOCALE_EXTENSION, "nu-hebr").build(); 

Je reçois 123.22

Pour répondre à ma propre question vous pouvez bu ILD un ENUM d'ici http://www.oracle.com/technetwork/java/javase/java8locales-2095355.html

Greek (el) Greece (GR) (Grek) el-GR 
Hebrew (iw) Israel (IL) (Hebr) iw-IL 

Donc en bref

pour la Grèce prendre dernier champ el-GR unicodeEXtension = -u nombre = -nu et un de dernier en minuscules -hebr vous donnant 'el-GR-u-nu-grek' pour la Grèce ou même pour Hebrew 'iw-IL-u-n-hebr'

Locale locale = new Locale.Builder().setLanguageTag('el-GR-u-nu-grek').build(); 

Si vous imprimez des nombres en grec mais que je vois des chiffres en anglais cela fonctionne pour certains ountries mais pas d'autres.

+0

fondamentalement, j'ai conclu que la version de Java est incomplète https://mvnrepository.com/artifact/com.ibm.icu/icu4j est ce dont vous avez besoin et semble couvrir tous les lieux correctement. Je me suis retrouvé avec la moitié et demi puis réalisé icu4 fait tout – Vahid

Répondre

0

Pour répondre à ma propre question car c'est plutôt un sujet complexe qui n'est pas expliqué bien là-bas.

En bref, selon mon commentaire, vous êtes probablement mieux d'utiliser icu4j. Puisque ceci offre une solution plus complète pour la conversion internationale de nombre/date.

La difficulté est de mettre au point toutes les normes nécessaires, car il semble que tous les langages locaux sont pris en charge correctement, juste pour savoir comment l'utiliser correctement.

Je fournirai un extrait - ce code est dans le besoin d'un nettoyage, mais offre une solution à la fois le nombre et la conversion date pour votre application java:

import groovy.transform.CompileStatic 

/** 
* 
* @author Vahid Hedayati 
* Looks complex but will explain 
* 
* ar-SA u = unicode nu = number arab = arabic 
* 
* https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry 
* to get langauge code such as arab = subtag 
* 
* Rest explained here 
* http://stackoverflow.com/questions/43456068/java-locale-builder-setextensionlocale-unicode-locale-extension 
* 
* 
*/ 
@CompileStatic 
enum LocaleCalendarExtensions { 
    SA('ar-SA-u-ca-arab'), 
    AM('hy-AM-u-ca-arevmda'), 
    CN('zh-TW-u-ca-hant'), 
    CZ('cs-CZ-u-ca-latn'), 
    DK('da-DK-u-ca-latn'), 
    NL('nl-NL-u-ca-latn'), 
    IE('ie-IE-u-ca-latn'), 
    FR('fr-FR-u-ca-latn'), 
    DE('de-DE-u-ca-latn'), 
    GR('el-GR-u-ca-grek'), 
    IL('iw-IL-u-ca-hebr'), 
    IN('hi-IN-u-ca-hindu'), 
    IT('it-IT-u-ca-latn'), 
    JP('ja-JP-u-ca-jpan'), 
    NO('nb-NO-u-ca-latn'), 
    IR(''), //fa-IR-u-ca-fars'), 
    PL('pl-PL-u-ca-latn'), 
    PT('pt-PT-u-ca-latn'), 
    RU('ru-RU-u-ca-cyrl'), 
    ES('es-ES-u-ca-latn'), 
    SE('sv-SE-u-ca-latn'), 
    TH('th-TH-u-ca-thai'), 
    TR('tr-TR-u-ca-latn'), 
    PK(''),//ur-PK-u-ca-arab'), 
    VN('vi-VN-u-ca-latn') 

    String value 

    LocaleCalendarExtensions(String val) { 
     this.value = val 
    } 
    public String getValue(){ 
     return value 
    } 
    static LocaleCalendarExtensions byValue(String val) { 
     values().find { it.value == val } 
    } 
    public static EnumSet<LocaleCalendarExtensions> getArabicSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(SA) 
     return ret_val 
    } 
    public static EnumSet<LocaleCalendarExtensions> getJapanSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(JP) 
     return ret_val 
    } 

    public static EnumSet<LocaleCalendarExtensions> getChinaSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(CN) 
     return ret_val 
    } 

    public static EnumSet<LocaleCalendarExtensions> getFarsiSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 

     ret_val.add(IR) 
     return ret_val 
    } 
    public static EnumSet<LocaleCalendarExtensions> getUrduSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(PK) 
     return ret_val 
    } 
    public static EnumSet<LocaleCalendarExtensions> getAsianSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(JP) 
     ret_val.add(CN) 
     return ret_val 
    } 
    public static EnumSet<LocaleCalendarExtensions> getHebrewSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(IL) 
     return ret_val 
    } 
    public static EnumSet<LocaleCalendarExtensions> getHinduSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(IN) 
     return ret_val 
    } 
    public static EnumSet<LocaleCalendarExtensions> getThaiSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(TH) 
     return ret_val 
    } 
    public static EnumSet<LocaleCalendarExtensions> getGreekSupport() { 
     final EnumSet<LocaleCalendarExtensions> ret_val = EnumSet.noneOf(LocaleCalendarExtensions.class) 
     ret_val.add(GR) 
     return ret_val 
    } 
} 

Maintenant, comment convertir une date appropriée aux lieux internationaux :

/** 
    * 
    * @param lang where lang code provider is ar en cn fr ur it is as per LocaleCalendarExtensions Enum main declarations 
    * @param date given date 
    * @param format definition in which case I have clause to deal with HH:mm and so on just read through below code 
    * @return 
    */ 
    public static String convertDate(String lang, java.util.Date date, String format) { 
     StringBuilder output=new StringBuilder() 
     if (lang != null && date) { 
      def found = LocaleICUCalendarExtensions?.find{it.toString()==lang} 
      if (found) { 
       def found1 = LocaleExtensions?.valueOf(lang) 
       com.ibm.icu.util.ULocale locale = new com.ibm.icu.util.ULocale(found1.value) 
       com.ibm.icu.util.Calendar calendar = com.ibm.icu.util.Calendar.getInstance(locale) 
       calendar.setTime(date) 
       com.ibm.icu.text.DateFormat df 
       if (format == 'HH:mm') { 
        df = com.ibm.icu.text.DateFormat.getPatternInstance(com.ibm.icu.text.DateFormat.HOUR_MINUTE, locale) 
       } else { 
        if (format=='dd MMM yyyy HH:mm:ss') { 
         df = com.ibm.icu.text.DateFormat.getDateInstance(DateFormat.FULL, locale) 
        } else if (format=='dd MMM') { 
         df = com.ibm.icu.text.DateFormat.getPatternInstance(com.ibm.icu.text.DateFormat.ABBR_MONTH_DAY, locale) 
        } else { 
         df = com.ibm.icu.text.DateFormat.getDateInstance(DateFormat.LONG, locale) 
        } 
        output << df.format(calendar) 
       } 

      } 
     } 
     return output.toString() 
    } 

pour convertir un certain nombre dans un autre pays système de numérotation:

/** 
    * Converts number to given locale 
    * @param lang 
    * @param number 
    * @return 
    */ 
    public static String convertNumber(String lang, number) { 
     String output='' 
     if (lang != null) { 
      boolean arabic = (LocaleCalendarExtensions.arabicSupport.find { it.toString() == lang } ? true : false) 
      boolean china = (LocaleCalendarExtensions.chinaSupport.find { it.toString() == lang } ? true : false) 
      boolean japan = (LocaleCalendarExtensions.japanSupport.find { it.toString() == lang } ? true : false) 
      boolean farsi = (LocaleCalendarExtensions.farsiSupport.find { it.toString() == lang } ? true : false) 
      boolean urdu = (LocaleCalendarExtensions.urduSupport.find { it.toString() == lang } ? true : false) 
      boolean hebrew = (LocaleCalendarExtensions.hebrewSupport.find { it.toString() == lang } ? true : false) 
      boolean greek = (LocaleCalendarExtensions.greekSupport.find { it.toString() == lang } ? true : false) 
      boolean hindu = (LocaleCalendarExtensions.hinduSupport.find { it.toString() == lang } ? true : false) 
      boolean thai = (LocaleCalendarExtensions.thaiSupport.find { it.toString() == lang } ? true : false) 
      if (arabic || hindu | thai || farsi||urdu) { 
       def found = LocaleExtensions?.valueOf(lang) 
       if (found) { 
        Locale locale = new Locale.Builder().setLanguageTag(found.value).build(); 
        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale); 
        NumberFormat numberFormat = NumberFormat.getNumberInstance(locale); 
        def numbers 
        if (number.toString().indexOf('.')>-1) { 
         numbers=number as Double 
        } else { 
         numbers=number as Long 
        } 
        output = (numberFormat?.format(numbers)) ?:'' 
       } 
      } 
      if (japan|china||hebrew||greek) { 
       // to extend look up types here 
       //http://www.atetric.com/atetric/javadoc/com.ibm.icu/icu4j/49.1/src-html/com/ibm/icu/util/ULocale.html 
       //http://icu-project.org/~yoshito/jacoco_57.1/com.ibm.icu.util/ULocale.java.html 
       com.ibm.icu.util.ULocale locale 

       if (japan) { 
        locale= new com.ibm.icu.util.ULocale("ja_JP_JP")//ja_JP_JP // 
       } 
       if (china) { 
        locale= new com.ibm.icu.util.ULocale("zh_Hans")//[email protected]=pinyin; 
       } 
       if (hebrew) { 
        locale= new com.ibm.icu.util.ULocale("he_IL") 

       } 
       if (greek) { 
        locale= new com.ibm.icu.util.ULocale("el_GR") 
       } 
       com.ibm.icu.text.NumberFormat nf = com.ibm.icu.text.NumberFormat.getInstance(locale) 
       def numbers 
       if (number.toString().indexOf('.')>-1) { 
        numbers=number as Double 
       } else { 
        numbers=number as Long 
       } 
       output = nf.format(numbers) 
      } 
     } 
     return output ?: number.toString() 
    } 

Maintenant, si vous utilisez Grails vous pouvez créer un taglib et passer outre formatDate et formatNumber DEFINITIONS travailler avec le code ci-dessus:

/** 
    * override default date formatter if translation translate 
    */ 

    def formatDate={attrs-> 
     String foundRecord 
     if (attrs.locale) { 
      String lang = attrs.locale.country 
      foundRecord = NumberHelper.convertDate(lang, attrs.date, attrs.format) 
     } 
     if (!foundRecord || foundRecord=='null') { 
      out << g.formatDate(attrs) 
     } else { 
      out << foundRecord 
     } 
    } 


/** 
* Override default formatNumber and translate number if possible otherwsie run default 
*/ 
def formatNumber={attrs-> 
    def foundRecord 
    if (attrs.locale && attrs.number) { 
     String lang = attrs.locale.country 
     foundRecord = NumberHelper.convertNumber(lang, attrs.number) 
    } 
    if (!foundRecord) { 
     out << g.formatNumber(attrs) 
    } else { 
     out << "${foundRecord}" 
    } 
} 

ICU4J Enum ci-dessus:

import groovy.transform.CompileStatic 


@CompileStatic 
enum LocaleICUCalendarExtensions { 
    SA('[email protected]=islamic'), 
AM('[email protected]=armenian'), 
CN('[email protected]=chinese'), 
CZ('[email protected]=latin'), 
DK('[email protected]=latin'), 
NL('[email protected]=latin'), 
IE('[email protected]=latin'), 
FR('[email protected]=latin'), 
DE('[email protected]=latin'), 
GR('[email protected]=greek'), 
IL('[email protected]=hebrew'), 
IN('[email protected]=hindu'), 
IT('[email protected]=Latin'), 
JP('[email protected]=japanese'), 
NO('[email protected]=latin'), 
IR('[email protected]=persian'), 
PL('[email protected]=latin'), 
PT('[email protected]=latin'), 
RU('[email protected]=cyrillic'), 
ES('[email protected]=latin'), 
SE('[email protected]=latin'), 
TH('[email protected]=buddhist'), 
TR('[email protected]=latin'), 
PK('[email protected]=pakistan'), 
VN('[email protected]=latin') 

    String value 

    LocaleICUCalendarExtensions(String val) { 
     this.value = val 
    } 
    public String getValue(){ 
     return value 
    } 
    static LocaleICUCalendarExtensions byValue(String val) { 
     values().find { it.value == val } 
    } 
    public static EnumSet<LocaleICUCalendarExtensions> getArabicSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 
     ret_val.add(SA) 
     return ret_val 
    } 
    public static EnumSet<LocaleICUCalendarExtensions> getJapanSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 
     ret_val.add(JP) 
     return ret_val 
    } 

    public static EnumSet<LocaleICUCalendarExtensions> getChinaSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 
     ret_val.add(CN) 
     return ret_val 
    } 

    public static EnumSet<LocaleICUCalendarExtensions> getFarsiSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 

     ret_val.add(IR) 
     return ret_val 
    } 
    public static EnumSet<LocaleICUCalendarExtensions> getUrduSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 
     ret_val.add(PK) 
     return ret_val 
    } 

    public static EnumSet<LocaleICUCalendarExtensions> getHebrewSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 
     ret_val.add(IL) 
     return ret_val 
    } 
    public static EnumSet<LocaleICUCalendarExtensions> getHinduSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 
     ret_val.add(IN) 
     return ret_val 
    } 
    public static EnumSet<LocaleICUCalendarExtensions> getThaiSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 
     ret_val.add(TH) 
     return ret_val 
    } 
    public static EnumSet<LocaleICUCalendarExtensions> getGreekSupport() { 
     final EnumSet<LocaleICUCalendarExtensions> ret_val = EnumSet.noneOf(LocaleICUCalendarExtensions.class) 
     ret_val.add(GR) 
     return ret_val 
    } 
} 

LocaleExtensions ENUM un peu comme LocaleCalendar juste a nu plutôt que ca

import groovy.transform.CompileStatic 

/** 
* Looks complex but will explain 
* 
* ar-SA u = unicode nu = number arab = arabic 
* 
* https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry 
* to get langauge code such as arab = subtag 
* 
* Rest explained here 
* http://stackoverflow.com/questions/43456068/java-locale-builder-setextensionlocale-unicode-locale-extension 
* 
* 
*/ 
@CompileStatic 
enum LocaleExtensions { 
    SA('ar-SA-u-nu-arab'), 
    AM('hy-AM-u-nu-arevmda'), 
    CN('zh-TW-u-nu-arab'), //'zh-TW-u-nu-hant' 
    CZ('cs-CZ-u-nu-latn'), 
    DK('da-DK-u-nu-latn'), 
    NL('nl-NL-u-nu-latn'), 
    IE('ie-IE-u-nu-latn'), 
    FR('fr-FR-u-nu-latn'), 
    DE('de-DE-u-nu-latn'), 
    GR('el-GR-u-nu-grek'), 
    IL('iw-IL-u-nu-hebr'), 
    IN('hi-IN-u-nu-hindu'), 
    IT('it-IT-u-nu-latn'), 
    JP('ja-JP-u-nu-arab'), 
    NO('nb-NO-u-nu-latn'), 
    IR('fa-IR-u-nu-arab'), 
    PL('pl-PL-u-nu-latn'), 
    PT('pt-PT-u-nu-latn'), 
    RU('ru-RU-u-nu-cyrl'), 
    ES('es-ES-u-nu-latn'), 
    SE('sv-SE-u-nu-latn'), 
    TH('th-TH-u-nu-thai'), 
    TR('tr-TR-u-nu-latn'), 
    PK('ur-PK-u-nu-arab'), 
    VN('vi-VN-u-nu-latn') 

    String value 

    LocaleExtensions(String val) { 
     this.value = val 
    } 
    public String getValue(){ 
     return value 
    } 
    static LocaleExtensions byValue(String val) { 
     values().find { it.value == val } 
    } 
    public static EnumSet<LocaleExtensions> getArabicSupport() { 
     final EnumSet<LocaleExtensions> ret_val = EnumSet.noneOf(LocaleExtensions.class) 
     ret_val.add(SA) 
     //TODO 
     ret_val.add(JP) 
     ret_val.add(CN) 
     return ret_val 
    } 
    public static EnumSet<LocaleExtensions> getFarsiSupport() { 
     final EnumSet<LocaleExtensions> ret_val = EnumSet.noneOf(LocaleExtensions.class) 
     ret_val.add(PK) 
     ret_val.add(IR) 
     return ret_val 
    } 

    public static EnumSet<LocaleExtensions> getAsianSupport() { 
     final EnumSet<LocaleExtensions> ret_val = EnumSet.noneOf(LocaleExtensions.class) 
     ret_val.add(JP) 
     ret_val.add(CN) 
     return ret_val 
    } 
    public static EnumSet<LocaleExtensions> getHebrewSupport() { 
     final EnumSet<LocaleExtensions> ret_val = EnumSet.noneOf(LocaleExtensions.class) 
     ret_val.add(IL) 
     return ret_val 
    } 
    public static EnumSet<LocaleExtensions> getHinduSupport() { 
     final EnumSet<LocaleExtensions> ret_val = EnumSet.noneOf(LocaleExtensions.class) 
     ret_val.add(IN) 
     return ret_val 
    } 
    public static EnumSet<LocaleExtensions> getThaiSupport() { 
     final EnumSet<LocaleExtensions> ret_val = EnumSet.noneOf(LocaleExtensions.class) 
     ret_val.add(TH) 
     return ret_val 
    } 
    public static EnumSet<LocaleExtensions> getGreekSupport() { 
     final EnumSet<LocaleExtensions> ret_val = EnumSet.noneOf(LocaleExtensions.class) 
     ret_val.add(GR) 
     return ret_val 
    } 
} 

Ceci concerne évidemment une gamme de locales et il fonctionne correctement pour moi dans les mots de Berna La date avait été divisée en ce que java supporté par défaut vs icu4j puis mieux compris tout déplacé vers icu4j Je pense que le système de numérotation utilise toujours la moitié et demi et pourrait probablement être également commuté sur icu4j.

De toute façon c'est foutu loin d'où j'ai commencé qui convertissait nombre de caractères du latin en arabe méchant méchant truc - vous avez fini avec 01/01/2016 en arabe pas l'équivalent et l'année correcte laisse dire en Arabie que je pense est quelque chose comme 1354 ou dans le cas de Thai 2056 ou quoi que ce soit ....