changeset 71:40c09e57d213

Fixes #31: Break out Translations for language to own class * Make Translation class use new extracted class objects
author IBBoard <dev@ibboard.co.uk>
date Tue, 06 Apr 2010 18:08:43 +0000
parents 753be4b6c3b0
children cec6c4c0892d
files Lang/Translation.cs
diffstat 1 files changed, 51 insertions(+), 155 deletions(-) [+]
line diff
     1.1 --- a/Lang/Translation.cs	Tue Apr 06 16:01:01 2010 +0000
     1.2 +++ b/Lang/Translation.cs	Tue Apr 06 18:08:43 2010 +0000
     1.3 @@ -16,49 +16,57 @@
     1.4  namespace IBBoard.Lang
     1.5  {
     1.6  	/// <summary>
     1.7 -	/// A basic string translator that loads a default language and a specified language and returns translated strings that correspond to translation IDs. 
     1.8 -	/// If the string doesn't exist in the specified language then the translator falls back to the default language. If the translation doesn't exist in the default language
     1.9 -	/// then either a supplied value or a "no validation available" message is returned.
    1.10 +	/// A basic string translator that a specified language and returns translated strings that correspond to translation IDs. 
    1.11 +	/// If the string doesn't exist in the specified language then the translator falls back defined 'super' languages.
    1.12 +	/// If the translation doesn't exist in the hierarchy of languages then either a supplied value, null or a "no validation available"
    1.13 +	/// message is returned, depending on the parameters supplied to the method.
    1.14 +	/// 
    1.15 +	/// Loaded languages are referenced by two-character language code (e.g. "en" or "it")
    1.16  	/// </summary>
    1.17  	public class Translation
    1.18 -	{		
    1.19 -		private static readonly string DEFAULT_LANGUAGE = "en";
    1.20 +	{
    1.21  		private static readonly string DIVIDER_STRING = "-";
    1.22 -		private static string lang = "";
    1.23  		private static DirectoryInfo translationDir;
    1.24 -		private static Dictionary<string, string> translationsLocal = new Dictionary<string, string>();
    1.25 -		private static Dictionary<string, string> translationsDefault = new Dictionary<string, string>();
    1.26 -		private static XmlReaderSettings settings;
    1.27 +		private static AbstractTranslationSet translations;
    1.28 +		private static TranslationXmlLoader loader;
    1.29  
    1.30  		/// <summary>
    1.31 -		/// Initialises the translations for the language specified and the default translations so that the Translation class can be used.
    1.32 +		/// Initialises the translations and loads the specified language so that the Translation class can be used.
    1.33  		/// Throws a TranslationLoadException if a problem occurred while loading translations. If this occurs then the translation methods can
    1.34  		/// still be called but no translation will be performed.
    1.35  		/// </summary>
    1.36  		/// <param name="appPath">
    1.37 -		/// The full path that the application is running from. Must contain the "translations" folder.
    1.38 +		/// The full path that the contains the "translations" folder - normally the application directory path.
    1.39  		/// </param>
    1.40  		/// <param name="language">
    1.41 -		/// The language to use as the load language
    1.42 +		/// The language to use as the loaded language
    1.43  		/// </param>
    1.44  		public static void InitialiseTranslations(string appPath, string language)
    1.45  		{
    1.46 +			InitialiseTranslations(appPath);
    1.47 +			LoadTranslationForLanguage(language);
    1.48 +		}
    1.49 +		
    1.50 +		/// <summary>
    1.51 +		/// Initialises the translation class for an application or source.
    1.52 +		/// </summary>
    1.53 +		/// <param name="appPath">
    1.54 +		/// The full path that the contains the "translations" folder - normally the application directory path.
    1.55 +		/// </param>
    1.56 +		public static void InitialiseTranslations(string appPath)
    1.57 +		{
    1.58  			InitialiseDefaults(appPath);
    1.59 -			FileInfo file = GetTranslationFile(DEFAULT_LANGUAGE);
    1.60 -			XmlDocument doc = LoadTranslationDocument(file);
    1.61 -			LoadTranslationsFromDocument(doc, translationsDefault);
    1.62 -			LoadTranslationForLanguage(language);
    1.63  		}
    1.64  		
    1.65  		private static void InitialiseDefaults(string appPath)
    1.66  		{
    1.67 -			string translationPath = appPath.TrimEnd(Constants.DirectoryChar) + Constants.DirectoryString + "translations";
    1.68 +			string translationPath = Path.Combine(appPath, "translations");
    1.69  
    1.70  			if (Directory.Exists(translationPath))
    1.71  			{
    1.72 -				translationsDefault = new Dictionary<string,string>();
    1.73 -				translationsLocal = new Dictionary<string,string>();
    1.74 +				translations = null;
    1.75  				translationDir = new DirectoryInfo(translationPath);
    1.76 +				loader = new TranslationXmlLoader(Path.Combine(appPath, "schemas/translation.xsd"));
    1.77  			}
    1.78  			else
    1.79  			{
    1.80 @@ -66,133 +74,17 @@
    1.81  			}
    1.82  		}
    1.83  		
    1.84 -		private static XmlDocument LoadTranslationDocument(FileInfo file)
    1.85 -		{
    1.86 -			XmlDocument doc = new XmlDocument();			
    1.87 -			XmlReader valReader = XmlReader.Create(file.FullName, GetReaderSettings());
    1.88 -			
    1.89 -			try
    1.90 -			{
    1.91 -				doc.Load(valReader);
    1.92 -			}
    1.93 -			catch (DirectoryNotFoundException ex)
    1.94 -			{
    1.95 -				throw new TranslationLoadException("Problem validating schema for translation: " + ex.Message, ex);
    1.96 -			}
    1.97 -			catch (XmlSchemaException ex)
    1.98 -			{
    1.99 -				throw new TranslationLoadException("Problem validating schema for translation: " + ex.Message, ex);
   1.100 -			}
   1.101 -			catch (XmlException ex)
   1.102 -			{
   1.103 -				throw new TranslationLoadException("Problem reading data for translation: " + ex.Message, ex);
   1.104 -			}
   1.105 -			finally
   1.106 -			{
   1.107 -				valReader.Close();
   1.108 -			}
   1.109 -			
   1.110 -			return doc;
   1.111 -		}
   1.112 -		
   1.113  		/// <summary>
   1.114 -		/// Lazy-getter for XML reader settings. May throw a <see cref="TranslationLoadException"/> if there is a problem with the translation schema.
   1.115 -		/// </summary>
   1.116 -		/// <returns>
   1.117 -		/// A <see cref="XmlReaderSettings"/> with the default values for validating the translation document against the translation schema
   1.118 -		/// </returns>
   1.119 -		private static XmlReaderSettings GetReaderSettings()
   1.120 -		{
   1.121 -			if (settings == null)
   1.122 -			{
   1.123 -				try
   1.124 -				{
   1.125 -					settings = new XmlReaderSettings();
   1.126 -					settings.ValidationType = ValidationType.Schema;
   1.127 -					settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;
   1.128 -					settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod);
   1.129 -					XmlSchemaSet cache = new XmlSchemaSet();
   1.130 -					cache.Add("http://ibboard.co.uk/translation", translationDir.Parent.FullName + "/schemas/translation.xsd");
   1.131 -					settings.Schemas.Add(cache);
   1.132 -				}
   1.133 -				catch (DirectoryNotFoundException ex)
   1.134 -				{
   1.135 -					throw new TranslationLoadException("Problem validating schema for translation: " + ex.Message, ex);
   1.136 -				}
   1.137 -				catch (XmlSchemaException ex)
   1.138 -				{
   1.139 -					throw new TranslationLoadException("Problem validating schema for translation: " + ex.Message, ex);
   1.140 -				}
   1.141 -				catch (XmlException ex)
   1.142 -				{
   1.143 -					throw new TranslationLoadException("Problem reading data for schema: " + ex.Message, ex);
   1.144 -				}
   1.145 -			}
   1.146 -			
   1.147 -			return settings;
   1.148 -		}
   1.149 -		
   1.150 -		private static FileInfo GetTranslationFile(string language)
   1.151 -		{
   1.152 -			FileInfo file = new FileInfo(translationDir.FullName + Constants.DirectoryString + language + ".translation");
   1.153 -
   1.154 -			if (!file.Exists)
   1.155 -			{
   1.156 -				throw new TranslationLoadException(language + ".translation could not be found in "+translationDir.FullName);
   1.157 -			}
   1.158 -			
   1.159 -			return file;
   1.160 -		}
   1.161 -		
   1.162 -		private static void LoadTranslationsFromDocument(XmlDocument doc, Dictionary<string, string> translationTable)
   1.163 -		{
   1.164 -			try
   1.165 -			{
   1.166 -				XmlNodeList translations = doc.GetElementsByTagName("translation");				
   1.167 -				Dictionary<string, string> tempTranslationTable = new Dictionary<string,string>();
   1.168 -
   1.169 -				foreach (XmlNode node in translations)
   1.170 -				{
   1.171 -					tempTranslationTable.Add(node.Attributes["id"].Value, node.InnerText);
   1.172 -				}
   1.173 -				
   1.174 -				translationTable.Clear();
   1.175 -				
   1.176 -				foreach (string key in tempTranslationTable.Keys)
   1.177 -				{
   1.178 -					string translation;
   1.179 -					tempTranslationTable.TryGetValue(key, out translation);
   1.180 -					translationTable.Add(key, translation);
   1.181 -				}
   1.182 -			}
   1.183 -			catch(Exception ex)
   1.184 -			{
   1.185 -				throw new TranslationLoadException("Error while parsing " + GetLanguageOfDocument(doc)+" translation: "+ex.Message, ex);
   1.186 -			}	
   1.187 -		}
   1.188 -		
   1.189 -		private static string GetLanguageOfDocument(XmlDocument doc)
   1.190 -		{
   1.191 -			return doc != null ? doc.DocumentElement.GetAttribute("lang") : "";
   1.192 -		}
   1.193 -		
   1.194 -		private static void ValidationEventMethod(object sender, ValidationEventArgs e)
   1.195 -		{
   1.196 -			throw new TranslationLoadException("Problem validating schema for translation: " + e.Exception.Message, e.Exception);
   1.197 -		}
   1.198 -		
   1.199 -		/// <summary>
   1.200 -		/// Resets the loaded translations
   1.201 +		/// Resets the loaded translations and reverts to no translations.
   1.202  		/// </summary>
   1.203  		public static void Reset()
   1.204  		{
   1.205 -			translationsLocal.Clear();
   1.206 -			translationsDefault.Clear();
   1.207 +			translations = null;
   1.208  		}
   1.209  
   1.210  		/// <summary>
   1.211 -		/// Loads translations for a given language and sets them as the local language.
   1.212 -		/// hrows a TranslationLoadException if a problem occurred while loading translations. If this occurs then the translation methods can
   1.213 +		/// Loads translations for a given language and sets them as the current language.
   1.214 +		/// Throws a TranslationLoadException if a problem occurred while loading translations. If this occurs then the translation methods can
   1.215  		/// still be called but all translations will fall back to the default translation.
   1.216  		/// </summary>
   1.217  		/// <param name="translationLang">
   1.218 @@ -210,18 +102,27 @@
   1.219  		
   1.220  		private static void LoadTranslationForLanguage(string translationLanguage)
   1.221  		{			
   1.222 -			if (translationLanguage != DEFAULT_LANGUAGE && translationLanguage != "" && translationLanguage != null)
   1.223 +			if (translationLanguage != "" && translationLanguage != null)
   1.224  			{
   1.225 -				FileInfo file = GetTranslationFile(translationLanguage);
   1.226 -				XmlDocument doc = LoadTranslationDocument(file);
   1.227 -				LoadTranslationsFromDocument(doc, translationsLocal);	
   1.228 +				translations = loader.LoadTranslations(GetTranslationFile(translationLanguage));
   1.229  			}
   1.230  			else
   1.231  			{
   1.232 -				translationsLocal.Clear();				
   1.233 +				translations = null;
   1.234 +			}
   1.235 +		}
   1.236 +		
   1.237 +		private static string GetTranslationFile(string language)
   1.238 +		{
   1.239 +			string translationFileName = language + ".translation";
   1.240 +			string path = Path.Combine(translationDir.FullName, translationFileName);
   1.241 +
   1.242 +			if (!File.Exists(path))
   1.243 +			{
   1.244 +				throw new TranslationLoadException(translationFileName +" could not be found in "+translationDir.FullName);
   1.245  			}
   1.246  			
   1.247 -			lang = translationLanguage;
   1.248 +			return path;
   1.249  		}
   1.250  
   1.251  		/// <summary>
   1.252 @@ -278,7 +179,7 @@
   1.253  		/// </returns>
   1.254  		public static string GetTranslation(string translationID, string defaultTranslation, params object[] replacements)
   1.255  		{
   1.256 -			string trans = GetTranslationFromTables(translationID);
   1.257 +			string trans = GetTranslationFromTranslationSet(translationID);
   1.258  			
   1.259  			if (trans == null)
   1.260  			{
   1.261 @@ -290,18 +191,13 @@
   1.262  			return trans;
   1.263  		}
   1.264  		
   1.265 -		private static string GetTranslationFromTables(string translationID)
   1.266 +		private static string GetTranslationFromTranslationSet(string translationID)
   1.267  		{
   1.268  			string translation = null;
   1.269  			
   1.270 -			if (translationsLocal!=null)
   1.271 +			if (translations!=null)
   1.272  			{
   1.273 -				translationsLocal.TryGetValue(translationID, out translation);
   1.274 -			}
   1.275 -			
   1.276 -			if (translation == null)
   1.277 -			{
   1.278 -				translationsDefault.TryGetValue(translationID, out translation);
   1.279 +				translation = translations[translationID];
   1.280  			}
   1.281  			
   1.282  			return translation;
   1.283 @@ -375,7 +271,7 @@
   1.284  		/// </returns>
   1.285  		public static string GetTranslationLanguage()
   1.286  		{
   1.287 -			return lang;
   1.288 +			return (translations!=null ? translations.LanguageCode : "");
   1.289  		}
   1.290  	}
   1.291  }