Java'daki String gösteriminden Locale nasıl alınır?


109

Locale yönteminin döndürdüğü şekliyle "programatik adından" bir Locale örneğini almanın düzgün bir yolu var mı toString()? Açık ve çirkin bir çözüm, String'i ayrıştırmak ve ardından buna göre yeni bir Locale örneği oluşturmak olabilir, ancak bunun için daha iyi bir yol / hazır çözüm olabilir mi?

İhtiyaç duyduğum şey, yerel ayarların kendileri de dahil olmak üzere yerel ayarlara özgü bazı ayarları bir SQL veritabanında depolamak istememdir, ancak oraya serileştirilmiş Locale nesnelerini koymak çirkin olurdu. Ayrıntılı olarak oldukça yeterli görünen String temsillerini saklamayı tercih ederim.

Yanıtlar:


34

Bkz Locale.getLanguage(), Locale.getCountry()yerine veritabanında bu kombinasyonu Mağaza ... "programatic name"...
sen Yerel geri inşa etmek istediğinizde, kullanılmasıpublic Locale(String language, String country)

İşte örnek bir kod :)

// 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
Bu derlenmez bile.
Adrian

1
@raj neden tokenizer kullanmalı, Java size hazır yöntemler veriyorsa? örneğin toLocale (String str). Lütfen
cevaptaki

9
Locale.forLanguageTag (String) kullanmalısınız
Rian

126

Dizeden yerel değeri döndüren yöntem, commons-lang kitaplığında mevcuttur: LocaleUtils.toLocale(localeAsString)


2
LocaleUtils.toLocale, "zh-Hans", "pt-PT" gibi dizeleri desteklemiyor
Hans van Dodewaard

10
-Yerel ayarlar arasında bir tire varsa, IETF BCP 47 etiketi ile uğraşıyorsanız, Java 7 kullanıyorsanız kullanabilirsinizLocale.forLanguageTag
Jaime Hablutzel

59

Java 7'den beri, IETF dil etiketlerini kullanan fabrika yöntemi Locale.forLanguageTagve örnek yöntemi vardır .Locale.toLanguageTag


8
Sadece Locale.forLanguageTagIETF yerel dizelerini (ie en-US) çalıştırdığını ve ISO yerel dizeleri (yani en_US) ile çalışmadığını vurgulamak istiyorum
Fabian

34
  1. Java, uygun uygulama ile pek çok şey sağlar, çok fazla karmaşıklık önlenebilir. Bu ms_MY döndürür .

    String key = "ms-MY";
    Locale locale = new Locale.Builder().setLanguageTag(key).build();
  2. Apache Commons, LocaleUtilsbir dizgi temsilini çözümlemeye yardımcı olmalıdır. Bu en_US döndürür

    String str = "en-US";
    Locale locale =  LocaleUtils.toLocale(str);
    System.out.println(locale.toString());
  3. Yerel kurucuları da kullanabilirsiniz.

    // 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)

Daha fazla yöntem keşfetmek için lütfen bu LocaleUtils'i ve bu Yerel Ayarı kontrol edin .


1
LocaleUtils.toLocale (localeStringRepresentation) işi düzgün bir şekilde yapar. Ayrıca bu yöntemin uygulanmasını görürseniz oldukça kapsamlı!
Yemek

15

Seçenek 1 :

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

Seçenek 2 :

Locale.forLanguageTag("en-US")

Lütfen 1. Seçeneğin dil ve ülke arasında "alt çizgi" ve 2. Seçeneğin "kısa çizgi" olduğunu unutmayın.


Çağrı, API seviyesi 21 gerektirir (şu anki dakika 17): java.util.Locale # forLanguageTag
Vlad

12

Bu cevap biraz geç olabilir, ancak dizeyi çözümlemenin OP'nin varsaydığı kadar çirkin olmadığı ortaya çıktı. Bunu oldukça basit ve öz buldum:

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]);
}

