aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/wix/WixToolset.Data/Localization.cs39
-rw-r--r--src/api/wix/WixToolset.Data/LocalizationLocation.cs31
-rw-r--r--src/api/wix/WixToolset.Data/LocalizedControl.cs10
-rw-r--r--src/api/wix/WixToolset.Extensibility/BaseExtensionData.cs4
-rw-r--r--src/api/wix/WixToolset.Extensibility/IExtensionData.cs6
-rw-r--r--src/ext/Bal/wixext/BalExtensionData.cs6
-rw-r--r--src/ext/ComPlus/wixext/ComPlusExtensionData.cs6
-rw-r--r--src/ext/ComPlus/wixlib/en-us.wxl2
-rw-r--r--src/ext/Dependency/wixext/DependencyExtensionData.cs6
-rw-r--r--src/ext/Dependency/wixlib/en-us.wxl2
-rw-r--r--src/ext/DirectX/wixext/DirectXExtensionData.cs6
-rw-r--r--src/ext/Firewall/wixext/FirewallExtensionData.cs2
-rw-r--r--src/ext/Firewall/wixlib/en-us.wxl2
-rw-r--r--src/ext/Http/wixext/HttpExtensionData.cs6
-rw-r--r--src/ext/Http/wixlib/en-us.wxl2
-rw-r--r--src/ext/Iis/wixext/IIsExtensionData.cs6
-rw-r--r--src/ext/Iis/wixlib/en-us.wxl2
-rw-r--r--src/ext/Msmq/wixext/MsmqExtensionData.cs6
-rw-r--r--src/ext/Msmq/wixlib/en-us.wxl2
-rw-r--r--src/ext/NetFx/wixext/NetFxExtensionData.cs2
-rw-r--r--src/ext/PowerShell/wixext/PSExtensionData.cs6
-rw-r--r--src/ext/Sql/wixext/SqlExtensionData.cs6
-rw-r--r--src/ext/Sql/wixlib/en-us.wxl2
-rw-r--r--src/ext/UI/wixext/UIExtensionData.cs2
-rw-r--r--src/ext/UI/wixlib/WixUI_en-us.wxl2
-rw-r--r--src/ext/Util/wixext/UtilExtensionData.cs2
-rw-r--r--src/ext/Util/wixlib/en-us.wxl2
-rw-r--r--src/ext/VisualStudio/wixext/VSExtensionData.cs6
-rw-r--r--src/wix/WixToolset.Core/Librarian.cs5
-rw-r--r--src/wix/WixToolset.Core/Linker.cs8
-rw-r--r--src/wix/WixToolset.Core/LocalizationParser.cs10
-rw-r--r--src/wix/WixToolset.Core/Resolver.cs24
-rw-r--r--src/wix/test/CompileCoreTestExtensionWixlib/CompileCoreTestExtensionWixlib.csproj17
-rw-r--r--src/wix/test/CompileCoreTestExtensionWixlib/Program.cs8
-rw-r--r--src/wix/test/Example.Extension/Data/example.en-us.wxl3
-rw-r--r--src/wix/test/Example.Extension/Data/example.ja-jp.wxl3
-rw-r--r--src/wix/test/Example.Extension/Data/example.wxs6
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs67
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/LocalizedPackage.wxs18
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/PackageComponents.wxs12
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/data/example.txt1
41 files changed, 237 insertions, 121 deletions
diff --git a/src/api/wix/WixToolset.Data/Localization.cs b/src/api/wix/WixToolset.Data/Localization.cs
index 70c096de..d7727f17 100644
--- a/src/api/wix/WixToolset.Data/Localization.cs
+++ b/src/api/wix/WixToolset.Data/Localization.cs
@@ -16,10 +16,19 @@ namespace WixToolset.Data
16 private readonly Dictionary<string, LocalizedControl> localizedControls = new Dictionary<string, LocalizedControl>(); 16 private readonly Dictionary<string, LocalizedControl> localizedControls = new Dictionary<string, LocalizedControl>();
17 17
18 /// <summary> 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>
19 /// Instantiates a new localization object. 27 /// Instantiates a new localization object.
20 /// </summary> 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)
22 { 30 {
31 this.Location = location;
23 this.Codepage = codepage; 32 this.Codepage = codepage;
24 this.SummaryInformationCodepage = summaryInformationCodepage; 33 this.SummaryInformationCodepage = summaryInformationCodepage;
25 this.Culture = culture?.ToLowerInvariant() ?? String.Empty; 34 this.Culture = culture?.ToLowerInvariant() ?? String.Empty;
@@ -28,6 +37,11 @@ namespace WixToolset.Data
28 } 37 }
29 38
30 /// <summary> 39 /// <summary>
40 /// Gets the location the localization came from.
41 /// </summary>
42 public LocalizationLocation Location { get; private set; }
43
44 /// <summary>
31 /// Gets the codepage. 45 /// Gets the codepage.
32 /// </summary> 46 /// </summary>
33 /// <value>The codepage.</value> 47 /// <value>The codepage.</value>
@@ -57,9 +71,27 @@ namespace WixToolset.Data
57 /// <value>The localized controls.</value> 71 /// <value>The localized controls.</value>
58 public ICollection<KeyValuePair<string, LocalizedControl>> LocalizedControls => this.localizedControls; 72 public ICollection<KeyValuePair<string, LocalizedControl>> LocalizedControls => this.localizedControls;
59 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
60 internal JsonObject Serialize() 89 internal JsonObject Serialize()
61 { 90 {
62 var jsonObject = new JsonObject(); 91 var jsonObject = new JsonObject()
92 {
93 { "location", this.Location.ToString().ToLowerInvariant() }
94 };
63 95
64 if (this.Codepage.HasValue) 96 if (this.Codepage.HasValue)
65 { 97 {
@@ -108,6 +140,7 @@ namespace WixToolset.Data
108 140
109 internal static Localization Deserialize(JsonObject jsonObject) 141 internal static Localization Deserialize(JsonObject jsonObject)
110 { 142 {
143 var location = jsonObject.GetEnumOrDefault("location", LocalizationLocation.Source);
111 var codepage = jsonObject.GetValueOrDefault("codepage", null); 144 var codepage = jsonObject.GetValueOrDefault("codepage", null);
112 var summaryCodepage = jsonObject.GetValueOrDefault("summaryCodepage", null); 145 var summaryCodepage = jsonObject.GetValueOrDefault("summaryCodepage", null);
113 var culture = jsonObject.GetValueOrDefault<string>("culture"); 146 var culture = jsonObject.GetValueOrDefault<string>("culture");
@@ -131,7 +164,7 @@ namespace WixToolset.Data
131 } 164 }
132 } 165 }
133 166
134 return new Localization(codepage, summaryCodepage, culture, variables, controls); 167 return new Localization(location, codepage, summaryCodepage, culture, variables, controls);
135 } 168 }
136 } 169 }
137} 170}
diff --git a/src/api/wix/WixToolset.Data/LocalizationLocation.cs b/src/api/wix/WixToolset.Data/LocalizationLocation.cs
new file mode 100644
index 00000000..773c4d9f
--- /dev/null
+++ b/src/api/wix/WixToolset.Data/LocalizationLocation.cs
@@ -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
3namespace 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}
diff --git a/src/api/wix/WixToolset.Data/LocalizedControl.cs b/src/api/wix/WixToolset.Data/LocalizedControl.cs
index 1252842b..9f59ce46 100644
--- a/src/api/wix/WixToolset.Data/LocalizedControl.cs
+++ b/src/api/wix/WixToolset.Data/LocalizedControl.cs
@@ -45,7 +45,10 @@ namespace WixToolset.Data
45 /// Get key for a localized control. 45 /// Get key for a localized control.
46 /// </summary> 46 /// </summary>
47 /// <returns>The localized control id.</returns> 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 }
49 52
50 /// <summary> 53 /// <summary>
51 /// Get key for a localized control. 54 /// Get key for a localized control.
@@ -53,7 +56,10 @@ namespace WixToolset.Data
53 /// <param name="dialog">The optional id of the control's dialog.</param> 56 /// <param name="dialog">The optional id of the control's dialog.</param>
54 /// <param name="control">The id of the control.</param> 57 /// <param name="control">The id of the control.</param>
55 /// <returns>The localized control id.</returns> 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 }
57 63
58 internal JsonObject Serialize() 64 internal JsonObject Serialize()
59 { 65 {
diff --git a/src/api/wix/WixToolset.Extensibility/BaseExtensionData.cs b/src/api/wix/WixToolset.Extensibility/BaseExtensionData.cs
index e4a10fd9..291b1014 100644
--- a/src/api/wix/WixToolset.Extensibility/BaseExtensionData.cs
+++ b/src/api/wix/WixToolset.Extensibility/BaseExtensionData.cs
@@ -2,6 +2,7 @@
2 2
3namespace WixToolset.Extensibility 3namespace WixToolset.Extensibility
4{ 4{
5 using System;
5 using WixToolset.Data; 6 using WixToolset.Data;
6 7
7 /// <summary> 8 /// <summary>
@@ -10,8 +11,9 @@ namespace WixToolset.Extensibility
10 public abstract class BaseExtensionData : IExtensionData 11 public abstract class BaseExtensionData : IExtensionData
11 { 12 {
12 /// <summary> 13 /// <summary>
13 /// See <see cref="IExtensionData.DefaultCulture"/> 14 /// Obsolete in WiX v5. Use the WixLocalization/@ExtensionDefaultCulture attribute in the wxl file instead.
14 /// </summary> 15 /// </summary>
16 [Obsolete("Set the ExtensionDefaultCulture attribute in the WixLocalization source file instead.")]
15 public virtual string DefaultCulture => null; 17 public virtual string DefaultCulture => null;
16 18
17 /// <summary> 19 /// <summary>
diff --git a/src/api/wix/WixToolset.Extensibility/IExtensionData.cs b/src/api/wix/WixToolset.Extensibility/IExtensionData.cs
index 823e2beb..e6565f4a 100644
--- a/src/api/wix/WixToolset.Extensibility/IExtensionData.cs
+++ b/src/api/wix/WixToolset.Extensibility/IExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.Extensibility
10 public interface IExtensionData 10 public interface IExtensionData
11 { 11 {
12 /// <summary> 12 /// <summary>
13 /// Gets the optional default culture.
14 /// </summary>
15 /// <value>The optional default culture.</value>
16 string DefaultCulture { get; }
17
18 /// <summary>
19 /// 13 ///
20 /// </summary> 14 /// </summary>
21 /// <param name="name"></param> 15 /// <param name="name"></param>
diff --git a/src/ext/Bal/wixext/BalExtensionData.cs b/src/ext/Bal/wixext/BalExtensionData.cs
index 55daf005..9dc99705 100644
--- a/src/ext/Bal/wixext/BalExtensionData.cs
+++ b/src/ext/Bal/wixext/BalExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.Bal
10 /// </summary> 10 /// </summary>
11 public sealed class BalExtensionData : BaseExtensionData 11 public sealed class BalExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
20 { 14 {
21 symbolDefinition = BalSymbolDefinitions.ByName(name); 15 symbolDefinition = BalSymbolDefinitions.ByName(name);
diff --git a/src/ext/ComPlus/wixext/ComPlusExtensionData.cs b/src/ext/ComPlus/wixext/ComPlusExtensionData.cs
index 9cd5341e..5e9d225d 100644
--- a/src/ext/ComPlus/wixext/ComPlusExtensionData.cs
+++ b/src/ext/ComPlus/wixext/ComPlusExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.ComPlus
10 /// </summary> 10 /// </summary>
11 public sealed class ComPlusExtensionData : BaseExtensionData 11 public sealed class ComPlusExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
20 { 14 {
21 symbolDefinition = ComPlusSymbolDefinitions.ByName(name); 15 symbolDefinition = ComPlusSymbolDefinitions.ByName(name);
diff --git a/src/ext/ComPlus/wixlib/en-us.wxl b/src/ext/ComPlus/wixlib/en-us.wxl
index 0ec0f55c..592cc641 100644
--- a/src/ext/ComPlus/wixlib/en-us.wxl
+++ b/src/ext/ComPlus/wixlib/en-us.wxl
@@ -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. --> 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 2
3 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])" /> 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])" /> 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])" /> 7 <String Id="msierrComPlusPartitionRoleReadFailed" Overridable="yes" Value="Failed to read COM+ partition roles. ([2] [3] [4] [5])" />
diff --git a/src/ext/Dependency/wixext/DependencyExtensionData.cs b/src/ext/Dependency/wixext/DependencyExtensionData.cs
index 2f30c2bf..c3c8fc03 100644
--- a/src/ext/Dependency/wixext/DependencyExtensionData.cs
+++ b/src/ext/Dependency/wixext/DependencyExtensionData.cs
@@ -11,12 +11,6 @@ namespace WixToolset.Dependency
11 public sealed class DependencyExtensionData : BaseExtensionData 11 public sealed class DependencyExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary> 13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 /// <summary>
20 /// Gets the contained .wixlib content. 14 /// Gets the contained .wixlib content.
21 /// </summary> 15 /// </summary>
22 /// <param name="symbolDefinitions">Strong typed symbold definitions.</param> 16 /// <param name="symbolDefinitions">Strong typed symbold definitions.</param>
diff --git a/src/ext/Dependency/wixlib/en-us.wxl b/src/ext/Dependency/wixlib/en-us.wxl
index ca0a3ea6..9d6cc63a 100644
--- a/src/ext/Dependency/wixlib/en-us.wxl
+++ b/src/ext/Dependency/wixlib/en-us.wxl
@@ -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. --> 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 2
3 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?" /> 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?" /> 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> 7</WixLocalization>
diff --git a/src/ext/DirectX/wixext/DirectXExtensionData.cs b/src/ext/DirectX/wixext/DirectXExtensionData.cs
index d61af23f..e0d81979 100644
--- a/src/ext/DirectX/wixext/DirectXExtensionData.cs
+++ b/src/ext/DirectX/wixext/DirectXExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.DirectX
10 /// </summary> 10 /// </summary>
11 public sealed class DirectXExtensionData : BaseExtensionData 11 public sealed class DirectXExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) 13 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
20 { 14 {
21 return Intermediate.Load(typeof(DirectXExtensionData).Assembly, "WixToolset.DirectX.directx.wixlib", symbolDefinitions); 15 return Intermediate.Load(typeof(DirectXExtensionData).Assembly, "WixToolset.DirectX.directx.wixlib", symbolDefinitions);
diff --git a/src/ext/Firewall/wixext/FirewallExtensionData.cs b/src/ext/Firewall/wixext/FirewallExtensionData.cs
index 7481d993..55a7b999 100644
--- a/src/ext/Firewall/wixext/FirewallExtensionData.cs
+++ b/src/ext/Firewall/wixext/FirewallExtensionData.cs
@@ -7,8 +7,6 @@ namespace WixToolset.Firewall
7 7
8 public sealed class FirewallExtensionData : BaseExtensionData 8 public sealed class FirewallExtensionData : BaseExtensionData
9 { 9 {
10 public override string DefaultCulture => "en-US";
11
12 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 10 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
13 { 11 {
14 symbolDefinition = FirewallSymbolDefinitions.ByName(name); 12 symbolDefinition = FirewallSymbolDefinitions.ByName(name);
diff --git a/src/ext/Firewall/wixlib/en-us.wxl b/src/ext/Firewall/wixlib/en-us.wxl
index 52dbab55..64c5a1ac 100644
--- a/src/ext/Firewall/wixlib/en-us.wxl
+++ b/src/ext/Firewall/wixlib/en-us.wxl
@@ -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. --> 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 2
3 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])" /> 5 <String Id="msierrFirewallCannotConnect" Overridable="yes" Value="Cannot connect to Windows Firewall. ([2] [3] [4] [5])" />
6 6
7 <String Id="WixSchedFirewallExceptionsInstall" Overridable="yes" Value="Configuring Windows Firewall" /> 7 <String Id="WixSchedFirewallExceptionsInstall" Overridable="yes" Value="Configuring Windows Firewall" />
diff --git a/src/ext/Http/wixext/HttpExtensionData.cs b/src/ext/Http/wixext/HttpExtensionData.cs
index 04e3dcee..ff6934bd 100644
--- a/src/ext/Http/wixext/HttpExtensionData.cs
+++ b/src/ext/Http/wixext/HttpExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.Http
10 /// </summary> 10 /// </summary>
11 public sealed class HttpExtensionData : BaseExtensionData 11 public sealed class HttpExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
20 { 14 {
21 symbolDefinition = HttpSymbolDefinitions.ByName(name); 15 symbolDefinition = HttpSymbolDefinitions.ByName(name);
diff --git a/src/ext/Http/wixlib/en-us.wxl b/src/ext/Http/wixlib/en-us.wxl
index de3e93cd..44731a5f 100644
--- a/src/ext/Http/wixlib/en-us.wxl
+++ b/src/ext/Http/wixlib/en-us.wxl
@@ -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. --> 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 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" /> 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" /> 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" /> 6 <String Id="WixRollbackHttpUrlReservationsInstall" Overridable="yes" Value="Rolling back Windows HTTP Server configuration" />
diff --git a/src/ext/Iis/wixext/IIsExtensionData.cs b/src/ext/Iis/wixext/IIsExtensionData.cs
index 6a0e1f09..ccbe362d 100644
--- a/src/ext/Iis/wixext/IIsExtensionData.cs
+++ b/src/ext/Iis/wixext/IIsExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.Iis
10 /// </summary> 10 /// </summary>
11 public sealed class IIsExtensionData : BaseExtensionData 11 public sealed class IIsExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
20 { 14 {
21 symbolDefinition = IisSymbolDefinitions.ByName(name); 15 symbolDefinition = IisSymbolDefinitions.ByName(name);
diff --git a/src/ext/Iis/wixlib/en-us.wxl b/src/ext/Iis/wixlib/en-us.wxl
index 1b6096fb..65bc1435 100644
--- a/src/ext/Iis/wixlib/en-us.wxl
+++ b/src/ext/Iis/wixlib/en-us.wxl
@@ -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. --> 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 2
3 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])" /> 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])" /> 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])" /> 7 <String Id="msierrIISFailedReadWebDirs" Overridable="yes" Value="Failed while processing WebDirs. ([2] [3] [4] [5])" />
diff --git a/src/ext/Msmq/wixext/MsmqExtensionData.cs b/src/ext/Msmq/wixext/MsmqExtensionData.cs
index 91485724..f434001f 100644
--- a/src/ext/Msmq/wixext/MsmqExtensionData.cs
+++ b/src/ext/Msmq/wixext/MsmqExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.Msmq
10 /// </summary> 10 /// </summary>
11 public sealed class MsmqExtensionData : BaseExtensionData 11 public sealed class MsmqExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
20 { 14 {
21 symbolDefinition = MsmqSymbolDefinitions.ByName(name); 15 symbolDefinition = MsmqSymbolDefinitions.ByName(name);
diff --git a/src/ext/Msmq/wixlib/en-us.wxl b/src/ext/Msmq/wixlib/en-us.wxl
index 3252fc17..9965ca51 100644
--- a/src/ext/Msmq/wixlib/en-us.wxl
+++ b/src/ext/Msmq/wixlib/en-us.wxl
@@ -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. --> 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 2
3 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" /> 5 <String Id="MessageQueuingExecuteInstall" Overridable="yes" Value="Configuring message queues" />
6 <String Id="MessageQueuingExecuteInstallTemplate" Overridable="yes" Value="Queue: [1]" /> 6 <String Id="MessageQueuingExecuteInstallTemplate" Overridable="yes" Value="Queue: [1]" />
7 <String Id="MessageQueuingExecuteUninstall" Overridable="yes" Value="Configuring message queues" /> 7 <String Id="MessageQueuingExecuteUninstall" Overridable="yes" Value="Configuring message queues" />
diff --git a/src/ext/NetFx/wixext/NetFxExtensionData.cs b/src/ext/NetFx/wixext/NetFxExtensionData.cs
index 8dd9e003..61d618cf 100644
--- a/src/ext/NetFx/wixext/NetFxExtensionData.cs
+++ b/src/ext/NetFx/wixext/NetFxExtensionData.cs
@@ -10,8 +10,6 @@ namespace WixToolset.Netfx
10 /// </summary> 10 /// </summary>
11 public sealed class NetfxExtensionData : BaseExtensionData 11 public sealed class NetfxExtensionData : BaseExtensionData
12 { 12 {
13 public override string DefaultCulture => "en-US";
14
15 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
16 { 14 {
17 symbolDefinition = NetfxSymbolDefinitions.ByName(name); 15 symbolDefinition = NetfxSymbolDefinitions.ByName(name);
diff --git a/src/ext/PowerShell/wixext/PSExtensionData.cs b/src/ext/PowerShell/wixext/PSExtensionData.cs
index 66627942..8ba83498 100644
--- a/src/ext/PowerShell/wixext/PSExtensionData.cs
+++ b/src/ext/PowerShell/wixext/PSExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.PowerShell
10 /// </summary> 10 /// </summary>
11 public sealed class PSExtensionData : BaseExtensionData 11 public sealed class PSExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) 13 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
20 { 14 {
21 return Intermediate.Load(typeof(PSExtensionData).Assembly, "WixToolset.PowerShell.powershell.wixlib", symbolDefinitions); 15 return Intermediate.Load(typeof(PSExtensionData).Assembly, "WixToolset.PowerShell.powershell.wixlib", symbolDefinitions);
diff --git a/src/ext/Sql/wixext/SqlExtensionData.cs b/src/ext/Sql/wixext/SqlExtensionData.cs
index 60de94fe..77a86bde 100644
--- a/src/ext/Sql/wixext/SqlExtensionData.cs
+++ b/src/ext/Sql/wixext/SqlExtensionData.cs
@@ -10,12 +10,6 @@ namespace WixToolset.Sql
10 /// </summary> 10 /// </summary>
11 public sealed class SqlExtensionData : BaseExtensionData 11 public sealed class SqlExtensionData : BaseExtensionData
12 { 12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 13 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
20 { 14 {
21 symbolDefinition = SqlSymbolDefinitions.ByName(name); 15 symbolDefinition = SqlSymbolDefinitions.ByName(name);
diff --git a/src/ext/Sql/wixlib/en-us.wxl b/src/ext/Sql/wixlib/en-us.wxl
index 9e6e8765..654970a8 100644
--- a/src/ext/Sql/wixlib/en-us.wxl
+++ b/src/ext/Sql/wixlib/en-us.wxl
@@ -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. --> 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 2
3 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]." /> 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]." /> 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])" /> 7 <String Id="msierrSQLFailedConnectDatabase" Overridable="yes" Value="Failed to connect to SQL database. ([2] [3] [4] [5])" />
diff --git a/src/ext/UI/wixext/UIExtensionData.cs b/src/ext/UI/wixext/UIExtensionData.cs
index 32557029..349a5912 100644
--- a/src/ext/UI/wixext/UIExtensionData.cs
+++ b/src/ext/UI/wixext/UIExtensionData.cs
@@ -7,8 +7,6 @@ namespace WixToolset.UI
7 7
8 public sealed class UIExtensionData : BaseExtensionData 8 public sealed class UIExtensionData : BaseExtensionData
9 { 9 {
10 public override string DefaultCulture => "en-US";
11
12 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 10 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
13 { 11 {
14 symbolDefinition = null; 12 symbolDefinition = null;
diff --git a/src/ext/UI/wixlib/WixUI_en-us.wxl b/src/ext/UI/wixlib/WixUI_en-us.wxl
index c9904b61..a06f8b17 100644
--- a/src/ext/UI/wixlib/WixUI_en-us.wxl
+++ b/src/ext/UI/wixlib/WixUI_en-us.wxl
@@ -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. --> 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 2
3 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" --> 5 <!-- _locID@Culture="en-US" _locComment="American English" -->
6 <!-- _locID@Codepage="1252" _locComment="Windows-1252" --> 6 <!-- _locID@Codepage="1252" _locComment="Windows-1252" -->
7 7
diff --git a/src/ext/Util/wixext/UtilExtensionData.cs b/src/ext/Util/wixext/UtilExtensionData.cs
index d3ca3358..c9de2876 100644
--- a/src/ext/Util/wixext/UtilExtensionData.cs
+++ b/src/ext/Util/wixext/UtilExtensionData.cs
@@ -7,8 +7,6 @@ namespace WixToolset.Util
7 7
8 public sealed class UtilExtensionData : BaseExtensionData 8 public sealed class UtilExtensionData : BaseExtensionData
9 { 9 {
10 public override string DefaultCulture => "en-US";
11
12 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) 10 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
13 { 11 {
14 symbolDefinition = UtilSymbolDefinitions.ByName(name); 12 symbolDefinition = UtilSymbolDefinitions.ByName(name);
diff --git a/src/ext/Util/wixlib/en-us.wxl b/src/ext/Util/wixlib/en-us.wxl
index fc2db184..b144989e 100644
--- a/src/ext/Util/wixlib/en-us.wxl
+++ b/src/ext/Util/wixlib/en-us.wxl
@@ -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. --> 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 2
3 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])" /> 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])" /> 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])" /> 7 <String Id="msierrUSRFailedUserGroupAdd" Overridable="yes" Value="Failed to add user to group. ([2] [3] [4] [5])" />
diff --git a/src/ext/VisualStudio/wixext/VSExtensionData.cs b/src/ext/VisualStudio/wixext/VSExtensionData.cs
index 82c5b118..9477ce67 100644
--- a/src/ext/VisualStudio/wixext/VSExtensionData.cs
+++ b/src/ext/VisualStudio/wixext/VSExtensionData.cs
@@ -7,12 +7,6 @@ namespace WixToolset.VisualStudio
7 7
8 public sealed class VSExtensionData : BaseExtensionData 8 public sealed class VSExtensionData : BaseExtensionData
9 { 9 {
10 /// <summary>
11 /// Gets the default culture.
12 /// </summary>
13 /// <value>The default culture.</value>
14 public override string DefaultCulture => "en-US";
15
16 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) 10 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
17 { 11 {
18 return Intermediate.Load(typeof(VSExtensionData).Assembly, "WixToolset.VisualStudio.vs.wixlib", symbolDefinitions); 12 return Intermediate.Load(typeof(VSExtensionData).Assembly, "WixToolset.VisualStudio.vs.wixlib", symbolDefinitions);
diff --git a/src/wix/WixToolset.Core/Librarian.cs b/src/wix/WixToolset.Core/Librarian.cs
index f6357c6c..8f5239c0 100644
--- a/src/wix/WixToolset.Core/Librarian.cs
+++ b/src/wix/WixToolset.Core/Librarian.cs
@@ -63,6 +63,11 @@ namespace WixToolset.Core
63 return null; 63 return null;
64 } 64 }
65 65
66 foreach (var localization in localizationsByCulture.Values)
67 {
68 localization.UpdateLocation(LocalizationLocation.Library);
69 }
70
66 trackedFiles = this.ResolveFilePathsToEmbed(context, sections); 71 trackedFiles = this.ResolveFilePathsToEmbed(context, sections);
67 72
68 if (this.Messaging.EncounteredError) 73 if (this.Messaging.EncounteredError)
diff --git a/src/wix/WixToolset.Core/Linker.cs b/src/wix/WixToolset.Core/Linker.cs
index 5c021ca0..59728741 100644
--- a/src/wix/WixToolset.Core/Linker.cs
+++ b/src/wix/WixToolset.Core/Linker.cs
@@ -87,6 +87,14 @@ namespace WixToolset.Core
87 if (library != null) 87 if (library != null)
88 { 88 {
89 sections.AddRange(library.Sections); 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 }
90 } 98 }
91 } 99 }
92 100
diff --git a/src/wix/WixToolset.Core/LocalizationParser.cs b/src/wix/WixToolset.Core/LocalizationParser.cs
index 995efe40..29d3d932 100644
--- a/src/wix/WixToolset.Core/LocalizationParser.cs
+++ b/src/wix/WixToolset.Core/LocalizationParser.cs
@@ -86,6 +86,7 @@ namespace WixToolset.Core
86 private static Localization ParseWixLocalizationElement(IMessaging messaging, XElement node) 86 private static Localization ParseWixLocalizationElement(IMessaging messaging, XElement node)
87 { 87 {
88 var sourceLineNumbers = SourceLineNumber.CreateFromXObject(node); 88 var sourceLineNumbers = SourceLineNumber.CreateFromXObject(node);
89 var location = LocalizationLocation.Source;
89 int? codepage = null; 90 int? codepage = null;
90 int? summaryInformationCodepage = null; 91 int? summaryInformationCodepage = null;
91 string culture = null; 92 string culture = null;
@@ -96,6 +97,13 @@ namespace WixToolset.Core
96 { 97 {
97 switch (attrib.Name.LocalName) 98 switch (attrib.Name.LocalName)
98 { 99 {
100 case "ExtensionDefaultCulture":
101 if (Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib) == YesNoType.Yes)
102 {
103 location = LocalizationLocation.ExtensionDefaultCulture;
104 }
105 break;
106
99 case "Codepage": 107 case "Codepage":
100 codepage = Common.GetValidCodePage(attrib.Value, allowNoChange: true, onlyAnsi: false, sourceLineNumbers); 108 codepage = Common.GetValidCodePage(attrib.Value, allowNoChange: true, onlyAnsi: false, sourceLineNumbers);
101 break; 109 break;
@@ -147,7 +155,7 @@ namespace WixToolset.Core
147 } 155 }
148 } 156 }
149 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);
151 } 159 }
152 160
153 /// <summary> 161 /// <summary>
diff --git a/src/wix/WixToolset.Core/Resolver.cs b/src/wix/WixToolset.Core/Resolver.cs
index 2eebc80a..97f0223f 100644
--- a/src/wix/WixToolset.Core/Resolver.cs
+++ b/src/wix/WixToolset.Core/Resolver.cs
@@ -230,21 +230,6 @@ namespace WixToolset.Core
230 230
231 AddFilteredLocalizations(result, filter, localizations); 231 AddFilteredLocalizations(result, filter, localizations);
232 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
248 return result; 233 return result;
249 } 234 }
250 235
@@ -265,10 +250,15 @@ namespace WixToolset.Core
265 250
266 private static void AddFilteredLocalizations(List<Localization> result, IEnumerable<string> filter, IEnumerable<Localization> localizations) 251 private static void AddFilteredLocalizations(List<Localization> result, IEnumerable<string> filter, IEnumerable<Localization> localizations)
267 { 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.
269 if (!filter.Any()) 255 if (!filter.Any())
270 { 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);
272 } 262 }
273 else // filter localizations in order specified by the filter 263 else // filter localizations in order specified by the filter
274 { 264 {
diff --git a/src/wix/test/CompileCoreTestExtensionWixlib/CompileCoreTestExtensionWixlib.csproj b/src/wix/test/CompileCoreTestExtensionWixlib/CompileCoreTestExtensionWixlib.csproj
index b526a209..2938be48 100644
--- a/src/wix/test/CompileCoreTestExtensionWixlib/CompileCoreTestExtensionWixlib.csproj
+++ b/src/wix/test/CompileCoreTestExtensionWixlib/CompileCoreTestExtensionWixlib.csproj
@@ -8,6 +8,8 @@
8 <OutputType>Exe</OutputType> 8 <OutputType>Exe</OutputType>
9 <SignOutput>false</SignOutput> 9 <SignOutput>false</SignOutput>
10 <RollForward>Major</RollForward> 10 <RollForward>Major</RollForward>
11
12 <WixlibPath>$(BaseOutputPath)TestData\$(Configuration)\example.wixlib</WixlibPath>
11 </PropertyGroup> 13 </PropertyGroup>
12 14
13 <ItemGroup> 15 <ItemGroup>
@@ -15,20 +17,19 @@
15 </ItemGroup> 17 </ItemGroup>
16 18
17 <ItemGroup> 19 <ItemGroup>
18 <ExtensionWxs Include="..\Example.Extension\Data\example.wxs"> 20 <ExtensionSource Include="..\Example.Extension\Data\example.wxs" />
19 <WixlibPath>$(BaseOutputPath)TestData\$(Configuration)\example.wixlib</WixlibPath> 21 <ExtensionSource Include="..\Example.Extension\Data\example.en-us.wxl" />
20 </ExtensionWxs> 22 <ExtensionSource Include="..\Example.Extension\Data\example.ja-jp.wxl" />
21 </ItemGroup> 23 </ItemGroup>
22 24
23 <Target Name="BuildExtensionWixlibs" 25 <Target Name="BuildExtensionWixlibs"
24 AfterTargets="AfterBuild" 26 AfterTargets="AfterBuild"
25 Inputs="@(ExtensionWxs)" 27 Inputs="@(ExtensionSource)"
26 Outputs="%(ExtensionWxs.WixlibPath)" 28 Outputs="$(WixlibPath)"
27 Condition=" '$(NCrunch)'!='1' "> 29 Condition=" '$(NCrunch)'!='1' ">
28 30
29 <Exec Command="dotnet @(TargetPathWithTargetPlatformMoniker) &quot;$(IntermediateOutputPath) &quot; &quot;%(ExtensionWxs.WixlibPath)&quot; &quot;%(ExtensionWxs.Filename)%(ExtensionWxs.Extension)&quot;" 31 <Exec Command="dotnet @(TargetPathWithTargetPlatformMoniker) &quot;$(IntermediateOutputPath) &quot; &quot;$(WixlibPath)&quot; &quot;@(ExtensionSource)&quot;" />
30 WorkingDirectory="%(ExtensionWxs.RelativeDir)" />
31 32
32 <Message Importance="high" Text="@(ExtensionWxs) -&gt; %(ExtensionWxs.WixlibPath)" /> 33 <Message Importance="high" Text="@(ExtensionSource) -&gt; $(WixlibPath)" />
33 </Target> 34 </Target>
34</Project> 35</Project>
diff --git a/src/wix/test/CompileCoreTestExtensionWixlib/Program.cs b/src/wix/test/CompileCoreTestExtensionWixlib/Program.cs
index a6c88ddb..bb65b467 100644
--- a/src/wix/test/CompileCoreTestExtensionWixlib/Program.cs
+++ b/src/wix/test/CompileCoreTestExtensionWixlib/Program.cs
@@ -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. 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 2
3using System.Collections.Generic; 3using System.Collections.Generic;
4using System.IO;
4using WixInternal.Core.TestPackage; 5using WixInternal.Core.TestPackage;
5 6
6namespace CompileCoreTestExtensionWixlib 7namespace CompileCoreTestExtensionWixlib
@@ -17,8 +18,6 @@ namespace CompileCoreTestExtensionWixlib
17 var buildArgs = new List<string>(); 18 var buildArgs = new List<string>();
18 buildArgs.Add("build"); 19 buildArgs.Add("build");
19 buildArgs.Add("-bindfiles"); 20 buildArgs.Add("-bindfiles");
20 buildArgs.Add("-bindpath");
21 buildArgs.Add("Data");
22 buildArgs.Add("-intermediateFolder"); 21 buildArgs.Add("-intermediateFolder");
23 buildArgs.Add(intermediateFolder); 22 buildArgs.Add(intermediateFolder);
24 buildArgs.Add("-o"); 23 buildArgs.Add("-o");
@@ -26,6 +25,11 @@ namespace CompileCoreTestExtensionWixlib
26 25
27 foreach (var path in args[2].Split(';')) 26 foreach (var path in args[2].Split(';'))
28 { 27 {
28 var folder = Path.GetDirectoryName(Path.GetFullPath(path));
29
30 buildArgs.Add("-bindpath");
31 buildArgs.Add(folder);
32
29 buildArgs.Add(path); 33 buildArgs.Add(path);
30 } 34 }
31 35
diff --git a/src/wix/test/Example.Extension/Data/example.en-us.wxl b/src/wix/test/Example.Extension/Data/example.en-us.wxl
new file mode 100644
index 00000000..8dfc1c30
--- /dev/null
+++ b/src/wix/test/Example.Extension/Data/example.en-us.wxl
@@ -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>
diff --git a/src/wix/test/Example.Extension/Data/example.ja-jp.wxl b/src/wix/test/Example.Extension/Data/example.ja-jp.wxl
new file mode 100644
index 00000000..32d52e83
--- /dev/null
+++ b/src/wix/test/Example.Extension/Data/example.ja-jp.wxl
@@ -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>
diff --git a/src/wix/test/Example.Extension/Data/example.wxs b/src/wix/test/Example.Extension/Data/example.wxs
index af5d5086..a5298ac3 100644
--- a/src/wix/test/Example.Extension/Data/example.wxs
+++ b/src/wix/test/Example.Extension/Data/example.wxs
@@ -4,11 +4,17 @@
4 4
5 <Binary Id="BinFromWir" SourceFile="example.txt" /> 5 <Binary Id="BinFromWir" SourceFile="example.txt" />
6 </Fragment> 6 </Fragment>
7
8 <Fragment>
9 <Property Id="LocalizedProperty" Value="!(loc.ExampleString)" />
10 </Fragment>
11
7 <Fragment> 12 <Fragment>
8 <BootstrapperApplication Id="fakeba"> 13 <BootstrapperApplication Id="fakeba">
9 <BootstrapperApplicationDll SourceFile="example.txt" /> 14 <BootstrapperApplicationDll SourceFile="example.txt" />
10 </BootstrapperApplication> 15 </BootstrapperApplication>
11 </Fragment> 16 </Fragment>
17
12 <Fragment> 18 <Fragment>
13 <BundleExtension Id="ExampleBundleExtension" SourceFile="example.txt" /> 19 <BundleExtension Id="ExampleBundleExtension" SourceFile="example.txt" />
14 </Fragment> 20 </Fragment>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
index 429226f5..a59187b6 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
@@ -18,7 +18,7 @@ namespace WixToolsetTest.CoreIntegration
18 [Fact] 18 [Fact]
19 public void CanBuildAndQuery() 19 public void CanBuildAndQuery()
20 { 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") }); 22 var build = new Builder(folder, typeof(ExampleExtensionFactory), new[] { Path.Combine(folder, "data") });
23 23
24 var results = build.BuildAndQuery(Build, "Wix4Example"); 24 var results = build.BuildAndQuery(Build, "Wix4Example");
@@ -58,7 +58,7 @@ namespace WixToolsetTest.CoreIntegration
58 [Fact] 58 [Fact]
59 public void CanBuildWithExampleExtension() 59 public void CanBuildWithExampleExtension()
60 { 60 {
61 var folder = TestData.Get(@"TestData\ExampleExtension"); 61 var folder = TestData.Get("TestData", "ExampleExtension");
62 62
63 using (var fs = new DisposableFileSystem()) 63 using (var fs = new DisposableFileSystem())
64 { 64 {
@@ -157,6 +157,65 @@ namespace WixToolsetTest.CoreIntegration
157 } 157 }
158 158
159 [Fact] 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]
160 public void CanParseCommandLineWithExtension() 219 public void CanParseCommandLineWithExtension()
161 { 220 {
162 var folder = TestData.Get(@"TestData\ExampleExtension"); 221 var folder = TestData.Get(@"TestData\ExampleExtension");
@@ -192,7 +251,7 @@ namespace WixToolsetTest.CoreIntegration
192 [Fact] 251 [Fact]
193 public void CannotBuildWithMissingExtension() 252 public void CannotBuildWithMissingExtension()
194 { 253 {
195 var folder = TestData.Get(@"TestData\ExampleExtension"); 254 var folder = TestData.Get("TestData", "ExampleExtension");
196 255
197 using (var fs = new DisposableFileSystem()) 256 using (var fs = new DisposableFileSystem())
198 { 257 {
@@ -213,7 +272,7 @@ namespace WixToolsetTest.CoreIntegration
213 [Fact] 272 [Fact]
214 public void CannotBuildWithMissingVersionedExtension() 273 public void CannotBuildWithMissingVersionedExtension()
215 { 274 {
216 var folder = TestData.Get(@"TestData\ExampleExtension"); 275 var folder = TestData.Get("TestData", "ExampleExtension");
217 276
218 using (var fs = new DisposableFileSystem()) 277 using (var fs = new DisposableFileSystem())
219 { 278 {
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/LocalizedPackage.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/LocalizedPackage.wxs
new file mode 100644
index 00000000..646c0875
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/LocalizedPackage.wxs
@@ -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>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/PackageComponents.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/PackageComponents.wxs
new file mode 100644
index 00000000..7f17b538
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/PackageComponents.wxs
@@ -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>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/data/example.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/data/example.txt
new file mode 100644
index 00000000..1b4ffe8a
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionLocalized/data/example.txt
@@ -0,0 +1 @@
This is example.txt. \ No newline at end of file