2012-02-28 30 views
41

Vì vậy, tôi muốn nhận được giá trị của một chuỗi trong một số miền địa phương bất kể cài đặt miền địa phương hiện tại của thiết bị/ứng dụng. Tôi nên làm như thế nào?cách nhận chuỗi từ các miền địa phương khác nhau trong Android?

Về cơ bản những gì tôi cần là một chức năng getString(int id, String locale) hơn getString(int id)

Làm thế nào tôi có thể làm điều đó?

Cảm ơn

+1

bạn đã thực sự triển khai điều này như thế nào ?? Vui lòng trả lời :) –

+0

làm câu trả lời được chấp nhận –

+0

là 'ResourceBundle' nghĩa vụ phải tham chiếu đến nội dung ?? hoặc họ có thể truy cập thư mục res của chúng tôi không? –

Trả lời

80

LƯU Ý Nếu API tối thiểu của bạn là 17+, đi thẳng xuống đáy của câu trả lời này. Nếu không, hãy đọc tiếp ...

Nếu bạn có thư mục res khác nhau cho miền địa phương khác nhau, bạn có thể làm một cái gì đó như thế này:

Configuration conf = getResources().getConfiguration(); 
conf.locale = new Locale("pl"); 
DisplayMetrics metrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metrics); 
Resources resources = new Resources(getAssets(), metrics, conf); 
String str = resources.getString(id); 

Ngoài ra, bạn có thể chỉ cần khởi động lại hoạt động của bạn sử dụng phương pháp này được trỏ đến bởi @ jyotiprakash.

LƯU Ý Gọi hàm tạo Resources như thế này sẽ thay đổi nội dung nào đó trong Android. Bạn sẽ phải gọi hàm tạo với ngôn ngữ gốc của bạn để lấy lại mọi thứ.

EDIT Một hơi khác nhau (và hơi bụi) công thức để lấy nguồn từ một miền địa phương cụ thể là:

Resources res = getResources(); 
Configuration conf = res.getConfiguration(); 
Locale savedLocale = conf.locale; 
conf.locale = desiredLocale; // whatever you want here 
res.updateConfiguration(conf, null); // second arg null means don't change 

// retrieve resources from desired locale 
String str = res.getString(id); 

// restore original locale 
conf.locale = savedLocale; 
res.updateConfiguration(conf, null); 

Tính đến mức API 17, bạn nên sử dụng conf.setLocale() thay vì trực tiếp thiết conf.locale. Điều này sẽ cập nhật chính xác hướng bố cục của cấu hình nếu bạn tình cờ chuyển đổi giữa các ngôn ngữ từ phải sang trái và từ trái sang phải. (Hướng bố cục được giới thiệu trong 17.)

Không có điểm khi tạo đối tượng Configuration mới (như @Nulano gợi ý trong nhận xét) vì gọi updateConfiguration sẽ thay đổi cấu hình ban đầu thu được bằng cách gọi res.getConfiguration().

Tôi sẽ ngần ngại đưa gói này vào phương thức getString(int id, String locale) nếu bạn sắp tải một số tài nguyên chuỗi cho một ngôn ngữ. Thay đổi ngôn ngữ (sử dụng một trong hai công thức) các cuộc gọi cho khuôn khổ để làm rất nhiều công việc rebinding tất cả các nguồn lực. Tốt hơn hết là cập nhật miền địa phương một lần, truy xuất mọi thứ bạn cần và sau đó đặt lại ngôn ngữ.

EDIT (Nhờ @Mygod):

Nếu mức API tối thiểu của bạn là 17+, có một cách tiếp cận tốt hơn nhiều, như trong this answer trên thread khác. Ví dụ, bạn có thể tạo nhiều Resource đối tượng, một cho mỗi miền địa phương bạn cần, với:

@NonNull Resources getLocalizedResources(Context context, Locale desiredLocale) { 
    Configuration conf = context.getResources().getConfiguration(); 
    conf = new Configuration(conf); 
    conf.setLocale(desiredLocale); 
    Context localizedContext = context.createConfigurationContext(conf); 
    return localizedContext.getResources(); 
} 