Bunu (Java 7'de) Locale.toString () belgelerinde verilen tüm örneklerle test ettim: "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "zh_CN_ # Hans", "zh_TW_ # Hant-x-java "ve" th_TH_TH_ # u-nu-thai ".

ÖNEMLİ GÜNCELLEME : Aşağıdaki belgelere göre Java 7+ ile kullanılması tavsiye edilmez :

Özellikle, toString'in çıktısını dil, ülke ve varyant alanlarına ayrıştıran istemciler bunu yapmaya devam edebilir (bu kesinlikle önerilmez ), ancak komut dosyası veya uzantılar varsa varyant alanında ek bilgiler olacaktır.

Bunun yerine Locale.forLanguageTag ve Locale.toLanguageTag kullanın veya gerekiyorsa Locale.Builder kullanın.


5
Java 7 Locale.forLanguageTagyalnızca IETF'in BCP 47'sinde belirtildiği gibi kodlanmış dil etiketleri için geçerlidir , 'nin yönteminin dönüşünde olduğu gibi bir kısa çizgi ( -), alt çizgi ( _) değilLocaletoString
Jaime Hablutzel

1
Haklısın. Mevcut Yerel ayar temsillerini BCP47 biçimine dönüştürmenin hala bir yolu olması gerekiyor. Niyetim, ileriye doğru, formlarında değil, daha kolay ve doğru bir şekilde geri dönüştürülebilen formlarında Localesaklanmalarını önermekti . toStringtoLanguageTagLocale
andy

Bu yöntemin, endeksin sınır dışı olmasına neden olabilecek birkaç uç durumu olmaz mıydı?
user2524908

@ user2524908: Elemanlarına erişmeden önce her zaman dizi uzunluğunu test ettiği için öyle düşünmüyorum. Çözüm, düzgün çalışmadığı, ancak "sınırların dışında indekslemediği" birçok uç duruma sahip olabilir
MestreLion

9

Projenizde Spring framework kullanıyorsanız şunları da kullanabilirsiniz:

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

Dokümantasyon :

Verilen String temsilini bir Yerel Ayara ayrıştırın


Bu konudaki doktorlar bunun özellikle Locale#toString()mükemmelin tersi olduğunu söylüyor ! :)
jocull


3

Bunun için statik bir valueOfyöntem yok gibi görünüyor , bu biraz şaşırtıcı.

Oldukça çirkin ama basit bir yol, Locale.getAvailableLocales()onların toStringdeğerlerini sizin değerinizle karşılaştırarak tekrarlamak olabilir .

Çok hoş değil, ama dize ayrıştırması gerekmez. Bir MapDizeyi Yerel Ayarlara önceden doldurabilir ve bu Harita'daki veritabanı dizinize bakabilirsiniz.


Ah, yineleme oldukça makul bir çözüm olabilir. Nitekim, Locale'in bunun için statik bir metodu olmaması şaşırtıcı.
Joonas Pulakka

Önceden tanımlanmış Localeörnekler, yalnızca geçerli yerel ayarların çok küçük bir alt kümesini temsil eder. Hiçbir şekilde tamamlanmadı.
BetaRide

3

Bunu Android'de kullanabilirsiniz. Benim için iyi çalışıyor.

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

Eh, bunun yerine bir dize concatenation saklamak istiyorum Locale.getISO3Language(), getISO3Country()ikincisi çağrı için bana izin ve anahtar olarak getVariant (), Locale(String language, String country, String variant)yapıcısı.

gerçekten, displayLanguage'a güvenmek onu göstermek için locale dilini kullanmayı gerektirir, bu da onu iso dil kodunun tersine yerel ayarı bağımlı kılar.

Örnek olarak, en yerel ayar anahtarı şu şekilde saklanabilir

en_EN
en_US

ve bunun gibi ...


1

Çünkü onu yeni uyguladım:

İçinde Groovy/ Grailsolacaktır:

def locale = Locale.getAvailableLocales().find { availableLocale ->
      return availableLocale.toString().equals(searchedLocale)
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.