如何按文化加载 ResourceDictionary
How to load a ResourceDictionary by culture
欢迎使用我在此建议的方法以外的任何其他方法。
我有一个项目,我正在尝试使用 XAML 资源字典来管理本地化。为了避免必须在我所有的代码隐藏文件上实现本地化加载,我编写了以下转换器:
public class LocalizationConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string filePrefix = value as string;
string language;
// Filter so only supported languages are let through
switch (culture.Name.Substring(0, 2))
{
case "da":
language = "da";
break;
default:
language = "en";
break;
}
return filePrefix + "." + language + ".xaml";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
如何编写 XAML 加载语言词典,将文件前缀作为值?
第一步是卸载当前的语言资源字典,否则你将拥有大量合并的资源字典,它们什么都不做。
最好将所有语言文件放在一个文件夹中,如下所示:
现在,考虑以下方法:
public static void ReplaceLanguage(Uri source)
{
//The name of the folder where the languages are contained (could be a parameter)
string folder = "languages";
if (source == null)
return;
ResourceDictionary dictionary;
try
{
dictionary = (ResourceDictionary)Application.LoadComponent(source);
}
catch (IOException)
{
//resource file doesn't exist.
return;
}
//Remove current resource from the merged dictionaries
var currentResource = Application.Current.Resources.MergedDictionaries.FirstOrDefault(x => x.Source != null && x.Source.ToString().Contains(folder));
if (currentResource != null)
Application.Current.Resources.MergedDictionaries.Remove(currentResource);
//Add the new resource to the dictionary
Application.Current.Resources.MergedDictionaries.Add(dictionary);
}
这个方法的作用是:
- 从 URI 源加载资源字典。
- 根据文件夹名称查找并删除当前语言词典。
- 将新词典添加到合并的词典列表中。
要获取语言文件的 Uri,您可以这样做:
Uri languagePath = new Uri(string.Format("/YourAppNamespace;component/resources/languages/{0}.xaml", language), UriKind.Relative);
以上代码假定您的语言文件命名为 de.xaml 或 en.xaml.
获得 Uri 后,您需要做的就是调用 ReplaceLanguage 方法。
好的。我最终使用静态方法来加载我的本地化。方法如下:
/// <summary>
/// Loads localization based on culture.
/// </summary>
/// <param name="dictionary">The dictionary to load localization to</param>
/// <param name="basePath">The base path of the localization files. See remarks for further info.</param>
/// <param name="cultureInfo">Culture to load localization for.</param>
/// <remarks>
/// The loaded localization file will be <code>basenameLocalization.languagecode.xaml</code>
/// (e.g. <code>MainWindowLocalization.de.xaml</code>), or <code>basenameLocalization.languagecode.xaml</code>
/// for the default localization.
/// </remarks>
internal static void ReplaceLocalization(
ResourceDictionary dictionary,
string basePath,
CultureInfo cultureInfo)
{
ResourceDictionary dict = new ResourceDictionary();
// Clean out old localization
ResourceDictionary oldLocalization = null;
foreach (ResourceDictionary d in dictionary.MergedDictionaries)
{
if (d.Source.OriginalString.StartsWith(basePath + "Localization."))
{
oldLocalization = d;
}
}
if (oldLocalization != null)
{
dictionary.MergedDictionaries.Remove(oldLocalization);
}
// Get thee language
string language = "";
if (cultureInfo.Name != null)
{
// We only need to look at the first two characters to determine language
language = cultureInfo.Name.Substring(0, 2);
}
bool defaultLanguage = false;
// Filter languages such that only supported languages are loadable,
// and any other defaults to the default/neutral language.
switch (language)
{
case "da":
break;
default:
defaultLanguage = true;
break;
}
// Construct the URI
string uri;
if (defaultLanguage)
{
uri = basePath + "Localization.xaml";
}
else
{
uri = basePath + "Localization." + language + ".xaml";
}
// Load new dictionary
dict.Source = new Uri(uri, UriKind.Relative);
dictionary.MergedDictionaries.Add(dict);
}
这也适用于在运行时更改语言。
请评论任何问题,以便我改进我的回答。
欢迎使用我在此建议的方法以外的任何其他方法。
我有一个项目,我正在尝试使用 XAML 资源字典来管理本地化。为了避免必须在我所有的代码隐藏文件上实现本地化加载,我编写了以下转换器:
public class LocalizationConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string filePrefix = value as string;
string language;
// Filter so only supported languages are let through
switch (culture.Name.Substring(0, 2))
{
case "da":
language = "da";
break;
default:
language = "en";
break;
}
return filePrefix + "." + language + ".xaml";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
如何编写 XAML 加载语言词典,将文件前缀作为值?
第一步是卸载当前的语言资源字典,否则你将拥有大量合并的资源字典,它们什么都不做。
最好将所有语言文件放在一个文件夹中,如下所示:
现在,考虑以下方法:
public static void ReplaceLanguage(Uri source)
{
//The name of the folder where the languages are contained (could be a parameter)
string folder = "languages";
if (source == null)
return;
ResourceDictionary dictionary;
try
{
dictionary = (ResourceDictionary)Application.LoadComponent(source);
}
catch (IOException)
{
//resource file doesn't exist.
return;
}
//Remove current resource from the merged dictionaries
var currentResource = Application.Current.Resources.MergedDictionaries.FirstOrDefault(x => x.Source != null && x.Source.ToString().Contains(folder));
if (currentResource != null)
Application.Current.Resources.MergedDictionaries.Remove(currentResource);
//Add the new resource to the dictionary
Application.Current.Resources.MergedDictionaries.Add(dictionary);
}
这个方法的作用是:
- 从 URI 源加载资源字典。
- 根据文件夹名称查找并删除当前语言词典。
- 将新词典添加到合并的词典列表中。
要获取语言文件的 Uri,您可以这样做:
Uri languagePath = new Uri(string.Format("/YourAppNamespace;component/resources/languages/{0}.xaml", language), UriKind.Relative);
以上代码假定您的语言文件命名为 de.xaml 或 en.xaml.
获得 Uri 后,您需要做的就是调用 ReplaceLanguage 方法。
好的。我最终使用静态方法来加载我的本地化。方法如下:
/// <summary>
/// Loads localization based on culture.
/// </summary>
/// <param name="dictionary">The dictionary to load localization to</param>
/// <param name="basePath">The base path of the localization files. See remarks for further info.</param>
/// <param name="cultureInfo">Culture to load localization for.</param>
/// <remarks>
/// The loaded localization file will be <code>basenameLocalization.languagecode.xaml</code>
/// (e.g. <code>MainWindowLocalization.de.xaml</code>), or <code>basenameLocalization.languagecode.xaml</code>
/// for the default localization.
/// </remarks>
internal static void ReplaceLocalization(
ResourceDictionary dictionary,
string basePath,
CultureInfo cultureInfo)
{
ResourceDictionary dict = new ResourceDictionary();
// Clean out old localization
ResourceDictionary oldLocalization = null;
foreach (ResourceDictionary d in dictionary.MergedDictionaries)
{
if (d.Source.OriginalString.StartsWith(basePath + "Localization."))
{
oldLocalization = d;
}
}
if (oldLocalization != null)
{
dictionary.MergedDictionaries.Remove(oldLocalization);
}
// Get thee language
string language = "";
if (cultureInfo.Name != null)
{
// We only need to look at the first two characters to determine language
language = cultureInfo.Name.Substring(0, 2);
}
bool defaultLanguage = false;
// Filter languages such that only supported languages are loadable,
// and any other defaults to the default/neutral language.
switch (language)
{
case "da":
break;
default:
defaultLanguage = true;
break;
}
// Construct the URI
string uri;
if (defaultLanguage)
{
uri = basePath + "Localization.xaml";
}
else
{
uri = basePath + "Localization." + language + ".xaml";
}
// Load new dictionary
dict.Source = new Uri(uri, UriKind.Relative);
dictionary.MergedDictionaries.Add(dict);
}
这也适用于在运行时更改语言。
请评论任何问题,以便我改进我的回答。