วิธีรับ Locale จากการแสดงสตริงใน Java


109

มีวิธีที่เป็นระเบียบในการรับอินสแตนซ์Localeจาก "ชื่อโปรแกรม" ตามที่ส่งคืนโดยtoString()วิธีของ Locale หรือไม่ วิธีแก้ปัญหาที่ชัดเจนและน่าเกลียดคือการแยกวิเคราะห์ String แล้วสร้างอินสแตนซ์ Locale ใหม่ตามนั้น แต่อาจมีวิธีที่ดีกว่า / พร้อมสำหรับสิ่งนั้น

ความต้องการคือฉันต้องการจัดเก็บการตั้งค่าเฉพาะบางภาษาในฐานข้อมูล SQL รวมถึง Locales ด้วยตัวเอง แต่มันจะน่าเกลียดที่จะใส่วัตถุ Locale แบบอนุกรมไว้ที่นั่น ฉันอยากจะจัดเก็บการแสดงสตริงของพวกเขาซึ่งดูเหมือนจะมีรายละเอียดเพียงพอ

คำตอบ:


34

ดูLocale.getLanguage(), Locale.getCountry()... เก็บรวมกันนี้ในฐานข้อมูลแทนการที่"programatic name"...
เมื่อคุณต้องการที่จะสร้างสถานที่เกิดเหตุกลับมาใช้public Locale(String language, String country)

นี่คือโค้ดตัวอย่าง :)

// May contain simple syntax error, I don't have java right now to test..
// but this is a bigger picture for your algo...
public String localeToString(Locale l) {
    return l.getLanguage() + "," + l.getCountry();
}

public Locale stringToLocale(String s) {
    StringTokenizer tempStringTokenizer = new StringTokenizer(s,",");
    if(tempStringTokenizer.hasMoreTokens())
    String l = tempStringTokenizer.nextElement();
    if(tempStringTokenizer.hasMoreTokens())
    String c = tempStringTokenizer.nextElement();
    return new Locale(l,c);
}

3
สิ่งนี้จะไม่รวบรวมด้วยซ้ำ
Adrian

1
@raj ทำไมต้องใช้ tokenizer ถ้า Java มีวิธีการพร้อม? เช่น toLocale (String str) โปรดดูตัวอย่างในคำตอบ
VdeX

9
คุณควรใช้ Locale.forLanguageTag (String)
Rian

126

วิธีที่ส่งคืนโลแคลจากสตริงที่มีอยู่ในไลบรารี commons-lang: LocaleUtils.toLocale(localeAsString)


2
LocaleUtils.toLocale ไม่รองรับสตริงเช่น 'zh-Hans', 'pt-PT' เป็นต้น
Hans van Dodewaard

10
หากคุณมียัติภังค์-ระหว่างส่วนโลแคลคุณกำลังจัดการกับแท็ก IETF BCP 47 หากคุณใช้ Java 7 คุณสามารถใช้ได้Locale.forLanguageTag
Jaime Hablutzel

59

ตั้งแต่ Java 7 มีวิธีโรงงานLocale.forLanguageTagและวิธีการเช่นLocale.toLanguageTagการใช้แท็กภาษา IETF


8
เพียงต้องการเน้นว่าใช้Locale.forLanguageTagงานสตริงโลแคล IETF (เช่นen-US) และไม่ทำงานกับสตริงโลแคล ISO (เช่นen_US)
Fabian

34
  1. Java มีหลายสิ่งหลายอย่างที่สามารถหลีกเลี่ยงการใช้งานที่ซับซ้อนได้อย่างเหมาะสม นี้จะส่งกลับms_MY

    String key = "ms-MY";
    Locale locale = new Locale.Builder().setLanguageTag(key).build();
    
  2. Apache Commons LocaleUtilsต้องช่วยแยกวิเคราะห์การแสดงสตริง สิ่งนี้จะคืนค่าen_US

    String str = "en-US";
    Locale locale =  LocaleUtils.toLocale(str);
    System.out.println(locale.toString());
    
  3. คุณยังสามารถใช้ตัวสร้างโลแคล

    // Construct a locale from a language code.(eg: en)
    new Locale(String language)
    // Construct a locale from language and country.(eg: en and US)
    new Locale(String language, String country)
    // Construct a locale from language, country and variant.
    new Locale(String language, String country, String variant)
    

