diff --git a/TestAssets/TestProjects/ResourcesTests/TestApp/.noautobuild b/TestAssets/TestProjects/ResourcesTests/TestApp/.noautobuild
new file mode 100644
index 000000000..e69de29bb
diff --git a/TestAssets/TestProjects/ResourcesTests/TestApp/Program.cs b/TestAssets/TestProjects/ResourcesTests/TestApp/Program.cs
new file mode 100644
index 000000000..51233cffa
--- /dev/null
+++ b/TestAssets/TestProjects/ResourcesTests/TestApp/Program.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace ConsoleApplication
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Hello World!");
+ }
+ }
+}
diff --git a/TestAssets/TestProjects/ResourcesTests/TestApp/project.json b/TestAssets/TestProjects/ResourcesTests/TestApp/project.json
new file mode 100644
index 000000000..68470fbf4
--- /dev/null
+++ b/TestAssets/TestProjects/ResourcesTests/TestApp/project.json
@@ -0,0 +1,19 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+ "dependencies": {
+ "Microsoft.Data.OData": "5.6.4",
+ "Microsoft.NETCore.App": {
+ "type": "platform",
+ "version": "1.0.0-rc2-24008"
+ },
+ "TestLibraryWithResources": { "target": "project" }
+ },
+ "frameworks": {
+ "netcoreapp1.0": {
+ "imports": [ "portable-net45+win8" ]
+ }
+ }
+}
diff --git a/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/.noautobuild b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/.noautobuild
new file mode 100644
index 000000000..e69de29bb
diff --git a/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Program.cs b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Program.cs
new file mode 100644
index 000000000..3b5a088e1
--- /dev/null
+++ b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Program.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Resources;
+using System.Reflection;
+using System.Globalization;
+
+namespace TestProjectWithCultureSpecificResource
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ var rm = new ResourceManager(
+ "TestProjectWithCultureSpecificResource.Strings",
+ typeof(Program).GetTypeInfo().Assembly);
+
+ Console.WriteLine(rm.GetString("hello"));
+ Console.WriteLine(rm.GetString("hello", new CultureInfo("fr")));
+ }
+ }
+}
diff --git a/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Strings.fr.resx b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Strings.fr.resx
new file mode 100644
index 000000000..f569847fa
--- /dev/null
+++ b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Strings.fr.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Bonjour!
+
+
\ No newline at end of file
diff --git a/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Strings.resx b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Strings.resx
new file mode 100644
index 000000000..bd249e209
--- /dev/null
+++ b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/Strings.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Hello World!
+
+
\ No newline at end of file
diff --git a/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/project.json b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/project.json
new file mode 100644
index 000000000..6e68954d6
--- /dev/null
+++ b/TestAssets/TestProjects/ResourcesTests/TestLibraryWithResources/project.json
@@ -0,0 +1,11 @@
+{
+ "version": "1.0.0-*",
+ "dependencies": {
+ "NETStandard.Library": "1.5.0-rc2-24008",
+ },
+ "frameworks": {
+ "netstandard1.5": {
+ "imports": "dnxcore50"
+ }
+ }
+}
diff --git a/TestAssets/TestProjects/TestProjectWithCultureSpecificResource/project.json b/TestAssets/TestProjects/TestProjectWithCultureSpecificResource/project.json
index 9ab4c5256..4b1d0a3e8 100644
--- a/TestAssets/TestProjects/TestProjectWithCultureSpecificResource/project.json
+++ b/TestAssets/TestProjects/TestProjectWithCultureSpecificResource/project.json
@@ -4,7 +4,7 @@
"emitEntryPoint": true
},
"dependencies": {
- "NETStandard.Library": "1.5.0-rc2-24015"
+ "NETStandard.Library": "1.5.0-rc2-24008"
},
"frameworks": {
"netstandardapp1.5": {
diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs
index 267cf7e49..e562d5f65 100644
--- a/scripts/dotnet-cli-build/CompileTargets.cs
+++ b/scripts/dotnet-cli-build/CompileTargets.cs
@@ -343,7 +343,7 @@ namespace Microsoft.DotNet.Cli.Build
}
string SharedFrameworkSourceRoot = GenerateSharedFrameworkProject(c, SharedFrameworkTemplateSourceRoot, sharedFrameworkRid);
-
+
dotnetCli.Restore("--verbosity", "verbose", "--disable-parallel", "--infer-runtimes", "--fallbacksource", Dirs.Corehost)
.WorkingDirectory(SharedFrameworkSourceRoot)
.Execute()
@@ -358,12 +358,9 @@ namespace Microsoft.DotNet.Cli.Build
Utils.DeleteDirectory(SharedFrameworkNameAndVersionRoot);
}
- string publishFramework = "dnxcore50"; // Temporary, use "netcoreapp" when we update nuget.
-
dotnetCli.Publish(
"--output", SharedFrameworkNameAndVersionRoot,
"-r", sharedFrameworkRid,
- "-f", publishFramework,
SharedFrameworkSourceRoot).Execute().EnsureSuccessful();
// Clean up artifacts that dotnet-publish generates which we don't need
diff --git a/src/Microsoft.DotNet.Compiler.Common/Executable.cs b/src/Microsoft.DotNet.Compiler.Common/Executable.cs
index 38a1b79d2..f5d6c7763 100644
--- a/src/Microsoft.DotNet.Compiler.Common/Executable.cs
+++ b/src/Microsoft.DotNet.Compiler.Common/Executable.cs
@@ -97,6 +97,16 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
{
libraryExport.RuntimeAssemblyGroups.GetDefaultAssets().CopyTo(_runtimeOutputPath);
libraryExport.NativeLibraryGroups.GetDefaultAssets().CopyTo(_runtimeOutputPath);
+
+ foreach(var group in libraryExport.ResourceAssemblies.GroupBy(r => r.Locale))
+ {
+ var localeSpecificDir = Path.Combine(_runtimeOutputPath, group.Key);
+ if(!Directory.Exists(localeSpecificDir))
+ {
+ Directory.CreateDirectory(localeSpecificDir);
+ }
+ group.Select(r => r.Asset).CopyTo(localeSpecificDir);
+ }
}
}
diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs
index f9e25ce98..5966f46e8 100644
--- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs
+++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs
@@ -196,6 +196,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
var builder = LibraryExportBuilder.Create(library);
builder.AddNativeLibraryGroup(new LibraryAssetGroup(PopulateAssets(library, library.NativeLibraries)));
builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(PopulateAssets(library, library.RuntimeAssemblies)));
+ builder.WithResourceAssemblies(PopulateResources(library, library.ResourceAssemblies));
builder.WithCompilationAssemblies(PopulateAssets(library, library.CompileTimeAssemblies));
if (library.Identity.Type.Equals(LibraryType.Package))
@@ -322,6 +323,10 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(new[] { compilationAssemblyAsset }));
builder.WithRuntimeAssets(CollectAssets(outputPaths.CompilationFiles));
}
+
+ builder.WithResourceAssemblies(outputPaths.CompilationFiles.Resources().Select(r => new LibraryResourceAssembly(
+ LibraryAsset.CreateFromAbsolutePath(outputPaths.CompilationFiles.BasePath, r.Path),
+ r.Locale)));
}
builder.WithSourceReferences(project.Project.Files.SharedFiles.Select(f =>
@@ -334,7 +339,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
private IEnumerable CollectAssets(CompilationOutputFiles files)
{
var assemblyPath = files.Assembly;
- foreach (var path in files.All())
+ foreach (var path in files.All().Except(files.Resources().Select(r => r.Path)))
{
if (string.Equals(assemblyPath, path))
{
@@ -458,6 +463,21 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
return analyzerRefs;
}
+ private IEnumerable PopulateResources(TargetLibraryWithAssets library, IEnumerable section)
+ {
+ foreach (var assemblyPath in section.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a.Path)))
+ {
+ string locale;
+ if(!assemblyPath.Properties.TryGetValue(Constants.LocaleLockFilePropertyName, out locale))
+ {
+ locale = null;
+ }
+ yield return new LibraryResourceAssembly(
+ LibraryAsset.CreateFromRelativePath(library.Path, assemblyPath.Path),
+ locale);
+ }
+ }
+
private IEnumerable PopulateAssets(TargetLibraryWithAssets library, IEnumerable section)
{
foreach (var assemblyPath in section.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a.Path)))
diff --git a/src/Microsoft.DotNet.ProjectModel/CompilationOutputFiles.cs b/src/Microsoft.DotNet.ProjectModel/CompilationOutputFiles.cs
index ddfbf5b86..90eeec5a7 100644
--- a/src/Microsoft.DotNet.ProjectModel/CompilationOutputFiles.cs
+++ b/src/Microsoft.DotNet.ProjectModel/CompilationOutputFiles.cs
@@ -56,7 +56,7 @@ namespace Microsoft.DotNet.ProjectModel
public string OutputExtension { get; }
- public virtual IEnumerable Resources()
+ public virtual IEnumerable Resources()
{
var resourceNames = Project.Files.ResourceFiles
.Select(f => ResourceUtility.GetResourceCultureName(f.Key))
@@ -65,7 +65,7 @@ namespace Microsoft.DotNet.ProjectModel
foreach (var resourceName in resourceNames)
{
- yield return Path.Combine(BasePath, resourceName, Project.Name + ".resources" + FileNameSuffixes.DotNet.DynamicLib);
+ yield return new ResourceFile(Path.Combine(BasePath, resourceName, Project.Name + ".resources" + FileNameSuffixes.DotNet.DynamicLib), resourceName);
}
}
@@ -80,7 +80,7 @@ namespace Microsoft.DotNet.ProjectModel
}
foreach (var resource in Resources())
{
- yield return resource;
+ yield return resource.Path;
}
}
}
diff --git a/src/Microsoft.DotNet.ProjectModel/Constants.cs b/src/Microsoft.DotNet.ProjectModel/Constants.cs
index 92c06fc15..5b0100a00 100644
--- a/src/Microsoft.DotNet.ProjectModel/Constants.cs
+++ b/src/Microsoft.DotNet.ProjectModel/Constants.cs
@@ -10,6 +10,8 @@ namespace Microsoft.DotNet.ProjectModel
public static readonly string DefaultOutputDirectory = "bin";
public static readonly string DefaultConfiguration = "Debug";
+ public static readonly string LocaleLockFilePropertyName = "locale";
+
public static readonly Version Version50 = new Version(5, 0);
}
}
diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileItem.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileItem.cs
index c147dfe21..fcd040ede 100644
--- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileItem.cs
+++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileItem.cs
@@ -7,9 +7,24 @@ namespace Microsoft.DotNet.ProjectModel.Graph
{
public class LockFileItem
{
+ public LockFileItem()
+ {
+ Properties = new Dictionary();;
+ }
+
+ public LockFileItem(string path) : this()
+ {
+ Path = path;
+ }
+
+ public LockFileItem(string path, IDictionary properties) : this(path)
+ {
+ Properties = new Dictionary(properties);
+ }
+
public string Path { get; set; }
- public IDictionary Properties { get; } = new Dictionary();
+ public IDictionary Properties { get; }
public static implicit operator string (LockFileItem item) => item.Path;
diff --git a/src/Microsoft.DotNet.ProjectModel/ResourceFile.cs b/src/Microsoft.DotNet.ProjectModel/ResourceFile.cs
new file mode 100644
index 000000000..73518481b
--- /dev/null
+++ b/src/Microsoft.DotNet.ProjectModel/ResourceFile.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Microsoft.DotNet.ProjectModel
+{
+ public class ResourceFile
+ {
+ public string Path { get; }
+ public string Locale { get; }
+
+ public ResourceFile(string path, string locale)
+ {
+ Path = path;
+ Locale = locale;
+ }
+ }
+}
diff --git a/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs
index f035550f2..8e14cd154 100644
--- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs
+++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs
@@ -147,6 +147,16 @@ namespace Microsoft.DotNet.Tools.Publish
var runtimeAssetsToCopy = export.RuntimeAssets.Where(a => ShouldCopyExportRuntimeAsset(context, buildOutputPaths, export, a));
runtimeAssetsToCopy.StructuredCopyTo(outputPath, outputPaths.IntermediateOutputDirectoryPath);
+
+ foreach(var resourceAsset in export.ResourceAssemblies)
+ {
+ var dir = Path.Combine(outputPath, resourceAsset.Locale);
+ if(!Directory.Exists(dir))
+ {
+ Directory.CreateDirectory(dir);
+ }
+ File.Copy(resourceAsset.Asset.ResolvedPath, Path.Combine(dir, resourceAsset.Asset.FileName), overwrite: true);
+ }
}
if (context.ProjectFile.HasRuntimeOutput(configuration) && !context.TargetFramework.IsDesktop())
@@ -281,7 +291,7 @@ namespace Microsoft.DotNet.Tools.Publish
{
Directory.CreateDirectory(refsPath);
}
-
+
// Do not copy compilation assembly if it's in runtime assemblies
var runtimeAssemblies = new HashSet(export.RuntimeAssemblyGroups.GetDefaultAssets());
foreach (var compilationAssembly in export.CompilationAssemblies)
@@ -343,7 +353,7 @@ namespace Microsoft.DotNet.Tools.Publish
return hostFile;
}
}
-
+
Reporter.Verbose.WriteLine($"failed to resolve published host in: {outputPath}");
return null;
}
@@ -416,12 +426,12 @@ namespace Microsoft.DotNet.Tools.Publish
ProjectContext.CreateContextForEachFramework(projectPath) :
new[] { ProjectContext.Create(projectPath, framework) };
- var runtimes = !string.IsNullOrEmpty(runtime) ?
+ var runtimes = !string.IsNullOrEmpty(runtime) ?
new [] {runtime} :
PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
return allContexts.Select(c => c.CreateRuntimeContext(runtimes));
}
-
+
private static void CopyContents(ProjectContext context, string outputPath)
{
var contentFiles = context.ProjectFile.Files.GetContentFiles();
diff --git a/src/sharedframework/framework/project.json.template b/src/sharedframework/framework/project.json.template
index fde657ccc..d458d4322 100644
--- a/src/sharedframework/framework/project.json.template
+++ b/src/sharedframework/framework/project.json.template
@@ -10,7 +10,7 @@
"$(RID)": {}
},
"frameworks": {
- "dnxcore50": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45+win8"
]
diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs
index 0a555e7b0..ea5571cc2 100644
--- a/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs
+++ b/test/Microsoft.DotNet.ProjectModel.Tests/LibraryExporterPackageTests.cs
@@ -126,6 +126,34 @@ namespace Microsoft.DotNet.ProjectModel.Tests
runtimeAsset.ResolvedPath.Should().Be(Path.Combine(PackagePath, "lib/Something.OSX.dll"));
}
+ [Fact]
+ public void ExportsPackageResourceAssemblies()
+ {
+ var description = CreateDescription(
+ new LockFileTargetLibrary()
+ {
+ ResourceAssemblies = new List()
+ {
+ new LockFileItem("resources/en-US/Res.dll", new Dictionary() { { "locale", "en-US"} }),
+ new LockFileItem("resources/ru-RU/Res.dll", new Dictionary() { { "locale", "ru-RU" } }),
+ }
+ });
+
+ var result = ExportSingle(description);
+ result.ResourceAssemblies.Should().HaveCount(2);
+ var asset = result.ResourceAssemblies.Should().Contain(g => g.Locale == "en-US").Subject.Asset;
+ asset.Name.Should().Be("Res");
+ asset.Transform.Should().BeNull();
+ asset.RelativePath.Should().Be("resources/en-US/Res.dll");
+ asset.ResolvedPath.Should().Be(Path.Combine(PackagePath, "resources/en-US/Res.dll"));
+
+ asset = result.ResourceAssemblies.Should().Contain(g => g.Locale == "ru-RU").Subject.Asset;
+ asset.Name.Should().Be("Res");
+ asset.Transform.Should().BeNull();
+ asset.RelativePath.Should().Be("resources/ru-RU/Res.dll");
+ asset.ResolvedPath.Should().Be(Path.Combine(PackagePath, "resources/ru-RU/Res.dll"));
+ }
+
[Fact]
public void ExportsSources()
{
diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs
index 45966e37c..987adbc10 100644
--- a/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs
+++ b/test/Microsoft.Extensions.DependencyModel.Tests/DependencyContextBuilderTests.cs
@@ -252,6 +252,24 @@ namespace Microsoft.Extensions.DependencyModel.Tests
asm.Assemblies.Should().OnlyContain(a => a == "System.Collections.dll");
}
+ [Fact]
+ public void FillsResources()
+ {
+ var context = Build(runtimeExports: new[]
+ {
+ Export(PackageDescription("Pack.Age", version: new NuGetVersion(1, 2, 3)),
+ resourceAssemblies: new []
+ {
+ new LibraryResourceAssembly(new LibraryAsset("Dll", "resources/en-US/Pack.Age.dll", ""), "en-US")
+ })
+ });
+
+ context.RuntimeLibraries.Should().HaveCount(1);
+
+ var lib = context.RuntimeLibraries.Should().Contain(l => l.Name == "Pack.Age").Subject;
+ lib.ResourceAssemblies.Should().OnlyContain(l => l.Locale == "en-US" && l.Path == "resources/en-US/Pack.Age.dll");
+ }
+
[Fact]
public void ReferenceAssembliesPathRelativeToDefaultRoot()
{
diff --git a/test/dotnet-build.Tests/BuildOutputTests.cs b/test/dotnet-build.Tests/BuildOutputTests.cs
index bf294f5b3..90125de87 100644
--- a/test/dotnet-build.Tests/BuildOutputTests.cs
+++ b/test/dotnet-build.Tests/BuildOutputTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@@ -8,6 +9,7 @@ using FluentAssertions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Extensions.PlatformAbstractions;
+using Newtonsoft.Json.Linq;
using NuGet.Frameworks;
using Xunit;
@@ -212,6 +214,41 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
}
}
+ [Fact]
+ public void PackageReferenceWithResourcesTest()
+ {
+ var testInstance = TestAssetsManager.CreateTestInstance("ResourcesTests")
+ .WithLockFiles();
+
+ var projectRoot = Path.Combine(testInstance.TestRoot, "TestApp");
+
+ var cmd = new BuildCommand(projectRoot);
+ var result = cmd.Execute();
+ result.Should().Pass();
+
+ var outputDir = new DirectoryInfo(Path.Combine(projectRoot, "bin", "Debug", "netcoreapp1.0"));
+
+ outputDir.Should().HaveFile("TestLibraryWithResources.dll");
+ outputDir.Sub("fr").Should().HaveFile("TestLibraryWithResources.resources.dll");
+
+ var depsJson = JObject.Parse(File.ReadAllText(Path.Combine(outputDir.FullName, $"{Path.GetFileNameWithoutExtension(cmd.GetOutputExecutableName())}.deps.json")));
+
+ foreach (var library in new[] { Tuple.Create("Microsoft.Data.OData", "5.6.4"), Tuple.Create("TestLibraryWithResources", "1.0.0") })
+ {
+ var resources = depsJson["targets"][".NETCoreApp,Version=v1.0"][library.Item1 + "/" + library.Item2]["resources"];
+
+ resources.Should().NotBeNull();
+
+ foreach (var item in resources.Children())
+ {
+ var locale = item.Value["locale"];
+ locale.Should().NotBeNull();
+
+ item.Name.Should().EndWith($"{locale}/{library.Item1}.resources.dll");
+ }
+ }
+ }
+
[Fact]
public void ResourceTest()
{
diff --git a/test/dotnet-publish.Tests/PublishAppWithDependencies.cs b/test/dotnet-publish.Tests/PublishAppWithDependencies.cs
index df2907f82..244692b17 100644
--- a/test/dotnet-publish.Tests/PublishAppWithDependencies.cs
+++ b/test/dotnet-publish.Tests/PublishAppWithDependencies.cs
@@ -42,5 +42,45 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
.Should()
.HaveFile("config.xml");
}
+
+ [Fact]
+ public void PublishTestAppWithReferencesToResources()
+ {
+ var testInstance = TestAssetsManager.CreateTestInstance("ResourcesTests")
+ .WithLockFiles();
+
+ var projectRoot = Path.Combine(testInstance.TestRoot, "TestApp");
+
+ var publishCommand = new PublishCommand(projectRoot);
+ var publishResult = publishCommand.Execute();
+
+ publishResult.Should().Pass();
+
+ var publishDir = publishCommand.GetOutputDirectory(portable: true);
+
+ publishDir.Should().HaveFiles(new[]
+ {
+ "TestApp.dll",
+ "TestApp.deps.json"
+ });
+
+ foreach (var culture in new[] { "de", "es", "fr", "it", "ja", "ko", "ru", "zh-Hans", "zh-Hant" })
+ {
+ var cultureDir = publishDir.Sub(culture);
+
+ // Provided by packages
+ cultureDir.Should().HaveFiles(new[] {
+ "Microsoft.Data.Edm.resources.dll",
+ "Microsoft.Data.OData.resources.dll",
+ "System.Spatial.resources.dll"
+ });
+
+ // Check for the project-to-project one
+ if (culture == "fr")
+ {
+ cultureDir.Should().HaveFile("TestLibraryWithResources.resources.dll");
+ }
+ }
+ }
}
}