Sau đó chỉ cần lấy tài nguyên mà bạn thích từ các địa phương Resource đối tượng được trả về bởi phương pháp này. Không cần phải đặt lại bất cứ điều gì khi bạn đã truy xuất tài nguyên.

+1

Bạn không nên tạo cấu hình mới từ cấu hình được trả về bởi 'getResources(). GetConfiguration()'? Theo GrepCode, nó trả về một cá thể cục bộ được lưu trữ trong phần Tài nguyên. Thay đổi lĩnh vực miền địa phương sau đó có lẽ là lý do thực sự Android bị nhầm lẫn. Bạn có lẽ nên làm 'conf = new Configuration (conf);' (để nhân bản cấu hình trả về) giữa dòng đầu tiên và dòng thứ hai. – Nulano

+0

@Nulano - Thật đáng thử, nhưng tôi không nghĩ đó là nguồn gốc của lý do tại sao Android bị "nhầm lẫn" (như bạn đặt nó). Nhìn vào nguồn của hàm tạo 'Resources' và bạn sẽ thấy rằng việc tạo một đối tượng' Tài nguyên' mới như thế này thay đổi mọi thứ sâu trong tài sản của quá trình (rõ ràng là một singleton). Một khi tôi nhận ra rằng mọi thứ sẽ cần phải được thiết lập lại, tôi không bận tâm theo dõi chính xác lý do tại sao. Một cách tiếp cận khác (có lẽ là sạch hơn) để xây dựng một đối tượng 'Resources' mới là gọi' resources.updateConfiguration (conf, null) 'sau khi thay đổi miền địa phương. –

+0

@TedHopp: Xin chào Ngài, xin hãy xem [câu hỏi] của tôi (http://stackoverflow.com/q/40398528). Tôi thực sự sẽ đánh giá cao nếu bạn có thể giúp đỡ. Cảm ơn ... :) –

-9

Điều bạn đang tìm kiếm được gọi là lớp ResourceBundle. Đây là liên kết:

Google Docs for ResourceBundle

+6

-1, không giải thích –

+0

Câu trả lời này không có ý nghĩa bởi vì nó trộn lẫn táo và cam. Khi bạn đặt một chuỗi vào 'res/values ​​/ strings.xml' như câu trả lời này cho thấy, giá trị là ** not ** được truy cập thông qua' ResourceBundle'. Thay vào đó nó được truy cập thông qua một đối tượng 'Resources' cụ thể của Android thu được từ một' Context'. 'ResourceBundle' không liên quan đến hoạt động này. Hơn nữa, trường 'R.string.my_message' là một giá trị' int', và phương thức 'ResourceBundle.getString()' lấy một đối số 'String', vì vậy ví dụ mã là gây hiểu lầm ở mức tốt nhất. Cuối cùng, không có vai trò cho 'Locale' trong câu trả lời này (vấn đề cốt lõi). –

+0

@TedHopp - bạn nói đúng, đó là một rắm não. Đã xóa thông tin xung đột. – BitBank

8

Đây là phiên bản kết hợp của các phương pháp được mô tả bởi Ted Hopp. Bằng cách này, các mã làm việc cho bất kỳ phiên bản Android:

public static String getLocaleStringResource(Locale requestedLocale, int resourceId, Context context) { 
    String result; 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // use latest api 
     Configuration config = new Configuration(context.getResources().getConfiguration()); 
     config.setLocale(requestedLocale); 
     result = context.createConfigurationContext(config).getText(resourceId).toString(); 
    } 
    else { // support older android versions 
     Resources resources = context.getResources(); 
     Configuration conf = resources.getConfiguration(); 
     Locale savedLocale = conf.locale; 
     conf.locale = requestedLocale; 
     resources.updateConfiguration(conf, null); 

     // retrieve resources from desired locale 
     result = resources.getString(resourceId); 

     // restore original locale 
     conf.locale = savedLocale; 
     resources.updateConfiguration(conf, null); 
    } 

    return result; 
} 

Cách sử dụng Ví dụ:

String englishName = getLocaleStringResource(new Locale("en"), id, R.string.name); 

Note

Như đã nêu trong câu trả lời ban đầu, nó có thể là hiệu quả hơn để thay thế nhiều cuộc gọi của mã ở trên với một thay đổi cấu hình đơn và nhiều cuộc gọi resources.getString().

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