โปรดตรวจสอบLocaleUtilsและLocaleนี้เพื่อสำรวจวิธีการเพิ่มเติม


1
LocaleUtils.toLocale (localeStringRepresentation) ทำงานอย่างเรียบร้อย นอกจากนี้หากคุณเห็นการใช้งานวิธีนี้มันค่อนข้างครอบคลุม!
Dish

15

ตัวเลือกที่ 1 :

org.apache.commons.lang3.LocaleUtils.toLocale("en_US")

ทางเลือกที่ 2:

Locale.forLanguageTag("en-US")

โปรดทราบว่าตัวเลือกที่ 1คือ "ขีดล่าง" ระหว่างภาษาและประเทศและตัวเลือกที่ 2คือ "เส้นประ"


การโทรต้องใช้ API ระดับ 21 (ขั้นต่ำปัจจุบันคือ 17): java.util.Locale # forLanguageTag
Vlad

12

คำตอบนี้อาจจะช้าไปหน่อย แต่ปรากฎว่าการแยกวิเคราะห์สตริงนั้นไม่น่าเกลียดอย่างที่ OP สันนิษฐาน ฉันพบว่ามันค่อนข้างง่ายและรัดกุม:

public static Locale fromString(String locale) {
    String parts[] = locale.split("_", -1);
    if (parts.length == 1) return new Locale(parts[0]);
    else if (parts.length == 2
            || (parts.length == 3 && parts[2].startsWith("#")))
        return new Locale(parts[0], parts[1]);
    else return new Locale(parts[0], parts[1], parts[2]);
}

ฉันทดสอบสิ่งนี้ (บน Java 7) กับตัวอย่างทั้งหมดที่ให้ไว้ในเอกสาร Locale.toString (): "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "zh_CN_ # Hans", "zh_TW_ # Hant-x-java "และ" th_TH_TH_ # u-nu-thai "

การอัปเดตที่สำคัญ : ไม่แนะนำให้ใช้ใน Java 7+ ตามเอกสารประกอบ :

โดยเฉพาะอย่างยิ่งไคลเอ็นต์ที่แยกวิเคราะห์ผลลัพธ์ของ toString เป็นช่องภาษาประเทศและตัวแปรสามารถดำเนินการต่อไปได้ (แม้ว่าจะไม่สนับสนุนอย่างยิ่ง ) แม้ว่าฟิลด์ตัวแปรจะมีข้อมูลเพิ่มเติมอยู่หากมีสคริปต์หรือส่วนขยาย

ใช้ Locale.forLanguageTag และ Locale.toLanguageTag แทนหรือถ้าคุณต้อง Locale.Builder


5
Java 7 Locale.forLanguageTagใช้เฉพาะสำหรับแท็กภาษาเข้ารหัสตามที่ระบุไว้ใน IETF ของ BCP 47 มียัติภังค์ ( -) ไม่ได้ขีดล่าง ( _) ในขณะที่การกลับมาของLocale's toStringวิธีการ
ไจ Hablutzel

1
คุณถูก. ยังคงต้องมีวิธีบางอย่างในการแปลงการแสดงสถานที่ที่มีอยู่เป็นรูปแบบ BCP47 ความตั้งใจของฉันคือแนะนำว่าต่อไปLocaleไม่ควรเก็บไว้ในtoStringรูปแบบของพวกเขาแต่อยู่ในtoLanguageTagรูปแบบของพวกเขาซึ่งสามารถแปลงกลับเป็นLocaleได้ง่ายและถูกต้องมากขึ้น
andy

วิธีนี้จะไม่มีขอบกรณีจำนวนมากที่อาจทำให้ดัชนีอยู่นอกขอบเขตหรือไม่?
user2524908

