Adding the Metadata Translation project.
This commit is contained in:
parent
0169a7a4c0
commit
8ec484fc17
25
MetadataTranslator/Metadata Translator.sln
Normal file
25
MetadataTranslator/Metadata Translator.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.30907.101
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metadata Translator", "Metadata Translator\Metadata Translator.csproj", "{CB7D493C-B67E-4438-B304-EFE5D418ADDF}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{CB7D493C-B67E-4438-B304-EFE5D418ADDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{CB7D493C-B67E-4438-B304-EFE5D418ADDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{CB7D493C-B67E-4438-B304-EFE5D418ADDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{CB7D493C-B67E-4438-B304-EFE5D418ADDF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {0733CEFA-6458-4D8F-B498-FC9827973880}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
13
MetadataTranslator/Metadata Translator/App.config
Normal file
13
MetadataTranslator/Metadata Translator/App.config
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||||
|
</startup>
|
||||||
|
<appSettings>
|
||||||
|
<add key="SubscriptionKey" value="" />
|
||||||
|
<add key="TranslatorEndpoint" value="https://api.cognitive.microsofttranslator.com/" />
|
||||||
|
<add key="TranslatorLocation" value="" />
|
||||||
|
<add key="OverwriteTranslation" value="false" />
|
||||||
|
<add key="LastUsedExportFolder" value="" />
|
||||||
|
</appSettings>
|
||||||
|
</configuration>
|
13
MetadataTranslator/Metadata Translator/App.xaml
Normal file
13
MetadataTranslator/Metadata Translator/App.xaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<Application x:Class="Metadata_Translator.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:Metadata_Translator"
|
||||||
|
Startup="Application_Startup">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="Resources\StringDictionary.xaml"/>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
22
MetadataTranslator/Metadata Translator/App.xaml.cs
Normal file
22
MetadataTranslator/Metadata Translator/App.xaml.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for App.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
private void Application_Startup(object sender, StartupEventArgs e)
|
||||||
|
{
|
||||||
|
MainWindow mainWindow = new MainWindow(e);
|
||||||
|
mainWindow.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class CollectionEmptyTrueFalseConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return (value is ObservableCollection<ExpandoObject> collection) ? collection.Count > 0 : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class PercentageConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is Double size)
|
||||||
|
{
|
||||||
|
return size * 0.5;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class TranslationPropertyToolTipConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if(parameter is string toolTipString)
|
||||||
|
{
|
||||||
|
string[] toolTip = toolTipString.Split('|');
|
||||||
|
if (value is ObservableCollection<ExpandoObject> collection && toolTip?.Length == 2)
|
||||||
|
{
|
||||||
|
return collection.Count > 0 ? toolTip[0] : toolTip[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return toolTipString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
class TrueFalseVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return (System.Convert.ToBoolean(value))? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FalseTrueVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return (System.Convert.ToBoolean(value)) ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
MetadataTranslator/Metadata Translator/Data/CsvRow.cs
Normal file
15
MetadataTranslator/Metadata Translator/Data/CsvRow.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class CsvRow
|
||||||
|
{
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string Original { get; set; }
|
||||||
|
public string Translation { get; set; }
|
||||||
|
}
|
||||||
|
}
|
420
MetadataTranslator/Metadata Translator/Data/DataModel.cs
Normal file
420
MetadataTranslator/Metadata Translator/Data/DataModel.cs
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AS = Microsoft.AnalysisServices;
|
||||||
|
using Microsoft.AnalysisServices.Tabular;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.IO;
|
||||||
|
using System.Web.Script.Serialization;
|
||||||
|
using Microsoft.VisualBasic.FileIO;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class DataModel
|
||||||
|
{
|
||||||
|
Model Model { get; set; }
|
||||||
|
|
||||||
|
public string ContainerColumnHeader { get => "Object"; }
|
||||||
|
public ObservableCollection<ExpandoObject> Captions { get; private set; }
|
||||||
|
public ObservableCollection<ExpandoObject> Descriptions { get; private set; }
|
||||||
|
public ObservableCollection<ExpandoObject> DisplayFolders { get; private set; }
|
||||||
|
|
||||||
|
public string DefaultCulture { get; set; }
|
||||||
|
|
||||||
|
public List<string> CultureNames
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<string> cultures = new List<string> { Model.Culture };
|
||||||
|
cultures.AddRange(Model?.Cultures.Where(i => !i.Name.Equals(Model.Culture)).Select(x => x.Name).ToList());
|
||||||
|
return cultures;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<Language> SupportedLanguages { get; private set; }
|
||||||
|
public List<Language> SelectedLanguages { get => SupportedLanguages?.Where(x => x.IsSelected==true).ToList(); }
|
||||||
|
public bool HasTargetLanguages { get => SelectedLanguages?.Count > 1; }
|
||||||
|
|
||||||
|
public DataModel(string server, string database)
|
||||||
|
{
|
||||||
|
LoadLanguages();
|
||||||
|
|
||||||
|
Server pbiDesktop = new Server();
|
||||||
|
pbiDesktop.Connect($"Data Source={server}");
|
||||||
|
Database dataset = pbiDesktop.Databases.GetByName(database);
|
||||||
|
Model = dataset.Model;
|
||||||
|
|
||||||
|
DefaultCulture = Model.Culture;
|
||||||
|
|
||||||
|
LoadNamedObjectCollections();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A static helper to get the DataModel object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="server"></param>
|
||||||
|
/// <param name="database"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static DataModel Connect(string server, string database)
|
||||||
|
{
|
||||||
|
return new DataModel(server, database);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tables from the dataset and within it all the columns, measures, and hierarchies
|
||||||
|
/// and adds these tabular objects to the collections for captions, descriptions, and display folders.
|
||||||
|
/// </summary>
|
||||||
|
private void LoadNamedObjectCollections()
|
||||||
|
{
|
||||||
|
Captions = new ObservableCollection<ExpandoObject>();
|
||||||
|
Descriptions = new ObservableCollection<ExpandoObject>();
|
||||||
|
DisplayFolders = new ObservableCollection<ExpandoObject>();
|
||||||
|
|
||||||
|
CultureCollection cultures = Model.Cultures;
|
||||||
|
|
||||||
|
Captions.Add(CreateRow(new MetadataObjectContainer(Model, TranslatedProperty.Caption), Model.Name, DefaultCulture, cultures));
|
||||||
|
if (!string.IsNullOrEmpty(Model.Description))
|
||||||
|
Descriptions.Add(CreateRow(new MetadataObjectContainer(Model, TranslatedProperty.Description), Model.Description, DefaultCulture, cultures));
|
||||||
|
|
||||||
|
foreach (Table table in Model.Tables)
|
||||||
|
{
|
||||||
|
Captions.Add(CreateRow(new MetadataObjectContainer(table, TranslatedProperty.Caption), table.Name, DefaultCulture, cultures));
|
||||||
|
if (!string.IsNullOrEmpty(table.Description))
|
||||||
|
Descriptions.Add(CreateRow(new MetadataObjectContainer(table, TranslatedProperty.Description), table.Description, DefaultCulture, cultures));
|
||||||
|
foreach (Column column in table.Columns)
|
||||||
|
{
|
||||||
|
if (column.Type != ColumnType.RowNumber)
|
||||||
|
{
|
||||||
|
Captions.Add(CreateRow(new MetadataObjectContainer(column, TranslatedProperty.Caption), column.Name, DefaultCulture, cultures));
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(column.Description))
|
||||||
|
Descriptions.Add(CreateRow(new MetadataObjectContainer(column, TranslatedProperty.Description), column.Description, DefaultCulture, cultures));
|
||||||
|
if (!string.IsNullOrEmpty(column.DisplayFolder))
|
||||||
|
DisplayFolders.AddDisplayFolder(column, column.DisplayFolder, DefaultCulture, cultures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Measure measure in table.Measures)
|
||||||
|
{
|
||||||
|
Captions.Add(CreateRow(new MetadataObjectContainer(measure, TranslatedProperty.Caption), measure.Name, DefaultCulture, cultures));
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(measure.Description))
|
||||||
|
Descriptions.Add(CreateRow(new MetadataObjectContainer(measure, TranslatedProperty.Description), measure.Description, DefaultCulture, cultures));
|
||||||
|
if (!string.IsNullOrEmpty(measure.DisplayFolder))
|
||||||
|
DisplayFolders.AddDisplayFolder(measure, measure.DisplayFolder, DefaultCulture, cultures);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Hierarchy hierarchy in table.Hierarchies)
|
||||||
|
{
|
||||||
|
Captions.Add(CreateRow(new MetadataObjectContainer(hierarchy, TranslatedProperty.Caption), hierarchy.Name, DefaultCulture, cultures));
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(hierarchy.Description))
|
||||||
|
Descriptions.Add(CreateRow(new MetadataObjectContainer(hierarchy, TranslatedProperty.Description), hierarchy.Description, DefaultCulture, cultures));
|
||||||
|
if (!string.IsNullOrEmpty(hierarchy.DisplayFolder))
|
||||||
|
DisplayFolders.AddDisplayFolder(hierarchy, hierarchy.DisplayFolder, DefaultCulture, cultures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the list of supported languages from the supportedlanguages.json file.
|
||||||
|
/// </summary>
|
||||||
|
private void LoadLanguages()
|
||||||
|
{
|
||||||
|
SupportedLanguages = new List<Language>();
|
||||||
|
string content = File.ReadAllText($"{System.AppDomain.CurrentDomain.BaseDirectory}Resources\\supportedlanguages.json");
|
||||||
|
foreach (Language lang in new JavaScriptSerializer().Deserialize<List<Language>>(content))
|
||||||
|
{
|
||||||
|
SupportedLanguages.Add(lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new ExpandoObject for a source string (displayString).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="objectContainer"></param>
|
||||||
|
/// <param name="displayString"></param>
|
||||||
|
/// <param name="defaultCulture"></param>
|
||||||
|
/// <param name="cultures"></param>
|
||||||
|
/// <returns>An ExpandoObject representing a data row.</returns>
|
||||||
|
public ExpandoObject CreateRow(MetadataObjectContainer objectContainer, string displayString, string defaultCulture, CultureCollection cultures)
|
||||||
|
{
|
||||||
|
dynamic row = new ExpandoObject();
|
||||||
|
|
||||||
|
((IDictionary<String, Object>)row)[ContainerColumnHeader] = objectContainer;
|
||||||
|
foreach (var culture in cultures)
|
||||||
|
{
|
||||||
|
((IDictionary<String, Object>)row)[culture.Name] = culture.Name.Equals(defaultCulture) ? displayString :
|
||||||
|
culture.ObjectTranslations[objectContainer.TabularObject, objectContainer.TranslatedProperty]?.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Combine all collections for translation and updating.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<ExpandoObject> GetAllDataRows()
|
||||||
|
{
|
||||||
|
var allRows = new List<ExpandoObject>();
|
||||||
|
foreach (var item in Captions) allRows.Add(item);
|
||||||
|
foreach (var item in Descriptions) allRows.Add(item);
|
||||||
|
foreach (var item in DisplayFolders) allRows.Add(item);
|
||||||
|
return allRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a translation to a Tabular metadata object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="culture"></param>
|
||||||
|
/// <param name="metadataObjectContainer"></param>
|
||||||
|
/// <param name="translation"></param>
|
||||||
|
private void SetTranslation(Culture culture, MetadataObjectContainer metadataObjectContainer, string translation)
|
||||||
|
{
|
||||||
|
culture.ObjectTranslations.SetTranslation(
|
||||||
|
metadataObjectContainer.TabularObject, metadataObjectContainer.TranslatedProperty,
|
||||||
|
translation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the Power BI dataset with the translations from the ExpandoObject collections and saves the changes.
|
||||||
|
/// </summary>
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
/// Delete any deselected cultures that still exist in the dataset.
|
||||||
|
///
|
||||||
|
List<string> cultureNames = SelectedLanguages?.Select(sl => sl.LanguageTag)?.ToList();
|
||||||
|
|
||||||
|
/// There must be at least the default culture in the cultureNames.
|
||||||
|
///
|
||||||
|
if (cultureNames == null || cultureNames.Count < 1) return;
|
||||||
|
|
||||||
|
var culturesToRemove = CultureNames.Where(cn1 => !cultureNames.Any(cn2 => cn2.Equals(cn1))).ToList();
|
||||||
|
culturesToRemove.Remove(DefaultCulture);
|
||||||
|
|
||||||
|
foreach(string cultureName in culturesToRemove)
|
||||||
|
{
|
||||||
|
if (Model.Cultures.Contains(cultureName))
|
||||||
|
{
|
||||||
|
Model.Cultures.Remove(cultureName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add any newly selected cultures.
|
||||||
|
///
|
||||||
|
foreach (string cultureName in cultureNames)
|
||||||
|
{
|
||||||
|
if (!Model.Cultures.Contains(cultureName))
|
||||||
|
{
|
||||||
|
Model.Cultures.Add(new Culture { Name = cultureName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add the translations to all the metadata objects.
|
||||||
|
///
|
||||||
|
foreach (ExpandoObject row in GetAllDataRows())
|
||||||
|
{
|
||||||
|
if (((IDictionary<string, Object>)row)[ContainerColumnHeader] is MetadataObjectContainer metadataObjectContainer)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Include this part when updating the default culture (i.e. updating the actual metadata objects) is supported.
|
||||||
|
*
|
||||||
|
switch (metadataObjectContainer.TranslatedProperty)
|
||||||
|
{
|
||||||
|
case TranslatedProperty.Caption:
|
||||||
|
metadataObjectContainer.TabularObject.Name = row.GetValue(DefaultCulture);
|
||||||
|
break;
|
||||||
|
case TranslatedProperty.Description:
|
||||||
|
if (metadataObjectContainer.TabularObject is Table table)
|
||||||
|
{
|
||||||
|
table.Description = row.GetValue(DefaultCulture);
|
||||||
|
}
|
||||||
|
else if (metadataObjectContainer.TabularObject is Column col)
|
||||||
|
{
|
||||||
|
col.Description = row.GetValue(DefaultCulture);
|
||||||
|
}
|
||||||
|
else if (metadataObjectContainer.TabularObject is Measure measure)
|
||||||
|
{
|
||||||
|
measure.Description = row.GetValue(DefaultCulture);
|
||||||
|
}
|
||||||
|
else if (metadataObjectContainer.TabularObject is Hierarchy hierarchy)
|
||||||
|
{
|
||||||
|
hierarchy.Description = row.GetValue(DefaultCulture);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TranslatedProperty.DisplayFolder:
|
||||||
|
if (metadataObjectContainer.TabularObject is Column column)
|
||||||
|
{
|
||||||
|
column.DisplayFolder = row.GetValue(DefaultCulture);
|
||||||
|
}
|
||||||
|
else if (metadataObjectContainer.TabularObject is Measure measure)
|
||||||
|
{
|
||||||
|
measure.DisplayFolder = row.GetValue(DefaultCulture);
|
||||||
|
}
|
||||||
|
else if (metadataObjectContainer.TabularObject is Hierarchy hierarchy)
|
||||||
|
{
|
||||||
|
hierarchy.DisplayFolder = row.GetValue(DefaultCulture);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
foreach (string cultureName in cultureNames)
|
||||||
|
{
|
||||||
|
SetTranslation(Model.Cultures[cultureName],
|
||||||
|
metadataObjectContainer,
|
||||||
|
row.GetValue(cultureName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save the changes in the dataset.
|
||||||
|
///
|
||||||
|
Model.Database.Update(AS.UpdateOptions.ExpandFull);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exports the translations to individual language files.
|
||||||
|
/// The files are placed into the specified export folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exportFolderPath"></param>
|
||||||
|
public void ExportToCsv(string exportFolderPath)
|
||||||
|
{
|
||||||
|
string separator = ",";
|
||||||
|
List<ExpandoObject> dataRows = GetAllDataRows();
|
||||||
|
if (dataRows != null && dataRows.Count > 0)
|
||||||
|
{
|
||||||
|
List<string> languages = SelectedLanguages.Where(l => l.IsModelDefault != true).Select(l => l.LanguageTag).ToList();
|
||||||
|
|
||||||
|
if (languages != null && languages.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (string lcid in languages)
|
||||||
|
{
|
||||||
|
StringBuilder csvContent = new StringBuilder();
|
||||||
|
csvContent.AppendLine("Type,Original,Translation");
|
||||||
|
|
||||||
|
foreach (var stringValues in dataRows.GetValues(ContainerColumnHeader, DefaultCulture, lcid))
|
||||||
|
{
|
||||||
|
csvContent.AppendLine(
|
||||||
|
string.Join(
|
||||||
|
separator,
|
||||||
|
new string[] {
|
||||||
|
stringValues.Type.ToCsvString(),
|
||||||
|
stringValues.Original.ToCsvString(),
|
||||||
|
stringValues.Translation.ToCsvString()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var sw = File.Create(System.IO.Path.Combine(exportFolderPath, $"{lcid}.csv")))
|
||||||
|
{
|
||||||
|
var preamble = Encoding.UTF8.GetPreamble();
|
||||||
|
sw.Write(preamble, 0, preamble.Length);
|
||||||
|
var data = Encoding.UTF8.GetBytes(csvContent.ToString());
|
||||||
|
sw.Write(data, 0, data.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Imports translations from a csv file. The file name must match the LCID of the target language.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath"></param>
|
||||||
|
/// <param name="lcid"></param>
|
||||||
|
/// <param name="replaceExistingTranslations"></param>
|
||||||
|
public void ImportFromCsv(string filePath, string lcid, bool replaceExistingTranslations)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string csvData = File.ReadAllText(filePath);
|
||||||
|
if (string.IsNullOrEmpty(csvData)) return;
|
||||||
|
|
||||||
|
List<CsvRow> parsedRows = new List<CsvRow>();
|
||||||
|
|
||||||
|
using (TextFieldParser parser = new TextFieldParser(new StringReader(csvData)))
|
||||||
|
{
|
||||||
|
parser.CommentTokens = new string[] { "#" };
|
||||||
|
parser.SetDelimiters(new string[] { "," });
|
||||||
|
parser.HasFieldsEnclosedInQuotes = true;
|
||||||
|
|
||||||
|
/// Skip the header row.
|
||||||
|
///
|
||||||
|
parser.ReadFields();
|
||||||
|
while (!parser.EndOfData)
|
||||||
|
{
|
||||||
|
var textFields = parser.ReadFields();
|
||||||
|
if (textFields != null && textFields.Count() == 3)
|
||||||
|
{
|
||||||
|
parsedRows.Add(new CsvRow
|
||||||
|
{
|
||||||
|
Type = textFields[0],
|
||||||
|
Original = textFields[1],
|
||||||
|
Translation = textFields[2]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyTranslation(lcid, parsedRows, replaceExistingTranslations);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies a list of translations to the ExpandoObject collections
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcid"></param>
|
||||||
|
/// <param name="translatedRows"></param>
|
||||||
|
/// <param name="replaceExistingTranslations"></param>
|
||||||
|
private void ApplyTranslation(string lcid, List<CsvRow> translatedRows, bool replaceExistingTranslations)
|
||||||
|
{
|
||||||
|
var allDataRows = GetAllDataRows();
|
||||||
|
if(!MatchAllRows(allDataRows, lcid, translatedRows, replaceExistingTranslations))
|
||||||
|
{
|
||||||
|
/// Not all rows matched, so let's do this the slow way
|
||||||
|
/// matching strings.
|
||||||
|
///
|
||||||
|
foreach(ExpandoObject row in allDataRows)
|
||||||
|
{
|
||||||
|
var metaContainer = (MetadataObjectContainer)row.GetObject(ContainerColumnHeader);
|
||||||
|
var original = row.GetValue(DefaultCulture);
|
||||||
|
var csvRow = translatedRows.Where(x => x.Type == metaContainer.TranslatedProperty.ToString() && x.Original.Equals(original)).FirstOrDefault();
|
||||||
|
if(csvRow != null)
|
||||||
|
{
|
||||||
|
row.SetValue(lcid, csvRow.Translation, replaceExistingTranslations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates over the dataRows and applies the translated strings with the assumption that
|
||||||
|
/// translatedRows matches the dataRows in number and order.
|
||||||
|
/// </summary>
|
||||||
|
private bool MatchAllRows(List<ExpandoObject> dataRows, string lcid, List<CsvRow> translatedRows, bool replaceExistingTranslations)
|
||||||
|
{
|
||||||
|
if(dataRows == null || dataRows.Count != translatedRows?.Count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(int i = 0; i < translatedRows.Count; i++)
|
||||||
|
{
|
||||||
|
ExpandoObject row = dataRows[i];
|
||||||
|
CsvRow csvRow = translatedRows[i];
|
||||||
|
|
||||||
|
if (row.GetValue(DefaultCulture) != csvRow.Original)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
row.SetValue(lcid, csvRow.Translation, replaceExistingTranslations);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.AnalysisServices.Tabular;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class DisplayFolderContainer : MetadataObjectContainer
|
||||||
|
{
|
||||||
|
public override NamedMetadataObject TabularObject { get => TabularObjects.FirstOrDefault(); protected set { } }
|
||||||
|
public List<NamedMetadataObject> TabularObjects { get; private set; }
|
||||||
|
|
||||||
|
public DisplayFolderContainer(NamedMetadataObject metadataObject, TranslatedProperty translatedProperty) : base(metadataObject, translatedProperty)
|
||||||
|
{
|
||||||
|
TabularObjects = new List<NamedMetadataObject>();
|
||||||
|
TabularObjects.Add(metadataObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return (TabularObjects.Count > 1)?
|
||||||
|
$"DisplayFolder - {TabularObjects.Count} Objects" :
|
||||||
|
$"DisplayFolder - 1 {TabularObject.ObjectType}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.AnalysisServices.Tabular;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class MetadataObjectContainer
|
||||||
|
{
|
||||||
|
public virtual NamedMetadataObject TabularObject { get; protected set; }
|
||||||
|
public TranslatedProperty TranslatedProperty { get; protected set; }
|
||||||
|
public MetadataObjectContainer(NamedMetadataObject metadataObject, TranslatedProperty translatedProperty)
|
||||||
|
{
|
||||||
|
TabularObject = metadataObject;
|
||||||
|
TranslatedProperty = translatedProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
switch(TranslatedProperty)
|
||||||
|
{
|
||||||
|
case TranslatedProperty.Caption:
|
||||||
|
return $"{TabularObject.ObjectType} - Caption";
|
||||||
|
case TranslatedProperty.Description:
|
||||||
|
return $"{TabularObject.ObjectType} - Description";
|
||||||
|
case TranslatedProperty.DisplayFolder:
|
||||||
|
return $"{TabularObject.ObjectType} - DisplayFolder";
|
||||||
|
default:
|
||||||
|
return TabularObject.ObjectType.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public static class ExpandoObjectExtensions
|
||||||
|
{
|
||||||
|
public static string SeparateCamelCase(this ExpandoObject expando, string columnName)
|
||||||
|
{
|
||||||
|
if (expando != null && ((IDictionary<String, Object>)expando)[columnName] is string text)
|
||||||
|
{
|
||||||
|
char separator = ' ';
|
||||||
|
char lastChar = separator;
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var currentChar in text.Replace("_", ""))
|
||||||
|
{
|
||||||
|
if (char.IsUpper(currentChar) && lastChar != separator)
|
||||||
|
sb.Append(separator);
|
||||||
|
|
||||||
|
sb.Append(currentChar);
|
||||||
|
|
||||||
|
lastChar = currentChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetValue(this ExpandoObject expando, string columnName)
|
||||||
|
{
|
||||||
|
return expando.GetObject(columnName)?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object GetObject(this ExpandoObject expando, string columnName)
|
||||||
|
{
|
||||||
|
if (expando != null && ((IDictionary<String, Object>)expando).ContainsKey(columnName))
|
||||||
|
{
|
||||||
|
return ((IDictionary<String, Object>)expando)[columnName];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetValue(this ExpandoObject expando, string columnName, string value, bool overwrite)
|
||||||
|
{
|
||||||
|
if (expando != null)
|
||||||
|
{
|
||||||
|
if (overwrite || string.IsNullOrEmpty(expando.GetValue(columnName)))
|
||||||
|
{
|
||||||
|
((IDictionary<String, Object>)expando)[columnName] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
MetadataTranslator/Metadata Translator/Helpers/Hourglass.cs
Normal file
25
MetadataTranslator/Metadata Translator/Helpers/Hourglass.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class Hourglass : IDisposable
|
||||||
|
{
|
||||||
|
private Cursor previousCursor;
|
||||||
|
|
||||||
|
public Hourglass()
|
||||||
|
{
|
||||||
|
previousCursor = Mouse.OverrideCursor;
|
||||||
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Mouse.OverrideCursor = previousCursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public static class ListExtensions
|
||||||
|
{
|
||||||
|
public static List<CsvRow> GetValues(this List<ExpandoObject> collection, string containerColumnName, string referenceColumnName, string columnName)
|
||||||
|
{
|
||||||
|
if (collection == null) return new List<CsvRow>();
|
||||||
|
|
||||||
|
var values = new List<CsvRow>();
|
||||||
|
foreach (ExpandoObject row in collection)
|
||||||
|
{
|
||||||
|
var metaContainer = (MetadataObjectContainer)row.GetObject(containerColumnName);
|
||||||
|
string refValue = row.GetValue(referenceColumnName);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(refValue))
|
||||||
|
values.Add(new CsvRow { Type = metaContainer.TranslatedProperty.ToString(), Original = refValue, Translation = row.GetValue(columnName) });
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
using Microsoft.AnalysisServices.Tabular;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public static class ObservableCollectionExtensions
|
||||||
|
{
|
||||||
|
public static string GetValueAt(this ObservableCollection<ExpandoObject> collection, int index, string columnName)
|
||||||
|
{
|
||||||
|
if (collection == null) return string.Empty;
|
||||||
|
|
||||||
|
ExpandoObject row = collection[index];
|
||||||
|
return ((IDictionary<String, Object>)row)[columnName]?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetValueAt(this ObservableCollection<ExpandoObject> collection, int index, string columnName, string value)
|
||||||
|
{
|
||||||
|
if (collection == null) return;
|
||||||
|
|
||||||
|
ExpandoObject row = collection[index];
|
||||||
|
((IDictionary<String, Object>)row)[columnName] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateDataValues(this ObservableCollection<ExpandoObject> collection, List<string> sourcePhrases, string sourceLanguage, List<string> targetPhrases, string targetLanguage)
|
||||||
|
{
|
||||||
|
if (collection == null) return;
|
||||||
|
int rowOffset = 0;
|
||||||
|
for (int i = 0; i < collection.Count; i++)
|
||||||
|
{
|
||||||
|
string columnValue = collection.GetValueAt(i, sourceLanguage);
|
||||||
|
if (!string.IsNullOrEmpty(columnValue) && columnValue.Equals(sourcePhrases[i - rowOffset]))
|
||||||
|
{
|
||||||
|
collection.SetValueAt(i, targetLanguage, targetPhrases[i - rowOffset]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rowOffset++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<string> GetValues(this ObservableCollection<ExpandoObject> collection, string columnName)
|
||||||
|
{
|
||||||
|
if (collection == null) return new List<string>();
|
||||||
|
|
||||||
|
List<string> values = new List<string>();
|
||||||
|
foreach (ExpandoObject row in collection)
|
||||||
|
{
|
||||||
|
string value = ((IDictionary<String, Object>)row)[columnName]?.ToString();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
values.Add(value);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddDisplayFolder(this ObservableCollection<ExpandoObject> collection, NamedMetadataObject metadataObject, string displayString, string defaultCulture, CultureCollection cultures)
|
||||||
|
{
|
||||||
|
if (collection == null) return;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(displayString))
|
||||||
|
{
|
||||||
|
foreach (ExpandoObject item in collection)
|
||||||
|
{
|
||||||
|
if (((IDictionary<String, Object>)item)[defaultCulture] is string displayName && displayName.Equals(displayString))
|
||||||
|
{
|
||||||
|
var existingDisplayFolderContainer = ((IDictionary<String, Object>)item)["Object"] as DisplayFolderContainer;
|
||||||
|
existingDisplayFolderContainer.TabularObjects.Add(metadataObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic row = new ExpandoObject();
|
||||||
|
var displayFolderContainer = new DisplayFolderContainer(metadataObject, TranslatedProperty.DisplayFolder);
|
||||||
|
|
||||||
|
((IDictionary<String, Object>)row)["Object"] = displayFolderContainer;
|
||||||
|
foreach (var culture in cultures)
|
||||||
|
{
|
||||||
|
((IDictionary<String, Object>)row)[culture.Name] = culture.Name.Equals(defaultCulture) ? displayString :
|
||||||
|
culture.ObjectTranslations[displayFolderContainer.TabularObject, displayFolderContainer.TranslatedProperty]?.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.Add(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.AnalysisServices.Tabular;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
public static string ToCsvString(this string value)
|
||||||
|
{
|
||||||
|
if (value == null) return string.Empty;
|
||||||
|
return value.Contains("\"") ? $"\"{value.Replace("\"", "\"\"")}\"" : value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,185 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{CB7D493C-B67E-4438-B304-EFE5D418ADDF}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<RootNamespace>Metadata_Translator</RootNamespace>
|
||||||
|
<AssemblyName>Metadata Translator</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.AnalysisServices, Version=19.16.3.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AnalysisServices.retail.amd64.19.16.3\lib\net45\Microsoft.AnalysisServices.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.AnalysisServices.AdomdClient, Version=19.16.3.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AnalysisServices.AdomdClient.retail.amd64.19.16.3\lib\net45\Microsoft.AnalysisServices.AdomdClient.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.AnalysisServices.Core, Version=19.16.3.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AnalysisServices.retail.amd64.19.16.3\lib\net45\Microsoft.AnalysisServices.Core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.AnalysisServices.SPClient.Interfaces, Version=19.16.3.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AnalysisServices.retail.amd64.19.16.3\lib\net45\Microsoft.AnalysisServices.SPClient.Interfaces.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.AnalysisServices.Tabular, Version=19.16.3.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AnalysisServices.retail.amd64.19.16.3\lib\net45\Microsoft.AnalysisServices.Tabular.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.AnalysisServices.Tabular.Json, Version=19.16.3.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AnalysisServices.retail.amd64.19.16.3\lib\net45\Microsoft.AnalysisServices.Tabular.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.VisualBasic" />
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Configuration" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Web.Extensions" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xaml">
|
||||||
|
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ApplicationDefinition Include="App.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</ApplicationDefinition>
|
||||||
|
<Compile Include="Converters\CollectionEmptyTrueFalseConverter.cs" />
|
||||||
|
<Compile Include="Converters\TranslationPropertyToolTipConverter.cs" />
|
||||||
|
<Compile Include="Data\CsvRow.cs" />
|
||||||
|
<Compile Include="Data\DisplayFolderContainer.cs" />
|
||||||
|
<Compile Include="Helpers\ExpandoObjectExtensions.cs" />
|
||||||
|
<Compile Include="Helpers\StringExtensions.cs" />
|
||||||
|
<Compile Include="Helpers\Hourglass.cs" />
|
||||||
|
<Compile Include="Helpers\ListExtensions.cs" />
|
||||||
|
<Compile Include="Helpers\ObservableCollectionExtensions.cs" />
|
||||||
|
<Compile Include="UI\ImportExportPanel.xaml.cs">
|
||||||
|
<DependentUpon>ImportExportPanel.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Translations\Language.cs" />
|
||||||
|
<Compile Include="UI\LanguagePanel.xaml.cs">
|
||||||
|
<DependentUpon>LanguagePanel.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Converters\PercentageConverter.cs" />
|
||||||
|
<Compile Include="UI\SettingsPanel.xaml.cs">
|
||||||
|
<DependentUpon>SettingsPanel.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Translations\TranslationGroup.cs" />
|
||||||
|
<Compile Include="UI\TranslationGroupPanel.xaml.cs">
|
||||||
|
<DependentUpon>TranslationGroupPanel.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Translations\TranslatorService.cs" />
|
||||||
|
<Compile Include="Converters\TrueFalseVisibilityConverter.cs" />
|
||||||
|
<Compile Include="Translations\Translation.cs" />
|
||||||
|
<Compile Include="Translations\TranslationResult.cs" />
|
||||||
|
<Page Include="UI\ImportExportPanel.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="UI\LanguagePanel.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="UI\MainWindow.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
<Compile Include="App.xaml.cs">
|
||||||
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Data\DataModel.cs" />
|
||||||
|
<Compile Include="UI\MainWindow.xaml.cs">
|
||||||
|
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Page Include="UI\SettingsPanel.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Resources\StringDictionary.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="UI\TranslationGroupPanel.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Data\MetadataObjectContainer.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
</Compile>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<None Include="metadata-translator.pbitool.json" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
<None Include="Resources\supportedlanguages.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<PostBuildEvent>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,55 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("Metadata Translator")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("Metadata Translator")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
//In order to begin building localizable applications, set
|
||||||
|
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||||
|
//inside a <PropertyGroup>. For example, if you are using US english
|
||||||
|
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||||
|
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||||
|
//the line below to match the UICulture setting in the project file.
|
||||||
|
|
||||||
|
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||||
|
|
||||||
|
|
||||||
|
[assembly: ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)]
|
||||||
|
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
70
MetadataTranslator/Metadata Translator/Properties/Resources.Designer.cs
generated
Normal file
70
MetadataTranslator/Metadata Translator/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
namespace Metadata_Translator.Properties
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources
|
||||||
|
{
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ((resourceMan == null))
|
||||||
|
{
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Metadata_Translator.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
MetadataTranslator/Metadata Translator/Properties/Resources.resx
Normal file
117
MetadataTranslator/Metadata Translator/Properties/Resources.resx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
29
MetadataTranslator/Metadata Translator/Properties/Settings.Designer.cs
generated
Normal file
29
MetadataTranslator/Metadata Translator/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
namespace Metadata_Translator.Properties
|
||||||
|
{
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||||
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
|
||||||
|
public static Settings Default
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
<Settings />
|
||||||
|
</SettingsFile>
|
@ -0,0 +1,43 @@
|
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:Metadata_Translator"
|
||||||
|
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||||
|
<system:String x:Key="Languages">Languages</system:String>
|
||||||
|
<system:String x:Key="LanguagesToolTip">Opens the Languages pane to choose the target languages.</system:String>
|
||||||
|
<system:String x:Key="Settings">Settings</system:String>
|
||||||
|
<system:String x:Key="SettingsToolTip">Opens the Settings pane to configure Machine Translator.</system:String>
|
||||||
|
<system:String x:Key="TranslatedProperty">Translated Property</system:String>
|
||||||
|
<system:String x:Key="Caption">Caption</system:String>
|
||||||
|
<system:String x:Key="CaptionToolTip">Displays the captions of the metadata objects and their translations.</system:String>
|
||||||
|
<system:String x:Key="Description">Description</system:String>
|
||||||
|
<system:String x:Key="DescriptionToolTip">Displays the descriptions of the metadata objects and their translations.|The metadata objects in the current dataset have no descriptions. Use Power BI Desktop to add descriptions.</system:String>
|
||||||
|
<system:String x:Key="DisplayFolder">DisplayFolder</system:String>
|
||||||
|
<system:String x:Key="DisplayFolderToolTip">Displays the display folder names of the metadata objects and their translations.|The current dataset does not have display folders. Use Power BI Desktop to group columns and measures in display folders.</system:String>
|
||||||
|
<system:String x:Key="Prepare">Prepare</system:String>
|
||||||
|
<system:String x:Key="Translate">Translate</system:String>
|
||||||
|
<system:String x:Key="TranslateToolTip">Translates the captions, descriptions, and display folder names using Microsoft Translator.</system:String>
|
||||||
|
<system:String x:Key="Apply">Apply</system:String>
|
||||||
|
<system:String x:Key="ApplyToolTip">Applies the translated captions, descriptions, and display folder names to the Power BI dataset.</system:String>
|
||||||
|
<system:String x:Key="ImportExport">Import/Export</system:String>
|
||||||
|
<system:String x:Key="ImportExportToolTip">Opens the Import/Export pane to export and import the captions, descriptions, and display folder names via .csv files.</system:String>
|
||||||
|
<system:String x:Key="InvalidArguments">Metadata Translator cannot start without server and database arguments. Double-check the 'arguments' setting in the metadata-translator.pbitool.json file in your Microsoft Shared\Power BI Desktop\External Tools folder. The value must be: "\"%server%\" \"%database%\"".</system:String>
|
||||||
|
<system:String x:Key="DatasetConnection">Dataset Connection String</system:String>
|
||||||
|
<system:String x:Key="SubscriptionKey">Translator Subscription Key</system:String>
|
||||||
|
<system:String x:Key="TranslatorEndpoint">Translator Endpoint</system:String>
|
||||||
|
<system:String x:Key="TranslatorLocation">Translator Location</system:String>
|
||||||
|
<system:String x:Key="OverwriteTranslation">Overwrite Translation</system:String>
|
||||||
|
<system:String x:Key="SubscriptionKeyPrompt">Enter your Microsoft Translator service subscription key.</system:String>
|
||||||
|
<system:String x:Key="TranslatorEndpointPrompt">Enter the Microsoft Translator URL, specifically: https://api.cognitive.microsofttranslator.com/</system:String>
|
||||||
|
<system:String x:Key="TranslatorLocationPrompt">This is typically the Global region, but could also be a single Azure region.</system:String>
|
||||||
|
<system:String x:Key="NothingToTranslate">Please select at least one language before you translate the metadata.</system:String>
|
||||||
|
<system:String x:Key="UnableToTranslate">Microsoft Translator was unable to translate the metadata strings into {0}. Please try again later or remove this language from the translation.</system:String>
|
||||||
|
<system:String x:Key="ExportHeading">Export .csv files</system:String>
|
||||||
|
<system:String x:Key="ExportDescription">You can export the metadata captions, descriptions, and display folder strings into .csv files based on the locale identifiers (LCIDs) of the selected languages. Metadata Translator creates a separate .csv file for each LCID.</system:String>
|
||||||
|
<system:String x:Key="ExportFolderDescription">Select the folder where you want to store your .csv files. Note that Metadata Translator might overwrite any existing files in this folder.</system:String>
|
||||||
|
<system:String x:Key="ExportButtonCaption">Export...</system:String>
|
||||||
|
<system:String x:Key="ImportHeading">Import .csv files</system:String>
|
||||||
|
<system:String x:Key="ImportDescription">You can import translated captions, descriptions, and display folder strings from .csv files. Each file name must match a locale identifier (LCID) of a supported language. You can import multiple .csv files in a single step.</system:String>
|
||||||
|
<system:String x:Key="ImportButtonCaption">Import...</system:String>
|
||||||
|
<system:String x:Key="TabularObjectColumnHeader">Object - Type</system:String>
|
||||||
|
<system:String x:Key="DefaultCultureColumnHeaderToolTip">The default culture is read-only. Use Power BI Desktop to change the names, descriptions, and display folder names for the default culture.</system:String>
|
||||||
|
</ResourceDictionary>
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class Language : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
#region INotifyPropertyChanged implementation
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void NotifyPropertyChanged(string propertyName = null)
|
||||||
|
{
|
||||||
|
if (PropertyChanged != null)
|
||||||
|
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public string LanguageTag { get; set; }
|
||||||
|
public string TranslationId { get; set; }
|
||||||
|
public string TranslationGroup { get; set; }
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
public string NativeName { get; set; }
|
||||||
|
|
||||||
|
private bool isSelected = false;
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get => isSelected;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
isSelected = value;
|
||||||
|
NotifyPropertyChanged("IsSelected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsModelDefault { get; set; }
|
||||||
|
public bool IsNotModelDefault { get => !IsModelDefault; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class Translation
|
||||||
|
{
|
||||||
|
public string text { get; set; }
|
||||||
|
public string to { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class TranslationGroup
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Tag { get; set; }
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is TranslationGroup comparewith)
|
||||||
|
{
|
||||||
|
return Name == comparewith.Name && Tag == comparewith.Tag;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return new { Tag, Name }.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class TranslationResult
|
||||||
|
{
|
||||||
|
public List<Translation> translations { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web.Script.Serialization;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
public class TranslatorService
|
||||||
|
{
|
||||||
|
List<Language> Languages { get; set; }
|
||||||
|
string SourceLanguage { get; set; }
|
||||||
|
string SubscriptionKey { get; set; }
|
||||||
|
string Endpoint { get; set; }
|
||||||
|
string Location { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sourceLanguage"></param>
|
||||||
|
/// <param name="targetLanguage"></param>
|
||||||
|
/// <param name="subscriptionKey"></param>
|
||||||
|
/// <param name="endpoint"></param>
|
||||||
|
/// <param name="location"></param>
|
||||||
|
public TranslatorService(List<Language> languages, string sourceLanguage, string subscriptionKey, string endpoint, string location)
|
||||||
|
{
|
||||||
|
Languages = languages;
|
||||||
|
SourceLanguage = sourceLanguage;
|
||||||
|
|
||||||
|
SubscriptionKey = subscriptionKey;
|
||||||
|
Endpoint = endpoint;
|
||||||
|
Location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Translate(List<ExpandoObject> dataRows, bool replaceExistingTranslations)
|
||||||
|
{
|
||||||
|
/// No languages, or only the one source language? Nothing to translate!
|
||||||
|
///
|
||||||
|
if (Languages == null || Languages.Count < 2) return;
|
||||||
|
|
||||||
|
/// Get the target languages (i.e. not the SourceLanguage).
|
||||||
|
///
|
||||||
|
List<Language> targetLanguages = Languages.Where(l => !l.LanguageTag.Equals(SourceLanguage)).ToList();
|
||||||
|
|
||||||
|
/// Filter down the data rows to those with values in the source language.
|
||||||
|
///
|
||||||
|
List<ExpandoObject> filteredRows = dataRows.Where(dr => !string.IsNullOrEmpty(dr.GetValue(SourceLanguage)))?.ToList();
|
||||||
|
|
||||||
|
/// No rows? Nothing to translate!
|
||||||
|
///
|
||||||
|
if (filteredRows == null || filteredRows.Count == 0) return;
|
||||||
|
|
||||||
|
/// Iterate over the TranslationGroups, all languages within the same group
|
||||||
|
/// share the same translation id.
|
||||||
|
///
|
||||||
|
foreach(string id in targetLanguages.Select(tl => tl.TranslationId).Distinct())
|
||||||
|
{
|
||||||
|
Translate(filteredRows, targetLanguages.Where(tl => tl.TranslationId.Equals(id)), id, replaceExistingTranslations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Translate(List<ExpandoObject> dataRows, IEnumerable<Language> targetLanguages, string translationId, bool replaceExistingTranslations)
|
||||||
|
{
|
||||||
|
List<ExpandoObject> rowsToTranslate = new List<ExpandoObject>();
|
||||||
|
|
||||||
|
/// Don't replace existing translations?
|
||||||
|
/// Filter down the data rows to those that are empty for at least one of the target languages.
|
||||||
|
///
|
||||||
|
if (!replaceExistingTranslations)
|
||||||
|
{
|
||||||
|
foreach(Language language in targetLanguages)
|
||||||
|
{
|
||||||
|
rowsToTranslate.AddRange(dataRows.Where(dr => string.IsNullOrEmpty(dr.GetValue(language.LanguageTag))));
|
||||||
|
}
|
||||||
|
rowsToTranslate = rowsToTranslate.Distinct()?.ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// Otherwise translate all data rows.
|
||||||
|
///
|
||||||
|
rowsToTranslate = dataRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Now translate the source strings recursively.
|
||||||
|
///
|
||||||
|
Translate(rowsToTranslate, targetLanguages, translationId, replaceExistingTranslations, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Translate(List<ExpandoObject> dataRows, IEnumerable<Language> targetLanguages, string translationId, bool replaceExistingTranslations, int iterationId)
|
||||||
|
{
|
||||||
|
int maxBatchSize = 100;
|
||||||
|
int batchStart = maxBatchSize * iterationId;
|
||||||
|
|
||||||
|
/// Check if all strings have been translated.
|
||||||
|
///
|
||||||
|
if (dataRows.Count <= batchStart) return;
|
||||||
|
|
||||||
|
/// Assemble a translation batch of up to maxBatchSize.
|
||||||
|
///
|
||||||
|
maxBatchSize = (dataRows.Count - batchStart) < maxBatchSize? dataRows.Count - batchStart : maxBatchSize;
|
||||||
|
List<object> translationBatch = new List<object>();
|
||||||
|
for (int i = 0; i < maxBatchSize; i++)
|
||||||
|
{
|
||||||
|
translationBatch.Add(new { Text = dataRows[batchStart + i].GetValue(SourceLanguage) });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Translate the batch and assign the translated strings to the target languages.
|
||||||
|
///
|
||||||
|
var translatedStrings = TranslateBatch(translationBatch, translationId);
|
||||||
|
for (int i = 0; i < maxBatchSize; i++)
|
||||||
|
{
|
||||||
|
foreach (Language language in targetLanguages)
|
||||||
|
{
|
||||||
|
dataRows[batchStart + i].SetValue(language.LanguageTag, translatedStrings[i], replaceExistingTranslations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Translate(dataRows, targetLanguages, translationId, replaceExistingTranslations, ++iterationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> TranslateBatch(List<object> sourceObjects, string targetLanguage)
|
||||||
|
{
|
||||||
|
List<string> translatedPhrases = new List<string>();
|
||||||
|
|
||||||
|
var requestBody = new JavaScriptSerializer().Serialize(sourceObjects);
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
using (var request = new HttpRequestMessage())
|
||||||
|
{
|
||||||
|
/// Build the Web request.
|
||||||
|
///
|
||||||
|
request.Method = HttpMethod.Post;
|
||||||
|
request.RequestUri = new Uri($"{Endpoint}/translate?api-version=3.0&from={SourceLanguage}&to={targetLanguage}");
|
||||||
|
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
|
||||||
|
request.Headers.Add("Ocp-Apim-Subscription-Key", SubscriptionKey);
|
||||||
|
request.Headers.Add("Ocp-Apim-Subscription-Region", Location);
|
||||||
|
|
||||||
|
/// Send the translation request and get the response.
|
||||||
|
///
|
||||||
|
HttpResponseMessage response = client.SendAsync(request).Result;
|
||||||
|
string result = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
|
/// Parse the results and add the strings to the translated phrases if there was no error,
|
||||||
|
/// i.e. the target language was returned together with the translated string, which is
|
||||||
|
/// not the case if the service gives back an error message.
|
||||||
|
///
|
||||||
|
List<TranslationResult> parsedResults = new JavaScriptSerializer().Deserialize<List<TranslationResult>>(result);
|
||||||
|
if (parsedResults != null)
|
||||||
|
{
|
||||||
|
for (int n = 0; n < parsedResults.Count; n++)
|
||||||
|
{
|
||||||
|
translatedPhrases.Add((string.IsNullOrEmpty(parsedResults[n].translations[0].to))? "" : parsedResults[n].translations[0].text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return translatedPhrases;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
<UserControl x:Class="Metadata_Translator.ImportExportPanel"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:Metadata_Translator"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<local:PercentageConverter x:Key="PercentageConverter" />
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Grid x:Name="underline" MinWidth="200" Margin="8,2">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Button Height="16" Width="16" Background="Transparent" Margin="0,2,4,2"
|
||||||
|
BorderThickness="0" HorizontalAlignment="Right" VerticalAlignment="Top"
|
||||||
|
Click="CancelButton_Click">
|
||||||
|
<Image>
|
||||||
|
<Image.Source>
|
||||||
|
<DrawingImage>
|
||||||
|
<DrawingImage.Drawing>
|
||||||
|
<DrawingGroup>
|
||||||
|
<DrawingGroup.Transform>
|
||||||
|
<TransformGroup>
|
||||||
|
<ScaleTransform ScaleX="1" ScaleY="1"/>
|
||||||
|
<SkewTransform/>
|
||||||
|
<RotateTransform/>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</TransformGroup>
|
||||||
|
</DrawingGroup.Transform>
|
||||||
|
<DrawingGroup.Children>
|
||||||
|
<GeometryDrawing Geometry="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm101.8-262.2L295.6 256l62.2 62.2c4.7 4.7 4.7 12.3 0 17l-22.6 22.6c-4.7 4.7-12.3 4.7-17 0L256 295.6l-62.2 62.2c-4.7 4.7-12.3 4.7-17 0l-22.6-22.6c-4.7-4.7-4.7-12.3 0-17l62.2-62.2-62.2-62.2c-4.7-4.7-4.7-12.3 0-17l22.6-22.6c4.7-4.7 12.3-4.7 17 0l62.2 62.2 62.2-62.2c4.7-4.7 12.3-4.7 17 0l22.6 22.6c4.7 4.7 4.7 12.3 0 17z">
|
||||||
|
<GeometryDrawing.Pen>
|
||||||
|
<Pen Brush="Black" Thickness="1"/>
|
||||||
|
</GeometryDrawing.Pen>
|
||||||
|
<GeometryDrawing.Brush>
|
||||||
|
<RadialGradientBrush>
|
||||||
|
<GradientStop Color="Gray"/>
|
||||||
|
</RadialGradientBrush>
|
||||||
|
</GeometryDrawing.Brush>
|
||||||
|
</GeometryDrawing>
|
||||||
|
</DrawingGroup.Children>
|
||||||
|
</DrawingGroup>
|
||||||
|
</DrawingImage.Drawing>
|
||||||
|
</DrawingImage>
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
|
</Button>
|
||||||
|
<StackPanel Grid.Row="1" Margin="4,0">
|
||||||
|
<Grid Margin="4">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Grid.Row="0" DockPanel.Dock="Top" Text="{StaticResource ExportHeading}" FontStyle="Italic" FontWeight="DemiBold"/>
|
||||||
|
<Rectangle Grid.Row="1" DockPanel.Dock="Top" Fill="Gray" Height="0.5"
|
||||||
|
Width="{Binding ElementName=underline, Path=ActualWidth, Converter={StaticResource PercentageConverter}}"
|
||||||
|
HorizontalAlignment="Left"/>
|
||||||
|
<TextBlock Grid.Row="2" Text="{StaticResource ExportDescription}" TextWrapping="Wrap" Width="260"
|
||||||
|
HorizontalAlignment="Left"/>
|
||||||
|
<Button Grid.Row="3" Margin="8,0" Padding="4" BorderThickness="0" Background="Transparent" Cursor="Hand"
|
||||||
|
Click="OnExportButton_Click" Tag="{StaticResource ExportFolderDescription}"
|
||||||
|
HorizontalAlignment="Right" >
|
||||||
|
<TextBlock TextDecorations="Underline" Text="{StaticResource ExportButtonCaption}" FontStyle="Italic" Foreground="Blue"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
<Grid Margin="4">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Grid.Row="0" DockPanel.Dock="Top" Text="{StaticResource ImportHeading}" FontStyle="Italic" FontWeight="DemiBold"/>
|
||||||
|
<Rectangle Grid.Row="1" DockPanel.Dock="Top" Fill="Gray" Height="0.5"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Width="{Binding ElementName=underline, Path=ActualWidth, Converter={StaticResource PercentageConverter}}" />
|
||||||
|
<TextBlock Grid.Row="2" Text="{StaticResource ImportDescription}" TextWrapping="Wrap" Width="260"
|
||||||
|
HorizontalAlignment="Left"/>
|
||||||
|
<Button Grid.Row="3" Click="OnImportButton_Click" HorizontalAlignment="Right" Margin="8,0" Padding="4" BorderThickness="0" Background="Transparent" Cursor="Hand">
|
||||||
|
<TextBlock TextDecorations="Underline" Text="{StaticResource ImportButtonCaption}" FontStyle="Italic" Foreground="Blue"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
@ -0,0 +1,95 @@
|
|||||||
|
using Microsoft.Win32;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using WF = System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for ImportExportPanel.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class ImportExportPanel : UserControl
|
||||||
|
{
|
||||||
|
public ImportExportPanel()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var mainWnd = MainWindow.GetMainWindow(this);
|
||||||
|
if (mainWnd != null)
|
||||||
|
{
|
||||||
|
mainWnd.ImportExportToggle.IsChecked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnImportButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var mainWnd = MainWindow.GetMainWindow(this);
|
||||||
|
if (mainWnd != null)
|
||||||
|
{
|
||||||
|
Button importButton = sender as Button;
|
||||||
|
|
||||||
|
OpenFileDialog openFileDialog1 = new OpenFileDialog();
|
||||||
|
|
||||||
|
// Set filter options and filter index.
|
||||||
|
openFileDialog1.Filter = "CSV Files (.csv)|*.csv|All Files (*.*)|*.*";
|
||||||
|
openFileDialog1.FilterIndex = 1;
|
||||||
|
|
||||||
|
openFileDialog1.Multiselect = true;
|
||||||
|
openFileDialog1.CheckFileExists = true;
|
||||||
|
|
||||||
|
if (openFileDialog1.ShowDialog() == true)
|
||||||
|
{
|
||||||
|
using (new Hourglass())
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach (string filePath in openFileDialog1.FileNames)
|
||||||
|
{
|
||||||
|
string lcid = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
mainWnd.AddColumn(lcid);
|
||||||
|
mainWnd.DataModel?.ImportFromCsv(filePath, lcid, mainWnd.OverwriteTranslation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mainWnd.ImportExportToggle.IsChecked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnExportButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var mainWnd = MainWindow.GetMainWindow(this);
|
||||||
|
if (mainWnd != null)
|
||||||
|
{
|
||||||
|
Button exportButton = sender as Button;
|
||||||
|
WF.FolderBrowserDialog folderDlg = new WF.FolderBrowserDialog
|
||||||
|
{
|
||||||
|
SelectedPath = mainWnd.LastUsedExportFolder,
|
||||||
|
Description = (string)exportButton.Tag,
|
||||||
|
ShowNewFolderButton = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
WF.DialogResult result = folderDlg.ShowDialog();
|
||||||
|
if (result == WF.DialogResult.OK)
|
||||||
|
{
|
||||||
|
mainWnd.LastUsedExportFolder = folderDlg.SelectedPath;
|
||||||
|
|
||||||
|
using (new Hourglass())
|
||||||
|
{
|
||||||
|
mainWnd.DataModel?.ExportToCsv(folderDlg.SelectedPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mainWnd.ImportExportToggle.IsChecked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
MetadataTranslator/Metadata Translator/UI/LanguagePanel.xaml
Normal file
89
MetadataTranslator/Metadata Translator/UI/LanguagePanel.xaml
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<UserControl x:Class="Metadata_Translator.LanguagePanel"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:Metadata_Translator"
|
||||||
|
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
x:Name="lPanel"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800" Background="#FFF9F5EB">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<CollectionViewSource x:Key="TranslationGroups"
|
||||||
|
Source="{Binding TranslationGroups, ElementName=lPanel}">
|
||||||
|
<CollectionViewSource.SortDescriptions>
|
||||||
|
<scm:SortDescription PropertyName="Name"/>
|
||||||
|
</CollectionViewSource.SortDescriptions>
|
||||||
|
</CollectionViewSource>
|
||||||
|
<local:PercentageConverter x:Key="PercentageConverter" />
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Button Grid.Column="1" Height="16" Width="16" Background="Transparent" Margin="0,2,18,2"
|
||||||
|
BorderThickness="0" HorizontalAlignment="Right" VerticalAlignment="Top"
|
||||||
|
Click="CancelButton_Click">
|
||||||
|
<Image>
|
||||||
|
<Image.Source>
|
||||||
|
<DrawingImage>
|
||||||
|
<DrawingImage.Drawing>
|
||||||
|
<DrawingGroup>
|
||||||
|
<DrawingGroup.Transform>
|
||||||
|
<TransformGroup>
|
||||||
|
<ScaleTransform ScaleX="1" ScaleY="1"/>
|
||||||
|
<SkewTransform/>
|
||||||
|
<RotateTransform/>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</TransformGroup>
|
||||||
|
</DrawingGroup.Transform>
|
||||||
|
<DrawingGroup.Children>
|
||||||
|
<GeometryDrawing Geometry="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm101.8-262.2L295.6 256l62.2 62.2c4.7 4.7 4.7 12.3 0 17l-22.6 22.6c-4.7 4.7-12.3 4.7-17 0L256 295.6l-62.2 62.2c-4.7 4.7-12.3 4.7-17 0l-22.6-22.6c-4.7-4.7-4.7-12.3 0-17l62.2-62.2-62.2-62.2c-4.7-4.7-4.7-12.3 0-17l22.6-22.6c4.7-4.7 12.3-4.7 17 0l62.2 62.2 62.2-62.2c4.7-4.7 12.3-4.7 17 0l22.6 22.6c4.7 4.7 4.7 12.3 0 17z">
|
||||||
|
<GeometryDrawing.Pen>
|
||||||
|
<Pen Brush="Black" Thickness="1"/>
|
||||||
|
</GeometryDrawing.Pen>
|
||||||
|
<GeometryDrawing.Brush>
|
||||||
|
<RadialGradientBrush>
|
||||||
|
<GradientStop Color="Gray"/>
|
||||||
|
</RadialGradientBrush>
|
||||||
|
</GeometryDrawing.Brush>
|
||||||
|
</GeometryDrawing>
|
||||||
|
</DrawingGroup.Children>
|
||||||
|
</DrawingGroup>
|
||||||
|
</DrawingImage.Drawing>
|
||||||
|
</DrawingImage>
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
|
</Button>
|
||||||
|
<ScrollViewer Grid.Row="1" x:Name="underline">
|
||||||
|
<ItemsControl ItemsSource="{Binding Source={StaticResource TranslationGroups}}">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Margin="4,0" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Grid.Row="0" DockPanel.Dock="Top" Text="{Binding Name}" FontStyle="Italic" FontWeight="DemiBold" Margin="4,0"/>
|
||||||
|
<Rectangle Grid.Row="1" DockPanel.Dock="Top" Fill="Gray" Height="0.5" Width="{Binding ElementName=underline, Path=ActualWidth, Converter={StaticResource PercentageConverter}}" />
|
||||||
|
<local:TranslationGroupPanel Grid.Row="2" Grid.ColumnSpan="2" Margin="18,0,4,4"
|
||||||
|
Languages="{Binding Languages, ElementName=lPanel}"
|
||||||
|
TranslationGroupId="{Binding Tag}"/>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for LanguagePanel.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class LanguagePanel : UserControl
|
||||||
|
{
|
||||||
|
public LanguagePanel()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var mainWnd = MainWindow.GetMainWindow(this);
|
||||||
|
if (mainWnd != null)
|
||||||
|
{
|
||||||
|
mainWnd.LanguageToggle.IsChecked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Dependency Properties
|
||||||
|
public static readonly DependencyProperty LanguagesProperty =
|
||||||
|
DependencyProperty.Register("Languages", typeof(ObservableCollection<Language>), typeof(LanguagePanel),
|
||||||
|
new PropertyMetadata(null, new PropertyChangedCallback(OnLanguagesChanged)));
|
||||||
|
|
||||||
|
public ObservableCollection<Language> Languages
|
||||||
|
{
|
||||||
|
get { return (ObservableCollection<Language>)GetValue(LanguagesProperty); }
|
||||||
|
set { SetValue(LanguagesProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnLanguagesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is LanguagePanel langPanel)
|
||||||
|
{
|
||||||
|
langPanel.OnLanguagesChanged(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLanguagesChanged(DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.NewValue is ObservableCollection<Language> newItem)
|
||||||
|
{
|
||||||
|
newItem.CollectionChanged += LanguagesCollection_Changed;
|
||||||
|
}
|
||||||
|
else if (e.OldValue is ObservableCollection<Language> oldItem)
|
||||||
|
{
|
||||||
|
oldItem.CollectionChanged -= LanguagesCollection_Changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LanguagesCollection_Changed(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
TranslationGroups = Languages.Select(x => new TranslationGroup { Name = x.TranslationGroup, Tag = x.TranslationId }).Distinct().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly DependencyProperty TranslationGroupsProperty =
|
||||||
|
DependencyProperty.Register("TranslationGroups", typeof(List<TranslationGroup>), typeof(LanguagePanel));
|
||||||
|
|
||||||
|
public List<TranslationGroup> TranslationGroups
|
||||||
|
{
|
||||||
|
get { return (List<TranslationGroup>)GetValue(TranslationGroupsProperty); }
|
||||||
|
set { SetValue(TranslationGroupsProperty, value); }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
298
MetadataTranslator/Metadata Translator/UI/MainWindow.xaml
Normal file
298
MetadataTranslator/Metadata Translator/UI/MainWindow.xaml
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
<Window x:Class="Metadata_Translator.MainWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:Metadata_Translator"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
x:Name="main"
|
||||||
|
Title="Metadata Translator" Height="450" Width="800">
|
||||||
|
<Window.Resources>
|
||||||
|
<local:TrueFalseVisibilityConverter x:Key="TrueFalseVisibilityConverter" />
|
||||||
|
<local:FalseTrueVisibilityConverter x:Key="FalseTrueVisibilityConverter" />
|
||||||
|
<local:CollectionEmptyTrueFalseConverter x:Key="CollectionEmptyTrueFalseConverter" />
|
||||||
|
<local:TranslationPropertyToolTipConverter x:Key="TranslationPropertyToolTipConverter" />
|
||||||
|
</Window.Resources>
|
||||||
|
<Grid Margin="0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<ToolBarPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0">
|
||||||
|
<ToolBar ToolBarTray.IsLocked="True" Loaded="ToolBar_Loaded">
|
||||||
|
<RadioButton x:Name="LanguageToggle" GroupName="PanelButtons" Height="48" Width="48"
|
||||||
|
ToolTip="{StaticResource LanguagesToolTip}"
|
||||||
|
Click="OnToggleButton_Click" Unchecked="OnToggleButton_Uncheck">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Height="24" Width="32">
|
||||||
|
<Image.Source>
|
||||||
|
<DrawingImage>
|
||||||
|
<DrawingImage.Drawing>
|
||||||
|
<DrawingGroup>
|
||||||
|
<DrawingGroup.Transform>
|
||||||
|
<TransformGroup>
|
||||||
|
<ScaleTransform ScaleX="1" ScaleY="1"/>
|
||||||
|
<SkewTransform/>
|
||||||
|
<RotateTransform/>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</TransformGroup>
|
||||||
|
</DrawingGroup.Transform>
|
||||||
|
<DrawingGroup.Children>
|
||||||
|
<GeometryDrawing Geometry="M152.1 236.2c-3.5-12.1-7.8-33.2-7.8-33.2h-.5s-4.3 21.1-7.8 33.2l-11.1 37.5H163zM616 96H336v320h280c13.3 0 24-10.7 24-24V120c0-13.3-10.7-24-24-24zm-24 120c0 6.6-5.4 12-12 12h-11.4c-6.9 23.6-21.7 47.4-42.7 69.9 8.4 6.4 17.1 12.5 26.1 18 5.5 3.4 7.3 10.5 4.1 16.2l-7.9 13.9c-3.4 5.9-10.9 7.8-16.7 4.3-12.6-7.8-24.5-16.1-35.4-24.9-10.9 8.7-22.7 17.1-35.4 24.9-5.8 3.5-13.3 1.6-16.7-4.3l-7.9-13.9c-3.2-5.6-1.4-12.8 4.2-16.2 9.3-5.7 18-11.7 26.1-18-7.9-8.4-14.9-17-21-25.7-4-5.7-2.2-13.6 3.7-17.1l6.5-3.9 7.3-4.3c5.4-3.2 12.4-1.7 16 3.4 5 7 10.8 14 17.4 20.9 13.5-14.2 23.8-28.9 30-43.2H412c-6.6 0-12-5.4-12-12v-16c0-6.6 5.4-12 12-12h64v-16c0-6.6 5.4-12 12-12h16c6.6 0 12 5.4 12 12v16h64c6.6 0 12 5.4 12 12zM0 120v272c0 13.3 10.7 24 24 24h280V96H24c-13.3 0-24 10.7-24 24zm58.9 216.1L116.4 167c1.7-4.9 6.2-8.1 11.4-8.1h32.5c5.1 0 9.7 3.3 11.4 8.1l57.5 169.1c2.6 7.8-3.1 15.9-11.4 15.9h-22.9a12 12 0 0 1-11.5-8.6l-9.4-31.9h-60.2l-9.1 31.8c-1.5 5.1-6.2 8.7-11.5 8.7H70.3c-8.2 0-14-8.1-11.4-15.9z">
|
||||||
|
<GeometryDrawing.Pen>
|
||||||
|
<Pen Brush="Black" Thickness="10"/>
|
||||||
|
</GeometryDrawing.Pen>
|
||||||
|
<GeometryDrawing.Brush>
|
||||||
|
<RadialGradientBrush>
|
||||||
|
<GradientStop Color="#FF2F7C03"/>
|
||||||
|
</RadialGradientBrush>
|
||||||
|
</GeometryDrawing.Brush>
|
||||||
|
</GeometryDrawing>
|
||||||
|
</DrawingGroup.Children>
|
||||||
|
</DrawingGroup>
|
||||||
|
</DrawingImage.Drawing>
|
||||||
|
</DrawingImage>
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
|
<TextBlock FontSize="9" HorizontalAlignment="Center" Text="{StaticResource Languages}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</RadioButton>
|
||||||
|
<RadioButton x:Name="SettingsToggle" GroupName="PanelButtons" Height="48" Width="48"
|
||||||
|
ToolTip="{StaticResource SettingsToolTip}"
|
||||||
|
Click="OnToggleButton_Click" Unchecked="OnToggleButton_Uncheck">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Height="24">
|
||||||
|
<Image.Source>
|
||||||
|
<DrawingImage>
|
||||||
|
<DrawingImage.Drawing>
|
||||||
|
<DrawingGroup>
|
||||||
|
<DrawingGroup.Transform>
|
||||||
|
<TransformGroup>
|
||||||
|
<ScaleTransform ScaleX="1" ScaleY="1"/>
|
||||||
|
<SkewTransform/>
|
||||||
|
<RotateTransform/>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</TransformGroup>
|
||||||
|
</DrawingGroup.Transform>
|
||||||
|
<DrawingGroup.Children>
|
||||||
|
<GeometryDrawing Geometry="M113.595,133.642l-5.932-13.169c5.655-4.151,10.512-9.315,14.307-15.209l13.507,5.118c2.583,0.979,5.469-0.322,6.447-2.904
|
||||||
|
l4.964-13.103c0.47-1.24,0.428-2.616-0.117-3.825c-0.545-1.209-1.547-2.152-2.788-2.622l-13.507-5.118
|
||||||
|
c1.064-6.93,0.848-14.014-0.637-20.871l13.169-5.932c1.209-0.545,2.152-1.547,2.622-2.788c0.47-1.24,0.428-2.616-0.117-3.825
|
||||||
|
l-5.755-12.775c-1.134-2.518-4.096-3.638-6.612-2.505l-13.169,5.932c-4.151-5.655-9.315-10.512-15.209-14.307l5.118-13.507
|
||||||
|
c0.978-2.582-0.322-5.469-2.904-6.447L93.88,0.82c-1.239-0.469-2.615-0.428-3.825,0.117c-1.209,0.545-2.152,1.547-2.622,2.788
|
||||||
|
l-5.117,13.506c-6.937-1.07-14.033-0.849-20.872,0.636L55.513,4.699c-0.545-1.209-1.547-2.152-2.788-2.622
|
||||||
|
c-1.239-0.469-2.616-0.428-3.825,0.117L36.124,7.949c-2.518,1.134-3.639,4.094-2.505,6.612l5.932,13.169
|
||||||
|
c-5.655,4.151-10.512,9.315-14.307,15.209l-13.507-5.118c-1.239-0.469-2.615-0.427-3.825,0.117
|
||||||
|
c-1.209,0.545-2.152,1.547-2.622,2.788L0.326,53.828c-0.978,2.582,0.322,5.469,2.904,6.447l13.507,5.118
|
||||||
|
c-1.064,6.929-0.848,14.015,0.637,20.871L4.204,92.196c-1.209,0.545-2.152,1.547-2.622,2.788c-0.47,1.24-0.428,2.616,0.117,3.825
|
||||||
|
l5.755,12.775c0.544,1.209,1.547,2.152,2.787,2.622c1.241,0.47,2.616,0.429,3.825-0.117l13.169-5.932
|
||||||
|
c4.151,5.656,9.314,10.512,15.209,14.307l-5.118,13.507c-0.978,2.582,0.322,5.469,2.904,6.447l13.103,4.964
|
||||||
|
c0.571,0.216,1.172,0.324,1.771,0.324c0.701,0,1.402-0.147,2.054-0.441c1.209-0.545,2.152-1.547,2.622-2.788l5.117-13.506
|
||||||
|
c6.937,1.069,14.034,0.849,20.872-0.636l5.931,13.168c0.545,1.209,1.547,2.152,2.788,2.622c1.24,0.47,2.617,0.429,3.825-0.117
|
||||||
|
l12.775-5.754C113.607,139.12,114.729,136.16,113.595,133.642z M105.309,86.113c-4.963,13.1-17.706,21.901-31.709,21.901
|
||||||
|
c-4.096,0-8.135-0.744-12.005-2.21c-8.468-3.208-15.18-9.522-18.899-17.779c-3.719-8.256-4-17.467-0.792-25.935
|
||||||
|
c4.963-13.1,17.706-21.901,31.709-21.901c4.096,0,8.135,0.744,12.005,2.21c8.468,3.208,15.18,9.522,18.899,17.778
|
||||||
|
C108.237,68.434,108.518,77.645,105.309,86.113z M216.478,154.389c-0.896-0.977-2.145-1.558-3.469-1.615l-9.418-0.404
|
||||||
|
c-0.867-4.445-2.433-8.736-4.633-12.697l6.945-6.374c2.035-1.867,2.17-5.03,0.303-7.064l-6.896-7.514
|
||||||
|
c-0.896-0.977-2.145-1.558-3.47-1.615c-1.322-0.049-2.618,0.416-3.595,1.312l-6.944,6.374c-3.759-2.531-7.9-4.458-12.254-5.702
|
||||||
|
l0.404-9.418c0.118-2.759-2.023-5.091-4.782-5.209l-10.189-0.437c-2.745-0.104-5.091,2.023-5.209,4.781l-0.404,9.418
|
||||||
|
c-4.444,0.867-8.735,2.433-12.697,4.632l-6.374-6.945c-0.896-0.977-2.145-1.558-3.469-1.615c-1.324-0.054-2.618,0.416-3.595,1.312
|
||||||
|
l-7.514,6.896c-2.035,1.867-2.17,5.03-0.303,7.064l6.374,6.945c-2.531,3.759-4.458,7.899-5.702,12.254l-9.417-0.404
|
||||||
|
c-2.747-0.111-5.092,2.022-5.21,4.781l-0.437,10.189c-0.057,1.325,0.415,2.618,1.312,3.595c0.896,0.977,2.145,1.558,3.47,1.615
|
||||||
|
l9.417,0.403c0.867,4.445,2.433,8.736,4.632,12.698l-6.944,6.374c-0.977,0.896-1.558,2.145-1.615,3.469
|
||||||
|
c-0.057,1.325,0.415,2.618,1.312,3.595l6.896,7.514c0.896,0.977,2.145,1.558,3.47,1.615c1.319,0.053,2.618-0.416,3.595-1.312
|
||||||
|
l6.944-6.374c3.759,2.531,7.9,4.458,12.254,5.702l-0.404,9.418c-0.118,2.759,2.022,5.091,4.781,5.209l10.189,0.437
|
||||||
|
c0.072,0.003,0.143,0.004,0.214,0.004c1.25,0,2.457-0.468,3.381-1.316c0.977-0.896,1.558-2.145,1.615-3.469l0.404-9.418
|
||||||
|
c4.444-0.867,8.735-2.433,12.697-4.632l6.374,6.945c0.896,0.977,2.145,1.558,3.469,1.615c1.33,0.058,2.619-0.416,3.595-1.312
|
||||||
|
l7.514-6.896c2.035-1.867,2.17-5.03,0.303-7.064l-6.374-6.945c2.531-3.759,4.458-7.899,5.702-12.254l9.417,0.404
|
||||||
|
c2.756,0.106,5.091-2.022,5.21-4.781l0.437-10.189C217.847,156.659,217.375,155.366,216.478,154.389z M160.157,183.953
|
||||||
|
c-12.844-0.55-22.846-11.448-22.295-24.292c0.536-12.514,10.759-22.317,23.273-22.317c0.338,0,0.678,0.007,1.019,0.022
|
||||||
|
c12.844,0.551,22.846,11.448,22.295,24.292C183.898,174.511,173.106,184.497,160.157,183.953z">
|
||||||
|
<GeometryDrawing.Pen>
|
||||||
|
<Pen Brush="Black" Thickness="10"/>
|
||||||
|
</GeometryDrawing.Pen>
|
||||||
|
<GeometryDrawing.Brush>
|
||||||
|
<RadialGradientBrush>
|
||||||
|
<GradientStop Color="#FFDEA210"/>
|
||||||
|
<GradientStop Color="#DEA210" Offset="0.992"/>
|
||||||
|
<GradientStop Color="#AADEA210" Offset="0.527"/>
|
||||||
|
<GradientStop Color="#FFDEA210" Offset="0.644"/>
|
||||||
|
</RadialGradientBrush>
|
||||||
|
</GeometryDrawing.Brush>
|
||||||
|
</GeometryDrawing>
|
||||||
|
</DrawingGroup.Children>
|
||||||
|
</DrawingGroup>
|
||||||
|
</DrawingImage.Drawing>
|
||||||
|
</DrawingImage>
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
|
<TextBlock FontSize="9" HorizontalAlignment="Center" Text="{StaticResource Settings}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</RadioButton>
|
||||||
|
<Separator/>
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock FontSize="9" Text="{StaticResource TranslatedProperty}" HorizontalAlignment="Center" Margin="0,4,0,-4"/>
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,8,0,0">
|
||||||
|
<StackPanel ToolTip="{StaticResource CaptionToolTip}">
|
||||||
|
<RadioButton GroupName="TranslationProperty" IsChecked="True" HorizontalAlignment="Center" Click="OnCaptionRadioButton_Click"/>
|
||||||
|
<TextBlock FontSize="8" Text="{StaticResource Caption}" Padding="2,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel ToolTip="{Binding DataModel.Descriptions, ElementName=main, Converter={StaticResource TranslationPropertyToolTipConverter}, ConverterParameter={StaticResource DescriptionToolTip}}">
|
||||||
|
<RadioButton GroupName="TranslationProperty" HorizontalAlignment="Center" Click="OnDescriptionRadioButton_Click"
|
||||||
|
IsEnabled="{Binding DataModel.Descriptions, ElementName=main, Converter={StaticResource CollectionEmptyTrueFalseConverter}}"/>
|
||||||
|
<TextBlock FontSize="8" Text="{StaticResource Description}" Padding="2,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel ToolTip="{Binding DataModel.DisplayFolders, ElementName=main, Converter={StaticResource TranslationPropertyToolTipConverter}, ConverterParameter={StaticResource DisplayFolderToolTip}}">
|
||||||
|
<RadioButton GroupName="TranslationProperty" HorizontalAlignment="Center" Click="OnDisplayFolderRadioButton_Click"
|
||||||
|
IsEnabled="{Binding DataModel.DisplayFolders, ElementName=main, Converter={StaticResource CollectionEmptyTrueFalseConverter}}"/>
|
||||||
|
<TextBlock FontSize="8" Text="{StaticResource DisplayFolder}" Padding="2,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
<Separator/>
|
||||||
|
<Button Height="48" Width="48" Click="OnPrepareButton_Click" Visibility="Collapsed">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Height="24" Width="32">
|
||||||
|
<Image.Source>
|
||||||
|
<DrawingImage>
|
||||||
|
<DrawingImage.Drawing>
|
||||||
|
<DrawingGroup>
|
||||||
|
<DrawingGroup.Transform>
|
||||||
|
<TransformGroup>
|
||||||
|
<ScaleTransform ScaleX="1" ScaleY="1"/>
|
||||||
|
<SkewTransform/>
|
||||||
|
<RotateTransform/>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</TransformGroup>
|
||||||
|
</DrawingGroup.Transform>
|
||||||
|
<DrawingGroup.Children>
|
||||||
|
<GeometryDrawing Geometry="M104 224H24c-13.255 0-24 10.745-24 24v240c0 13.255 10.745 24 24 24h80c13.255 0 24-10.745 24-24V248c0-13.255-10.745-24-24-24zM64 472c-13.255 0-24-10.745-24-24s10.745-24 24-24 24 10.745 24 24-10.745 24-24 24zM384 81.452c0 42.416-25.97 66.208-33.277 94.548h101.723c33.397 0 59.397 27.746 59.553 58.098.084 17.938-7.546 37.249-19.439 49.197l-.11.11c9.836 23.337 8.237 56.037-9.308 79.469 8.681 25.895-.069 57.704-16.382 74.757 4.298 17.598 2.244 32.575-6.148 44.632C440.202 511.587 389.616 512 346.839 512l-2.845-.001c-48.287-.017-87.806-17.598-119.56-31.725-15.957-7.099-36.821-15.887-52.651-16.178-6.54-.12-11.783-5.457-11.783-11.998v-213.77c0-3.2 1.282-6.271 3.558-8.521 39.614-39.144 56.648-80.587 89.117-113.111 14.804-14.832 20.188-37.236 25.393-58.902C282.515 39.293 291.817 0 312 0c24 0 72 8 72 81.452z">
|
||||||
|
<GeometryDrawing.Pen>
|
||||||
|
<Pen Brush="Black" Thickness="10"/>
|
||||||
|
</GeometryDrawing.Pen>
|
||||||
|
<GeometryDrawing.Brush>
|
||||||
|
<RadialGradientBrush>
|
||||||
|
<GradientStop Color="#FFAF800D"/>
|
||||||
|
</RadialGradientBrush>
|
||||||
|
</GeometryDrawing.Brush>
|
||||||
|
</GeometryDrawing>
|
||||||
|
</DrawingGroup.Children>
|
||||||
|
</DrawingGroup>
|
||||||
|
</DrawingImage.Drawing>
|
||||||
|
</DrawingImage>
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
|
<TextBlock FontSize="9" HorizontalAlignment="Center" Text="{StaticResource Prepare}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Height="48" Width="48" Click="OnTranslateButton_Click" ToolTip="{StaticResource TranslateToolTip}">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Source="..\icon.ico" Height="24"/>
|
||||||
|
<TextBlock FontSize="9" HorizontalAlignment="Center" Text="{StaticResource Translate}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Height="48" Width="48" Click="OnApplyButton_Click" ToolTip="{StaticResource ApplyToolTip}">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Height="24" Width="32">
|
||||||
|
<Image.Source>
|
||||||
|
<DrawingImage>
|
||||||
|
<DrawingImage.Drawing>
|
||||||
|
<DrawingGroup>
|
||||||
|
<DrawingGroup.Transform>
|
||||||
|
<TransformGroup>
|
||||||
|
<ScaleTransform ScaleX="1" ScaleY="1"/>
|
||||||
|
<SkewTransform/>
|
||||||
|
<RotateTransform/>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</TransformGroup>
|
||||||
|
</DrawingGroup.Transform>
|
||||||
|
<DrawingGroup.Children>
|
||||||
|
<GeometryDrawing Geometry="M400 480H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48v352c0 26.51-21.49 48-48 48zm-204.686-98.059l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.248-16.379-6.249-22.628 0L184 302.745l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.25 16.379 6.25 22.628.001z">
|
||||||
|
<GeometryDrawing.Pen>
|
||||||
|
<Pen Brush="Black" Thickness="10"/>
|
||||||
|
</GeometryDrawing.Pen>
|
||||||
|
<GeometryDrawing.Brush>
|
||||||
|
<RadialGradientBrush>
|
||||||
|
<GradientStop Color="#FF2F7C03"/>
|
||||||
|
</RadialGradientBrush>
|
||||||
|
</GeometryDrawing.Brush>
|
||||||
|
</GeometryDrawing>
|
||||||
|
</DrawingGroup.Children>
|
||||||
|
</DrawingGroup>
|
||||||
|
</DrawingImage.Drawing>
|
||||||
|
</DrawingImage>
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
|
<TextBlock FontSize="9" HorizontalAlignment="Center" Text="{StaticResource Apply}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</ToolBar>
|
||||||
|
</ToolBarPanel>
|
||||||
|
<ToolBarPanel Grid.Row="0" Grid.Column="2" Margin="0">
|
||||||
|
<ToolBar ToolBarTray.IsLocked="True" Loaded="ToolBar_Loaded">
|
||||||
|
<RadioButton x:Name="ImportExportToggle" GroupName="PanelButtons" Height="48" Width="68"
|
||||||
|
ToolTip="{StaticResource ImportExportToolTip}"
|
||||||
|
Click="OnToggleButton_Click" Unchecked="OnToggleButton_Uncheck">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Height="24">
|
||||||
|
<Image.Source>
|
||||||
|
<DrawingImage>
|
||||||
|
<DrawingImage.Drawing>
|
||||||
|
<DrawingGroup>
|
||||||
|
<DrawingGroup.Transform>
|
||||||
|
<TransformGroup>
|
||||||
|
<ScaleTransform ScaleX="1" ScaleY="1"/>
|
||||||
|
<SkewTransform/>
|
||||||
|
<RotateTransform/>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</TransformGroup>
|
||||||
|
</DrawingGroup.Transform>
|
||||||
|
<DrawingGroup.Children>
|
||||||
|
<GeometryDrawing Geometry="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm-96 144c0 4.42-3.58 8-8 8h-8c-8.84 0-16 7.16-16 16v32c0 8.84 7.16 16 16 16h8c4.42 0 8 3.58 8 8v16c0 4.42-3.58 8-8 8h-8c-26.51 0-48-21.49-48-48v-32c0-26.51 21.49-48 48-48h8c4.42 0 8 3.58 8 8v16zm44.27 104H160c-4.42 0-8-3.58-8-8v-16c0-4.42 3.58-8 8-8h12.27c5.95 0 10.41-3.5 10.41-6.62 0-1.3-.75-2.66-2.12-3.84l-21.89-18.77c-8.47-7.22-13.33-17.48-13.33-28.14 0-21.3 19.02-38.62 42.41-38.62H200c4.42 0 8 3.58 8 8v16c0 4.42-3.58 8-8 8h-12.27c-5.95 0-10.41 3.5-10.41 6.62 0 1.3.75 2.66 2.12 3.84l21.89 18.77c8.47 7.22 13.33 17.48 13.33 28.14.01 21.29-19 38.62-42.39 38.62zM256 264v20.8c0 20.27 5.7 40.17 16 56.88 10.3-16.7 16-36.61 16-56.88V264c0-4.42 3.58-8 8-8h16c4.42 0 8 3.58 8 8v20.8c0 35.48-12.88 68.89-36.28 94.09-3.02 3.25-7.27 5.11-11.72 5.11s-8.7-1.86-11.72-5.11c-23.4-25.2-36.28-58.61-36.28-94.09V264c0-4.42 3.58-8 8-8h16c4.42 0 8 3.58 8 8zm121-159L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z">
|
||||||
|
<GeometryDrawing.Pen>
|
||||||
|
<Pen Brush="White" Thickness="8"/>
|
||||||
|
</GeometryDrawing.Pen>
|
||||||
|
<GeometryDrawing.Brush>
|
||||||
|
<RadialGradientBrush>
|
||||||
|
<GradientStop Color="Black"/>
|
||||||
|
</RadialGradientBrush>
|
||||||
|
</GeometryDrawing.Brush>
|
||||||
|
</GeometryDrawing>
|
||||||
|
</DrawingGroup.Children>
|
||||||
|
</DrawingGroup>
|
||||||
|
</DrawingImage.Drawing>
|
||||||
|
</DrawingImage>
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
|
<TextBlock FontSize="9" HorizontalAlignment="Center" Text="{StaticResource ImportExport}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</RadioButton>
|
||||||
|
</ToolBar>
|
||||||
|
</ToolBarPanel>
|
||||||
|
<Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<local:SettingsPanel Grid.Row="0" Grid.ColumnSpan="3"
|
||||||
|
Visibility="{Binding IsChecked, ElementName=SettingsToggle, Converter={StaticResource FalseTrueVisibilityConverter}}"/>
|
||||||
|
<local:LanguagePanel Grid.Row="1" Visibility="{Binding IsChecked, ElementName=LanguageToggle, Converter={StaticResource FalseTrueVisibilityConverter}}"
|
||||||
|
Languages="{Binding Languages, ElementName=main}"/>
|
||||||
|
<ScrollViewer Grid.Row="1" Grid.Column="1" HorizontalScrollBarVisibility="Auto">
|
||||||
|
<DataGrid x:Name="dataGrid" AutoGenerateColumns="False" CanUserAddRows="False" BorderThickness="0"/>
|
||||||
|
</ScrollViewer>
|
||||||
|
<local:ImportExportPanel Grid.Row="1" Grid.Column="2" Visibility="{Binding IsChecked, ElementName=ImportExportToggle, Converter={StaticResource FalseTrueVisibilityConverter}}"/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
638
MetadataTranslator/Metadata Translator/UI/MainWindow.xaml.cs
Normal file
638
MetadataTranslator/Metadata Translator/UI/MainWindow.xaml.cs
Normal file
@ -0,0 +1,638 @@
|
|||||||
|
using Microsoft.AnalysisServices.Tabular;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web.Script.Serialization;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Controls.Primitives;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for MainWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
Configuration AppConfig { get; set; }
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
AppConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||||
|
|
||||||
|
SetDependencyProperty("SubscriptionKey");
|
||||||
|
SetDependencyProperty("TranslatorEndpoint");
|
||||||
|
SetDependencyProperty("TranslatorLocation");
|
||||||
|
SetDependencyProperty("OverwriteTranslation");
|
||||||
|
SetDependencyProperty("LastUsedExportFolder");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(SubscriptionKey))
|
||||||
|
{
|
||||||
|
SettingsToggle.IsChecked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MainWindow(StartupEventArgs e) : this()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (e.Args.Length != 2)
|
||||||
|
{
|
||||||
|
throw new Exception((string)Application.Current.FindResource("InvalidArguments"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PowerBIEngine = e.Args[0];
|
||||||
|
DatabaseName = e.Args[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
DataModel = DataModel.Connect(PowerBIEngine, DatabaseName);
|
||||||
|
|
||||||
|
SetDependencyProperty("Languages");
|
||||||
|
InitializeDataGrid();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(ex.Message);
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddColumn(string lcid)
|
||||||
|
{
|
||||||
|
Language language = GetLanguageByLcid(lcid);
|
||||||
|
if (language != null)
|
||||||
|
{
|
||||||
|
dataGrid.Columns.Add(new DataGridTextColumn
|
||||||
|
{
|
||||||
|
Header = language.DisplayName,
|
||||||
|
Binding = new Binding(lcid)
|
||||||
|
});
|
||||||
|
|
||||||
|
language.IsSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Helper functions
|
||||||
|
/// <summary>
|
||||||
|
/// Set Dependency Properties that wrap apps ettings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parameterName"></param>
|
||||||
|
private void SetDependencyProperty(string parameterName)
|
||||||
|
{
|
||||||
|
switch (parameterName)
|
||||||
|
{
|
||||||
|
case "SubscriptionKey":
|
||||||
|
SubscriptionKey = AppConfig.AppSettings.Settings[parameterName].Value;
|
||||||
|
break;
|
||||||
|
case "TranslatorEndpoint":
|
||||||
|
TranslatorEndpoint = AppConfig.AppSettings.Settings[parameterName].Value;
|
||||||
|
break;
|
||||||
|
case "TranslatorLocation":
|
||||||
|
TranslatorLocation = AppConfig.AppSettings.Settings[parameterName].Value;
|
||||||
|
break;
|
||||||
|
case "OverwriteTranslation":
|
||||||
|
string configSetting = AppConfig.AppSettings.Settings[parameterName].Value;
|
||||||
|
OverwriteTranslation = bool.TryParse(configSetting, out bool value) && value;
|
||||||
|
break;
|
||||||
|
case "LastUsedExportFolder":
|
||||||
|
LastUsedExportFolder = AppConfig.AppSettings.Settings[parameterName].Value;
|
||||||
|
break;
|
||||||
|
case "Languages":
|
||||||
|
Languages = new ObservableCollection<Language>();
|
||||||
|
foreach (var language in DataModel.SupportedLanguages)
|
||||||
|
{
|
||||||
|
Languages.Add(language);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the datagrid columns and sets the ItemsSource to the default collection.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeDataGrid()
|
||||||
|
{
|
||||||
|
List<string> cultures = DataModel.CultureNames;
|
||||||
|
|
||||||
|
/// Create some setters and triggers for the
|
||||||
|
/// styles of the read-only columns.
|
||||||
|
///
|
||||||
|
Trigger iIsSelectedTrigger = new Trigger()
|
||||||
|
{
|
||||||
|
Property = DataGridTextColumn.IsReadOnlyProperty,
|
||||||
|
Value = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var foregroundSetter = new Setter(DataGridCell.ForegroundProperty, new SolidColorBrush(Colors.Black));
|
||||||
|
iIsSelectedTrigger.Setters.Add(foregroundSetter);
|
||||||
|
|
||||||
|
var backgroundSetter = new Setter(DataGridCell.BackgroundProperty, new SolidColorBrush(Colors.LightGray));
|
||||||
|
|
||||||
|
/// The first column is for the metadata container object.
|
||||||
|
///
|
||||||
|
var objectColumnStyle = new Style(typeof(DataGridCell));
|
||||||
|
objectColumnStyle.Setters.Add(backgroundSetter);
|
||||||
|
objectColumnStyle.Setters.Add(foregroundSetter);
|
||||||
|
objectColumnStyle.Triggers.Add(iIsSelectedTrigger);
|
||||||
|
dataGrid.Columns.Add(new DataGridTextColumn
|
||||||
|
{
|
||||||
|
Header = FindResource("TabularObjectColumnHeader").ToString(),
|
||||||
|
Binding = new Binding(DataModel.ContainerColumnHeader),
|
||||||
|
IsReadOnly = true,
|
||||||
|
CellStyle = objectColumnStyle
|
||||||
|
});
|
||||||
|
|
||||||
|
/// The second column is for the default culture of the data model,
|
||||||
|
/// which is always the first language in the list of data model cultures.
|
||||||
|
///
|
||||||
|
var defaultLangColumnStyle = new Style(typeof(DataGridCell));
|
||||||
|
defaultLangColumnStyle.Setters.Add(foregroundSetter);
|
||||||
|
defaultLangColumnStyle.Triggers.Add(iIsSelectedTrigger);
|
||||||
|
|
||||||
|
/// Add a tooltip to flag that the default culture is readonly.
|
||||||
|
///
|
||||||
|
var objectHeaderStyle = new Style(typeof(DataGridColumnHeader));
|
||||||
|
objectHeaderStyle.Setters.Add(new Setter(ToolTipService.ToolTipProperty,
|
||||||
|
FindResource("DefaultCultureColumnHeaderToolTip").ToString()));
|
||||||
|
|
||||||
|
Language defaultLang = GetLanguageByLcid(cultures[0]);
|
||||||
|
dataGrid.Columns.Add(new DataGridTextColumn
|
||||||
|
{
|
||||||
|
Header = $"{defaultLang.DisplayName}*",
|
||||||
|
HeaderStyle = objectHeaderStyle,
|
||||||
|
Binding = new Binding(cultures[0]),
|
||||||
|
IsReadOnly = true,
|
||||||
|
CellStyle = defaultLangColumnStyle
|
||||||
|
});
|
||||||
|
SetLanguageFlags(cultures[0], true, true);
|
||||||
|
|
||||||
|
|
||||||
|
/// Add the remaining languages that already exist in the data model
|
||||||
|
/// and mark them as selected in the list of supported languages.
|
||||||
|
///
|
||||||
|
for (int i = 1; i< cultures.Count; i++)
|
||||||
|
{
|
||||||
|
AddColumn(cultures[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// And set Captions as the default content of the datagrid.
|
||||||
|
dataGrid.ItemsSource = DataModel.Captions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marks a language specified by lcid as selected and as model default.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcid"></param>
|
||||||
|
/// <param name="isSelected"></param>
|
||||||
|
/// <param name="isModelDefault"></param>
|
||||||
|
private void SetLanguageFlags(string lcid, bool isSelected, bool isModelDefault = false)
|
||||||
|
{
|
||||||
|
Language language = Languages.Where(x => x.LanguageTag.Equals(lcid)).FirstOrDefault();
|
||||||
|
if (language != null)
|
||||||
|
{
|
||||||
|
language.IsSelected = isSelected;
|
||||||
|
language.IsModelDefault = isModelDefault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Language object based on the lcid (i.e. LanguageTag).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcid"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private Language GetLanguageByLcid(string lcid)
|
||||||
|
{
|
||||||
|
return Languages.Where(x => x.LanguageTag.Equals(lcid)).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a handle to the main window object so that other user controls can
|
||||||
|
/// access the public properties of the main window object directly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="child"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static MainWindow GetMainWindow(DependencyObject child)
|
||||||
|
{
|
||||||
|
if (child == null) return null;
|
||||||
|
|
||||||
|
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
|
||||||
|
if (parentObject is MainWindow parent)
|
||||||
|
{
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return GetMainWindow(parentObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save app settings to the application config file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="settingName"></param>
|
||||||
|
/// <param name="newValue"></param>
|
||||||
|
private void OnAppSettingChanged(string settingName, string newValue)
|
||||||
|
{
|
||||||
|
AppConfig.AppSettings.Settings[settingName].Value = newValue;
|
||||||
|
AppConfig.Save(ConfigurationSaveMode.Modified);
|
||||||
|
ConfigurationManager.RefreshSection("appSettings");
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Dependency Properties
|
||||||
|
public static readonly DependencyProperty DataModelProperty =
|
||||||
|
DependencyProperty.Register("DataModel", typeof(DataModel), typeof(MainWindow));
|
||||||
|
|
||||||
|
public DataModel DataModel
|
||||||
|
{
|
||||||
|
get { return (DataModel)GetValue(DataModelProperty); }
|
||||||
|
set { SetValue(DataModelProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Supported languages collection
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty LanguagesProperty =
|
||||||
|
DependencyProperty.Register("Languages", typeof(ObservableCollection<Language>), typeof(MainWindow),
|
||||||
|
new PropertyMetadata(null, new PropertyChangedCallback(OnLanguagesChanged)));
|
||||||
|
|
||||||
|
public ObservableCollection<Language> Languages
|
||||||
|
{
|
||||||
|
get { return (ObservableCollection<Language>)GetValue(LanguagesProperty); }
|
||||||
|
set { SetValue(LanguagesProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnLanguagesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
(sender as MainWindow).OnLanguagesChanged(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLanguagesChanged(DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.NewValue is ObservableCollection<Language> newCollection)
|
||||||
|
{
|
||||||
|
newCollection.CollectionChanged += LanguagesCollection_Changed;
|
||||||
|
|
||||||
|
if (newCollection.Count > 0)
|
||||||
|
AttachLanguagePropertyChangedEventHandler(newCollection);
|
||||||
|
}
|
||||||
|
else if (e.OldValue is ObservableCollection<Language> oldCollection)
|
||||||
|
{
|
||||||
|
oldCollection.CollectionChanged -= LanguagesCollection_Changed;
|
||||||
|
|
||||||
|
if (oldCollection.Count > 0)
|
||||||
|
RemoveLanguagePropertyChangedEventHandler(oldCollection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LanguagesCollection_Changed(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
switch(e.Action)
|
||||||
|
{
|
||||||
|
case NotifyCollectionChangedAction.Add:
|
||||||
|
AttachLanguagePropertyChangedEventHandler(e.NewItems);
|
||||||
|
break;
|
||||||
|
case NotifyCollectionChangedAction.Remove:
|
||||||
|
RemoveLanguagePropertyChangedEventHandler(e.OldItems);
|
||||||
|
break;
|
||||||
|
case NotifyCollectionChangedAction.Replace:
|
||||||
|
RemoveLanguagePropertyChangedEventHandler(e.OldItems);
|
||||||
|
AttachLanguagePropertyChangedEventHandler(e.NewItems);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AttachLanguagePropertyChangedEventHandler(System.Collections.IList items)
|
||||||
|
{
|
||||||
|
foreach (Language language in items)
|
||||||
|
{
|
||||||
|
language.PropertyChanged += LanguageProperty_Changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveLanguagePropertyChangedEventHandler(System.Collections.IList items)
|
||||||
|
{
|
||||||
|
foreach (Language language in items)
|
||||||
|
{
|
||||||
|
language.PropertyChanged -= LanguageProperty_Changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler for LanguageProperty_Changed event to add or remove a lanugage
|
||||||
|
/// from the datagrid headers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void LanguageProperty_Changed(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(sender is Language language
|
||||||
|
&& e.PropertyName == "IsSelected"
|
||||||
|
&& !language.LanguageTag.Equals(DataModel.DefaultCulture))
|
||||||
|
{
|
||||||
|
var existingColumn = dataGrid.Columns.Where(x => language.DisplayName.Equals(x.Header.ToString())).FirstOrDefault();
|
||||||
|
if (language.IsSelected)
|
||||||
|
{
|
||||||
|
if (existingColumn == null)
|
||||||
|
{
|
||||||
|
dataGrid.Columns.Add(new DataGridTextColumn
|
||||||
|
{
|
||||||
|
Header = language.DisplayName,
|
||||||
|
Binding = new Binding(language.LanguageTag)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (existingColumn != null)
|
||||||
|
{
|
||||||
|
dataGrid.Columns.Remove(existingColumn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SubscriptionKey Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty SubscriptionKeyProperty =
|
||||||
|
DependencyProperty.Register("SubscriptionKey", typeof(string), typeof(MainWindow),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnSubscriptionKeyChanged)));
|
||||||
|
|
||||||
|
public string SubscriptionKey
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(SubscriptionKeyProperty); }
|
||||||
|
set { SetValue(SubscriptionKeyProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnSubscriptionKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
(d as MainWindow)?.OnAppSettingChanged("SubscriptionKey", (string)e.NewValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TranslatorEndpoint Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty TranslatorEndpointProperty =
|
||||||
|
DependencyProperty.Register("TranslatorEndpoint", typeof(string), typeof(MainWindow),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnTranslatorEndpointChanged)));
|
||||||
|
|
||||||
|
public string TranslatorEndpoint
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(TranslatorEndpointProperty); }
|
||||||
|
set { SetValue(TranslatorEndpointProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnTranslatorEndpointChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
(d as MainWindow)?.OnAppSettingChanged("TranslatorEndpoint", (string)e.NewValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TranslatorLocation Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty TranslatorLocationProperty =
|
||||||
|
DependencyProperty.Register("TranslatorLocation", typeof(string), typeof(MainWindow),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnTranslatorLocationChanged)));
|
||||||
|
|
||||||
|
public string TranslatorLocation
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(TranslatorLocationProperty); }
|
||||||
|
set { SetValue(TranslatorLocationProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnTranslatorLocationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
(d as MainWindow)?.OnAppSettingChanged("TranslatorLocation", (string)e.NewValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OverwriteTranslation Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty OverwriteTranslationProperty =
|
||||||
|
DependencyProperty.Register("OverwriteTranslation", typeof(bool), typeof(MainWindow),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnOverwriteTranslationChanged)));
|
||||||
|
|
||||||
|
public bool OverwriteTranslation
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(OverwriteTranslationProperty); }
|
||||||
|
set { SetValue(OverwriteTranslationProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnOverwriteTranslationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
(d as MainWindow)?.OnAppSettingChanged("OverwriteTranslation", e.NewValue.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// LastUsedExportFolder Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty LastUsedExportFolderProperty =
|
||||||
|
DependencyProperty.Register("LastUsedExportFolder", typeof(string), typeof(MainWindow),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnLastUsedExportFolderChanged)));
|
||||||
|
|
||||||
|
public string LastUsedExportFolder
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(LastUsedExportFolderProperty); }
|
||||||
|
set { SetValue(LastUsedExportFolderProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnLastUsedExportFolderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
(d as MainWindow)?.OnAppSettingChanged("LastUsedExportFolder", (string)e.NewValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PowerBIEngine Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty PowerBIEngineProperty =
|
||||||
|
DependencyProperty.Register("PowerBIEngine", typeof(string), typeof(MainWindow));
|
||||||
|
public string PowerBIEngine
|
||||||
|
{
|
||||||
|
set { SetValue(PowerBIEngineProperty, value); }
|
||||||
|
get { return (string)GetValue(PowerBIEngineProperty); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DatabaseName Property
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty DatabaseNameProperty =
|
||||||
|
DependencyProperty.Register("DatabaseName", typeof(string), typeof(MainWindow));
|
||||||
|
public string DatabaseName
|
||||||
|
{
|
||||||
|
set { SetValue(DatabaseNameProperty, value); }
|
||||||
|
get { return (string)GetValue(DatabaseNameProperty); }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Event Handlers
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler for ToolBar_Loaded event to remove some of the
|
||||||
|
/// unnecessary standard UI elements of the toolbar.
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void ToolBar_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if(sender is ToolBar toolBar)
|
||||||
|
{
|
||||||
|
if (toolBar.Template.FindName("OverflowGrid", toolBar) is FrameworkElement overflowGrid)
|
||||||
|
{
|
||||||
|
overflowGrid.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolBar.Template.FindName("MainPanelBorder", toolBar) is FrameworkElement mainPanelBorder)
|
||||||
|
{
|
||||||
|
mainPanelBorder.Margin = new Thickness();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enabling the deselect of a selected toggle button on mouseclick.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void OnToggleButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if(sender is RadioButton radio)
|
||||||
|
{
|
||||||
|
bool tagState = (radio.Tag == null);
|
||||||
|
radio.Tag = (radio.Tag == null) ? new object() : null;
|
||||||
|
radio.IsChecked = tagState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unsets the tag that indicates if a toggle button was clicked to be deselected.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void OnToggleButton_Uncheck(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is RadioButton radio)
|
||||||
|
{
|
||||||
|
radio.Tag = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Display the Captions in the datagrid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void OnCaptionRadioButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataModel != null)
|
||||||
|
{
|
||||||
|
dataGrid.ItemsSource = DataModel.Captions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Display the Descriptions in the datagrid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void OnDescriptionRadioButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataModel != null)
|
||||||
|
{
|
||||||
|
dataGrid.ItemsSource = DataModel.Descriptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Display the DisplayFolder strings in the datagrid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void OnDisplayFolderRadioButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataModel != null)
|
||||||
|
{
|
||||||
|
dataGrid.ItemsSource = DataModel.DisplayFolders;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make the terms in the default culture more translatable by splitting the strings
|
||||||
|
/// based on camel casing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void OnPrepareButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataModel == null) return;
|
||||||
|
|
||||||
|
string defaultCulture = DataModel.DefaultCulture;
|
||||||
|
foreach(ExpandoObject row in DataModel.GetAllDataRows())
|
||||||
|
{
|
||||||
|
((IDictionary<String, Object>)row)[defaultCulture] = row.SeparateCamelCase(defaultCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Translate the strings tn the default culture into the
|
||||||
|
/// selected target languages.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void OnTranslateButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataModel.HasTargetLanguages)
|
||||||
|
{
|
||||||
|
using (new Hourglass())
|
||||||
|
{
|
||||||
|
var ts = new TranslatorService(Languages.Where(x => x.IsSelected == true)?.ToList(), DataModel.DefaultCulture, SubscriptionKey, TranslatorEndpoint, TranslatorLocation);
|
||||||
|
ts.Translate(DataModel.GetAllDataRows(), OverwriteTranslation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBox.Show(FindResource("NothingToTranslate").ToString());
|
||||||
|
LanguageToggle.IsChecked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply the current values in the Captions, Descriptions, and DisplayFolders collections to the data model.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void OnApplyButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
DataModel.Update();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
117
MetadataTranslator/Metadata Translator/UI/SettingsPanel.xaml
Normal file
117
MetadataTranslator/Metadata Translator/UI/SettingsPanel.xaml
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<UserControl x:Class="Metadata_Translator.SettingsPanel"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:Metadata_Translator"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
|
IsVisibleChanged="Visibility_Changed" Background="#FFE7EBEC">
|
||||||
|
<Grid x:Name="grid">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="32"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Label Grid.Row="0" Content="{StaticResource DatasetConnection}" Margin="4,10,8,0" VerticalContentAlignment="Center"/>
|
||||||
|
<Label Grid.Row="1" Content="{StaticResource SubscriptionKey}" Margin="4,0,8,0"/>
|
||||||
|
<Label Grid.Row="2" Content="{StaticResource TranslatorEndpoint}" Margin="4,0,8,0"/>
|
||||||
|
<Label Grid.Row="3" Content="{StaticResource TranslatorLocation}" Margin="4,0,8,0"/>
|
||||||
|
<TextBox x:Name="AsServerInfo" Grid.Column="1" BorderThickness="0" Background="Transparent" IsReadOnly="True" Margin="4,10,8,0" VerticalContentAlignment="Center" Foreground="Gray"/>
|
||||||
|
<TextBox x:Name="SubscriptionKey" Grid.Row="1" Grid.Column="1" Margin="4,2,26,2">
|
||||||
|
<TextBox.Style>
|
||||||
|
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
|
||||||
|
<Style.Resources>
|
||||||
|
<VisualBrush x:Key="CueBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
|
||||||
|
<VisualBrush.Visual>
|
||||||
|
<Grid>
|
||||||
|
<Rectangle Width="3000" Height="100" Fill="White"/>
|
||||||
|
<Label Content="{StaticResource SubscriptionKeyPrompt}" Foreground="Gray" FontStyle="Italic" VerticalAlignment="Center"/>
|
||||||
|
</Grid>
|
||||||
|
</VisualBrush.Visual>
|
||||||
|
</VisualBrush>
|
||||||
|
</Style.Resources>
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
|
||||||
|
<Setter Property="Background" Value="{StaticResource CueBrush}" />
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="Text" Value="{x:Null}">
|
||||||
|
<Setter Property="Background" Value="{StaticResource CueBrush}" />
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsKeyboardFocused" Value="True">
|
||||||
|
<Setter Property="Background" Value="White" />
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBox.Style>
|
||||||
|
</TextBox>
|
||||||
|
<TextBox x:Name="TranslatorEndpoint" Grid.Row="2" Grid.Column="1" Margin="4,2,26,2">
|
||||||
|
<TextBox.Style>
|
||||||
|
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
|
||||||
|
<Style.Resources>
|
||||||
|
<VisualBrush x:Key="CueBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
|
||||||
|
<VisualBrush.Visual>
|
||||||
|
<Grid>
|
||||||
|
<Rectangle Width="3000" Height="100" Fill="White"/>
|
||||||
|
<Label Content="{StaticResource TranslatorEndpointPrompt}" Foreground="Gray" FontStyle="Italic" VerticalAlignment="Center"/>
|
||||||
|
</Grid>
|
||||||
|
</VisualBrush.Visual>
|
||||||
|
</VisualBrush>
|
||||||
|
</Style.Resources>
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
|
||||||
|
<Setter Property="Background" Value="{StaticResource CueBrush}" />
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="Text" Value="{x:Null}">
|
||||||
|
<Setter Property="Background" Value="{StaticResource CueBrush}" />
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsKeyboardFocused" Value="True">
|
||||||
|
<Setter Property="Background" Value="White" />
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBox.Style>
|
||||||
|
</TextBox>
|
||||||
|
<TextBox x:Name="TranslatorLocation" Grid.Row="3" Grid.Column="1" Margin="4,2,26,2">
|
||||||
|
<TextBox.Style>
|
||||||
|
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
|
||||||
|
<Style.Resources>
|
||||||
|
<VisualBrush x:Key="CueBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
|
||||||
|
<VisualBrush.Visual>
|
||||||
|
<Grid>
|
||||||
|
<Rectangle Width="3000" Height="100" Fill="White"/>
|
||||||
|
<Label Content="{StaticResource TranslatorLocationPrompt}" Foreground="Gray" FontStyle="Italic" VerticalAlignment="Center"/>
|
||||||
|
</Grid>
|
||||||
|
</VisualBrush.Visual>
|
||||||
|
</VisualBrush>
|
||||||
|
</Style.Resources>
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
|
||||||
|
<Setter Property="Background" Value="{StaticResource CueBrush}" />
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="Text" Value="{x:Null}">
|
||||||
|
<Setter Property="Background" Value="{StaticResource CueBrush}" />
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsKeyboardFocused" Value="True">
|
||||||
|
<Setter Property="Background" Value="White" />
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBox.Style>
|
||||||
|
</TextBox>
|
||||||
|
<StackPanel Grid.Column="1" Grid.Row="4" Orientation="Horizontal" Margin="4,0">
|
||||||
|
<CheckBox x:Name="OverwriteTranslation" VerticalAlignment="Center"/>
|
||||||
|
<Label Content="{StaticResource OverwriteTranslation}" VerticalAlignment="Center"/>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Column="1" Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
|
<Button Content="OK" Margin="4" Width="48" Click="OKButton_Click"/>
|
||||||
|
<Button Content="Cancel" Margin="4" Width="48" Click="CancelButton_Click"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for SettingsPanel.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class SettingsPanel : UserControl
|
||||||
|
{
|
||||||
|
public SettingsPanel()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var mainWnd = MainWindow.GetMainWindow(this);
|
||||||
|
if(mainWnd != null)
|
||||||
|
{
|
||||||
|
mainWnd.SettingsToggle.IsChecked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Visibility_Changed(object sender, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var mainWnd = MainWindow.GetMainWindow(this);
|
||||||
|
if (mainWnd == null) return;
|
||||||
|
|
||||||
|
if (e.NewValue is Boolean show && show == true)
|
||||||
|
{
|
||||||
|
AsServerInfo.Text = $"Data Source={mainWnd.PowerBIEngine};Initial Catalog={mainWnd.DatabaseName}";
|
||||||
|
SubscriptionKey.Text = mainWnd.SubscriptionKey;
|
||||||
|
TranslatorEndpoint.Text = mainWnd.TranslatorEndpoint;
|
||||||
|
TranslatorLocation.Text = mainWnd.TranslatorLocation;
|
||||||
|
OverwriteTranslation.IsChecked = mainWnd.OverwriteTranslation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OKButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var mainWnd = MainWindow.GetMainWindow(this);
|
||||||
|
if (mainWnd != null)
|
||||||
|
{
|
||||||
|
mainWnd.SubscriptionKey = SubscriptionKey.Text;
|
||||||
|
mainWnd.TranslatorEndpoint = TranslatorEndpoint.Text;
|
||||||
|
mainWnd.TranslatorLocation = TranslatorLocation.Text;
|
||||||
|
mainWnd.OverwriteTranslation = (bool) OverwriteTranslation.IsChecked;
|
||||||
|
mainWnd.SettingsToggle.IsChecked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
<UserControl x:Class="Metadata_Translator.TranslationGroupPanel"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
|
||||||
|
xmlns:local="clr-namespace:Metadata_Translator"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
x:Name="tgPanel"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<CollectionViewSource x:Key="FilteredLanguages"
|
||||||
|
Source="{Binding Languages, ElementName=tgPanel}"
|
||||||
|
Filter="Languages_Filter">
|
||||||
|
<CollectionViewSource.SortDescriptions>
|
||||||
|
<scm:SortDescription PropertyName="DisplayName"/>
|
||||||
|
</CollectionViewSource.SortDescriptions>
|
||||||
|
</CollectionViewSource>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Grid Margin="0,4,0,0">
|
||||||
|
<ItemsControl ItemsSource="{Binding Source={StaticResource FilteredLanguages}}">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" Margin="1" VerticalAlignment="Center" IsEnabled="{Binding IsNotModelDefault}"/>
|
||||||
|
<TextBlock Text="{Binding DisplayName}" VerticalAlignment="Center" Margin="2,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace Metadata_Translator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for TranslationGroupPanel.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class TranslationGroupPanel : UserControl
|
||||||
|
{
|
||||||
|
public TranslationGroupPanel()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Dependency Properties
|
||||||
|
public static readonly DependencyProperty LanguagesProperty =
|
||||||
|
DependencyProperty.Register("Languages", typeof(ObservableCollection<Language>), typeof(TranslationGroupPanel));
|
||||||
|
|
||||||
|
public ObservableCollection<Language> Languages
|
||||||
|
{
|
||||||
|
get { return (ObservableCollection<Language>)GetValue(LanguagesProperty); }
|
||||||
|
set { SetValue(LanguagesProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty TranslationGroupIdProperty =
|
||||||
|
DependencyProperty.Register("TranslationGroupId", typeof(string), typeof(TranslationGroupPanel));
|
||||||
|
|
||||||
|
public string TranslationGroupId
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(TranslationGroupIdProperty); }
|
||||||
|
set { SetValue(TranslationGroupIdProperty, value); }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void Languages_Filter(object sender, FilterEventArgs e)
|
||||||
|
{
|
||||||
|
e.Accepted = (e.Item is Language langItem && langItem.TranslationId == TranslationGroupId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
MetadataTranslator/Metadata Translator/icon.ico
Normal file
BIN
MetadataTranslator/Metadata Translator/icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
File diff suppressed because one or more lines are too long
5
MetadataTranslator/Metadata Translator/packages.config
Normal file
5
MetadataTranslator/Metadata Translator/packages.config
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.AnalysisServices.AdomdClient.retail.amd64" version="19.16.3" targetFramework="net472" />
|
||||||
|
<package id="Microsoft.AnalysisServices.retail.amd64" version="19.16.3" targetFramework="net472" />
|
||||||
|
</packages>
|
Loading…
Reference in New Issue
Block a user