2010-03-26 31 views
78

Có cách nào gọn gàng để lấy một cá thể Locale từ "tên có lập trình" của nó như được trả về bởi phương thức toString() của Locale không? Một giải pháp rõ ràng và xấu xí sẽ phân tích cú pháp chuỗi và sau đó xây dựng một trường hợp Locale mới theo đó, nhưng có lẽ có một giải pháp tốt hơn/sẵn sàng cho điều đó?Làm thế nào để có được Locale từ biểu diễn String của nó trong Java?

Sự cần thiết là tôi muốn lưu trữ một số cài đặt cụ thể miền địa phương trong cơ sở dữ liệu SQL, kể cả Locales, nhưng sẽ rất xấu khi đặt các đối tượng Locale được tuần tự hóa ở đó. Tôi thà lưu trữ các biểu diễn String của họ, mà dường như khá đầy đủ chi tiết.

Trả lời

29

Xem Locale.getLanguage(), Locale.getCountry() ... Lưu trữ kết hợp này trong cơ sở dữ liệu thay vì "programatic name" ...
Khi bạn muốn xây dựng các Locale trở lại, sử dụng public Locale(String language, String country)

Dưới đây là một số mẫu mã :)

// 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); 
} 
+0

Suy nghĩ rất tốt, cảm ơn! –

+2

Điều này thậm chí sẽ không biên dịch. – Adrian

+1

@raj lý do tại sao sử dụng mã thông báo, Nếu Java cung cấp cho bạn các phương pháp sẵn sàng? ví dụ: toLocale (Chuỗi str). Vui lòng xem các ví dụ trong câu trả lời – VedX

3

Có vẻ như không phải là phương pháp tĩnh valueOf cho điều này, điều này hơi đáng ngạc nhiên.

Một cách khá xấu, nhưng đơn giản, sẽ lặp lại trên Locale.getAvailableLocales(), so sánh giá trị toString với giá trị của bạn.

Không tốt lắm, nhưng không yêu cầu phân tích cú pháp chuỗi. Bạn có thể điền trước một số Map của chuỗi vào miền địa phương và tra cứu chuỗi cơ sở dữ liệu của bạn trong Bản đồ đó.

+0

Ah, sự lặp lại có thể là một giải pháp khá hợp lý. Thật sự ngạc nhiên khi Locale không có phương pháp tĩnh cho việc này. –

+0

Các cá thể 'Locale' đã được định trước chỉ thể hiện một tập hợp con rất nhỏ của các ngôn ngữ hợp lệ. Nó không có nghĩa là hoàn thành. – BetaRide

1

Vâng, tôi sẽ lưu trữ thay vì một chuỗi nối của Locale.getISO3Language(), getISO3Country() và getVariant() như chìa khóa, mà sẽ cho phép tôi gọi sau Locale(String language, String country, String variant) constructor.

thực sự, dựa vào displayLanguage ngụ ý sử dụng ngôn ngữ của ngôn ngữ để hiển thị nó, làm cho ngôn ngữ phụ thuộc, ngược lại với mã ngôn ngữ iso. hơn

Như một ví dụ, en chốt locale sẽ có thể lưu trữ như

en_EN 
en_US 

và vân vân ...

7

Cũ câu hỏi với rất nhiều câu trả lời, nhưng đây là giải pháp:

+0

Ví dụ java2s khá tốt và cũng bao gồm biến thể xử lý –

+0

URL đầu tiên là tất cả những gì tôi muốn .. Cảm ơn –

103

Phương pháp trả về địa phương từ chuỗi tồn tại trong commons-lang thư viện: LocaleUtils.toLocale(localeAsString)

+2

LocaleUtils.toLocale không hỗ trợ các chuỗi như 'zh-Hans', 'pt-PT', v.v. –

+7

Nếu bạn có dấu gạch ngang '-' giữa các phần địa phương bạn đang xử lý với thẻ IETF BCP 47, nếu bạn đang sử dụng Java 7, bạn có thể sử dụng' Locale.forLanguageTag' –

