| File: Model\VsctDocument.cs | Web Access |
| Project: src\arcade\src\Microsoft.DotNet.XliffTasks\Microsoft.DotNet.XliffTasks.csproj (Microsoft.DotNet.XliffTasks) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.IO; using System.Xml.Linq; namespace XliffTasks.Model { /// <summary> /// A <see cref="TranslatableDocument"/> for files in .vsct format. /// See https://msdn.microsoft.com/en-us/library/bb164699.aspx /// </summary> internal sealed class VsctDocument : TranslatableXmlDocument { protected override IEnumerable<TranslatableNode> GetTranslatableNodes() { HashSet<string> nonUniqueIds = FindNonUniqueIds(); foreach (XElement strings in Document.Descendants(Document.Root.Name.Namespace + "Strings")) { string id = strings.Parent.Attribute("id").Value; if (nonUniqueIds.Contains(id)) { // The ID by itself is not unique in this document; we must include // the GUID as well. string guid = strings.Parent.Attribute("guid").Value; id = guid + "|" + id; } foreach (XElement child in strings.Elements()) { XName name = child.Name; if (name.LocalName == "CanonicalName") { // CanonicalName is never localized. // LocCanonicalName can be used to specify a localized alternative. // See https://msdn.microsoft.com/en-us/library/bb491712.aspx continue; } yield return new TranslatableXmlElement( id: $"{id}|{name.LocalName}", source: child.Value, note: null, element: child); } } } /// <summary> /// Finds the set of IDs that do not uniquely identify a single set of strings. /// Within a .vsct file only the combination of GUID and ID needs to be unique, /// but for brevity we'd prefer to use just the ID when we can. By finding the /// set of non-unique IDs we can identify when this will not be sufficient. /// </summary> /// <returns></returns> private HashSet<string> FindNonUniqueIds() { HashSet<string> idsAlreadySeen = new(); HashSet<string> conflictingIds = new(); foreach (XElement strings in Document.Descendants(Document.Root.Name.Namespace + "Strings")) { string id = strings.Parent.Attribute("id").Value; if (!idsAlreadySeen.Add(id)) { conflictingIds.Add(id); } } return conflictingIds; } public override void RewriteRelativePathsToAbsolute(string sourceFullPath) { foreach (XElement imageTag in Document.Descendants(Document.Root.Name.Namespace + "Bitmap")) { XAttribute hrefAttribute = imageTag.Attribute("href"); if (hrefAttribute != null) { string resourceRelativePath = hrefAttribute.Value.Replace('\\', Path.DirectorySeparatorChar); string absolutePath = Path.Combine(Path.GetDirectoryName(sourceFullPath), resourceRelativePath); imageTag.Attribute("href").Value = absolutePath; } } } } }