2012-07-23 28 views
14

Có thể, khi chạy, để biết ngôn ngữ tài nguyên nào được nhúng trong ứng dụng của tôi?nhận các ngôn ngữ tài nguyên của ứng dụng

tức là sự hiện diện của các thư mục này:

values-en 
values-de 
values-fr 
... 
+1

Chỉ cần tò mò: nhưng theo mặc định, bạn sẽ không biết được ngôn ngữ nào ở đó vì bạn đã đặt chúng trong ứng dụng? –

+2

Bạn nói đúng!nhưng tôi đang tạo thư viện (vì vậy các nhà phát triển cuối có thể thêm ngôn ngữ) và tôi cần biết lập trình có bao nhiêu được nhúng – VinceFR

Trả lời

10

AssetManager.getLocales() thực sự là cách để làm điều này. Tuy nhiên, từ API công khai, mỗi AssetManager bạn tạo cũng có các tài nguyên khung công cụ được bao gồm trong đường dẫn tìm kiếm của nó ... vì vậy khi bạn gọi AssetManager.getLocales(), bạn cũng sẽ thấy bất kỳ ngôn ngữ nào là một phần của tài nguyên khung công tác. Không có cách nào để giải quyết vấn đề này với SDK, xin lỗi.

1

Bạn đang nói về điều này?

String language = Locale.getDefault().getDisplayLanguage(); 
+0

không, phương pháp này chỉ trả về ngôn ngữ mặc định, tôi muốn biết tất cả các ngôn ngữ được chỉ định trong thư mục res của tôi – VinceFR

2

những res-lang thực sự phụ thuộc vào miền địa phương, vì vậy bạn cần phải nhận được locale từ điện thoại và bạn có thể nhận được trong đó ngôn ngữ là nhận được hiển thị từ miền địa phương ..

Locale myPhoneLocale = Locale.getDefault(); 

Bạn có thể sau đó gọi getDisplayLanguage () để biết ngôn ngữ nào đang được hiển thị.

tham khảo: Locale

+0

như user370305, tôi muốn biết tất cả các ngôn ngữ có sẵn trong ứng dụng của tôi – VinceFR

1

thử gọi AssetManager.getLocales():

Lấy miền địa phương đó quản lý tài sản này chứa dữ liệu cho.

Hoặc bạn có thể thử xem bạn có thể lấy danh sách bằng cách sử dụng list() hay không.

Trả về mảng chuỗi của tất cả nội dung tại đường dẫn đã cho.

+0

getLocales() trả lại cho tôi ngôn ngữ khả dụng trên thiết bị của tôi, chứ không phải trên ứng dụng của tôi. danh sách (Chuỗi đường dẫn) không thực hiện thủ thuật – VinceFR

0

Bạn có nghĩa là:

String[] locales = getAssets().getLocales(); 

này sẽ cho phép bạn có được ngôn ngữ mà thiết bị của bạn có.

+1

Tôi không muốn có ngôn ngữ mà thiết bị của tôi có nhưng ngôn ngữ mà ứng dụng của tôi có – VinceFR

11

Điều này phức tạp vì ngay cả khi bạn có thư mục có tên values-de điều đó không có nghĩa là bạn có bất kỳ tài nguyên nào ở đó. Nếu bạn có string.xml trong values-de điều đó không có nghĩa là bạn có giá trị chuỗi ở đó.

giá trị:

<resources> 
    <string name="app_name">LocTest</string> 
    <string name="hello_world">Hello world!</string> 
    <string name="menu_settings">Settings</string> 
</resources> 

giá trị-de:

<resources> 
    <string name="hello_world">Hallo Welt!</string> 
</resources> 

Bạn có thể kiểm tra nếu một nguồn lực cho một miền địa phương cụ thể là khác nhau hơn so với mặc định:

DisplayMetrics metrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metrics); 
Resources r = getResources(); 
Configuration c = r.getConfiguration(); 
String[] loc = r.getAssets().getLocales(); 
for (int i = 0; i < loc.length; i++) { 
    Log.d("LOCALE", i + ": " + loc[i]); 

    c.locale = new Locale(loc[i]); 
    Resources res = new Resources(getAssets(), metrics, c); 
    String s1 = res.getString(R.string.hello_world); 
    c.locale = new Locale(""); 
    Resources res2 = new Resources(getAssets(), metrics, c); 
    String s2 = res2.getString(R.string.hello_world); 

    if(!s1.equals(s2)){ 
     Log.d("DIFFERENT LOCALE", i + ": "+ s1+" "+s2 +" "+ loc[i]); 
    } 
} 

Nó có một lỗi - bạn có thể kiểm tra một giá trị cho dù nó có bản dịch hay không.

Mã bẩn trên sẽ in cái gì đó như:

LOCALE (5667): 51: en_NZ LOCALE (5667): 52: uk_UA LOCALE (5667): 53: nl_BE LOCALE (5667): 54 : de_DE DIFFERENT LOCALE (5667): 54: Chào mừng bạn! Xin chào thế giới! de_DE LOCALE (5667): 55: ka_GE LOCALE (5667): 56: sv_SE LOCALE (5667): 57: bg_BG LOCALE (5667): 58: de_CH DIFFERENT LOCALE (5667): 58: Hallo Welt! Chào thế giới!de_CH LOCALE (5667): 59: fr_CH LOCALE (5667): 60: fi_FI

+0

đây phải là câu trả lời – injecteer

2

Lấy cảm hứng từ những câu trả lời trên, chúng tôi đã tạo ra một phương pháp đơn giản để có được ngôn ngữ tất cả các ứng dụng dựa trên bản dịch được cung cấp:

