From 4ebc33174c02e1c9f5693b5ef38ecfe3292c687f Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Fri, 11 Aug 2017 00:39:04 -0700 Subject: Move to .NET Core 2.0 --- src/WixToolset.Data/Localization.cs | 372 ++++++++++++++++++++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100644 src/WixToolset.Data/Localization.cs (limited to 'src/WixToolset.Data/Localization.cs') diff --git a/src/WixToolset.Data/Localization.cs b/src/WixToolset.Data/Localization.cs new file mode 100644 index 00000000..658ce14a --- /dev/null +++ b/src/WixToolset.Data/Localization.cs @@ -0,0 +1,372 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Data +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Reflection; + using System.Xml; + using System.Xml.Linq; + using System.Xml.Schema; + using WixToolset.Data.Msi; + using WixToolset.Data.Rows; + + /// + /// Object that represents a localization file. + /// + public sealed class Localization + { + private static string XmlElementName = "localization"; + + private Dictionary variables = new Dictionary(); + private Dictionary localizedControls = new Dictionary(); + + /// + /// Instantiates a new localization object. + /// + public Localization(int codepage, string culture, IDictionary variables, IDictionary localizedControls) + { + this.Codepage = codepage; + this.Culture = String.IsNullOrEmpty(culture) ? String.Empty : culture.ToLowerInvariant(); + this.variables = new Dictionary(variables); + this.localizedControls = new Dictionary(localizedControls); + } + + /// + /// Gets the codepage. + /// + /// The codepage. + public int Codepage { get; private set; } + + /// + /// Gets the culture. + /// + /// The culture. + public string Culture { get; private set; } + + /// + /// Gets the variables. + /// + /// The variables. + public ICollection Variables + { + get { return this.variables.Values; } + } + + /// + /// Gets the localized controls. + /// + /// The localized controls. + public ICollection> LocalizedControls + { + get { return this.localizedControls; } + } + + /// + /// Merge the information from another localization object into this one. + /// + /// The localization object to be merged into this one. + public void Merge(Localization localization) + { + foreach (WixVariableRow wixVariableRow in localization.Variables) + { + WixVariableRow existingWixVariableRow; + if (!this.variables.TryGetValue(wixVariableRow.Id, out existingWixVariableRow) || (existingWixVariableRow.Overridable && !wixVariableRow.Overridable)) + { + variables[wixVariableRow.Id] = wixVariableRow; + } + else if (!wixVariableRow.Overridable) + { + throw new WixException(WixDataErrors.DuplicateLocalizationIdentifier(wixVariableRow.SourceLineNumbers, wixVariableRow.Id)); + } + } + } + + /// + /// Loads a localization file from a stream. + /// + /// XmlReader where the intermediate is persisted. + /// Collection containing TableDefinitions to use when loading the localization file. + /// Returns the loaded localization. + internal static Localization Read(XmlReader reader, TableDefinitionCollection tableDefinitions) + { + Debug.Assert("localization" == reader.LocalName); + + int codepage = 0; + string culture = null; + bool empty = reader.IsEmptyElement; + + while (reader.MoveToNextAttribute()) + { + switch (reader.Name) + { + case "codepage": + codepage = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); + break; + case "culture": + culture = reader.Value; + break; + } + } + + TableDefinition wixVariableTable = tableDefinitions["WixVariable"]; + Dictionary variables = new Dictionary(); + Dictionary localizedControls = new Dictionary(); + + if (!empty) + { + bool done = false; + + while (!done && reader.Read()) + { + switch (reader.NodeType) + { + case XmlNodeType.Element: + switch (reader.LocalName) + { + case "string": + WixVariableRow row = Localization.ReadString(reader, wixVariableTable); + variables.Add(row.Id, row); + break; + + case "ui": + LocalizedControl ui = Localization.ReadUI(reader); + localizedControls.Add(ui.GetKey(), ui); + break; + + default: + throw new XmlException(); + } + break; + case XmlNodeType.EndElement: + done = true; + break; + } + } + + if (!done) + { + throw new XmlException(); + } + } + + return new Localization(codepage, culture, variables, localizedControls); + } + + /// + /// Writes a localization file into an XML format. + /// + /// XmlWriter where the localization file should persist itself as XML. + internal void Write(XmlWriter writer) + { + writer.WriteStartElement(Localization.XmlElementName, Library.XmlNamespaceUri); + + if (-1 != this.Codepage) + { + writer.WriteAttributeString("codepage", this.Codepage.ToString(CultureInfo.InvariantCulture)); + } + + if (!String.IsNullOrEmpty(this.Culture)) + { + writer.WriteAttributeString("culture", this.Culture); + } + + foreach (WixVariableRow wixVariableRow in this.variables.Values) + { + writer.WriteStartElement("string", Library.XmlNamespaceUri); + + writer.WriteAttributeString("id", wixVariableRow.Id); + + if (wixVariableRow.Overridable) + { + writer.WriteAttributeString("overridable", "yes"); + } + + writer.WriteCData(wixVariableRow.Value); + + writer.WriteEndElement(); + } + + foreach (string controlKey in this.localizedControls.Keys) + { + writer.WriteStartElement("ui", Library.XmlNamespaceUri); + + string[] controlKeys = controlKey.Split('/'); + string dialog = controlKeys[0]; + string control = controlKeys[1]; + + if (!String.IsNullOrEmpty(dialog)) + { + writer.WriteAttributeString("dialog", dialog); + } + + if (!String.IsNullOrEmpty(control)) + { + writer.WriteAttributeString("control", control); + } + + LocalizedControl localizedControl = this.localizedControls[controlKey]; + + if (Common.IntegerNotSet != localizedControl.X) + { + writer.WriteAttributeString("x", localizedControl.X.ToString()); + } + + if (Common.IntegerNotSet != localizedControl.Y) + { + writer.WriteAttributeString("y", localizedControl.Y.ToString()); + } + + if (Common.IntegerNotSet != localizedControl.Width) + { + writer.WriteAttributeString("width", localizedControl.Width.ToString()); + } + + if (Common.IntegerNotSet != localizedControl.Height) + { + writer.WriteAttributeString("height", localizedControl.Height.ToString()); + } + + if (MsiInterop.MsidbControlAttributesRTLRO == (localizedControl.Attributes & MsiInterop.MsidbControlAttributesRTLRO)) + { + writer.WriteAttributeString("rightToLeft", "yes"); + } + + if (MsiInterop.MsidbControlAttributesRightAligned == (localizedControl.Attributes & MsiInterop.MsidbControlAttributesRightAligned)) + { + writer.WriteAttributeString("rightAligned", "yes"); + } + + if (MsiInterop.MsidbControlAttributesLeftScroll == (localizedControl.Attributes & MsiInterop.MsidbControlAttributesLeftScroll)) + { + writer.WriteAttributeString("leftScroll", "yes"); + } + + if (!String.IsNullOrEmpty(localizedControl.Text)) + { + writer.WriteCData(localizedControl.Text); + } + + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + } + + /// + /// Loads a localization file from a stream. + /// + /// XmlReader where the intermediate is persisted. + /// Collection containing TableDefinitions to use when loading the localization file. + /// Returns the loaded localization. + private static WixVariableRow ReadString(XmlReader reader, TableDefinition wixVariableTable) + { + Debug.Assert("string" == reader.LocalName); + + string id = null; + string value = null; + bool overridable = false; + bool empty = reader.IsEmptyElement; + + while (reader.MoveToNextAttribute()) + { + switch (reader.Name) + { + case "id": + id = reader.Value; + break; + case "overridable": + overridable = reader.Value.Equals("yes"); + break; + } + } + + + if (!empty) + { + reader.Read(); + + value = reader.Value; + + reader.Read(); + + if (XmlNodeType.EndElement != reader.NodeType) + { + throw new XmlException(); + } + } + + WixVariableRow wixVariableRow = new WixVariableRow(SourceLineNumber.CreateFromUri(reader.BaseURI), wixVariableTable); + wixVariableRow.Id = id; + wixVariableRow.Overridable = overridable; + wixVariableRow.Value = value; + + return wixVariableRow; + } + + private static LocalizedControl ReadUI(XmlReader reader) + { + Debug.Assert("ui" == reader.LocalName); + + string dialog = null; + string control = null; + int x = Common.IntegerNotSet; + int y = Common.IntegerNotSet; + int width = Common.IntegerNotSet; + int height = Common.IntegerNotSet; + int attributes = Common.IntegerNotSet; + string text = null; + bool empty = reader.IsEmptyElement; + + while (reader.MoveToNextAttribute()) + { + switch (reader.Name) + { + case "dialog": + dialog = reader.Value; + break; + case "control": + control = reader.Value; + break; + case "x": + x = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); + break; + case "y": + y = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); + break; + case "width": + width = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); + break; + case "height": + height = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); + break; + case "attributes": + attributes = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); + break; + } + } + + if (!empty) + { + reader.Read(); + + text = reader.Value; + + reader.Read(); + + if (XmlNodeType.EndElement != reader.NodeType) + { + throw new XmlException(); + } + } + + return new LocalizedControl(dialog, control, x, y, width, height, attributes, text); + } + } +} -- cgit v1.2.3-55-g6feb