Skip to content

Commit

Permalink
External translations, Refactored Silent mode
Browse files Browse the repository at this point in the history
Refactored silent mode code before pull #12 arrived, but integrated some
features from it.  Translations will be available shortly.
  • Loading branch information
lenovo-inc committed Feb 24, 2015
1 parent 2388732 commit 65094ee
Show file tree
Hide file tree
Showing 19 changed files with 541 additions and 273 deletions.
56 changes: 56 additions & 0 deletions SuperFishRemovalTool/Localization/AppStrings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SuperFishRemovalTool.Localization
{
public class AppStrings
{
public string UtilityAbout { get; set; }
public string UtilityName { get; set; }
public string Version { get; set; }

public string AboutSuperfish { get; set; }
public string AboutThisTool { get; set; }

public string DetectorNameApp { get; set; }
public string DetectorNameReg { get; set; }
public string DetectorNameCert { get; set; }
public string DetectorNameFile { get; set; }
public string DetectorNameMozilla { get; set; }

public string SelectRemoveToStart { get; set; }

public string StatusRegNotExists { get; set; }
public string Remove { get; set; }
public string CloseWebBrowsers { get; set; }
public string LearnMoreText { get; set; }
public string LearnMoreLocation { get; set; }
public string RemovalCompleteMessage { get; set; }

public string ResultFoundAndRemoved { get; set; }
public string ResultFoundButNotRemoved { get; set; }
public string ResultNotFound { get; set; }
public string Error { get; set; }

public string OverallStatusAppRemoved { get; set; }
public string OverallStatusError { get; set; }
public string OverallStatusNotOnSystem { get; set; }

public string RestartNow { get; set; }
public string RestartLater { get; set; }

public string MoreInformationText { get; set; }
public string ManualRemovalInstructionsText { get; set; }
public string ManualRemovalInstructionsLink { get; set; }
public string LenovoSecurityAdvisoryLink { get; set; }
public string LenovoSecurityAdvisoryText { get; set; }
public string LenovoStatementText { get; set; }
public string LenovoStatementLink { get; set; }
public string LicenseAgreementText { get; set; }
public string LicenseAgreementLink { get; set; }
}

}
39 changes: 39 additions & 0 deletions SuperFishRemovalTool/Localization/AppStrings_en.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?>
<LocalizationSet language="en">
<ItemList>
<Item key="DetectorNameApp">Superfish Application</Item>
<Item key="DetectorNameReg">Superfish Registry entries</Item>
<Item key="DetectorNameCert">SuperFish Root Certificate</Item>
<Item key="DetectorNameFile">SuperFish Files</Item>
<Item key="DetectorNameMozilla">SuperFish Root Certificate for Mozilla products</Item>
<Item key="Version">Version</Item>
<Item key="AboutSuperfish">SuperFish was pre-installed on a limited group of Lenovo branded notebooks beginning September, 2014. Lenovo recommends removing SuperFish and the SuperFish certificates from all systems.</Item>

