Browse Source

Implicit localization strings

flabbet 1 year ago
parent
commit
26d7a0ae29

+ 2 - 2
samples/LocalizationSample/Localization/en.json

@@ -1,4 +1,4 @@
 {
 {
-  "LOC_SAM:HELLO_WORLD": "Hello World!",
-  "LOC_SAM:HELLO_NAME": "Hello {0}!"
+  "HELLO_WORLD": "Hello World!",
+  "HELLO_NAME": "Hello {0}!"
 }
 }

+ 7 - 2
samples/LocalizationSample/LocalizationSampleExtension.cs

@@ -18,7 +18,12 @@ public class LocalizationSampleExtension : WasmExtension
     /// </summary>
     /// </summary>
     public override void OnInitialized()
     public override void OnInitialized()
     {
     {
-        Api.Logger.Log(new LocalizedString("LOC_SAM:HELLO_WORLD"));
-        Api.Logger.Log(new LocalizedString("LOC_SAM:HELLO_NAME", "John Doe"));
+        // You can either use direct key or ExtensionUniqueName:Key to access localization strings.
+        Api.Logger.Log(new LocalizedString("HELLO_WORLD"));
+        Api.Logger.Log(new LocalizedString("HELLO_NAME", "John Doe"));
+
+        // By prepending "PixiEditor:" to the key, you can access built-in PixiEditor localization strings.
+        // if you prepend any other extension unique name, you can access that extension localization strings.
+        Api.Logger.Log(new LocalizedString("PixiEditor:SHOW_IMAGE_PREVIEW_TASKBAR"));
     }
     }
 }
 }

+ 0 - 0
samples/Preferences/readme.md → samples/Preferences/README.md


+ 38 - 9
src/PixiEditor.Extensions.MSPackageBuilder/PackageBuilder.cs

@@ -18,7 +18,6 @@ public static class PackageBuilder
 
 
     public static void Build(string buildResultDirectory, string targetDirectory)
     public static void Build(string buildResultDirectory, string targetDirectory)
     {
     {
-        string packageName = Path.GetFileName(buildResultDirectory);
         if (!Directory.Exists(buildResultDirectory))
         if (!Directory.Exists(buildResultDirectory))
         {
         {
             throw new DirectoryNotFoundException($"Directory {buildResultDirectory} does not exist.");
             throw new DirectoryNotFoundException($"Directory {buildResultDirectory} does not exist.");
@@ -41,6 +40,10 @@ public static class PackageBuilder
         {
         {
             throw new InvalidOperationException("Build result directory and target directory cannot be the same.");
             throw new InvalidOperationException("Build result directory and target directory cannot be the same.");
         }
         }
+        
+        SimplifiedExtensionMetadata metadata =
+            JsonConvert.DeserializeObject<SimplifiedExtensionMetadata>(
+                File.ReadAllText(Path.Combine(buildResultDirectory, "extension.json")));
 
 
         foreach (ElementToInclude element in ElementsToInclude)
         foreach (ElementToInclude element in ElementsToInclude)
         {
         {
@@ -50,14 +53,10 @@ public static class PackageBuilder
             }
             }
             else
             else
             {
             {
-                CopyDirectory(element.Path, buildResultDirectory, targetTmpDirectory, element.IsRequired);
+                CopyDirectory(element.Path, buildResultDirectory, targetTmpDirectory, element.IsRequired, metadata);
             }
             }
         }
         }
 
 
-        SimplifiedExtensionMetadata metadata =
-            JsonConvert.DeserializeObject<SimplifiedExtensionMetadata>(
-                File.ReadAllText(Path.Combine(buildResultDirectory, "extension.json")));
-
         string packagePath = Path.Combine(targetDirectory, $"{metadata.UniqueName}.pixiext");
         string packagePath = Path.Combine(targetDirectory, $"{metadata.UniqueName}.pixiext");
         if (File.Exists(packagePath))
         if (File.Exists(packagePath))
         {
         {
@@ -95,7 +94,7 @@ public static class PackageBuilder
     }
     }
 
 
     private static void CopyDirectory(string elementPath, string buildResultDirectory, string targetDirectory,
     private static void CopyDirectory(string elementPath, string buildResultDirectory, string targetDirectory,
-        bool elementIsRequired)
+        bool elementIsRequired, SimplifiedExtensionMetadata metadata)
     {
     {
         string directoryPath = Path.Combine(buildResultDirectory, elementPath);
         string directoryPath = Path.Combine(buildResultDirectory, elementPath);
         if (!Directory.Exists(directoryPath))
         if (!Directory.Exists(directoryPath))
@@ -109,13 +108,43 @@ public static class PackageBuilder
             return;
             return;
         }
         }
 
 
-        string targetDir = Path.Combine(targetDirectory, directoryPath);
+        string targetDir = Path.Combine(targetDirectory, elementPath);
         Directory.CreateDirectory(targetDir);
         Directory.CreateDirectory(targetDir);
         var files = Directory.GetFiles(directoryPath);
         var files = Directory.GetFiles(directoryPath);
         foreach (string file in files)
         foreach (string file in files)
         {
         {
-            File.Copy(file, Path.Combine(targetDir, Path.GetFileName(file)), true);
+            string destination = Path.Combine(targetDir, Path.GetFileName(file));
+            if(FileIsLocale(elementPath))
+            {
+                WriteLocale(file, destination, metadata.UniqueName);
+                return;
+            }
+            
+            File.Copy(file, destination, true);
+        }
+    }
+
+    private static void WriteLocale(string file, string destination, string metadataUniqueName)
+    {
+        Dictionary<string, string> dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(file));
+        Dictionary<string, string> newDict = new();
+        foreach (KeyValuePair<string, string> pair in dict)
+        {
+            if (pair.Key.Contains(":"))
+            {
+                continue;
+            }
+            
+            newDict.Add($"{metadataUniqueName}:{pair.Key}", pair.Value);
         }
         }
+        
+        File.WriteAllText(destination, JsonConvert.SerializeObject(newDict));
+    }
+    
+    
+    private static bool FileIsLocale(string elementPath)
+    {
+        return elementPath.EndsWith("Localization/");
     }
     }
 }
 }
 
 