@ user2524908: ฉันไม่คิดอย่างนั้นเพราะเขามักจะทดสอบความยาวอาร์เรย์ก่อนเข้าถึงองค์ประกอบ วิธีแก้ปัญหาอาจมีหลายกรณีที่ไม่สามารถทำงานได้อย่างถูกต้อง แต่ไม่ใช่ "ดัชนีนอกขอบเขต"
MestreLion

9

หากคุณใช้ Spring framework ในโปรเจ็กต์ของคุณคุณยังสามารถใช้:

org.springframework.util.StringUtils.parseLocaleString("en_US");

เอกสารประกอบ :

แยกวิเคราะห์การแสดงสตริงที่กำหนดให้เป็นโลแคล


เอกสารเกี่ยวกับเรื่องนี้บอกว่ามันเป็นสิ่งที่ตรงกันข้ามโดยเฉพาะLocale#toString()- สมบูรณ์แบบ! :)
jocull

8

คำถามเก่าที่มีคำตอบมากมาย แต่นี่คือคำตอบเพิ่มเติม:


ตัวอย่าง java2s ค่อนข้างดีและยังรวมถึงการจัดการที่แตกต่างกันด้วย
Paul Gregoire

URL แรกคือทั้งหมดที่ฉันต้องการ .. ขอบคุณ
KD

3

ดูเหมือนจะไม่มีvalueOfวิธีคงที่สำหรับสิ่งนี้ซึ่งน่าแปลกใจเล็กน้อย

วิธีหนึ่งที่ค่อนข้างน่าเกลียด แต่เรียบง่ายคือการทำซ้ำLocale.getAvailableLocales()โดยเปรียบเทียบtoStringค่าของมันกับคุณค่าของคุณ

ไม่ค่อยดีนัก แต่ไม่จำเป็นต้องมีการแยกวิเคราะห์สตริง คุณสามารถเติมข้อมูลMapสตริงเป็นสถานที่ไว้ล่วงหน้าและค้นหาสตริงฐานข้อมูลของคุณในแผนที่นั้น


อ่าการทำซ้ำอาจเป็นวิธีแก้ปัญหาที่สมเหตุสมผล แน่นอนว่ามันน่าแปลกใจที่ Locale ไม่มีวิธีการคงที่สำหรับสิ่งนี้
Joonas Pulakka

Localeอินสแตนซ์ที่กำหนดไว้ล่วงหน้าแสดงถึงชุดย่อยที่มีขนาดเล็กมากของโลแคลที่ถูกต้องเท่านั้น มันไม่สมบูรณ์
BetaRide

3

คุณสามารถใช้สิ่งนี้บน Android ใช้ได้ดีสำหรับฉัน

private static final Pattern localeMatcher = Pattern.compile
        ("^([^_]*)(_([^_]*)(_#(.*))?)?$");

public static Locale parseLocale(String value) {
    Matcher matcher = localeMatcher.matcher(value.replace('-', '_'));
    return matcher.find()
            ? TextUtils.isEmpty(matcher.group(5))
                ? TextUtils.isEmpty(matcher.group(3))
                    ? TextUtils.isEmpty(matcher.group(1))
                        ? null
                        : new Locale(matcher.group(1))
                    : new Locale(matcher.group(1), matcher.group(3))
                : new Locale(matcher.group(1), matcher.group(3),
                             matcher.group(5))
            : null;
}

1

ดีฉันจะเก็บแทน concatenation สตริงLocale.getISO3Language(), getISO3Country()และ getVariant () เป็นกุญแจสำคัญที่จะช่วยให้ฉันโทรหลังLocale(String language, String country, String variant)คอนสตรัค

แท้จริงแล้วการใช้ displayLanguage หมายถึงการใช้ภาษาของโลแคลเพื่อแสดงซึ่งทำให้มันขึ้นอยู่กับโลแคลตรงกันข้ามกับรหัสภาษา iso

ตัวอย่างเช่นคีย์ en locale จะถูกเก็บไว้เป็น

en_EN
en_US

และอื่น ๆ ...


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.