@joebigelow / wix-1 / commits / 7be5d945

Link localizations from WixExtensions the same as sections

Rob Mensching committed Dec 6, 2023 at 15:30 UTC 7be5d94529c8419b4bd5da4dcd838795622643cb
41 files changed +237 -121
src/api/wix/WixToolset.Data/Localization.cs
+36 -3
@@ -15,11 +15,20 @@ namespace WixToolset.Data
15 private readonly Dictionary<string, BindVariable> variables = new Dictionary<string, BindVariable>();
16 private readonly Dictionary<string, LocalizedControl> localizedControls = new Dictionary<string, LocalizedControl>();
17
18 + /// <summary>
19 + /// Instantiates a new localization object with default location.
20 + /// </summary>
21 + public Localization(int? codepage, int? summaryInformationCodepage, string culture, IDictionary<string, BindVariable> variables, IDictionary<string, LocalizedControl> localizedControls) :
22 + this(LocalizationLocation.Source, codepage, summaryInformationCodepage, culture, variables, localizedControls)
23 + {
24 + }
25 +
26 /// <summary>
27 /// Instantiates a new localization object.
28 /// </summary>
21 - public Localization(int? codepage, int? summaryInformationCodepage, string culture, IDictionary<string, BindVariable> variables, IDictionary<string, LocalizedControl> localizedControls)
29 + public Localization(LocalizationLocation location, int? codepage, int? summaryInformationCodepage, string culture, IDictionary<string, BindVariable> variables, IDictionary<string, LocalizedControl> localizedControls)
30 {
31 + this.Location = location;
32 this.Codepage = codepage;
33 this.SummaryInformationCodepage = summaryInformationCodepage;
34 this.Culture = culture?.ToLowerInvariant() ?? String.Empty;
@@ -27,6 +36,11 @@ namespace WixToolset.Data
36 this.localizedControls = new Dictionary<string, LocalizedControl>(localizedControls);
37 }
38
39 + /// <summary>
40 + /// Gets the location the localization came from.
41 + /// </summary>
42 + public LocalizationLocation Location { get; private set; }
43 +
44 /// <summary>
45 /// Gets the codepage.
46 /// </summary>
@@ -57,9 +71,27 @@ namespace WixToolset.Data
71 /// <value>The localized controls.</value>
72 public ICollection<KeyValuePair<string, LocalizedControl>> LocalizedControls => this.localizedControls;
73
74 + /// <summary>
75 + /// Updates the location, if the location is a higher state than the current state.
76 + /// </summary>
77 + /// <param name="location">Location to update to.</param>
78 + /// <returns>This localization object.</returns>
79 + public Localization UpdateLocation(LocalizationLocation location)
80 + {
81 + if (this.Location < location)
82 + {
83 + this.Location = location;
84 + }
85 +
86 + return this;
87 + }
88 +
89 internal JsonObject Serialize()
90 {
62 - var jsonObject = new JsonObject();
91 + var jsonObject = new JsonObject()
92 + {
93 + { "location", this.Location.ToString().ToLowerInvariant() }
94 + };
95
96 if (this.Codepage.HasValue)
97 {
@@ -108,6 +140,7 @@ namespace WixToolset.Data
140
141 internal static Localization Deserialize(JsonObject jsonObject)
142 {
143 + var location = jsonObject.GetEnumOrDefault("location", LocalizationLocation.Source);
144 var codepage = jsonObject.GetValueOrDefault("codepage", null);
145 var summaryCodepage = jsonObject.GetValueOrDefault("summaryCodepage", null);
146 var culture = jsonObject.GetValueOrDefault<string>("culture");
@@ -131,7 +164,7 @@ namespace WixToolset.Data
164 }
165 }
166
134 - return new Localization(codepage, summaryCodepage, culture, variables, controls);
167 + return new Localization(location, codepage, summaryCodepage, culture, variables, controls);
168 }
169 }
170 }
src/api/wix/WixToolset.Data/LocalizationLocation.cs new
+31
@@ -0,0 +1,31 @@
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 +
3 +namespace WixToolset.Data
4 +{
5 + /// <summary>
6 + /// Location where the localization was loaded.
7 + /// </summary>
8 + public enum LocalizationLocation
9 + {
10 + /// <summary>
11 + /// Localization loaded from .wxl source file.
12 + /// </summary>
13 + Source,
14 +
15 + /// <summary>
16 + /// Localization loaded from .wixlib library.
17 + /// </summary>
18 + Library,
19 +
20 + /// <summary>
21 + /// Localization loaded from .wixlib library within .wixext WixExtension.
22 + /// </summary>
23 + Extension,
24 +
25 + /// <summary>
26 + /// Localization placed in .wixext WixExtension as the default culture localization for the
27 + /// WixExtension.
28 + /// </summary>
29 + ExtensionDefaultCulture
30 + }
31 +}
src/api/wix/WixToolset.Data/LocalizedControl.cs
+8 -2
@@ -45,7 +45,10 @@ namespace WixToolset.Data
45 /// Get key for a localized control.
46 /// </summary>
47 /// <returns>The localized control id.</returns>
48 - public string GetKey() => LocalizedControl.GetKey(this.Dialog, this.Control);
48 + public string GetKey()
49 + {
50 + return LocalizedControl.GetKey(this.Dialog, this.Control);
51 + }
52
53 /// <summary>
54 /// Get key for a localized control.
@@ -53,7 +56,10 @@ namespace WixToolset.Data
56 /// <param name="dialog">The optional id of the control's dialog.</param>
57 /// <param name="control">The id of the control.</param>
58 /// <returns>The localized control id.</returns>
56 - public static string GetKey(string dialog, string control) => String.Concat(dialog, "/", control);
59 + public static string GetKey(string dialog, string control)
60 + {
61 + return String.Concat(dialog, "/", control);
62 + }
63
64 internal JsonObject Serialize()
65 {
src/api/wix/WixToolset.Extensibility/BaseExtensionData.cs
+3 -1
@@ -2,6 +2,7 @@
2
3 namespace WixToolset.Extensibility
4 {
5 + using System;
6 using WixToolset.Data;
7
8 /// <summary>
@@ -10,8 +11,9 @@ namespace WixToolset.Extensibility
11 public abstract class BaseExtensionData : IExtensionData
12 {
13 /// <summary>
13 - /// See <see cref="IExtensionData.DefaultCulture"/>
14 + /// Obsolete in WiX v5. Use the WixLocalization/@ExtensionDefaultCulture attribute in the wxl file instead.
15 /// </summary>
16 + [Obsolete("Set the ExtensionDefaultCulture attribute in the WixLocalization source file instead.")]
17 public virtual string DefaultCulture => null;
18
19 /// <summary>
src/api/wix/WixToolset.Extensibility/IExtensionData.cs
-6
@@ -9,12 +9,6 @@ namespace WixToolset.Extensibility
9 /// </summary>
10 public interface IExtensionData
11 {
12 - /// <summary>
13 - /// Gets the optional default culture.
14 - /// </summary>
15 - /// <value>The optional default culture.</value>
16 - string DefaultCulture { get; }
17 -
12 /// <summary>
13 ///
14 /// </summary>
src/ext/Bal/wixext/BalExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.Bal
10 /// </summary>
11 public sealed class BalExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
14 {
15 symbolDefinition = BalSymbolDefinitions.ByName(name);
src/ext/ComPlus/wixext/ComPlusExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.ComPlus
10 /// </summary>
11 public sealed class ComPlusExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
14 {
15 symbolDefinition = ComPlusSymbolDefinitions.ByName(name);
src/ext/ComPlus/wixlib/en-us.wxl
+1 -1
@@ -1,7 +1,7 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4 -<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 +<WixLocalization Culture="en-us" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrComPlusCannotConnect" Overridable="yes" Value="Cannot connect to the COM+ admin catalog. ([2] [3] [4] [5])" />
6 <String Id="msierrComPlusPartitionReadFailed" Overridable="yes" Value="Failed to read COM+ partitions. ([2] [3] [4] [5])" />
7 <String Id="msierrComPlusPartitionRoleReadFailed" Overridable="yes" Value="Failed to read COM+ partition roles. ([2] [3] [4] [5])" />
src/ext/Dependency/wixext/DependencyExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.Dependency
10 /// </summary>
11 public sealed class DependencyExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 /// <summary>
14 /// Gets the contained .wixlib content.
15 /// </summary>
src/ext/Dependency/wixlib/en-us.wxl
+1 -1
@@ -1,7 +1,7 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4 -<WixLocalization Culture="en-US" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 +<WixLocalization Culture="en-US" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrDependencyMissingDependencies" Overridable="yes" Value="If you continue with this install, the product may not work properly because [2] or more dependencies are missing. Do you want to continue with this install anyway?" />
6 <String Id="msierrDependencyHasDependents" Overridable="yes" Value="If you continue with this uninstall, [2] or more products may stop working properly. Do you want to continue with this uninstall anyway?" />
7 </WixLocalization>
src/ext/DirectX/wixext/DirectXExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.DirectX
10 /// </summary>
11 public sealed class DirectXExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
14 {
15 return Intermediate.Load(typeof(DirectXExtensionData).Assembly, "WixToolset.DirectX.directx.wixlib", symbolDefinitions);
src/ext/Firewall/wixext/FirewallExtensionData.cs
-2
@@ -7,8 +7,6 @@ namespace WixToolset.Firewall
7
8 public sealed class FirewallExtensionData : BaseExtensionData
9 {
10 - public override string DefaultCulture => "en-US";
11 -
10 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
11 {
12 symbolDefinition = FirewallSymbolDefinitions.ByName(name);
src/ext/Firewall/wixlib/en-us.wxl
+1 -1
@@ -1,7 +1,7 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4 -<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 +<WixLocalization Culture="en-us" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrFirewallCannotConnect" Overridable="yes" Value="Cannot connect to Windows Firewall. ([2] [3] [4] [5])" />
6
7 <String Id="WixSchedFirewallExceptionsInstall" Overridable="yes" Value="Configuring Windows Firewall" />
src/ext/Http/wixext/HttpExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.Http
10 /// </summary>
11 public sealed class HttpExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
14 {
15 symbolDefinition = HttpSymbolDefinitions.ByName(name);
src/ext/Http/wixlib/en-us.wxl
+1 -1
@@ -1,6 +1,6 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3 -<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
3 +<WixLocalization Culture="en-us" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 <String Id="WixSchedHttpUrlReservationsInstall" Overridable="yes" Value="Preparing to configure Windows HTTP Server" />
5 <String Id="WixSchedHttpUrlReservationsUninstall" Overridable="yes" Value="Preparing to configure Windows HTTP Server" />
6 <String Id="WixRollbackHttpUrlReservationsInstall" Overridable="yes" Value="Rolling back Windows HTTP Server configuration" />
src/ext/Iis/wixext/IIsExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.Iis
10 /// </summary>
11 public sealed class IIsExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
14 {
15 symbolDefinition = IisSymbolDefinitions.ByName(name);
src/ext/Iis/wixlib/en-us.wxl
+1 -1
@@ -1,7 +1,7 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4 -<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 +<WixLocalization Culture="en-us" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrIISCannotConnect" Overridable="yes" Value="Cannot connect to Internet Information Server. ([2] [3] [4] [5])" />
6 <String Id="msierrIISFailedReadWebSite" Overridable="yes" Value="Failed while processing WebSites. ([2] [3] [4] [5])" />
7 <String Id="msierrIISFailedReadWebDirs" Overridable="yes" Value="Failed while processing WebDirs. ([2] [3] [4] [5])" />
src/ext/Msmq/wixext/MsmqExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.Msmq
10 /// </summary>
11 public sealed class MsmqExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
14 {
15 symbolDefinition = MsmqSymbolDefinitions.ByName(name);
src/ext/Msmq/wixlib/en-us.wxl
+1 -1
@@ -1,7 +1,7 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4 -<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 +<WixLocalization Culture="en-us" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="MessageQueuingExecuteInstall" Overridable="yes" Value="Configuring message queues" />
6 <String Id="MessageQueuingExecuteInstallTemplate" Overridable="yes" Value="Queue: [1]" />
7 <String Id="MessageQueuingExecuteUninstall" Overridable="yes" Value="Configuring message queues" />
src/ext/NetFx/wixext/NetFxExtensionData.cs
-2
@@ -10,8 +10,6 @@ namespace WixToolset.Netfx
10 /// </summary>
11 public sealed class NetfxExtensionData : BaseExtensionData
12 {
13 - public override string DefaultCulture => "en-US";
14 -
13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
14 {
15 symbolDefinition = NetfxSymbolDefinitions.ByName(name);
src/ext/PowerShell/wixext/PSExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.PowerShell
10 /// </summary>
11 public sealed class PSExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
14 {
15 return Intermediate.Load(typeof(PSExtensionData).Assembly, "WixToolset.PowerShell.powershell.wixlib", symbolDefinitions);
src/ext/Sql/wixext/SqlExtensionData.cs
-6
@@ -10,12 +10,6 @@ namespace WixToolset.Sql
10 /// </summary>
11 public sealed class SqlExtensionData : BaseExtensionData
12 {
13 - /// <summary>
14 - /// Gets the default culture.
15 - /// </summary>
16 - /// <value>The default culture.</value>
17 - public override string DefaultCulture => "en-US";
18 -
13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
14 {
15 symbolDefinition = SqlSymbolDefinitions.ByName(name);
src/ext/Sql/wixlib/en-us.wxl
+1 -1
@@ -1,7 +1,7 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4 -<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 +<WixLocalization Culture="en-us" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrSQLFailedCreateDatabase" Overridable="yes" Value="Error [2]: failed to create SQL database: [3], error detail: [4]." />
6 <String Id="msierrSQLFailedDropDatabase" Overridable="yes" Value="Error [2]: failed to drop SQL database: [3], error detail: [4]." />
7 <String Id="msierrSQLFailedConnectDatabase" Overridable="yes" Value="Failed to connect to SQL database. ([2] [3] [4] [5])" />
src/ext/UI/wixext/UIExtensionData.cs
-2
@@ -7,8 +7,6 @@ namespace WixToolset.UI
7
8 public sealed class UIExtensionData : BaseExtensionData
9 {
10 - public override string DefaultCulture => "en-US";
11 -
10 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
11 {
12 symbolDefinition = null;
src/ext/UI/wixlib/WixUI_en-us.wxl
+1 -1
@@ -1,7 +1,7 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4 -<WixLocalization Culture="en-US" Codepage="1252" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 +<WixLocalization Culture="en-US" ExtensionDefaultCulture="yes" Codepage="1252" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <!-- _locID@Culture="en-US" _locComment="American English" -->
6 <!-- _locID@Codepage="1252" _locComment="Windows-1252" -->
7
src/ext/Util/wixext/UtilExtensionData.cs
-2
@@ -7,8 +7,6 @@ namespace WixToolset.Util
7
8 public sealed class UtilExtensionData : BaseExtensionData
9 {
10 - public override string DefaultCulture => "en-US";
11 -
10 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
11 {
12 symbolDefinition = UtilSymbolDefinitions.ByName(name);
src/ext/Util/wixlib/en-us.wxl
+1 -1
@@ -1,7 +1,7 @@
1 <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4 -<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 +<WixLocalization Culture="en-us" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrUSRFailedUserCreate" Overridable="yes" Value="Failed to create user. ([2] [3] [4] [5])" />
6 <String Id="msierrUSRFailedUserCreatePswd" Overridable="yes" Value="Failed to create user due to invalid password. ([2] [3] [4] [5])" />
7 <String Id="msierrUSRFailedUserGroupAdd" Overridable="yes" Value="Failed to add user to group. ([2] [3] [4] [5])" />
src/ext/VisualStudio/wixext/VSExtensionData.cs
-6
@@ -7,12 +7,6 @@ namespace WixToolset.VisualStudio
7
8 public sealed class VSExtensionData : BaseExtensionData
9 {
10 - /// <summary>
11 - /// Gets the default culture.
12 - /// </summary>
13 - /// <value>The default culture.</value>
14 - public override string DefaultCulture => "en-US";
15 -
10 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
11 {
12 return Intermediate.Load(typeof(VSExtensionData).Assembly, "WixToolset.VisualStudio.vs.wixlib", symbolDefinitions);
src/wix/WixToolset.Core/Librarian.cs
+5
@@ -63,6 +63,11 @@ namespace WixToolset.Core
63 return null;
64 }
65
66 + foreach (var localization in localizationsByCulture.Values)
67 + {
68 + localization.UpdateLocation(LocalizationLocation.Library);
69 + }
70 +
71 trackedFiles = this.ResolveFilePathsToEmbed(context, sections);
72
73 if (this.Messaging.EncounteredError)
src/wix/WixToolset.Core/Linker.cs
+8
@@ -87,6 +87,14 @@ namespace WixToolset.Core
87 if (library != null)
88 {
89 sections.AddRange(library.Sections);
90 +
91 + if (library.Localizations?.Count > 0)
92 + {
93 + // Include localizations from the extension data and be sure to note that the localization came from
94 + // an extension. It is important to remember whiche localization came from an extension when filtering
95 + // localizations during the resolve process later.
96 + localizations.AddRange(library.Localizations.Select(l => l.UpdateLocation(LocalizationLocation.Extension)));
97 + }
98 }
99 }
100
src/wix/WixToolset.Core/LocalizationParser.cs
+9 -1
@@ -86,6 +86,7 @@ namespace WixToolset.Core
86 private static Localization ParseWixLocalizationElement(IMessaging messaging, XElement node)
87 {
88 var sourceLineNumbers = SourceLineNumber.CreateFromXObject(node);
89 + var location = LocalizationLocation.Source;
90 int? codepage = null;
91 int? summaryInformationCodepage = null;
92 string culture = null;
@@ -96,6 +97,13 @@ namespace WixToolset.Core
97 {
98 switch (attrib.Name.LocalName)
99 {
100 + case "ExtensionDefaultCulture":
101 + if (Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib) == YesNoType.Yes)
102 + {
103 + location = LocalizationLocation.ExtensionDefaultCulture;
104 + }
105 + break;
106 +
107 case "Codepage":
108 codepage = Common.GetValidCodePage(attrib.Value, allowNoChange: true, onlyAnsi: false, sourceLineNumbers);
109 break;
@@ -147,7 +155,7 @@ namespace WixToolset.Core
155 }
156 }
157
150 - return messaging.EncounteredError ? null : new Localization(codepage, summaryInformationCodepage, culture, variables, localizedControls);
158 + return messaging.EncounteredError ? null : new Localization(location, codepage, summaryInformationCodepage, culture, variables, localizedControls);
159 }
160
161 /// <summary>
src/wix/WixToolset.Core/Resolver.cs
+7 -17
@@ -230,21 +230,6 @@ namespace WixToolset.Core
230
231 AddFilteredLocalizations(result, filter, localizations);
232
233 - // Filter localizations provided by extensions with data.
234 - var creator = context.ServiceProvider.GetService<ISymbolDefinitionCreator>();
235 -
236 - foreach (var data in context.ExtensionData)
237 - {
238 - var library = data.GetLibrary(creator);
239 -
240 - if (library?.Localizations != null && library.Localizations.Any())
241 - {
242 - var extensionFilter = (!filter.Any() && data.DefaultCulture != null) ? new[] { data.DefaultCulture } : filter;
243 -
244 - AddFilteredLocalizations(result, extensionFilter, library.Localizations);
245 - }
246 - }
247 -
233 return result;
234 }
235
@@ -265,10 +250,15 @@ namespace WixToolset.Core
250
251 private static void AddFilteredLocalizations(List<Localization> result, IEnumerable<string> filter, IEnumerable<Localization> localizations)
252 {
268 - // If there is no filter, return all localizations.
253 + // If there is no filter, return all localizations provided by the user (either as a .wxl or from a .wixlib on the command-line)
254 + // **and only** the extension's default culture localizations.
255 if (!filter.Any())
256 {
271 - result.AddRange(localizations);
257 + // The filter turns out to be really simple, skip localizations that came from an extension (LocalizationLocation.Extension)
258 + // but keep those that are marked as the extension's default culture (LocalizationLocation.ExtensionDefaultCulture).
259 + var filtered = localizations.Where(l => l.Location != LocalizationLocation.Extension);
260 +
261 + result.AddRange(filtered);
262 }
263 else // filter localizations in order specified by the filter
264 {
src/wix/test/CompileCoreTestExtensionWixlib/CompileCoreTestExtensionWixlib.csproj
+9 -8
@@ -8,6 +8,8 @@
8 <OutputType>Exe</OutputType>
9 <SignOutput>false</SignOutput>
10 <RollForward>Major</RollForward>
11 +
12 + <WixlibPath>$(BaseOutputPath)TestData\$(Configuration)\example.wixlib</WixlibPath>
13 </PropertyGroup>
14
15 <ItemGroup>
@@ -15,20 +17,19 @@
17 </ItemGroup>
18
19 <ItemGroup>
18 - <ExtensionWxs Include="..\Example.Extension\Data\example.wxs">
19 - <WixlibPath>$(BaseOutputPath)TestData\$(Configuration)\example.wixlib</WixlibPath>
20 - </ExtensionWxs>
20 + <ExtensionSource Include="..\Example.Extension\Data\example.wxs" />
21 + <ExtensionSource Include="..\Example.Extension\Data\example.en-us.wxl" />
22 + <ExtensionSource Include="..\Example.Extension\Data\example.ja-jp.wxl" />
23 </ItemGroup>
24
25 <Target Name="BuildExtensionWixlibs"
26 AfterTargets="AfterBuild"
25 - Inputs="@(ExtensionWxs)"
26 - Outputs="%(ExtensionWxs.WixlibPath)"
27 + Inputs="@(ExtensionSource)"
28 + Outputs="$(WixlibPath)"
29 Condition=" '$(NCrunch)'!='1' ">
30
29 - <Exec Command="dotnet @(TargetPathWithTargetPlatformMoniker) &quot;$(IntermediateOutputPath) &quot; &quot;%(ExtensionWxs.WixlibPath)&quot; &quot;%(ExtensionWxs.Filename)%(ExtensionWxs.Extension)&quot;"
30 - WorkingDirectory="%(ExtensionWxs.RelativeDir)" />
31 + <Exec Command="dotnet @(TargetPathWithTargetPlatformMoniker) &quot;$(IntermediateOutputPath) &quot; &quot;$(WixlibPath)&quot; &quot;@(ExtensionSource)&quot;" />
32
32 - <Message Importance="high" Text="@(ExtensionWxs) -&gt; %(ExtensionWxs.WixlibPath)" />
33 + <Message Importance="high" Text="@(ExtensionSource) -&gt; $(WixlibPath)" />
34 </Target>
35 </Project>
src/wix/test/CompileCoreTestExtensionWixlib/Program.cs
+6 -2
@@ -1,6 +1,7 @@
1 // Copyright(c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 using System.Collections.Generic;
4 +using System.IO;
5 using WixInternal.Core.TestPackage;
6
7 namespace CompileCoreTestExtensionWixlib
@@ -17,8 +18,6 @@ namespace CompileCoreTestExtensionWixlib
18 var buildArgs = new List<string>();
19 buildArgs.Add("build");
20 buildArgs.Add("-bindfiles");
20 - buildArgs.Add("-bindpath");
21 - buildArgs.Add("Data");
21 buildArgs.Add("-intermediateFolder");
22 buildArgs.Add(intermediateFolder);
23 buildArgs.Add("-o");
@@ -26,6 +25,11 @@ namespace CompileCoreTestExtensionWixlib
25
26 foreach (var path in args[2].Split(';'))
27 {
28 + var folder = Path.GetDirectoryName(Path.GetFullPath(path));
29 +
30 + buildArgs.Add("-bindpath");
31 + buildArgs.Add(folder);
32 +
33 buildArgs.Add(path);
34 }
35
src/wix/test/Example.Extension/Data/example.en-us.wxl new
+3
@@ -0,0 +1,3 @@
1 +<WixLocalization Culture="en-us" ExtensionDefaultCulture="yes" xmlns="http://wixtoolset.org/schemas/v4/wxl">
2 + <String Id="ExampleString" Overridable="yes" Value="en-us" />
3 +</WixLocalization>
src/wix/test/Example.Extension/Data/example.ja-jp.wxl new
+3
@@ -0,0 +1,3 @@
1 +<WixLocalization Culture="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl">
2 + <String Id="ExampleString" Overridable="yes" Value="ja-jp" />
3 +</WixLocalization>
src/wix/test/Example.Extension/Data/example.wxs
+6
@@ -4,11 +4,17 @@
4
5 <Binary Id="BinFromWir" SourceFile="example.txt" />
6 </Fragment>
7 +
8 + <Fragment>
9 + <Property Id="LocalizedProperty" Value="!(loc.ExampleString)" />
10 + </Fragment>
11 +
12 <Fragment>
13 <BootstrapperApplication Id="fakeba">
14 <BootstrapperApplicationDll SourceFile="example.txt" />
15 </BootstrapperApplication>
16 </Fragment>
17 +
18 <Fragment>
19 <BundleExtension Id="ExampleBundleExtension" SourceFile="example.txt" />
20 </Fragment>
src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
+63 -4
@@ -18,7 +18,7 @@ namespace WixToolsetTest.CoreIntegration
18 [Fact]
19 public void CanBuildAndQuery()
20 {
21 - var folder = TestData.Get(@"TestData\ExampleExtension");
21 + var folder = TestData.Get("TestData", "ExampleExtension");
22 var build = new Builder(folder, typeof(ExampleExtensionFactory), new[] { Path.Combine(folder, "data") });
23
24 var results = build.BuildAndQuery(Build, "Wix4Example");
@@ -58,7 +58,7 @@ namespace WixToolsetTest.CoreIntegration
58 [Fact]
59 public void CanBuildWithExampleExtension()
60 {
61 - var folder = TestData.Get(@"TestData\ExampleExtension");
61 + var folder = TestData.Get("TestData", "ExampleExtension");
62
63 using (var fs = new DisposableFileSystem())
64 {
@@ -156,6 +156,65 @@ namespace WixToolsetTest.CoreIntegration
156 }
157 }
158
159 + [Fact]
160 + public void CanBuildWithExampleExtensionLocalizedDefault()
161 + {
162 + var folder = TestData.Get("TestData", "ExampleExtensionLocalized");
163 +
164 + using (var fs = new DisposableFileSystem())
165 + {
166 + var intermediateFolder = fs.GetFolder();
167 +
168 + var result = WixRunner.Execute(new[]
169 + {
170 + "build",
171 + Path.Combine(folder, "LocalizedPackage.wxs"),
172 + "-ext", ExtensionPaths.ExampleExtensionPath,
173 + "-bindpath", Path.Combine(folder, "data"),
174 + "-intermediateFolder", intermediateFolder,
175 + "-o", Path.Combine(intermediateFolder, "bin", "extest.msi")
176 + });
177 +
178 + result.AssertSuccess();
179 +
180 + var pdb = Intermediate.Load(Path.Combine(intermediateFolder, "bin", "extest.wixpdb"));
181 + var section = pdb.Sections.Single();
182 +
183 + var property = section.Symbols.OfType<PropertySymbol>().Single(t => t.Id.Id == "LocalizedProperty");
184 + WixAssert.StringEqual("en-us", property.Value);
185 + }
186 + }
187 +
188 + [Fact]
189 + public void CanBuildWithExampleExtensionLocalizedNonDefault()
190 + {
191 + var folder = TestData.Get("TestData", "ExampleExtensionLocalized");
192 +
193 + using (var fs = new DisposableFileSystem())
194 + {
195 + var intermediateFolder = fs.GetFolder();
196 +
197 + var result = WixRunner.Execute(new[]
198 + {
199 + "build",
200 + Path.Combine(folder, "LocalizedPackage.wxs"),
201 + "-culture", "ja-jp",
202 + "-ext", ExtensionPaths.ExampleExtensionPath,
203 + "-bindpath", Path.Combine(folder, "data"),
204 + "-intermediateFolder", intermediateFolder,
205 + "-o", Path.Combine(intermediateFolder, "bin", "extest.msi")
206 + });
207 +
208 + result.AssertSuccess();
209 +
210 + var pdb = Intermediate.Load(Path.Combine(intermediateFolder, "bin", "extest.wixpdb"));
211 + var section = pdb.Sections.Single();
212 +
213 + var property = section.Symbols.OfType<PropertySymbol>().Single(t => t.Id.Id == "LocalizedProperty");
214 + WixAssert.StringEqual("ja-jp", property.Value);
215 + }
216 + }
217 +
218 [Fact]
219 public void CanParseCommandLineWithExtension()
220 {
@@ -192,7 +251,7 @@ namespace WixToolsetTest.CoreIntegration
251 [Fact]
252 public void CannotBuildWithMissingExtension()
253 {
195 - var folder = TestData.Get(@"TestData\ExampleExtension");
254 + var folder = TestData.Get("TestData", "ExampleExtension");
255
256 using (var fs = new DisposableFileSystem())
257 {
@@ -213,7 +272,7 @@ namespace WixToolsetTest.CoreIntegration
272 [Fact]
273 public void CannotBuildWithMissingVersionedExtension()
274 {
216 - var folder = TestData.Get(@"TestData\ExampleExtension");
275 + var folder = TestData.Get("TestData", "ExampleExtension");
276
277 using (var fs = new DisposableFileSystem())
278 {
src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/LocalizedPackage.wxs new
+18
@@ -0,0 +1,18 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 + <Package Name="LocalizedPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="no" Scope="perMachine">
3 +
4 + <PropertyRef Id="LocalizedProperty" />
5 +
6 + <Feature Id="ProductFeature">
7 + <Component Directory="INSTALLFOLDER">
8 + <File Source="example.txt" />
9 + </Component>
10 + </Feature>
11 + </Package>
12 +
13 + <Fragment>
14 + <StandardDirectory Id="ProgramFilesFolder">
15 + <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
16 + </StandardDirectory>
17 + </Fragment>
18 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/PackageComponents.wxs new
+12
@@ -0,0 +1,12 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3 + xmlns:ex="http://www.example.com/scheams/v1/wxs">
4 + <Fragment>
5 + <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
6 + <Component>
7 + <File Source="example.txt" />
8 + <ex:Example Id="Foo" Value="Bar" />
9 + </Component>
10 + </ComponentGroup>
11 + </Fragment>
12 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/data/example.txt new
+1
@@ -0,0 +1 @@
1 +This is example.txt.
\ No newline at end of file