From 8e62a9397e0d20e59f3fc397f2d1deaf8831f4f0 Mon Sep 17 00:00:00 2001 From: RKrom Date: Wed, 18 Apr 2012 06:57:50 +0000 Subject: [PATCH] Cleanup of language code: remove all unneeded code, commented the method and made sure the IETF (language code) is used more error-tolerant git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1787 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4 --- GreenshotPlugin/Core/Language.cs | 438 ++++++++++++++++++++----------- 1 file changed, 290 insertions(+), 148 deletions(-) diff --git a/GreenshotPlugin/Core/Language.cs b/GreenshotPlugin/Core/Language.cs index 4f84f77f9..e527bffa5 100644 --- a/GreenshotPlugin/Core/Language.cs +++ b/GreenshotPlugin/Core/Language.cs @@ -1,4 +1,24 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System; using System.Collections.Generic; using System.Text; using System.IO; @@ -9,97 +29,29 @@ using Greenshot.IniFile; using System.Text.RegularExpressions; namespace GreenshotPlugin.Core { - public class LanguageFile : IEquatable { - public string Description { - get; - set; - } - - public string Ietf { - get; - set; - } - - public Version Version { - get; - set; - } - - public string LanguageGroup { - get; - set; - } - - public string Filepath { - get; - set; - } - - public string Prefix { - get; - set; - } - - public bool Equals(LanguageFile other) { - if (Prefix != null) { - if (!Prefix.Equals(other.Prefix)) { - return false; - } - } else if (other.Prefix != null) { - return false; - } - if (Ietf != null) { - if (!Ietf.Equals(other.Ietf)) { - return false; - } - } else if (other.Ietf != null) { - return false; - } - if (Version != null) { - if (!Version.Equals(other.Version)) { - return false; - } - } else if (other.Version != null) { - return false; - } - if (Filepath != null) { - if (!Filepath.Equals(other.Filepath)) { - return false; - } - } else if (other.Filepath != null) { - return false; - } - return true; - } - } - - class HelpFile { - public string Ietf { - get; - set; - } - - public string Filepath { - get; - set; - } - } - + /// + /// This class supplies the GUI with translations, based upon keys. + /// The language resources are loaded from the language files found on fixed or supplied paths + /// public class Language { private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(Language)); private static List languagePaths = new List(); private static IDictionary> languageFiles = new Dictionary>(); - private static IDictionary helpFiles = new Dictionary(); + private static IDictionary helpFiles = new Dictionary(); private const string DEFAULT_LANGUAGE = "en-US"; private const string HELP_FILENAME_PATTERN = @"help-*.html"; private const string LANGUAGE_FILENAME_PATTERN = @"language*.xml"; private static Regex PREFIX_REGEXP = new Regex(@"language_([a-zA-Z0-9]+).*"); + private static Regex IETF_REGEXP = new Regex(@"[^a-zA-Z]+"); private const string LANGUAGE_GROUPS_KEY = @"SYSTEM\CurrentControlSet\Control\Nls\Language Groups"; private static List unsupportedLanguageGroups = new List(); private static IDictionary resources = new Dictionary(); private static string currentLanguage = null; private static CoreConfiguration coreConfig = null; + /// + /// Static initializer for the language code + /// static Language() { if (!LogHelper.isInitialized) { LOG.Warn("Log4net hasn't been initialized yet! (Design mode?)"); @@ -148,19 +100,29 @@ namespace GreenshotPlugin.Core { Reload(); } + /// + /// Internal method to add a path to the paths that will be scanned for language files! + /// + /// + /// true if the path exists and is added private static bool AddPath(string path) { if (!languagePaths.Contains(path)) { if (Directory.Exists(path)) { LOG.DebugFormat("Adding language path {0}", path); languagePaths.Add(path); + return true; } else { LOG.InfoFormat("Not adding non existing language path {0}", path); - return false; } } - return true; + return false; } + /// + /// Add a new path to the paths that will be scanned for language files! + /// + /// + /// true if the path exists and is added public static bool AddLanguageFilePath(string path) { if (!languagePaths.Contains(path)) { LOG.DebugFormat("New language path {0}", path); @@ -174,7 +136,12 @@ namespace GreenshotPlugin.Core { return true; } + /// + /// Load the files for the specified ietf + /// + /// private static void LoadFiles(string ietf) { + ietf = ClearIETF(ietf); if (!languageFiles.ContainsKey(ietf)) { LOG.ErrorFormat("No language {0} available.", ietf); return; @@ -185,6 +152,9 @@ namespace GreenshotPlugin.Core { } } + /// + /// Load the language resources from the scanned files + /// private static void Reload() { resources.Clear(); LoadFiles(DEFAULT_LANGUAGE); @@ -193,29 +163,67 @@ namespace GreenshotPlugin.Core { } } + /// + /// Get or set the current language + /// public static string CurrentLanguage { get { return currentLanguage; } set { - LOG.DebugFormat("CurrentLangue = {0}", value); - // Change the resources, if we can find the wanted value - if (!string.IsNullOrEmpty(value) && currentLanguage == null || (currentLanguage != null && !currentLanguage.Equals(value))) { - currentLanguage = value; + LOG.DebugFormat("CurrentLangue = {0}, new value {1}", currentLanguage, value); + string ietf = ClearIETF(value); + if (!string.IsNullOrEmpty(ietf)) { + if (!languageFiles.ContainsKey(ietf)) { + LOG.WarnFormat("Unknown language {0}, trying best match!", ietf); + foreach (string availableIETF in languageFiles.Keys) { + if (availableIETF.StartsWith(ietf)) { + LOG.InfoFormat("Found language {0}, best match for!", availableIETF, ietf); + ietf = availableIETF; + break; + } + } + } + if (!languageFiles.ContainsKey(ietf)) { + LOG.WarnFormat("No match for language {0} found!", ietf); + } else { + if (currentLanguage == null && !currentLanguage.Equals(ietf)) { + currentLanguage = ietf; + Reload(); + return; + } + } } - Reload(); + LOG.Debug("CurrentLanguage not changed!"); } } - public static string LanguageName(string ietf) { - return languageFiles[ietf][0].Description; + /// + /// This helper method clears all non alpha characters from the IETF, and does a tolower. + /// So only "dede" or "enus" is left, this prevents problems with multiple formats or typos. + /// + /// + /// + private static string ClearIETF(string inputIETF) { + string returnIETF = null; + if (!string.IsNullOrEmpty(inputIETF)) { + returnIETF = inputIETF.ToLower(); + returnIETF = IETF_REGEXP.Replace(returnIETF, ""); + } + return returnIETF; } + /// + /// Return a list of all the supported languages + /// public static IList SupportedLanguages { get { IList languages = new List(); + // Loop over all languages with all the files in there foreach (List langs in languageFiles.Values) { + // Loop over all the files for a language foreach (LanguageFile langFile in langs) { + // Only take the ones without prefix, these are the "base" language files if (langFile.Prefix == null) { languages.Add(langFile); break; @@ -225,12 +233,16 @@ namespace GreenshotPlugin.Core { return languages; } } + + /// + /// Return the path to the help-file + /// public static string HelpFilePath { get { if (helpFiles.ContainsKey(currentLanguage)) { - return helpFiles[currentLanguage].Filepath; + return helpFiles[currentLanguage]; } - return helpFiles[DEFAULT_LANGUAGE].Filepath; + return helpFiles[DEFAULT_LANGUAGE]; } } @@ -279,7 +291,7 @@ namespace GreenshotPlugin.Core { languageFile.Filepath = languageFilePath; XmlNode node = nodes.Item(0); languageFile.Description = node.Attributes["description"].Value; - languageFile.Ietf = node.Attributes["ietf"].Value; + languageFile.Ietf = ClearIETF(node.Attributes["ietf"].Value); if (node.Attributes["version"] != null) { languageFile.Version = new Version(node.Attributes["version"].Value); } @@ -316,51 +328,55 @@ namespace GreenshotPlugin.Core { foreach (string languageFilepath in Directory.GetFiles(languagePath, LANGUAGE_FILENAME_PATTERN, SearchOption.AllDirectories)) { LOG.DebugFormat("Found language file: {0}", languageFilepath); LanguageFile languageFile = LoadFileInfo(languageFilepath); - if (languageFile != null) { - // build prefix - if (string.IsNullOrEmpty(languageFile.Prefix)) { - string languageFilename = Path.GetFileNameWithoutExtension(languageFilepath); - if (PREFIX_REGEXP.IsMatch(languageFilename)) { - languageFile.Prefix = PREFIX_REGEXP.Replace(languageFilename, "$1"); - if (!string.IsNullOrEmpty(languageFile.Prefix)) { - languageFile.Prefix = languageFile.Prefix.Replace("plugin", "").ToLower(); + if (languageFile == null) { + continue; + } + + // Check if we can display the file + if (!string.IsNullOrEmpty(languageFile.LanguageGroup) && unsupportedLanguageGroups.Contains(languageFile.LanguageGroup)) { + LOG.InfoFormat("Skipping unsuported (not able to display) language {0}", languageFile.Description); + continue; + } + + // build prefix, based on the filename, but only if it's not set in the file itself. + if (string.IsNullOrEmpty(languageFile.Prefix)) { + string languageFilename = Path.GetFileNameWithoutExtension(languageFilepath); + if (PREFIX_REGEXP.IsMatch(languageFilename)) { + languageFile.Prefix = PREFIX_REGEXP.Replace(languageFilename, "$1"); + if (!string.IsNullOrEmpty(languageFile.Prefix)) { + languageFile.Prefix = languageFile.Prefix.Replace("plugin", "").ToLower(); + } + } + } + List currentFiles = null; + if (languageFiles.ContainsKey(languageFile.Ietf)) { + currentFiles = languageFiles[languageFile.Ietf]; + bool needToAdd = true; + List deleteList = new List(); + foreach (LanguageFile compareWithLangfile in currentFiles) { + if ((languageFile.Prefix == null && compareWithLangfile.Prefix == null) || (languageFile.Prefix != null && languageFile.Prefix.Equals(compareWithLangfile.Prefix))) { + if (compareWithLangfile.Version > languageFile.Version) { + LOG.WarnFormat("Skipping {0}:{1}:{2} as {3}:{4}:{5} is newer", languageFile.Filepath, languageFile.Prefix, languageFile.Version, compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version); + needToAdd = false; + break; + } else { + LOG.WarnFormat("Found {0}:{1}:{2} and deleting {3}:{4}:{5}", languageFile.Filepath, languageFile.Prefix, languageFile.Version, compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version); + deleteList.Add(compareWithLangfile); } } } - if (string.IsNullOrEmpty(languageFile.LanguageGroup) || !unsupportedLanguageGroups.Contains(languageFile.LanguageGroup)) { - List currentFiles = null; - if (languageFiles.ContainsKey(languageFile.Ietf)) { - currentFiles = languageFiles[languageFile.Ietf]; - bool needToAdd = true; - List deleteList = new List(); - foreach (LanguageFile compareWithLangfile in currentFiles) { - if ((languageFile.Prefix == null && compareWithLangfile.Prefix == null) || (languageFile.Prefix != null && languageFile.Prefix.Equals(compareWithLangfile.Prefix))) { - if (compareWithLangfile.Version > languageFile.Version) { - LOG.WarnFormat("Skipping {0}:{1}:{2} as {3}:{4}:{5} is newer", languageFile.Filepath, languageFile.Prefix, languageFile.Version, compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version); - needToAdd = false; - break; - } else { - LOG.WarnFormat("Found {0}:{1}:{2} and deleting {3}:{4}:{5}", languageFile.Filepath, languageFile.Prefix, languageFile.Version, compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version); - deleteList.Add(compareWithLangfile); - } - } - } - if (needToAdd) { - foreach (LanguageFile deleteFile in deleteList) { - currentFiles.Remove(deleteFile); - } - LOG.InfoFormat("Added language {0} from: {1}", languageFile.Description, languageFile.Filepath); - currentFiles.Add(languageFile); - } - } else { - currentFiles = new List(); - currentFiles.Add(languageFile); - languageFiles.Add(languageFile.Ietf, currentFiles); - LOG.InfoFormat("Added language {0} from: {1}", languageFile.Description, languageFile.Filepath); + if (needToAdd) { + foreach (LanguageFile deleteFile in deleteList) { + currentFiles.Remove(deleteFile); } - } else { - LOG.InfoFormat("Skipping unsupported language: {0}", languageFile.Description); + LOG.InfoFormat("Added language {0} from: {1}", languageFile.Description, languageFile.Filepath); + currentFiles.Add(languageFile); } + } else { + currentFiles = new List(); + currentFiles.Add(languageFile); + languageFiles.Add(languageFile.Ietf, currentFiles); + LOG.InfoFormat("Added language {0} from: {1}", languageFile.Description, languageFile.Filepath); } } } catch (DirectoryNotFoundException) { @@ -368,18 +384,18 @@ namespace GreenshotPlugin.Core { } catch (Exception e) { LOG.Error("Error trying for read directory " + languagePath, e); } + + // Now find the help files LOG.InfoFormat("Searching language directory '{0}' for help files with pattern '{1}'", languagePath, HELP_FILENAME_PATTERN); try { foreach (string helpFilepath in Directory.GetFiles(languagePath, HELP_FILENAME_PATTERN, SearchOption.AllDirectories)) { LOG.DebugFormat("Found help file: {0}", helpFilepath); - HelpFile helpFile = new HelpFile(); - helpFile.Filepath = helpFilepath; string helpFilename = Path.GetFileName(helpFilepath); - helpFile.Ietf = helpFilename.Replace(".html", "").Replace("help-", ""); - if (!helpFiles.ContainsKey(helpFile.Ietf)) { - helpFiles.Add(helpFile.Ietf, helpFile); + string ietf = ClearIETF(helpFilename.Replace(".html", "").Replace("help-", "")); + if (!helpFiles.ContainsKey(ietf)) { + helpFiles.Add(ietf, helpFilepath); } else { - LOG.WarnFormat("skipping help file {0}, already a file with the same IETF found!", helpFilepath); + LOG.WarnFormat("skipping help file {0}, already a file with the same IETF {1} found!", helpFilepath, ietf); } } } catch (DirectoryNotFoundException) { @@ -390,17 +406,12 @@ namespace GreenshotPlugin.Core { } } - public static string Dump() { - int max = 40; - StringBuilder dump = new StringBuilder(); - foreach (string key in resources.Keys) { - dump.AppendFormat("{0}={1}", key, resources[key]).AppendLine(); - if (max-- == 0) { - break; - } - } - return dump.ToString(); - } + /// + /// Check if a resource with prefix.key exists + /// + /// + /// + /// true if available public static bool hasKey(string prefix, Enum key) { if (key == null) { return false; @@ -408,6 +419,11 @@ namespace GreenshotPlugin.Core { return hasKey(prefix + "." + key.ToString()); } + /// + /// Check if a resource with key exists + /// + /// + /// true if available public static bool hasKey(Enum key) { if (key == null) { return false; @@ -415,10 +431,21 @@ namespace GreenshotPlugin.Core { return hasKey(key.ToString()); } + /// + /// Check if a resource with prefix.key exists + /// + /// + /// + /// true if available public static bool hasKey(string prefix, string key) { return hasKey(prefix + "." + key); } + /// + /// Check if a resource with key exists + /// + /// + /// true if available public static bool hasKey(string key) { if (key == null) { return false; @@ -426,6 +453,11 @@ namespace GreenshotPlugin.Core { return resources.ContainsKey(key); } + /// + /// Get the resource for key + /// + /// + /// resource or a "string ###key### not found" public static string GetString(Enum key) { if (key == null) { return null; @@ -433,6 +465,12 @@ namespace GreenshotPlugin.Core { return GetString(key.ToString()); } + /// + /// Get the resource for prefix.key + /// + /// + /// + /// resource or a "string ###prefix.key### not found" public static string GetString(string prefix, Enum key) { if (key == null) { return null; @@ -440,10 +478,21 @@ namespace GreenshotPlugin.Core { return GetString(prefix + "." + key.ToString()); } + /// + /// Get the resource for prefix.key + /// + /// + /// + /// resource or a "string ###prefix.key### not found" public static string GetString(string prefix, string key) { return GetString(prefix + "." + key); } + /// + /// Get the resource for key + /// + /// + /// resource or a "string ###key### not found" public static string GetString(string key) { if (key == null) { return null; @@ -455,24 +504,117 @@ namespace GreenshotPlugin.Core { return returnValue; } + /// + /// Get the resource for key, format with with string.format an supply the parameters + /// + /// + /// formatted resource or a "string ###key### not found" public static string GetFormattedString(Enum key, object param) { return GetFormattedString(key.ToString(), param); } + /// + /// Get the resource for prefix.key, format with with string.format an supply the parameters + /// + /// + /// formatted resource or a "string ###prefix.key### not found" public static string GetFormattedString(string prefix, Enum key, object param) { return GetFormattedString(prefix, key.ToString(), param); } + /// + /// Get the resource for prefix.key, format with with string.format an supply the parameters + /// + /// + /// formatted resource or a "string ###prefix.key### not found" public static string GetFormattedString(string prefix, string key, object param) { return GetFormattedString(prefix + "." + key, param); } + /// + /// Get the resource for key, format with with string.format an supply the parameters + /// + /// + /// formatted resource or a "string ###key### not found" public static string GetFormattedString(string key, object param) { string returnValue; if (!resources.TryGetValue(key, out returnValue)) { return "string ###" + key + "### not found"; } - return String.Format(returnValue, param); ; + return String.Format(returnValue, param); } } + + /// + /// This class contains the information about a language file + /// + public class LanguageFile : IEquatable { + public string Description { + get; + set; + } + + public string Ietf { + get; + set; + } + + public Version Version { + get; + set; + } + + public string LanguageGroup { + get; + set; + } + + public string Filepath { + get; + set; + } + + public string Prefix { + get; + set; + } + + /// + /// Overload equals so we can delete a entry from a collection + /// + /// + /// + public bool Equals(LanguageFile other) { + if (Prefix != null) { + if (!Prefix.Equals(other.Prefix)) { + return false; + } + } else if (other.Prefix != null) { + return false; + } + if (Ietf != null) { + if (!Ietf.Equals(other.Ietf)) { + return false; + } + } else if (other.Ietf != null) { + return false; + } + if (Version != null) { + if (!Version.Equals(other.Version)) { + return false; + } + } else if (other.Version != null) { + return false; + } + if (Filepath != null) { + if (!Filepath.Equals(other.Filepath)) { + return false; + } + } else if (other.Filepath != null) { + return false; + } + return true; + } + } + }