+ 1 - 0
src/PixiEditor.Extensions.MSPackageBuilder/PixiEditor.Extensions.MSPackageBuilder.csproj

@@ -7,6 +7,7 @@
     <LangVersion>default</LangVersion>
     <LangVersion>default</LangVersion>
     <OutputPath>../PixiEditor.Extensions.Wasm/build/</OutputPath>
     <OutputPath>../PixiEditor.Extensions.Wasm/build/</OutputPath>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+    <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
     <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
     <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
     <DebugType>None</DebugType>
     <DebugType>None</DebugType>
   </PropertyGroup>
   </PropertyGroup>

+ 2 - 2
src/PixiEditor.Extensions.Wasm/build/PixiEditor.Extensions.MSPackageBuilder.deps.json

@@ -1,12 +1,12 @@
 {
 {
   "runtimeTarget": {
   "runtimeTarget": {
-    "name": ".NETStandard,Version=v2.0/",
+    "name": ".NETStandard,Version=v2.0/win-x64",
     "signature": ""
     "signature": ""
   },
   },
   "compilationOptions": {},
   "compilationOptions": {},
   "targets": {
   "targets": {
     ".NETStandard,Version=v2.0": {},
     ".NETStandard,Version=v2.0": {},
-    ".NETStandard,Version=v2.0/": {
+    ".NETStandard,Version=v2.0/win-x64": {
       "PixiEditor.Extensions.MSPackageBuilder/1.0.0": {
       "PixiEditor.Extensions.MSPackageBuilder/1.0.0": {
         "dependencies": {
         "dependencies": {
           "Microsoft.Build.Utilities.Core": "17.9.5",
           "Microsoft.Build.Utilities.Core": "17.9.5",

BIN
src/PixiEditor.Extensions.Wasm/build/PixiEditor.Extensions.MSPackageBuilder.dll


BIN
src/PixiEditor.Extensions.Wasm/build/win-x64/Newtonsoft.Json.dll


+ 0 - 244
src/PixiEditor.Extensions.Wasm/build/win-x64/PixiEditor.Extensions.MSPackageBuilder.deps.json

@@ -1,244 +0,0 @@
-{
-  "runtimeTarget": {
-    "name": ".NETStandard,Version=v2.0/win-x64",
-    "signature": ""
-  },
-  "compilationOptions": {},
-  "targets": {
-    ".NETStandard,Version=v2.0": {},
-    ".NETStandard,Version=v2.0/win-x64": {
-      "PixiEditor.Extensions.MSPackageBuilder/1.0.0": {
-        "dependencies": {
-          "Microsoft.Build.Utilities.Core": "17.9.5",
-          "NETStandard.Library": "2.0.3",
-          "Newtonsoft.Json": "13.0.1",
-          "StyleCop.Analyzers": "1.1.118"
-        },
-        "runtime": {
-          "PixiEditor.Extensions.MSPackageBuilder.dll": {}
-        }
-      },
-      "Microsoft.Build.Framework/17.9.5": {
-        "dependencies": {
-          "Microsoft.Win32.Registry": "5.0.0",
-          "System.Memory": "4.5.5",
-          "System.Runtime.CompilerServices.Unsafe": "6.0.0",
-          "System.Security.Principal.Windows": "5.0.0"
-        }
-      },
-      "Microsoft.Build.Utilities.Core/17.9.5": {
-        "dependencies": {
-          "Microsoft.Build.Framework": "17.9.5",
-          "Microsoft.NET.StringTools": "17.9.5",
-          "Microsoft.Win32.Registry": "5.0.0",
-          "System.Collections.Immutable": "8.0.0",
-          "System.Configuration.ConfigurationManager": "8.0.0",
-          "System.Memory": "4.5.5",
-          "System.Runtime.CompilerServices.Unsafe": "6.0.0",
-          "System.Security.Principal.Windows": "5.0.0",
-          "System.Text.Encoding.CodePages": "7.0.0"
-        }
-      },
-      "Microsoft.NET.StringTools/17.9.5": {
-        "dependencies": {
-          "System.Memory": "4.5.5",
-          "System.Runtime.CompilerServices.Unsafe": "6.0.0"
-        }
-      },
-      "Microsoft.NETCore.Platforms/1.1.0": {},
-      "Microsoft.Win32.Registry/5.0.0": {
-        "dependencies": {
-          "System.Buffers": "4.5.1",
-          "System.Memory": "4.5.5",
-          "System.Security.AccessControl": "5.0.0",
-          "System.Security.Principal.Windows": "5.0.0"
-        }
-      },
-      "NETStandard.Library/2.0.3": {
-        "dependencies": {
-          "Microsoft.NETCore.Platforms": "1.1.0"
-        }
-      },
-      "Newtonsoft.Json/13.0.1": {
-        "runtime": {
-          "lib/netstandard2.0/Newtonsoft.Json.dll": {
-            "assemblyVersion": "13.0.0.0",
-            "fileVersion": "13.0.1.25517"
-          }
-        }
-      },
-      "StyleCop.Analyzers/1.1.118": {},
-      "System.Buffers/4.5.1": {},
-      "System.Collections.Immutable/8.0.0": {
-        "dependencies": {
-          "System.Memory": "4.5.5",
-          "System.Runtime.CompilerServices.Unsafe": "6.0.0"
-        }
-      },
-      "System.Configuration.ConfigurationManager/8.0.0": {
-        "dependencies": {
-          "System.Security.Cryptography.ProtectedData": "8.0.0"
-        }
-      },
-      "System.Memory/4.5.5": {
-        "dependencies": {
-          "System.Buffers": "4.5.1",
-          "System.Numerics.Vectors": "4.4.0",
-          "System.Runtime.CompilerServices.Unsafe": "6.0.0"
-        }
-      },
-      "System.Numerics.Vectors/4.4.0": {},
-      "System.Runtime.CompilerServices.Unsafe/6.0.0": {},
-      "System.Security.AccessControl/5.0.0": {
-        "dependencies": {
-          "System.Security.Principal.Windows": "5.0.0"
-        }
-      },
-      "System.Security.Cryptography.ProtectedData/8.0.0": {
-        "dependencies": {
-          "System.Memory": "4.5.5"
-        }
-      },
-      "System.Security.Principal.Windows/5.0.0": {},
-      "System.Text.Encoding.CodePages/7.0.0": {
-        "dependencies": {
-          "System.Memory": "4.5.5",
-          "System.Runtime.CompilerServices.Unsafe": "6.0.0"
-        }
-      }
-    }
-  },
-  "libraries": {
-    "PixiEditor.Extensions.MSPackageBuilder/1.0.0": {
-      "type": "project",
-      "serviceable": false,
-      "sha512": ""
-    },
-    "Microsoft.Build.Framework/17.9.5": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-CjRmqu9Wv2fyC1d7NKOuBDXcNMI8+GiXGM6izygB+skGGu4Vf0cBcoPq7AFqZCcMpn5DtZ+y7RpaLpB2qrzanQ==",
-      "path": "microsoft.build.framework/17.9.5",
-      "hashPath": "microsoft.build.framework.17.9.5.nupkg.sha512"
-    },
-    "Microsoft.Build.Utilities.Core/17.9.5": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-H2hpVdm7cX/uGJD1HOfab3RKgD5tlnvzQkFqvsrAqGHRi0sqb2w1+hRwERFm23witCjmERnqNgiQjYks6/ds8A==",
-      "path": "microsoft.build.utilities.core/17.9.5",
-      "hashPath": "microsoft.build.utilities.core.17.9.5.nupkg.sha512"
-    },
-    "Microsoft.NET.StringTools/17.9.5": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-C/oPRnjcIZBRzcpl1V06R1eEMCxOGt6mIm+8ioyblELgJEXLM8XjUPuCwljMO52VetsHw54xMcYwU8UEeHEIEg==",
-      "path": "microsoft.net.stringtools/17.9.5",
-      "hashPath": "microsoft.net.stringtools.17.9.5.nupkg.sha512"
-    },
-    "Microsoft.NETCore.Platforms/1.1.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==",
-      "path": "microsoft.netcore.platforms/1.1.0",
-      "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512"
-    },
-    "Microsoft.Win32.Registry/5.0.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
-      "path": "microsoft.win32.registry/5.0.0",
-      "hashPath": "microsoft.win32.registry.5.0.0.nupkg.sha512"
-    },
-    "NETStandard.Library/2.0.3": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
-      "path": "netstandard.library/2.0.3",
-      "hashPath": "netstandard.library.2.0.3.nupkg.sha512"
-    },
-    "Newtonsoft.Json/13.0.1": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
-      "path": "newtonsoft.json/13.0.1",
-      "hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
-    },
-    "StyleCop.Analyzers/1.1.118": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-Onx6ovGSqXSK07n/0eM3ZusiNdB6cIlJdabQhWGgJp3Vooy9AaLS/tigeybOJAobqbtggTamoWndz72JscZBvw==",
-      "path": "stylecop.analyzers/1.1.118",
-      "hashPath": "stylecop.analyzers.1.1.118.nupkg.sha512"
-    },
-    "System.Buffers/4.5.1": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==",
-      "path": "system.buffers/4.5.1",
-      "hashPath": "system.buffers.4.5.1.nupkg.sha512"
-    },
-    "System.Collections.Immutable/8.0.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==",
-      "path": "system.collections.immutable/8.0.0",
-      "hashPath": "system.collections.immutable.8.0.0.nupkg.sha512"
-    },
-    "System.Configuration.ConfigurationManager/8.0.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-JlYi9XVvIREURRUlGMr1F6vOFLk7YSY4p1vHo4kX3tQ0AGrjqlRWHDi66ImHhy6qwXBG3BJ6Y1QlYQ+Qz6Xgww==",
-      "path": "system.configuration.configurationmanager/8.0.0",
-      "hashPath": "system.configuration.configurationmanager.8.0.0.nupkg.sha512"
-    },
-    "System.Memory/4.5.5": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
-      "path": "system.memory/4.5.5",
-      "hashPath": "system.memory.4.5.5.nupkg.sha512"
-    },
-    "System.Numerics.Vectors/4.4.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==",
-      "path": "system.numerics.vectors/4.4.0",
-      "hashPath": "system.numerics.vectors.4.4.0.nupkg.sha512"
-    },
-    "System.Runtime.CompilerServices.Unsafe/6.0.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
-      "path": "system.runtime.compilerservices.unsafe/6.0.0",
-      "hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
-    },
-    "System.Security.AccessControl/5.0.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
-      "path": "system.security.accesscontrol/5.0.0",
-      "hashPath": "system.security.accesscontrol.5.0.0.nupkg.sha512"
-    },
-    "System.Security.Cryptography.ProtectedData/8.0.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==",
-      "path": "system.security.cryptography.protecteddata/8.0.0",
-      "hashPath": "system.security.cryptography.protecteddata.8.0.0.nupkg.sha512"
-    },
-    "System.Security.Principal.Windows/5.0.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==",
-      "path": "system.security.principal.windows/5.0.0",
-      "hashPath": "system.security.principal.windows.5.0.0.nupkg.sha512"
-    },
-    "System.Text.Encoding.CodePages/7.0.0": {
-      "type": "package",
-      "serviceable": true,
-      "sha512": "sha512-LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==",
-      "path": "system.text.encoding.codepages/7.0.0",
-      "hashPath": "system.text.encoding.codepages.7.0.0.nupkg.sha512"
-    }
-  }
-}

