diff --git a/src/Middleware/Localization/Localization.slnf b/src/Middleware/Localization/Localization.slnf new file mode 100644 index 000000000000..e4494b3619c2 --- /dev/null +++ b/src/Middleware/Localization/Localization.slnf @@ -0,0 +1,16 @@ +{ + "solution": { + "path": "..\\Middleware.sln", + "projects": [ + "Localization.Routing\\src\\Microsoft.AspNetCore.Localization.Routing.csproj", + "Localization.Routing\\test\\Microsoft.AspNetCore.Localization.Routing.Tests.csproj", + "Localization\\sample\\LocalizationSample.csproj", + "Localization\\src\\Microsoft.AspNetCore.Localization.csproj", + "Localization\\test\\FunctionalTests\\Microsoft.AspNetCore.Localization.FunctionalTests.csproj", + "Localization\\test\\UnitTests\\Microsoft.AspNetCore.Localization.Tests.csproj", + "Localization\\testassets\\LocalizationWebsite\\LocalizationWebsite.csproj", + "Localization\\testassets\\ResourcesClassLibraryNoAttribute\\ResourcesClassLibraryNoAttribute.csproj", + "Localization\\testassets\\ResourcesClassLibraryWithAttribute\\ResourcesClassLibraryWithAttribute.csproj" + ] + } +} \ No newline at end of file diff --git a/src/Middleware/Localization/ref/Microsoft.AspNetCore.Localization.netcoreapp3.0.cs b/src/Middleware/Localization/ref/Microsoft.AspNetCore.Localization.netcoreapp3.0.cs index 599db4aca6c1..558921ba6b9d 100644 --- a/src/Middleware/Localization/ref/Microsoft.AspNetCore.Localization.netcoreapp3.0.cs +++ b/src/Middleware/Localization/ref/Microsoft.AspNetCore.Localization.netcoreapp3.0.cs @@ -13,6 +13,7 @@ public static partial class ApplicationBuilderExtensions public partial class RequestLocalizationOptions { public RequestLocalizationOptions() { } + public bool ApplyCurrentCultureToResponseHeaders { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public Microsoft.AspNetCore.Localization.RequestCulture DefaultRequestCulture { get { throw null; } set { } } public bool FallBackToParentCultures { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public bool FallBackToParentUICultures { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } diff --git a/src/Middleware/Localization/src/RequestLocalizationMiddleware.cs b/src/Middleware/Localization/src/RequestLocalizationMiddleware.cs index c6ec3e1c0602..07277ecdd72b 100644 --- a/src/Middleware/Localization/src/RequestLocalizationMiddleware.cs +++ b/src/Middleware/Localization/src/RequestLocalizationMiddleware.cs @@ -1,5 +1,5 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; @@ -13,6 +13,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; +using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Localization { @@ -146,6 +147,11 @@ public async Task Invoke(HttpContext context) SetCurrentThreadCulture(requestCulture); + if (_options.ApplyCurrentCultureToResponseHeaders) + { + context.Response.Headers.Add(HeaderNames.ContentLanguage, requestCulture.UICulture.Name); + } + await _next(context); } diff --git a/src/Middleware/Localization/src/RequestLocalizationOptions.cs b/src/Middleware/Localization/src/RequestLocalizationOptions.cs index 16776364f0cc..95ca74fe32b5 100644 --- a/src/Middleware/Localization/src/RequestLocalizationOptions.cs +++ b/src/Middleware/Localization/src/RequestLocalizationOptions.cs @@ -84,6 +84,11 @@ public RequestCulture DefaultRequestCulture /// public bool FallBackToParentUICultures { get; set; } = true; + /// + /// Gets or sets a value that determines if is applied to the response Content-Language header. + /// + public bool ApplyCurrentCultureToResponseHeaders { get; set; } + /// /// The cultures supported by the application. The will only set /// the current request culture to an entry in this list. diff --git a/src/Middleware/Localization/test/FunctionalTests/LocalizationTest.cs b/src/Middleware/Localization/test/FunctionalTests/LocalizationTest.cs index 5f09115be2c8..15b00dfacfe2 100644 --- a/src/Middleware/Localization/test/FunctionalTests/LocalizationTest.cs +++ b/src/Middleware/Localization/test/FunctionalTests/LocalizationTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Net; @@ -14,6 +14,15 @@ namespace Microsoft.AspNetCore.Localization.FunctionalTests { public class LocalizationTest { + [Fact] + public Task Localization_ContentLanguageHeader() + { + return RunTest( + typeof(StartupContentLanguageHeader), + "ar-YE", + "True ar-YE"); + } + [Fact] public Task Localization_CustomCulture() { diff --git a/src/Middleware/Localization/testassets/LocalizationWebsite/StartupContentLanguageHeader.cs b/src/Middleware/Localization/testassets/LocalizationWebsite/StartupContentLanguageHeader.cs new file mode 100644 index 000000000000..849743184c1e --- /dev/null +++ b/src/Middleware/Localization/testassets/LocalizationWebsite/StartupContentLanguageHeader.cs @@ -0,0 +1,49 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Globalization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Localization; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Net.Http.Headers; + +namespace LocalizationWebsite +{ + public class StartupContentLanguageHeader + { + public void ConfigureServices(IServiceCollection services) + { + services.AddLocalization(); + } + + public void Configure( + IApplicationBuilder app) + { + app.UseRequestLocalization(new RequestLocalizationOptions + { + DefaultRequestCulture = new RequestCulture("en-US"), + SupportedCultures = new List() + { + new CultureInfo("ar-YE") + }, + SupportedUICultures = new List() + { + new CultureInfo("ar-YE") + }, + ApplyCurrentCultureToResponseHeaders = true + }); + + app.Run(async (context) => + { + var hasContentLanguageHeader = context.Response.Headers.ContainsKey(HeaderNames.ContentLanguage); + var contentLanguage = context.Response.Headers[HeaderNames.ContentLanguage].ToString(); + + await context.Response.WriteAsync(hasContentLanguageHeader.ToString()); + await context.Response.WriteAsync(" "); + await context.Response.WriteAsync(contentLanguage); + }); + } + } +} \ No newline at end of file