Mercurial > repos > IBBoard
view Lang/Translation.cs @ 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 | b5d7e8b93205 |
children | 091bfa54d6c7 |
line wrap: on
line source
// This file (Translation.cs) is a part of the IBBoard library and is copyright 2009 IBBoard. // // The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license. using System; using System.IO; using System.Xml; using System.Xml.Schema; using System.Collections.Generic; using System.Reflection; using System.ComponentModel; using IBBoard.IO; using IBBoard.Logging; using IBBoard.Xml; namespace IBBoard.Lang { /// <summary> /// A basic string translator that a specified language and returns translated strings that correspond to translation IDs. /// If the string doesn't exist in the specified language then the translator falls back defined 'super' languages. /// If the translation doesn't exist in the hierarchy of languages then either a supplied value, null or a "no validation available" /// message is returned, depending on the parameters supplied to the method. /// /// Loaded languages are referenced by two-character language code (e.g. "en" or "it") /// </summary> public class Translation { private static readonly string DIVIDER_STRING = "-"; private static DirectoryInfo translationDir; private static AbstractTranslationSet translations; private static TranslationXmlLoader loader; /// <summary> /// Initialises the translations and loads the specified language so that the Translation class can be used. /// Throws a TranslationLoadException if a problem occurred while loading translations. If this occurs then the translation methods can /// still be called but no translation will be performed. /// </summary> /// <param name="appPath"> /// The full path that the contains the "translations" folder - normally the application directory path. /// </param> /// <param name="language"> /// The language to use as the loaded language /// </param> public static void InitialiseTranslations(string appPath, string language) { InitialiseTranslations(appPath); LoadTranslationForLanguage(language); } /// <summary> /// Initialises the translation class for an application or source. /// </summary> /// <param name="appPath"> /// The full path that the contains the "translations" folder - normally the application directory path. /// </param> public static void InitialiseTranslations(string appPath) { InitialiseDefaults(appPath); } private static void InitialiseDefaults(string appPath) { string translationPath = Path.Combine(appPath, "translations"); if (Directory.Exists(translationPath)) { translations = null; translationDir = new DirectoryInfo(translationPath); loader = new TranslationXmlLoader(Path.Combine(appPath, "schemas/translation.xsd")); } else { throw new TranslationLoadException("Translation path not found ("+new FileInfo(translationPath).FullName+")"); } } /// <summary> /// Resets the loaded translations and reverts to no translations. /// </summary> public static void Reset() { translations = null; } /// <summary> /// Loads translations for a given language and sets them as the current language. /// Throws a TranslationLoadException if a problem occurred while loading translations. If this occurs then the translation methods can /// still be called but all translations will fall back to the default translation. /// </summary> /// <param name="translationLang"> /// The new local language to load /// </param> public static void LoadTranslation(string translationLanguage) { if (translationLanguage == "" || translationLanguage == null) { throw new ArgumentException("Translation language cannot be null or empty"); } LoadTranslationForLanguage(translationLanguage); } private static void LoadTranslationForLanguage(string translationLanguage) { if (translationLanguage != "" && translationLanguage != null) { translations = loader.LoadTranslations(GetTranslationFile(translationLanguage)); } else { translations = null; } } private static string GetTranslationFile(string language) { string translationFileName = language + ".translation"; string path = Path.Combine(translationDir.FullName, translationFileName); if (!File.Exists(path)) { throw new TranslationLoadException(translationFileName +" could not be found in "+translationDir.FullName); } return path; } /// <summary> /// Gets a translation for a given ID, falling back to a "missing translation" message if none can be found. Also optionally replaces any placeholders with the supplied values. /// </summary> /// <param name="translationID"> /// The ID to look up the translation for /// </param> /// <param name="replacements"> /// A collection of <see cref="System.Object"/>s to replace placeholders with /// </param> /// <returns> /// The translation with the placeholders replaced or a "missing translation" message /// </returns> public static string GetTranslation(string translationID, params object[] replacements) { return GetTranslation(translationID, false, replacements); } /// <summary> /// Gets a translation for a given ID, falling back to null or a warning message if a translation cannot be found. Also optionally replaces any placeholders with the supplied values. /// </summary> /// <param name="translationID"> /// The ID to look up the translation for /// </param> /// <param name="returnNullOnFail"> /// TRUE if null should be returned when no translation can be found, or FALSE if a "missing translation" message should be returned /// </param> /// <param name="replacements"> /// A collection of <see cref="System.Object"/>s to replace placeholders with /// </param> /// <returns> /// The translation with the placeholders replaced, or a "missing translation" message or null depending on <param name="returnNullOnFail"> /// </returns> public static string GetTranslation(string translationID, bool returnNullOnFail, params object[] replacements) { return GetTranslation(translationID, returnNullOnFail ? null : "", replacements); } /// <summary> /// Gets a translation for a given ID, falling back to a supplied default if a translation cannot be found. Also optionally replaces any placeholders with the supplied values. /// </summary> /// <param name="translationID"> /// The ID to look up the translation for /// </param> /// <param name="defaultTranslation"> /// The string to return if no translation can be found. Can be null or any string. /// </param> /// <param name="replacements"> /// A collection of <see cref="System.Object"/>s to replace placeholders with /// </param> /// <returns> /// The translation, if one exists, or the supplied default with the placeholders replaced /// </returns> public static string GetTranslation(string translationID, string defaultTranslation, params object[] replacements) { string trans = GetTranslationFromTranslationSet(translationID); if (trans == null) { trans = GetDefaultTranslation(translationID, defaultTranslation); } trans = AddVariablesToTranslation(trans, replacements); return trans; } private static string GetTranslationFromTranslationSet(string translationID) { string translation = null; if (translations!=null) { translation = translations[translationID]; } return translation; } private static string GetDefaultTranslation(string translationID, string defaultTranslation) { return (defaultTranslation != "" || defaultTranslation == null) ? defaultTranslation : GetMissingTranslationMessage(translationID); } private static string GetMissingTranslationMessage(string translationID) { return "++ Missing Translation "+translationID+" ++"; } private static string AddVariablesToTranslation(string translation, object[] replacements) { if (translation != null && replacements != null && replacements.Length > 0) { translation = String.Format(translation, replacements); } return translation; } /// <summary> /// Translate an <see cref="ITranslatable"/> item, with optional string replacement. If the translation /// does not exist then a warning message will be used as the translated text. /// </summary> /// <param name="item"> /// A <see cref="ITranslatable"/> to set the text for /// </param> /// <param name="replacements"> /// A collection of <see cref="System.Object"/>s that will be used to fill place-holders /// </param> public static void Translate(ITranslatable item, params object[] replacements) { Translate(item, GetMissingTranslationMessage(item.Name), replacements); } /// <summary> /// Translate an <see cref="ITranslatable"/> item, with optional string replacement. The <code>defaultText</code> /// can be used to specify an alternate translation. Passing <code>null</code> will result in a warning message /// about a missing translation ID. /// </summary> /// <param name="item"> /// A <see cref="ITranslatable"/> to set the text for /// </param> /// <param name="defaultText"> /// The default string to display if no translation could be found. /// </param> /// <param name="replacements"> /// A collection of <see cref="System.Object"/>s that will be used to fill place-holders /// </param> public static void Translate(ITranslatable item, string defaultText, params object[] replacements) { if (item.Text == "" || item.Text == DIVIDER_STRING) { //it doesn't need translating - either there is no text from the developer or it's a hyphen for a divider return; } item.Text = GetTranslation(item.Name, defaultText, replacements); } /// <summary> /// Get the current local translation language. This is an arbitrary string used in the translation file's name and will not necessarily match the ISO language code. /// </summary> /// <returns> /// The string used in the file name of the current local translation /// </returns> public static string GetTranslationLanguage() { return (translations!=null ? translations.LanguageCode : ""); } } }