BIN
src/PixiEditor.Extensions.Wasm/build/win-x64/PixiEditor.Extensions.MSPackageBuilder.dll


+ 18 - 2
src/PixiEditor.Extensions.WasmRuntime/Api/LocalizationApi.cs

@@ -5,9 +5,25 @@ namespace PixiEditor.Extensions.WasmRuntime.Api;
 internal class LocalizationApi : ApiGroupHandler
 internal class LocalizationApi : ApiGroupHandler
 {
 {
     [ApiFunction("translate_key")]
     [ApiFunction("translate_key")]
-    public static string TranslateKey(string key)
+    public string TranslateKey(string key)
     {
     {
-        LocalizedString localizedString = new LocalizedString(key);
+        string finalKey = key;
+        var split = key.Split(":");
+        if (split.Length == 1)
+        {
+            finalKey = $"{Metadata.UniqueName}:{key}";
+        }
+        else if (split.Length == 2)
+        {
+            string caller = split[0];
+            string keyName = split[1];
+            if (caller.Equals("pixieditor", StringComparison.InvariantCultureIgnoreCase))
+            {
+                finalKey = keyName;
+            }
+        }
+        
+        LocalizedString localizedString = new LocalizedString(finalKey);
         return localizedString.Value;
         return localizedString.Value;
     }
     }
 }
 }

