2009-02-16 9 views
22

Tôi đang thiết kế một ứng dụng đa ngôn ngữ bằng các tệp .resx.Cách lập trình để nhận tất cả các ngôn ngữ có sẵn (trong các cụm vệ tinh)

Tôi có một vài tệp như GlobalStrings.resx, GlobalStrings.es.resx, GlobalStrings.en.resx, v.v. Khi tôi muốn sử dụng, tôi chỉ cần đặt Thread.CurrentThread.CurrentCulture.

Vấn đề: Tôi có một combobox với tất cả các ngôn ngữ có sẵn, nhưng tôi tải này bằng tay:

comboLanguage.Items.Add(CultureInfo.GetCultureInfo("en")); 
comboLanguage.Items.Add(CultureInfo.GetCultureInfo("es")); 

Tôi đã thử với

cmbLanguage.Items.AddRange(CultureInfo.GetCultures(CultureTypes.UserCustomCulture)); 

mà không cần bất kỳ sự thành công. Cũng cố gắng với tất cả các yếu tố trong CultureTypes, nhưng tôi chỉ nhận được một danh sách lớn với nhiều ngôn ngữ hơn mà tôi không sử dụng hoặc danh sách trống.

Có cách nào để chỉ nhận các ngôn ngữ được hỗ trợ không?

Trả lời

1

Sử dụng những gì Rune Grimstad nói tôi kết thúc với điều này:

string executablePath = Path.GetDirectoryName(Application.ExecutablePath); 
string[] directories = Directory.GetDirectories(executablePath); 
foreach (string s in directories) 
{ 
    try 
    { 
     DirectoryInfo langDirectory = new DirectoryInfo(s); 
     cmbLanguage.Items.Add(CultureInfo.GetCultureInfo(langDirectory.Name)); 
    } 
    catch (Exception) 
    { 

    } 
} 

hoặc một cách khác

int pathLenght = executablePath.Length + 1; 
foreach (string s in directories) 
{ 
    try 
    { 
     cmbLanguage.Items.Add(CultureInfo.GetCultureInfo(s.Remove(0, pathLenght))); 
    } 
    catch (Exception) 
    { 

    } 
} 

Tôi vẫn không nghĩ rằng đây là một ý tưởng tốt ...

+0

Tôi nghĩ đây là giải pháp duy nhất chúng tôi nhận được. Tôi ở trên cùng một con thuyền. – Jippers

+0

Liệu điều này cũng không nhận được các thư mục tài nguyên mà các phụ thuộc của bạn triển khai (nếu có)? Vì vậy, bạn có thể kết thúc với một số nền văn hóa bạn không hỗ trợ nhưng một số phụ thuộc của bạn làm. –

2

Tôi không chắc chắn về việc nhận các ngôn ngữ, có thể bạn có thể quét thư mục cài đặt của bạn cho các tệp dll, nhưng đặt ngôn ngữ của bạn thành ngôn ngữ không được hỗ trợ sẽ không thành vấn đề.

.NET sẽ dự phòng tài nguyên trung gian văn hóa nếu không tìm thấy tệp văn hóa cụ thể để bạn có thể chọn ngôn ngữ không được hỗ trợ một cách an toàn.

Miễn là bạn tự kiểm soát ứng dụng, bạn chỉ có thể lưu trữ các ngôn ngữ có sẵn trong cài đặt ứng dụng ở đâu đó. Chỉ cần một chuỗi bằng dấu phẩy với tên văn hóa nên đủ: "en, es"

37

Bạn có thể lập trình danh sách các nền văn hóa có sẵn trong ứng dụng của bạn

// Pass the class name of your resources as a parameter e.g. MyResources for MyResources.resx 
ResourceManager rm = new ResourceManager(typeof(MyResources)); 

CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); 
foreach (CultureInfo culture in cultures) 
{ 
    try 
    { 
     ResourceSet rs = rm.GetResourceSet(culture, true, false); 
     // or ResourceSet rs = rm.GetResourceSet(new CultureInfo(culture.TwoLetterISOLanguageName), true, false); 
     string isSupported = (rs == null) ? " is not supported" : " is supported"; 
     Console.WriteLine(culture + isSupported); 
    } 
    catch (CultureNotFoundException exc) 
    { 
     Console.WriteLine(culture + " is not available on the machine or is an invalid culture identifier."); 
    } 
} 
+0

Lưu ý rằng 'GlobalStrings.resx' sẽ được phát hiện trong' InvariantCulture'. – Hans

+5

Về cơ bản, điều này có buộc tải tất cả các cụm vệ tinh không? –

+0

@TaylorBuchanan có thể có thể gọi ReleaseAllResources sau đó (https://msdn.microsoft.com/en-us/library/system.resources.resourcemanager.releaseallresources(v=vs.110).aspx) và sau đó tải lại tài nguyên cụ thể –

1

dựa trên câu trả lời của @ hans-holzbart nhưng cố định không trả lại InvariantCulture quá và quấn thành một phương pháp tái sử dụng:

public static IEnumerable<CultureInfo> GetAvailableCultures() 
{ 
    List<CultureInfo> result = new List<CultureInfo>(); 

    ResourceManager rm = new ResourceManager(typeof(Resources)); 

    CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); 
    foreach (CultureInfo culture in cultures) 
    { 
    try 
    { 
     if (culture.Equals(CultureInfo.InvariantCulture)) continue; //do not use "==", won't work 

     ResourceSet rs = rm.GetResourceSet(culture, true, false); 
     if (rs != null) 
     result.Add(culture); 
    } 
    catch (CultureNotFoundException) 
    { 
     //NOP 
    } 
    } 
    return result; 
} 

sử dụng phương pháp này, bạn có thể nhận được một danh sách các chuỗi để thêm vào một số ComboBox với những điều sau đây:

public static ObservableCollection<string> GetAvailableLanguages() 
{ 
    var languages = new ObservableCollection<string>(); 
    var cultures = GetAvailableCultures(); 
    foreach (CultureInfo culture in cultures) 
    languages.Add(culture.NativeName + " (" + culture.EnglishName + " [" + culture.TwoLetterISOLanguageName + "])"); 
    return languages; 
} 
4

Đây sẽ là một trong những giải pháp trên cơ sở tuyên bố sau:
Mỗi lắp ráp vệ tinh cho một ngôn ngữ cụ thể được đặt tên giống nhau nhưng nằm trong một thư mục con được đặt tên theo văn hóa cụ thể, ví dụ: fr hoặc fr-CA.

public IEnumerable<CultureInfo> GetSupportedCulture() 
{ 
    //Get all culture 
    CultureInfo[] culture = CultureInfo.GetCultures(CultureTypes.AllCultures); 

    //Find the location where application installed. 
    string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); 

    //Return all culture for which satellite folder found with culture code. 
    return culture.Where(cultureInfo => Directory.Exists(Path.Combine(exeLocation, cultureInfo.Name))); 
} 
+1

Giải pháp này hoạt động trên dự án ASP.net MVC của tôi. Cảm ơn bạn !! –

+0

@JeffT. Có, nó là nhiều chung chung trong cách, tôi đã sử dụng phương pháp này cho dự án WPF của chúng tôi! –

+0

Xin lưu ý rằng điều này cũng sẽ trả về ngôn ngữ bất biến. – ooorndtski