File: Tasks\TransformTemplates.cs
Web Access
Project: src\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;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using XliffTasks.Model;
 
namespace XliffTasks.Tasks
{
    public sealed class TransformTemplates : XlfTask
    {
        [Required]
        public ITaskItem[] Templates { get; set; }
 
        [Required]
        public ITaskItem[] UnstructuredResources { get; set; }
 
        [Required]
        public string[] Languages { get; set; }
 
        [Required]
        public string TranslatedOutputDirectory { get; set; }
 
        [Output]
        public ITaskItem[] TransformedTemplates { get; set; }
 
        protected override void ExecuteCore()
        {
            List<ITaskItem> transformedTemplates = new();
            Dictionary<string, ITaskItem> resourceMap = UnstructuredResources.ToDictionary(item => item.GetMetadata("FullPath"));
            foreach (ITaskItem template in Templates)
            {
                // special-case the default template items as the 1033 culture
                ITaskItem defaultTemplate = TransformTemplate(template, language: null, resourceMap: null);
                transformedTemplates.Add(defaultTemplate);
 
                // and process other languages like normal
                foreach (string language in Languages)
                {
                    ITaskItem item = TransformTemplate(template, language, resourceMap);
                    transformedTemplates.Add(item);
                }
            }
 
            TransformedTemplates = transformedTemplates.ToArray();
        }
 
        private ITaskItem TransformTemplate(ITaskItem template, string language, IDictionary<string, ITaskItem> resourceMap)
        {
            if ((language == null) ^ (resourceMap == null))
            {
                throw new ArgumentException($"Either both '{nameof(language)}' and '{nameof(resourceMap)}' must be specified, or they both must be 'null'.");
            }
 
            bool transformingDefaultTemplate = language == null;
            string templateCulture = transformingDefaultTemplate ? "1033" : language;
 
            string templateName = Path.GetFileNameWithoutExtension(template.ItemSpec);
            string templatePath = template.GetMetadata("FullPath");
            string templateDirectory = Path.GetDirectoryName(templatePath);
            XDocument templateXml = XDocument.Load(templatePath);
 
            // create a copy of the .vstemplate and all files
            string localizedTemplateDirectory = transformingDefaultTemplate
                ? Path.Combine(TranslatedOutputDirectory, $"{templateName}.default.1033")
                : Path.Combine(TranslatedOutputDirectory, $"{templateName}.{language}");
            Directory.CreateDirectory(localizedTemplateDirectory);
            string cultureSpecificTemplateFile = Path.Combine(localizedTemplateDirectory, Path.GetFileName(template.ItemSpec));
            File.Copy(templatePath, cultureSpecificTemplateFile, overwrite: true);
 
            // copy the template project files
            foreach (XElement projectNode in templateXml.Descendants().Where(d => d.Name.LocalName == "Project"))
            {
                string projectFileFullPath = Path.Combine(templateDirectory, projectNode.Attribute("File").Value);
                File.Copy(projectFileFullPath, Path.Combine(localizedTemplateDirectory, Path.GetFileName(projectNode.Attribute("File").Value)), overwrite: true);
            }
 
            // copy the template project items
            foreach (XElement templateItem in templateXml.Descendants().Where(d => d.Name.LocalName == "ProjectItem"))
            {
                string templateItemFullPath = Path.Combine(templateDirectory, templateItem.Value);
                string templateItemDestinationPath = Path.Combine(localizedTemplateDirectory, templateItem.Value);
                if (transformingDefaultTemplate)
                {
                    // if not localizing anything, simply strip out the translation markers
                    UnstructuredDocument document = new();
                    document.Load(templateItemFullPath);
                    Dictionary<string, string> defaultTranslation = document.Nodes.ToDictionary(node => node.Id, node => node.Source);
                    document.Translate(defaultTranslation);
                    document.Save(templateItemDestinationPath);
                }
                else
                {
                    // try to localize the template items
                    if (resourceMap.TryGetValue(templateItemFullPath, out ITaskItem unstructuredResource))
                    {
                        // copy a localized file
                        string localizedFileName = string.Concat(
                            Path.GetFileNameWithoutExtension(unstructuredResource.ItemSpec),
                            ".",
                            language,
                            Path.GetExtension(unstructuredResource.ItemSpec));
                        File.Copy(Path.Combine(TranslatedOutputDirectory, localizedFileName), templateItemDestinationPath, overwrite: true);
                    }
                    else
                    {
                        // copy the original unaltered file
                        File.Copy(templateItemFullPath, templateItemDestinationPath, overwrite: true);
                    }
                }
            }
 
            TaskItem item = new(cultureSpecificTemplateFile);
            item.SetMetadata("Culture", templateCulture);
            return item;
        }
    }
}