//
//
//
//
// $Revision: 3287 $
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Threading;
namespace ICSharpCode.Core
{
///
/// This Class contains two ResourceManagers, which handle string and image resources
/// for the application. It do handle localization strings on this level.
///
public static class ResourceService
{
const string uiLanguageProperty = "CoreProperties.UILanguage";
const string stringResources = "StringResources";
const string imageResources = "BitmapResources";
static string resourceDirectory;
public static void InitializeService(string resourceDirectory)
{
if (ResourceService.resourceDirectory != null)
throw new InvalidOperationException("Service is already initialized.");
if (resourceDirectory == null)
throw new ArgumentNullException("resourceDirectory");
ResourceService.resourceDirectory = resourceDirectory;
PropertyService.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChange);
LoadLanguageResources(ResourceService.Language);
}
public static string Language {
get {
return PropertyService.Get(uiLanguageProperty, Thread.CurrentThread.CurrentUICulture.Name);
}
set {
PropertyService.Set(uiLanguageProperty, value);
}
}
/// English strings (list of resource managers)
static List strings = new List();
/// Neutral/English images (list of resource managers)
static List icons = new List();
/// Hashtable containing the local strings from the main application.
static Hashtable localStrings = null;
static Hashtable localIcons = null;
/// Strings resource managers for the current language
static List localStringsResMgrs = new List();
/// Image resource managers for the current language
static List localIconsResMgrs = new List();
/// List of ResourceAssembly
static List resourceAssemblies = new List();
class ResourceAssembly
{
Assembly assembly;
string baseResourceName;
bool isIcons;
public ResourceAssembly(Assembly assembly, string baseResourceName, bool isIcons)
{
this.assembly = assembly;
this.baseResourceName = baseResourceName;
this.isIcons = isIcons;
}
ResourceManager TrySatellite(string language)
{
// ResourceManager should automatically use satellite assemblies, but it doesn't work
// and we have to do it manually.
string fileName = Path.GetFileNameWithoutExtension(assembly.Location) + ".resources.dll";
fileName = Path.Combine(Path.Combine(Path.GetDirectoryName(assembly.Location), language), fileName);
if (File.Exists(fileName)) {
LoggingService.Info("Loging resources " + baseResourceName + " loading from satellite " + language);
return new ResourceManager(baseResourceName, Assembly.LoadFrom(fileName));
} else {
return null;
}
}
public void Load()
{
string logMessage = "Loading resources " + baseResourceName + "." + currentLanguage + ": ";
ResourceManager manager = null;
if (assembly.GetManifestResourceInfo(baseResourceName + "." + currentLanguage + ".resources") != null) {
LoggingService.Info(logMessage + " loading from main assembly");
manager = new ResourceManager(baseResourceName + "." + currentLanguage, assembly);
} else if (currentLanguage.IndexOf('-') > 0
&& assembly.GetManifestResourceInfo(baseResourceName + "." + currentLanguage.Split('-')[0] + ".resources") != null)
{
LoggingService.Info(logMessage + " loading from main assembly (no country match)");
manager = new ResourceManager(baseResourceName + "." + currentLanguage.Split('-')[0], assembly);
} else {
// try satellite assembly
manager = TrySatellite(currentLanguage);
if (manager == null && currentLanguage.IndexOf('-') > 0) {
manager = TrySatellite(currentLanguage.Split('-')[0]);
}
}
if (manager == null) {
LoggingService.Warn(logMessage + "NOT FOUND");
} else {
if (isIcons)
localIconsResMgrs.Add(manager);
else
localStringsResMgrs.Add(manager);
}
}
}
///
/// Registers string resources in the resource service.
///
/// The base name of the resource file embedded in the assembly.
/// The assembly which contains the resource file.
/// ResourceService.RegisterStrings("TestAddin.Resources.StringResources", GetType().Assembly);
public static void RegisterStrings(string baseResourceName, Assembly assembly)
{
RegisterNeutralStrings(new ResourceManager(baseResourceName, assembly));
ResourceAssembly ra = new ResourceAssembly(assembly, baseResourceName, false);
resourceAssemblies.Add(ra);
ra.Load();
}
public static void RegisterNeutralStrings(ResourceManager stringManager)
{
strings.Add(stringManager);
}
///
/// Registers image resources in the resource service.
///
/// The base name of the resource file embedded in the assembly.
/// The assembly which contains the resource file.
/// ResourceService.RegisterImages("TestAddin.Resources.BitmapResources", GetType().Assembly);
public static void RegisterImages(string baseResourceName, Assembly assembly)
{
RegisterNeutralImages(new ResourceManager(baseResourceName, assembly));
ResourceAssembly ra = new ResourceAssembly(assembly, baseResourceName, true);
resourceAssemblies.Add(ra);
ra.Load();
}
public static void RegisterNeutralImages(ResourceManager imageManager)
{
icons.Add(imageManager);
}
static void OnPropertyChange(object sender, PropertyChangedEventArgs e)
{
if (e.Key == uiLanguageProperty && e.NewValue != e.OldValue) {
LoadLanguageResources((string)e.NewValue);
if (LanguageChanged != null)
LanguageChanged(null, e);
}
}
public static event EventHandler ClearCaches;
public static event EventHandler LanguageChanged;
static string currentLanguage;
static void LoadLanguageResources(string language)
{
if (ClearCaches != null)
ClearCaches(null, EventArgs.Empty);
try {
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
} catch (Exception) {
try {
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language.Split('-')[0]);
} catch (Exception) {}
}
localStrings = Load(stringResources, language);
if (localStrings == null && language.IndexOf('-') > 0) {
localStrings = Load(stringResources, language.Split('-')[0]);
}
localIcons = Load(imageResources, language);
if (localIcons == null && language.IndexOf('-') > 0) {
localIcons = Load(imageResources, language.Split('-')[0]);
}
localStringsResMgrs.Clear();
localIconsResMgrs.Clear();
currentLanguage = language;
foreach (ResourceAssembly ra in resourceAssemblies) {
ra.Load();
}
}
static Hashtable Load(string fileName)
{
if (File.Exists(fileName)) {
Hashtable resources = new Hashtable();
ResourceReader rr = new ResourceReader(fileName);
foreach (DictionaryEntry entry in rr) {
resources.Add(entry.Key, entry.Value);
}
rr.Close();
return resources;
}
return null;
}
static Hashtable Load(string name, string language)
{
return Load(resourceDirectory + Path.DirectorySeparatorChar + name + "." + language + ".resources");
}
///
/// Returns a string from the resource database, it handles localization
/// transparent for the user.
///
///
/// The string in the (localized) resource database.
///
///
/// The name of the requested resource.
///
///
/// Is thrown when the GlobalResource manager can't find a requested resource.
///
public static string GetString(string name)
{
if (localStrings != null && localStrings[name] != null) {
return localStrings[name].ToString();
}
string s = null;
foreach (ResourceManager resourceManger in localStringsResMgrs) {
try {
s = resourceManger.GetString(name);
}
catch (Exception) { }
if (s != null) {
break;
}
}
if (s == null) {
foreach (ResourceManager resourceManger in strings) {
try {
s = resourceManger.GetString(name);
}
catch (Exception) { }
if (s != null) {
break;
}
}
}
if (s == null) {
throw new ResourceNotFoundException("string >" + name + "<");
}
return s;
}
public static object GetImageResource(string name)
{
object iconobj = null;
if (localIcons != null && localIcons[name] != null) {
iconobj = localIcons[name];
} else {
foreach (ResourceManager resourceManger in localIconsResMgrs) {
iconobj = resourceManger.GetObject(name);
if (iconobj != null) {
break;
}
}
if (iconobj == null) {
foreach (ResourceManager resourceManger in icons) {
try {
iconobj = resourceManger.GetObject(name);
}
catch (Exception) { }
if (iconobj != null) {
break;
}
}
}
}
return iconobj;
}
}
}