1

Bởi vì tôi vừa thực hiện nó:

Trong Groovy/Grails nó sẽ là:

def locale = Locale.getAvailableLocales().find { availableLocale -> 
     return availableLocale.toString().equals(searchedLocale) 
} 
46

Kể từ Java 7 có phương pháp nhà máy Locale.forLanguageTag và phương pháp mẫu Locale.toLanguageTag sử dụng IETF language tags.

12

Câu trả lời này có thể hơi muộn, nhưng hóa ra việc phân tích cú pháp chuỗi không phải là xấu như OP được giả định. Tôi thấy nó khá đơn giản và ngắn gọn:

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

Tôi thử nghiệm này (trên Java 7) với tất cả các ví dụ được đưa ra trong Locale.toString() tài liệu: "en", "de_DE", "_GB", " en_US_WIN "," de__POSIX "," zh_CN_ # Hans "," zh_TW_ # Hant-x-java "và" th_TH_TH_ # u-nu-thai ".

CẬP NHẬT QUAN TRỌNG: Đây là không được khuyến khích để sử dụng trong Java 7+ theo documentation:

Đặc biệt, khách hàng phân tích đầu ra của toString sang ngôn ngữ, quốc gia, và các lĩnh vực biến thể có thể tiếp tục để làm như vậy (mặc dù đây là được khuyến khích mạnh mẽ), mặc dù trường biến thể sẽ có thêm thông tin trong đó nếu tập lệnh hoặc tiện ích có mặt.

Sử dụng Locale.forLanguageTag và Locale.toLanguageTag thay vào đó, hoặc nếu bạn phải, Locale.Builder.

+4

Java 7 'Locale.forLanguageTag' chỉ áp dụng cho các thẻ ngôn ngữ được mã hóa như được chỉ ra trong BCP 47 của IETF, với dấu gạch nối (' -'), không phải dấu gạch dưới ('_') như trong' '' '' 'của' Locale' 'phương thức –

+0

Bạn nói đúng. Vẫn cần phải có một số cách để chuyển đổi các đại diện Locale hiện có sang định dạng BCP47. Ý định của tôi là gợi ý rằng, 'Locale' không nên được lưu trữ trong dạng 'toString' của họ, nhưng trong dạng' toLanguageTag' của họ, có thể chuyển đổi thành 'Locale' dễ dàng hơn và chính xác hơn. – andy

+0

Phương pháp này không có một số trường hợp cạnh có thể khiến chỉ mục vượt quá giới hạn? – user2524908

3

Bạn có thể sử dụng tính năng này trên Android. Làm việc tốt cho tôi.

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; 
} 
21

Java cung cấp rất nhiều thứ với rất nhiều thực hiện đúng độ phức tạp có thể tránh được:

Ví dụ:

  1. này trả ms_MY.

    String key = ms-MY; 
    Locale locale = new Locale.Builder().setLanguageTag(key).build(); 
    
  2. này sẽ trở lại en_US

    String str = "en-US"; 
    Locale locale = LocaleUtils.toLocale(str); 
    System.out.println(locale.toString()); 
    
  3. Bạn cũng có thể sử dụng nhà thầu địa phương.

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

Vui lòng kiểm tra này LocaleUtils và điều này Locale để khám phá phương pháp hơn.

+1

LocaleUtils.toLocale (localeStringRepresentation) thực hiện công việc gọn gàng. Ngoài ra nếu bạn thấy việc thực hiện phương pháp này, nó là khá toàn diện! – Dish

6

Lựa chọn 1:

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

Phương án 2:

Locale.forLanguageTag("en-US") 

Xin lưu ý Lựa chọn 1 là "gạch" giữa ngôn ngữ và quốc gia, và Lựa chọn 2 là " dấu gạch ngang ".

Các vấn đề liên quan