Skip to content

Commit 0cdee08

Browse files
author
Paul van Brenk
committed
* Add lock files to Dev15 build
* Generated xlf files for localization * Tool for generating xlif files, and localized vsct files
1 parent 96300be commit 0cdee08

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+6775
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
5+
</startup>
6+
</configuration>
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/* ****************************************************************************
2+
*
3+
* Copyright (c) Microsoft Corporation.
4+
*
5+
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6+
* copy of the license can be found in the License.html file at the root of this distribution.
7+
* By using this source code in any fashion, you are agreeing to be bound by the terms of
8+
* the Apache License, Version 2.0.
9+
*
10+
* You must not remove this notice, or any other, from this software.
11+
*
12+
* ***************************************************************************/
13+
14+
using System;
15+
using System.Collections.Generic;
16+
using System.IO;
17+
18+
namespace VsctToXliff
19+
{
20+
class Program
21+
{
22+
private static readonly string[] Locales = new[] { "cs", "de", "en", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW" };
23+
24+
private static int Main(string[] args)
25+
{
26+
var parsedArgs = new Args(args);
27+
if (parsedArgs.IsError)
28+
{
29+
return -1;
30+
}
31+
32+
switch (parsedArgs.Mode)
33+
{
34+
case Mode.GenerateXliff:
35+
CreateXliffFiles(parsedArgs.SourceFile, parsedArgs.XliffDir);
36+
return 0;
37+
case Mode.GenerateVsct:
38+
CreateVsctFiles(parsedArgs.SourceFile, parsedArgs.XliffDir);
39+
return 0;
40+
case Mode.Error:
41+
default:
42+
Console.WriteLine($"Unexpected processing mode: \'{parsedArgs.Mode}\'.");
43+
return -1;
44+
}
45+
}
46+
47+
private static void CreateXliffFiles(string sourceFile, string xlfDir)
48+
{
49+
if (string.IsNullOrEmpty(sourceFile) || string.IsNullOrEmpty(xlfDir))
50+
{
51+
throw new ArgumentNullException("file and targetDir should be set.");
52+
}
53+
54+
var rootName = Utilities.VsctFileNameWithoutExtension(sourceFile);
55+
56+
var reader = new VsctFile(sourceFile);
57+
var writer = new XliffFile(xlfDir, rootName);
58+
59+
foreach (var locale in Locales)
60+
{
61+
writer.WriteTranslationFile(sourceFile, reader.ReadTranslatableUnits(), locale);
62+
}
63+
}
64+
65+
private static void CreateVsctFiles(string sourceFile, string xlfDir)
66+
{
67+
if (string.IsNullOrEmpty(sourceFile))
68+
{
69+
throw new ArgumentNullException("file should be set.");
70+
}
71+
72+
var targetDir = Path.GetDirectoryName(sourceFile);
73+
var rootName = Utilities.VsctFileNameWithoutExtension(sourceFile);
74+
75+
var vsctFile = new VsctFile(sourceFile);
76+
var xlfFiles = new XliffFile(xlfDir, rootName);
77+
78+
foreach (var locale in Locales)
79+
{
80+
var translations = xlfFiles.LoadTranslatedElements(locale);
81+
vsctFile.WriteTranslatedFile(translations, locale);
82+
}
83+
}
84+
85+
private class Args
86+
{
87+
public bool IsError { get; }
88+
89+
public string XliffDir { get; }
90+
91+
public string SourceFile { get; }
92+
93+
public Mode Mode { get; }
94+
95+
public Args(string[] args)
96+
{
97+
if (args.Length < 3)
98+
{
99+
this.IsError = true;
100+
DisplayHelp();
101+
}
102+
else
103+
{
104+
this.SourceFile = Utilities.EnsureRootPath(args[0]);
105+
this.XliffDir = Utilities.EnsureRootPath(args[1]);
106+
switch (args[2].ToLowerInvariant())
107+
{
108+
case "--generatexlf":
109+
this.Mode = Mode.GenerateXliff;
110+
break;
111+
case "--generatevsct":
112+
this.Mode = Mode.GenerateVsct;
113+
break;
114+
default:
115+
this.IsError = true;
116+
break;
117+
}
118+
}
119+
}
120+
121+
private void DisplayHelp()
122+
{
123+
Console.WriteLine("usage: VsctToXliff.exe <sourcefile.vsct> <xliff dir> [--generatexlf | --generatevsct].");
124+
Console.WriteLine("--generatexlf\tThis will create xlf files for all VS locales in the xliff dir, overwriting any existing files!");
125+
Console.WriteLine("--generatevsct\tThis will create vsct files for all VS locales in the same dir as the sourecfile.vsct, overwriting any existing files!");
126+
}
127+
}
128+
129+
private enum Mode
130+
{
131+
Error,
132+
GenerateXliff,
133+
GenerateVsct,
134+
}
135+
}
136+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System.Reflection;
2+
using System.Runtime.InteropServices;
3+
4+
// General Information about an assembly is controlled through the following
5+
// set of attributes. Change these attribute values to modify the information
6+
// associated with an assembly.
7+
[assembly: AssemblyTitle("VsctToXliff")]
8+
[assembly: AssemblyDescription("Tool to generate Xliff files from vsct files, and generate localized vsct files.")]
9+
[assembly: AssemblyConfiguration("")]
10+
[assembly: AssemblyCompany("Microsoft")]
11+
[assembly: AssemblyProduct("VsctToXliff")]
12+
[assembly: AssemblyCopyright("Copyright © Microsoft 2016")]
13+
[assembly: AssemblyTrademark("")]
14+
[assembly: AssemblyCulture("")]
15+
16+
// Setting ComVisible to false makes the types in this assembly not visible
17+
// to COM components. If you need to access a type in this assembly from
18+
// COM, set the ComVisible attribute to true on that type.
19+
[assembly: ComVisible(false)]
20+
21+
// The following GUID is for the ID of the typelib if this project is exposed to COM
22+
[assembly: Guid("bbf7fd3f-26ba-4f6c-8485-f221cca1cf6a")]
23+
24+
// Version information for an assembly consists of the following four values:
25+
//
26+
// Major Version
27+
// Minor Version
28+
// Build Number
29+
// Revision
30+
//
31+
// You can specify all the values or you can default the Build and Revision Numbers
32+
// by using the '*' as shown below:
33+
// [assembly: AssemblyVersion("1.0.*")]
34+
[assembly: AssemblyVersion("1.0.0.0")]
35+
[assembly: AssemblyFileVersion("1.0.0.0")]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* ****************************************************************************
2+
*
3+
* Copyright (c) Microsoft Corporation.
4+
*
5+
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6+
* copy of the license can be found in the License.html file at the root of this distribution.
7+
* By using this source code in any fashion, you are agreeing to be bound by the terms of
8+
* the Apache License, Version 2.0.
9+
*
10+
* You must not remove this notice, or any other, from this software.
11+
*
12+
* ***************************************************************************/
13+
14+
using System;
15+
using System.IO;
16+
17+
namespace VsctToXliff
18+
{
19+
internal static class Utilities
20+
{
21+
public static string EnsureRootPath(string path)
22+
{
23+
if (Path.IsPathRooted(path))
24+
{
25+
return path;
26+
}
27+
28+
return new FileInfo(Path.Combine(Environment.CurrentDirectory, path)).FullName;
29+
}
30+
31+
/// <returns>The filename without extension or locale.</returns>
32+
public static string VsctFileNameWithoutExtension(string fileName)
33+
{
34+
// assume filename have the following structure: <filename>.<locale>.vsct
35+
var file = Path.GetFileName(fileName);
36+
37+
return file.Substring(0, file.IndexOf('.'));
38+
}
39+
}
40+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/* ****************************************************************************
2+
*
3+
* Copyright (c) Microsoft Corporation.
4+
*
5+
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6+
* copy of the license can be found in the License.html file at the root of this distribution.
7+
* By using this source code in any fashion, you are agreeing to be bound by the terms of
8+
* the Apache License, Version 2.0.
9+
*
10+
* You must not remove this notice, or any other, from this software.
11+
*
12+
* ***************************************************************************/
13+
14+
using System;
15+
using System.Collections.Generic;
16+
using System.IO;
17+
using System.Xml.Linq;
18+
19+
namespace VsctToXliff
20+
{
21+
internal sealed class VsctFile
22+
{
23+
private static readonly XNamespace NS = @"http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable";
24+
private static readonly string[] ChildNames = { "ButtonText", "ToolTipText", "MenuText", "CommandName" };
25+
26+
private const string VsctExt = ".vsct";
27+
28+
public string FileName { get; }
29+
30+
public VsctFile(string fileName)
31+
{
32+
if (string.IsNullOrEmpty(fileName))
33+
{
34+
throw new ArgumentException("fileName should be set");
35+
}
36+
37+
if (!Path.IsPathRooted(fileName))
38+
{
39+
throw new ArgumentException("Expected a rooted path");
40+
}
41+
42+
this.FileName = fileName;
43+
}
44+
45+
public IEnumerable<ITranslationUnit> ReadTranslatableUnits()
46+
{
47+
var document = XDocument.Load(this.FileName);
48+
foreach (var element in this.GetTranslatableElements(document))
49+
{
50+
var id = element.Attribute("id").Value;
51+
var strings = element.Element(NS + "Strings");
52+
53+
foreach (var name in ChildNames)
54+
{
55+
var child = strings.Element(NS + name);
56+
if (child != null)
57+
{
58+
yield return new TranslationUnit($"{id}|{name}", child.Value);
59+
}
60+
}
61+
}
62+
}
63+
64+
private IEnumerable<XElement> GetTranslatableElements(XDocument root)
65+
{
66+
foreach (var menuItem in root.Descendants(NS + "Menu"))
67+
{
68+
yield return menuItem;
69+
}
70+
foreach (var menuItem in root.Descendants(NS + "Button"))
71+
{
72+
yield return menuItem;
73+
}
74+
}
75+
76+
public void WriteTranslatedFile(IDictionary<string, string> translations, string targetLanguage)
77+
{
78+
var document = XDocument.Load(this.FileName);
79+
foreach( var element in this.GetTranslatableElements(document))
80+
{
81+
var id = element.Attribute("id").Value;
82+
var strings = element.Element(NS + "Strings");
83+
84+
foreach (var name in ChildNames)
85+
{
86+
var child = strings.Element(NS + name);
87+
if (child != null && translations.TryGetValue($"{id}|{name}", out var value))
88+
{
89+
child.Value = value;
90+
}
91+
}
92+
}
93+
94+
var rootDir = Path.GetDirectoryName(this.FileName);
95+
var rootName = Utilities.VsctFileNameWithoutExtension(this.FileName);
96+
97+
document.Save(Path.Combine(rootDir, $"{rootName}.{targetLanguage}{VsctExt}"));
98+
}
99+
100+
private sealed class TranslationUnit : ITranslationUnit
101+
{
102+
public string Key { get; }
103+
public string EnglishValue { get; }
104+
105+
public TranslationUnit(string key, string value)
106+
{
107+
this.Key = key;
108+
this.EnglishValue = value;
109+
}
110+
}
111+
}
112+
113+
internal interface ITranslationUnit
114+
{
115+
string Key { get; }
116+
string EnglishValue { get; }
117+
}
118+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{BBF7FD3F-26BA-4F6C-8485-F221CCA1CF6A}</ProjectGuid>
8+
<OutputType>Exe</OutputType>
9+
<RootNamespace>VsctToXliff</RootNamespace>
10+
<AssemblyName>VsctToXliff</AssemblyName>
11+
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
12+
<FileAlignment>512</FileAlignment>
13+
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
14+
<TargetFrameworkProfile />
15+
</PropertyGroup>
16+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
17+
<PlatformTarget>AnyCPU</PlatformTarget>
18+
<DebugSymbols>true</DebugSymbols>
19+
<DebugType>full</DebugType>
20+
<Optimize>false</Optimize>
21+
<OutputPath>bin\Debug\</OutputPath>
22+
<DefineConstants>DEBUG;TRACE</DefineConstants>
23+
<ErrorReport>prompt</ErrorReport>
24+
<WarningLevel>4</WarningLevel>
25+
</PropertyGroup>
26+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27+
<PlatformTarget>AnyCPU</PlatformTarget>
28+
<DebugType>pdbonly</DebugType>
29+
<Optimize>true</Optimize>
30+
<OutputPath>bin\Release\</OutputPath>
31+
<DefineConstants>TRACE</DefineConstants>
32+
<ErrorReport>prompt</ErrorReport>
33+
<WarningLevel>4</WarningLevel>
34+
</PropertyGroup>
35+
<ItemGroup>
36+
<Reference Include="System" />
37+
<Reference Include="System.Core" />
38+
<Reference Include="System.Xml.Linq" />
39+
<Reference Include="System.Data.DataSetExtensions" />
40+
<Reference Include="Microsoft.CSharp" />
41+
<Reference Include="System.Data" />
42+
<Reference Include="System.Net.Http" />
43+
<Reference Include="System.Xml" />
44+
</ItemGroup>
45+
<ItemGroup>
46+
<Compile Include="Program.cs" />
47+
<Compile Include="Properties\AssemblyInfo.cs" />
48+
<Compile Include="Utilities.cs" />
49+
<Compile Include="VsctFile.cs" />
50+
<Compile Include="XliffFile.cs" />
51+
</ItemGroup>
52+
<ItemGroup>
53+
<None Include="App.config" />
54+
</ItemGroup>
55+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
56+
</Project>

0 commit comments

Comments
 (0)