+ 0 - 5
tests/CGlueTestLib/Exports.cs

@@ -7,10 +7,5 @@ namespace CGlueTestLib;
 
 
 internal static class Exports
 internal static class Exports
 {
 {
-    [ApiExport("testExport")]
-    internal static void TestExport()
-    {
-
-    }
 
 
 }
 }

+ 6 - 0
tests/PixiEditorTests.sln

@@ -37,6 +37,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor.Extensions.Wasm.
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor.Extensions.WasmRuntime.Tests", "PixiEditor.Extensions.WasmRuntime.Tests\PixiEditor.Extensions.WasmRuntime.Tests.csproj", "{DA31D2E8-2AC2-41D1-921B-7571881EE85F}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor.Extensions.WasmRuntime.Tests", "PixiEditor.Extensions.WasmRuntime.Tests\PixiEditor.Extensions.WasmRuntime.Tests.csproj", "{DA31D2E8-2AC2-41D1-921B-7571881EE85F}"
 EndProject
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor.Extensions.MSPackageBuilder", "..\src\PixiEditor.Extensions.MSPackageBuilder\PixiEditor.Extensions.MSPackageBuilder.csproj", "{6D965165-3B4D-4C70-A559-6AD093879D5A}"
+EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
 		Debug|Any CPU = Debug|Any CPU
@@ -102,6 +104,10 @@ Global
 		{DA31D2E8-2AC2-41D1-921B-7571881EE85F}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{DA31D2E8-2AC2-41D1-921B-7571881EE85F}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{DA31D2E8-2AC2-41D1-921B-7571881EE85F}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{DA31D2E8-2AC2-41D1-921B-7571881EE85F}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{DA31D2E8-2AC2-41D1-921B-7571881EE85F}.Release|Any CPU.Build.0 = Release|Any CPU
 		{DA31D2E8-2AC2-41D1-921B-7571881EE85F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6D965165-3B4D-4C70-A559-6AD093879D5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6D965165-3B4D-4C70-A559-6AD093879D5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6D965165-3B4D-4C70-A559-6AD093879D5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6D965165-3B4D-4C70-A559-6AD093879D5A}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(NestedProjects) = preSolution
 	GlobalSection(NestedProjects) = preSolution
 		{7F2DBBFC-FBDB-4772-806F-3B0829032DC0} = {E118E6FE-67E7-4472-A8D7-E7F470E66131}
 		{7F2DBBFC-FBDB-4772-806F-3B0829032DC0} = {E118E6FE-67E7-4472-A8D7-E7F470E66131}