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) "$(IntermediateOutputPath) " "%(ExtensionWxs.WixlibPath)" "%(ExtensionWxs.Filename)%(ExtensionWxs.Extension)""
30
- WorkingDirectory="%(ExtensionWxs.RelativeDir)" />
31
+ <Exec Command="dotnet @(TargetPathWithTargetPlatformMoniker) "$(IntermediateOutputPath) " "$(WixlibPath)" "@(ExtensionSource)"" />
32
32
- <Message Importance="high" Text="@(ExtensionWxs) -> %(ExtensionWxs.WixlibPath)" />
33
+ <Message Importance="high" Text="@(ExtensionSource) -> $(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