public static Set<String> getAppLanguages(Context ctx, int id) { 
    DisplayMetrics dm = ctx.getResources().getDisplayMetrics(); 
    Configuration conf = ctx.getResources().getConfiguration(); 
    Locale originalLocale = conf.locale; 
    conf.locale = Locale.ENGLISH; 
    final String reference = new Resources(ctx.getAssets(), dm, conf).getString(id); 

    Set<String> result = new HashSet<>(); 
    result.add(Locale.ENGLISH.getLanguage()); 

    for(String loc : ctx.getAssets().getLocales()){ 
    if(loc.isEmpty()) continue; 
    Locale l = Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT_WATCH ? new Locale(loc.substring(0, 2)) : Locale.forLanguageTag(loc); 
    conf.locale = l; 
    if(!reference.equals(new Resources(ctx.getAssets(), dm, conf).getString(id))) result.add(l.getLanguage()); 
    } 
    conf.locale = originalLocale; 
    return result; 
} 

nơi như id arg nên được sử dụng một R.string.some_message được cung cấp trong tất cả các bản dịch và chứa phân biệt rõ ràng văn bản, như "Do you really want to delete the object?"

có lẽ nó sẽ giúp ai đó ...

2

Đối với bất cứ ai sử dụng Gradle, tôi đã làm nó như vậy dưới nó đi qua tất cả strings.xml , lấy tên thư mục và tìm ra các ngôn ngữ từ đó. Nó cho biết thêm một String[] để BuildConfig mà bạn có thể truy cập như BuildConfig.TRANSLATION_ARRAY

task buildTranslationArray << { 
    def foundLocales = new StringBuilder() 
    foundLocales.append("new String[]{") 

    fileTree("src/main/res").visit { FileVisitDetails details -> 
     if(details.file.path.endsWith("strings.xml")){ 
      def languageCode = details.file.parent.tokenize('/').last().replaceAll('values-','').replaceAll('-r','-') 
      languageCode = (languageCode == "values") ? "en" : languageCode; 
      foundLocales.append("\"").append(languageCode).append("\"").append(",") 
     } 
    } 

    foundLocales.append("}") 
    //Don't forget to remove the trailing comma 
    def foundLocalesString = foundLocales.toString().replaceAll(',}','}') 
    android.defaultConfig.buildConfigField "String[]", "TRANSLATION_ARRAY", foundLocalesString 

} 
preBuild.dependsOn buildTranslationArray 

Vì vậy, sau khi nhiệm vụ trên xảy ra (trên prebuild) các BuildConfig.TRANSLATION_ARRAY có danh sách các miền địa phương.

Tôi không phải là chuyên gia Gradle/Groovy vì vậy điều này chắc chắn có thể là một chút neater.

Lý do - Tôi gặp phải quá nhiều vấn đề khi triển khai giải pháp của pawelzieba, tôi không có chuỗi đáng tin cậy nào để 'so sánh' vì các bản dịch đã được cộng đồng hóa. Cách dễ nhất sau đó là thực sự xem xét các thư mục giá trị-blah có sẵn.

0

Lấy cảm hứng với mã bởi @ Injecteer Tôi đã làm như sau:

cho danh sách các ngôn ngữ mà sự hỗ trợ ứng dụng, nó là cần thiết để vượt qua ngôn ngữ mặc định, vì nó không thể phát hiện

public static Map<String,String> getAppLanguages(Context context, String appDefaultLang) { 
    Map<String, String> listAppLocales = new LinkedHashMap<>(); 

    listAppLocales.put("default","Auto"); 

    DisplayMetrics metrics = new DisplayMetrics(); 
      Resources res = context.getResources(); 
    Configuration conf = res.getConfiguration(); 
    String[] listLocates = res.getAssets().getLocales(); 

    for (String locate : listLocates) { 

     conf.locale = new Locale(locate); 
     Resources res1 = new Resources(context.getAssets(), metrics, conf); 
     String s1 = res1.getString(R.string.title_itinerary); 
     String value = ucfirst(conf.locale.getDisplayName()); 

     conf.locale = new Locale(""); 
     Resources res2 = new Resources(context.getAssets(), metrics, conf); 
     String s2 = res2.getString(R.string.title_itinerary); 

     if (!s1.equals(s2)) { 
      listAppLocales.put(locate, value); 
     } else if (locate.equals(appDefaultLang)) { 
      listAppLocales.put(locate, value); 
     } 
    } 
    return listAppLocales; 
} 

kết quả là một danh sách map<key,value> các ngôn ngữ được hỗ trợ bởi ứng dụng, điều đầu tiên là vì nếu bạn muốn sử dụng để cư trú một listPreference

3

Lấy cảm hứng từ Mend giải pháp hak của tôi tạo ra một cái gì đó một chút bụi:

defaultConfig { 
     .... 

     def locales = ["en", "it", "pl", "fr", "es", "de", "ru"] 

     buildConfigField "String[]", "TRANSLATION_ARRAY", "new String[]{\""+locales.join("\",\"")+"\"}" 
     resConfigs locales 
    } 

Sau đó, trong Java sử dụng:

BuildConfig.TRANSLATION_ARRAY 

Advatages của phương pháp này:

  • apk nhỏ - resConfigs sẽ cắt ra nguồn lực từ các thư viện mà bạn không cần (một số có hàng trăm)
  • Nhanh - Không cần phải phân tích cấu hình tài nguyên
Các vấn đề liên quan