<Item key="AboutThisTool">This utility will completely analyze your system for this problem and remove the SuperFish application, associated registry entries, files and security certificates, if needed.</Item>
<Item key="UtilityName">SuperFish Removal Utility</Item>
<Item key="SelectRemoveToStart">Select 'Remove' to start</Item>
<Item key="CloseWebBrowsers">Please close all browsers before continuing</Item>
<Item key="Remove">Analyze and Remove SuperFish Now</Item>
<Item key="LearnMoreText">Click here to learn about this tool</Item>
<Item key="LearnMoreLocation">http://forums.lenovo.com/t5/Lenovo-P-Y-and-Z-series/Removal-Instructions-for-VisualDiscovery-Superfish-application/ta-p/2029206</Item>
<Item key="RemovalCompleteMessage"></Item>
<Item key="OverallStatusAppRemoved">SuperFish was removed from this system. We recommend restarting your system.</Item>
<Item key="OverallStatusError">Error: We could not remove one or more components. We recommend you follow the manual removal instructions below.</Item>
<Item key="OverallStatusNotOnSystem">Complete: SuperFish was not found on this system and no action is required.</Item>
<Item key="RestartNow">Restart now</Item>
<Item key="RestartLater">Restart later</Item>
<Item key="ResultFoundAndRemoved">Found and removed</Item>
<Item key="ResultFoundButNotRemoved">Found but not removed</Item>
<Item key="ResultNotFound">Not Found</Item>
<Item key="Error">Error</Item>
<Item key="MoreInformationText">More information:</Item>
<Item key="ManualRemovalInstructionsText">Manual Removal Instructions</Item>
<Item key="LenovoSecurityAdvisoryText">Lenovo Security Advisory</Item>
<Item key="LenovoStatementText">Lenovo Statement</Item>
<Item key="LenovoStatementLink">http://news.lenovo.com/article_display.cfm?article_id=1929</Item>
<Item key="ManualRemovalInstructionsLink">http://support.lenovo.com/us/en/product_security/superfish_uninstall</Item>
<Item key="LenovoSecurityAdvisoryLink">http://support.lenovo.com/us/en/product_security/superfish</Item>
<Item key="LicenseAgreementLink">http://support.lenovo.com/us/en/documents/ht100141</Item>
<Item key="LicenseAgreementText">Lenovo License Agreement</Item>
</ItemList>
</LocalizationSet>
161 changes: 161 additions & 0 deletions SuperFishRemovalTool/Localization/LocalizationManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SuperFishRemovalTool.Localization
{
/// <summary>
/// Responsible for loading strongly typed localizations from embedded XML translation files
/// </summary>
/// <remarks>
/// The primary reason for not using standard localization (resx) is to avoid satellite assemblies
/// </remarks>
internal static class LocalizationManager
{
/// <summary>
/// Gets a set of translations for the most applicable user language
/// </summary>
/// <returns></returns>
public static AppStrings Get()
{
if (_cachedAppStrings == null)
{
AppStrings appStrings = null;
try
{
LocalizationSet localizations = LocateIdealTranslationFile(translationFilePrefix: "AppStrings");
appStrings = MapTranslationItemsToStronglyTypedInstance<AppStrings>(localizations);
}
catch(Exception ex)
{
Logging.Logger.Log(ex, "Unable to locate translations");
}

_cachedAppStrings = appStrings ?? new AppStrings(); // prevent from trying again
}
return _cachedAppStrings;
}

private static AppStrings _cachedAppStrings;

/// <summary>
/// Examines embedded translation files and looks for the most ideal one based on current culture
/// </summary>
/// <returns></returns>
private static LocalizationSet LocateIdealTranslationFile(string translationFilePrefix)
{
LocalizationSet localizationSet = null;
var currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
var listOfTranslationFiles = GetLocalizationFilePaths();
if(listOfTranslationFiles == null || !listOfTranslationFiles.Any())
{
throw new Exception("No localization files found");
}

List<string> prioritizedLanguages = new List<string>()
{
currentCulture.Name, // "en-US"
currentCulture.TwoLetterISOLanguageName, // "en"
"en", // en is default
};

foreach(var priority in prioritizedLanguages)
{
string predictedFileName = String.Format("{0}_{1}.xml", translationFilePrefix, priority);
try
{
string foundMatchingTranslationFile = listOfTranslationFiles.FirstOrDefault(filePath =>
!String.IsNullOrWhiteSpace(filePath) &&
filePath.EndsWith(predictedFileName, StringComparison.InvariantCultureIgnoreCase));

if (!String.IsNullOrWhiteSpace(foundMatchingTranslationFile))
{
localizationSet = LoadStringsFromFile(foundMatchingTranslationFile);
if(localizationSet != null)
{
break;
}
}
}
catch(Exception ex)
{
Logging.Logger.Log(ex, "Unable to process localization file {0} ", predictedFileName);
}
}

if(localizationSet == null)
{
throw new System.IO.FileNotFoundException("No valid translation files matching expected values");
}
return localizationSet;
}

/// <summary>
/// Maps each item in a localized set into a strongly typed stringtable
/// </summary>
/// <typeparam name="T">The type that contains properties for each string</typeparam>
/// <param name="translations"></param>
/// <returns></returns>
private static T MapTranslationItemsToStronglyTypedInstance<T>(LocalizationSet translations) where T : class
{
T result = (T)Activator.CreateInstance(typeof(T));

var properties = typeof(T).GetProperties();
foreach(var property in properties)
{
string name = property.Name;
var matchingTranslatedItem = translations.ItemList.FirstOrDefault(item =>
item.Key != null &&
item.Key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase));
if (matchingTranslatedItem != null)
{
property.SetMethod.Invoke(result, new object[] { matchingTranslatedItem.Value });
}
}


return result;
}

/// <summary>
/// Deserializes a translation xml file into an instance
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
private static LocalizationSet LoadStringsFromFile(string filePath)
{
LocalizationSet set = null;
using (var stream = (System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceStream(filePath)))
{
using (var reader = new System.IO.StreamReader(stream))
{
string xmlFileContents = reader.ReadToEnd();
var deserializedObject = Serializer.Deserialize<LocalizationSet>(xmlFileContents);
set = deserializedObject;

}
}
return set;
}

/// <summary>
/// Locates all xml files that may be translation files
/// </summary>
/// <returns></returns>
private static IEnumerable<string> GetLocalizationFilePaths()
{
var dataFiles = System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceNames()
.Where(s =>
s.StartsWith(typeof(LocalizationManager).Namespace) &&
s.EndsWith(".xml"));
return dataFiles;
}

}


}
29 changes: 29 additions & 0 deletions SuperFishRemovalTool/Localization/LocalizationSet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace SuperFishRemovalTool.Localization
{
[XmlRoot(ElementName = "LocalizationSet", Namespace = null)]
public class LocalizationSet
{
[XmlAttribute(AttributeName = "language")]
public string Language { get; set; }

[XmlArray("ItemList")]
[XmlArrayItem("Item")]
public Item[] ItemList { get; set; }
}

public class Item
{
[XmlAttribute(AttributeName = "key")]
public string Key { get; set; }
[XmlText]
public string Value { get; set; }

}
}
Loading

0 comments on commit 65094ee

Please sign in to comment.