Bunch of changes:
- Implemented pluggable strategies for determining request culture - Added NotNull on public APIs - Added support for a default request culture - Added options class for configuring the middleware - Improved the query string logic to support separate formatting & language cultures - Implemented the logic for accept-language header - Added more doc comments
This commit is contained in:
parent
5795d331bc
commit
b11f7d51c3
|
|
@ -0,0 +1,67 @@
|
|||
// 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.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Localization.Internal;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the culture information for a request via the value of the Accept-Language header.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// </remarks>
|
||||
public class AcceptLanguageHeaderRequestCultureStrategy : IRequestCultureStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum number of values in the Accept-Language header to attempt to create a <see cref="CultureInfo"/>
|
||||
/// from for the current request.
|
||||
/// Defaults to <c>3</c>.
|
||||
/// </summary>
|
||||
public int MaximumAcceptLanguageHeaderValuesToTry { get; set; } = 3;
|
||||
|
||||
/// <inheritdoc />
|
||||
public RequestCulture DetermineRequestCulture([NotNull] HttpContext httpContext)
|
||||
{
|
||||
var acceptLanguageHeader = httpContext.Request.GetTypedHeaders().AcceptLanguage;
|
||||
|
||||
if (acceptLanguageHeader == null || acceptLanguageHeader.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var languages = acceptLanguageHeader.AsEnumerable();
|
||||
|
||||
if (MaximumAcceptLanguageHeaderValuesToTry > 0)
|
||||
{
|
||||
// We take only the first configured number of languages from the header and then order those that we
|
||||
// attempt to parse as a CultureInfo to mitigate potentially spinning CPU on lots of parse attempts.
|
||||
languages = languages.Take(MaximumAcceptLanguageHeaderValuesToTry);
|
||||
}
|
||||
|
||||
var orderedLanguages = languages.OrderByDescending(h => h, StringWithQualityHeaderValueComparer.QualityComparer)
|
||||
.ToList();
|
||||
|
||||
foreach (var language in orderedLanguages)
|
||||
{
|
||||
// Allow empty string values as they map to InvariantCulture, whereas null culture values will throw in
|
||||
// the CultureInfo ctor
|
||||
if (language.Value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new RequestCulture(CultureUtilities.GetCultureFromName(language.Value));
|
||||
}
|
||||
catch (CultureNotFoundException) { }
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// 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 Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
public class CookieRequestCultureStrategy : IRequestCultureStrategy
|
||||
{
|
||||
public RequestCulture DetermineRequestCulture([NotNull] HttpContext httpContext)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// 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 Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
public class CustomRequestCultureStrategy : IRequestCultureStrategy
|
||||
{
|
||||
private readonly Func<HttpContext, RequestCulture> _strategy;
|
||||
|
||||
public CustomRequestCultureStrategy([NotNull] Func<HttpContext, RequestCulture> strategy)
|
||||
{
|
||||
_strategy = strategy;
|
||||
}
|
||||
|
||||
public RequestCulture DetermineRequestCulture([NotNull] HttpContext httpContext)
|
||||
{
|
||||
return _strategy(httpContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Localization;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Builder
|
||||
{
|
||||
|
|
@ -12,13 +13,29 @@ namespace Microsoft.AspNet.Builder
|
|||
{
|
||||
/// <summary>
|
||||
/// Adds the <see cref="RequestLocalizationMiddleware"/> to automatically set culture information for
|
||||
/// requests based on information provided by the client.
|
||||
/// requests based on information provided by the client using the default options.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
||||
public static IApplicationBuilder UseRequestLocalization(this IApplicationBuilder builder)
|
||||
public static IApplicationBuilder UseRequestLocalization([NotNull] this IApplicationBuilder builder)
|
||||
{
|
||||
return builder.UseMiddleware<RequestLocalizationMiddleware>();
|
||||
var options = new RequestLocalizationMiddlewareOptions();
|
||||
|
||||
return UseRequestLocalization(builder, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the <see cref="RequestLocalizationMiddleware"/> to automatically set culture information for
|
||||
/// requests based on information provided by the client.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <param name="options">The options to configure the middleware with.</param>
|
||||
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
||||
public static IApplicationBuilder UseRequestLocalization(
|
||||
[NotNull] this IApplicationBuilder builder,
|
||||
[NotNull] RequestLocalizationMiddlewareOptions options)
|
||||
{
|
||||
return builder.UseMiddleware<RequestLocalizationMiddleware>(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,5 +12,12 @@ namespace Microsoft.AspNet.Localization
|
|||
/// The <see cref="Localization.RequestCulture"/> of the request.
|
||||
/// </summary>
|
||||
RequestCulture RequestCulture { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IRequestCultureStrategy"/> that determined the request's culture information.
|
||||
/// If the value is <c>null</c> then no strategy was used and the request's culture was set to the value of
|
||||
/// <see cref="RequestLocalizationMiddlewareOptions.DefaultRequestCulture"/>.
|
||||
/// </summary>
|
||||
IRequestCultureStrategy Strategy { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// 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 Microsoft.AspNet.Http;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
public interface IRequestCultureStrategy
|
||||
{
|
||||
RequestCulture DetermineRequestCulture(HttpContext httpContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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.Globalization;
|
||||
|
||||
namespace Microsoft.AspNet.Localization.Internal
|
||||
{
|
||||
public static class CultureUtilities
|
||||
{
|
||||
public static CultureInfo GetCultureFromName(string cultureName)
|
||||
{
|
||||
// Allow empty string values as they map to InvariantCulture, whereas null culture values will throw in
|
||||
// the CultureInfo ctor
|
||||
if (cultureName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new CultureInfo(cultureName);
|
||||
}
|
||||
catch (CultureNotFoundException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// 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 Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Localization.Internal;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the culture information for a request via values in the query string.
|
||||
/// </summary>
|
||||
public class QueryStringRequestCultureStrategy : IRequestCultureStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// The key that contains the culture name.
|
||||
/// Defaults to "culture".
|
||||
/// </summary>
|
||||
public string QueryStringKey { get; set; } = "culture";
|
||||
|
||||
/// <summary>
|
||||
/// The key that contains the UI culture name. If not specified or no value is found,
|
||||
/// <see cref="QueryStringKey"/> will be used.
|
||||
/// Defaults to "ui-culture".
|
||||
/// </summary>
|
||||
public string UIQueryStringKey { get; set; } = "ui-culture";
|
||||
|
||||
/// <inheritdoc />
|
||||
public RequestCulture DetermineRequestCulture([NotNull] HttpContext httpContext)
|
||||
{
|
||||
var request = httpContext.Request;
|
||||
if (!request.QueryString.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string queryCulture = null;
|
||||
string queryUICulture = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(QueryStringKey))
|
||||
{
|
||||
queryCulture = request.Query[QueryStringKey];
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(UIQueryStringKey))
|
||||
{
|
||||
queryUICulture = request.Query[UIQueryStringKey];
|
||||
}
|
||||
|
||||
if (queryCulture == null && queryUICulture == null)
|
||||
{
|
||||
// No values specified for either so no match
|
||||
return null;
|
||||
}
|
||||
|
||||
if (queryCulture != null && queryUICulture == null)
|
||||
{
|
||||
// Value for culture but not for UI culture so default to culture value for both
|
||||
queryUICulture = queryCulture;
|
||||
}
|
||||
|
||||
return new RequestCulture(
|
||||
CultureUtilities.GetCultureFromName(queryCulture),
|
||||
CultureUtilities.GetCultureFromName(queryUICulture));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Globalization;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
|
|
@ -15,7 +16,7 @@ namespace Microsoft.AspNet.Localization
|
|||
/// properties set to the same <see cref="CultureInfo"/> value.
|
||||
/// </summary>
|
||||
/// <param name="culture">The <see cref="CultureInfo"/> for the request.</param>
|
||||
public RequestCulture(CultureInfo culture)
|
||||
public RequestCulture([NotNull] CultureInfo culture)
|
||||
: this (culture, culture)
|
||||
{
|
||||
|
||||
|
|
@ -27,7 +28,7 @@ namespace Microsoft.AspNet.Localization
|
|||
/// </summary>
|
||||
/// <param name="culture">The <see cref="CultureInfo"/> for the request to be used for formatting.</param>
|
||||
/// <param name="uiCulture">The <see cref="CultureInfo"/> for the request to be used for text, i.e. language.</param>
|
||||
public RequestCulture(CultureInfo culture, CultureInfo uiCulture)
|
||||
public RequestCulture([NotNull] CultureInfo culture, [NotNull] CultureInfo uiCulture)
|
||||
{
|
||||
Culture = culture;
|
||||
UICulture = uiCulture;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// 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 Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -12,12 +14,16 @@ namespace Microsoft.AspNet.Localization
|
|||
/// Creates a new <see cref="RequestCultureFeature"/> with the specified <see cref="Localization.RequestCulture"/>.
|
||||
/// </summary>
|
||||
/// <param name="requestCulture">The <see cref="Localization.RequestCulture"/>.</param>
|
||||
public RequestCultureFeature(RequestCulture requestCulture)
|
||||
public RequestCultureFeature([NotNull] RequestCulture requestCulture, IRequestCultureStrategy strategy)
|
||||
{
|
||||
RequestCulture = requestCulture;
|
||||
Strategy = strategy;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public RequestCulture RequestCulture { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestCultureStrategy Strategy { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
|
|
@ -16,14 +17,17 @@ namespace Microsoft.AspNet.Localization
|
|||
public class RequestLocalizationMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
private readonly RequestLocalizationMiddlewareOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestLocalizationMiddleware"/>.
|
||||
/// </summary>
|
||||
/// <param name="next">The <see cref="RequestDelegate"/> representing the next middleware in the pipeline.</param>
|
||||
public RequestLocalizationMiddleware(RequestDelegate next)
|
||||
/// <param name="options"></param>
|
||||
public RequestLocalizationMiddleware([NotNull] RequestDelegate next, [NotNull] RequestLocalizationMiddlewareOptions options)
|
||||
{
|
||||
_next = next;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -31,42 +35,35 @@ namespace Microsoft.AspNet.Localization
|
|||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the middleware has completed processing.</returns>
|
||||
public async Task Invoke(HttpContext context)
|
||||
public async Task Invoke([NotNull] HttpContext context)
|
||||
{
|
||||
// TODO: Make this read from Accept-Language header, cookie, app-provided delegate, etc.
|
||||
if (context.Request.QueryString.HasValue)
|
||||
var requestCulture = _options.DefaultRequestCulture ??
|
||||
new RequestCulture(CultureInfo.DefaultThreadCurrentCulture, CultureInfo.DefaultThreadCurrentUICulture);
|
||||
|
||||
IRequestCultureStrategy winningStrategy = null;
|
||||
|
||||
if (_options.RequestCultureStrategies != null)
|
||||
{
|
||||
var queryCulture = context.Request.Query["culture"];
|
||||
if (!string.IsNullOrEmpty(queryCulture))
|
||||
foreach (var strategy in _options.RequestCultureStrategies)
|
||||
{
|
||||
var requestCulture = new RequestCulture(new CultureInfo(queryCulture));
|
||||
|
||||
context.SetFeature<IRequestCultureFeature>(new RequestCultureFeature(requestCulture));
|
||||
|
||||
var originalCulture = CultureInfo.CurrentCulture;
|
||||
var originalUICulture = CultureInfo.CurrentUICulture;
|
||||
|
||||
SetCurrentCulture(requestCulture);
|
||||
|
||||
await _next(context);
|
||||
|
||||
return;
|
||||
var result = strategy.DetermineRequestCulture(context);
|
||||
if (result != null)
|
||||
{
|
||||
requestCulture = result;
|
||||
winningStrategy = strategy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: The below doesn't seem to be needed anymore now that DNX is correctly managing culture across
|
||||
// async calls but we'll need to verify properly.
|
||||
// Forcibly set thread to en-US as sometimes previous threads have wrong culture across async calls,
|
||||
// see note above.
|
||||
//var defaultRequestCulture = new RequestCulture(new CultureInfo("en-US"));
|
||||
//SetCurrentCulture(defaultRequestCulture);
|
||||
}
|
||||
|
||||
context.SetFeature<IRequestCultureFeature>(new RequestCultureFeature(requestCulture, winningStrategy));
|
||||
|
||||
SetCurrentThreadCulture(requestCulture);
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
|
||||
private void SetCurrentCulture(RequestCulture requestCulture)
|
||||
private static void SetCurrentThreadCulture(RequestCulture requestCulture)
|
||||
{
|
||||
#if DNX451
|
||||
Thread.CurrentThread.CurrentCulture = requestCulture.Culture;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
// 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.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Microsoft.AspNet.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies options for the <see cref="RequestLocalizationMiddleware"/>.
|
||||
/// </summary>
|
||||
public class RequestLocalizationMiddlewareOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestLocalizationMiddlewareOptions"/> with default values.
|
||||
/// </summary>
|
||||
public RequestLocalizationMiddlewareOptions()
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture(CultureInfo.DefaultThreadCurrentCulture, CultureInfo.DefaultThreadCurrentUICulture);
|
||||
|
||||
RequestCultureStrategies = new List<IRequestCultureStrategy>
|
||||
{
|
||||
new QueryStringRequestCultureStrategy(),
|
||||
new CookieRequestCultureStrategy(),
|
||||
new AcceptLanguageHeaderRequestCultureStrategy { MaximumAcceptLanguageHeaderValuesToTry = MaximumAcceptLanguageHeaderValuesToTry }
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of values in the Accept-Language header to attempt to create a <see cref="CultureInfo"/>
|
||||
/// from for the current request.
|
||||
/// Defaults to <c>3</c>.
|
||||
/// </summary>
|
||||
public int MaximumAcceptLanguageHeaderValuesToTry { get; set; } = 3;
|
||||
|
||||
/// <summary>
|
||||
/// The default <see cref="RequestCulture"/> to use. This value will be used if none of the configured
|
||||
/// <see cref="IRequestCultureStrategy"/> options result in a non-<c>null</c> result.
|
||||
/// Defaults to <see cref="RequestCulture.Culture"/> set to <see cref="CultureInfo.DefaultThreadCurrentCulture"/>
|
||||
/// and <see cref="RequestCulture.UICulture"/> set to <see cref="CultureInfo.DefaultThreadCurrentUICulture"/>.
|
||||
/// </summary>
|
||||
public RequestCulture DefaultRequestCulture { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The cultures supported by the application. If this value is non-<c>null</c>, the
|
||||
/// <see cref="RequestLocalizationMiddleware"/> will only set the current request culture to an entry in this
|
||||
/// list. A value of <c>null</c> means all cultures are supported.
|
||||
/// Defaults to <c>null</c>.
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Improves usability")]
|
||||
public IList<CultureInfo> SupportedCultures { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The UI cultures supported by the application. If this value is non-<c>null</c>, the
|
||||
/// <see cref="RequestLocalizationMiddleware"/> will only set the current request culture to an entry in this
|
||||
/// list. A value of <c>null</c> means all cultures are supported.
|
||||
/// Defaults to <c>null</c>.
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Improves usability")]
|
||||
public IList<CultureInfo> SupportedUICultures { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An ordered list of strategies used to determine a request's culture information. The first strategy that
|
||||
/// returns a non-<c>null</c> result for a given request will be used.
|
||||
/// Defaults to the following:
|
||||
/// <list type="number">
|
||||
/// <item><description><see cref="QueryStringRequestCultureStrategy"/></description></item>
|
||||
/// <item><description><see cref="CookieRequestCultureStrategy"/></description></item>
|
||||
/// <item><description><see cref="AcceptLanguageHeaderRequestCultureStrategy"/></description></item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Improves usability")]
|
||||
public IList<IRequestCultureStrategy> RequestCultureStrategies { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
"dependencies": {
|
||||
"Microsoft.Framework.Localization.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" },
|
||||
"Microsoft.AspNet.Http.Extensions": "1.0.0-*"
|
||||
},
|
||||
|
||||
|
|
@ -13,6 +14,7 @@
|
|||
"dependencies": {
|
||||
"System.Collections": "4.0.10-*",
|
||||
"System.Linq": "4.0.0-*",
|
||||
"System.Globalization": "4.0.10-*",
|
||||
"System.Threading": "4.0.10-*",
|
||||
"Microsoft.CSharp": "4.0.0-*"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// 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 Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.Framework.Localization
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -13,7 +15,7 @@ namespace Microsoft.Framework.Localization
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the string in the resource it was loaded from.</param>
|
||||
/// <param name="value">The actual string.</param>
|
||||
public LocalizedString(string name, string value)
|
||||
public LocalizedString([NotNull] string name, [NotNull] string value)
|
||||
: this(name, value, resourceNotFound: false)
|
||||
{
|
||||
|
||||
|
|
@ -25,7 +27,7 @@ namespace Microsoft.Framework.Localization
|
|||
/// <param name="name">The name of the string in the resource it was loaded from.</param>
|
||||
/// <param name="value">The actual string.</param>
|
||||
/// <param name="resourceNotFound">Whether the string was found in a resource. Set this to <c>false</c> to indicate an alternate string value was used.</param>
|
||||
public LocalizedString(string name, string value, bool resourceNotFound)
|
||||
public LocalizedString([NotNull] string name, [NotNull] string value, bool resourceNotFound)
|
||||
{
|
||||
Name = name;
|
||||
Value = value;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.Framework.Localization
|
||||
{
|
||||
|
|
@ -19,7 +20,7 @@ namespace Microsoft.Framework.Localization
|
|||
/// Creates a new <see cref="StringLocalizer{TResourceSource}"/>.
|
||||
/// </summary>
|
||||
/// <param name="factory">The <see cref="IStringLocalizerFactory"/> to use.</param>
|
||||
public StringLocalizer(IStringLocalizerFactory factory)
|
||||
public StringLocalizer([NotNull] IStringLocalizerFactory factory)
|
||||
{
|
||||
_localizer = factory.Create(typeof(TResourceSource));
|
||||
}
|
||||
|
|
@ -28,16 +29,17 @@ namespace Microsoft.Framework.Localization
|
|||
public virtual IStringLocalizer WithCulture(CultureInfo culture) => _localizer.WithCulture(culture);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual LocalizedString this[string key] => _localizer[key];
|
||||
public virtual LocalizedString this[[NotNull] string key] => _localizer[key];
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual LocalizedString this[string key, params object[] arguments] => _localizer[key, arguments];
|
||||
public virtual LocalizedString this[[NotNull] string key, params object[] arguments] =>
|
||||
_localizer[key, arguments];
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual LocalizedString GetString(string key) => _localizer.GetString(key);
|
||||
public virtual LocalizedString GetString([NotNull] string key) => _localizer.GetString(key);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual LocalizedString GetString(string key, params object[] arguments) =>
|
||||
public virtual LocalizedString GetString([NotNull] string key, params object[] arguments) =>
|
||||
_localizer.GetString(key, arguments);
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"description": "Abstractions of application localization services.",
|
||||
|
||||
"dependencies": {
|
||||
|
||||
"Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" }
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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 Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.Localization;
|
||||
|
||||
namespace Microsoft.Framework.DependencyInjection
|
||||
|
|
@ -15,7 +16,7 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
/// </summary>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
|
||||
/// <returns>The <see cref="IServiceCollection"/>.</returns>
|
||||
public static IServiceCollection AddLocalization(this IServiceCollection services)
|
||||
public static IServiceCollection AddLocalization([NotNull] this IServiceCollection services)
|
||||
{
|
||||
services.TryAdd(new ServiceDescriptor(
|
||||
typeof(IStringLocalizerFactory),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.Framework.Localization
|
||||
{
|
||||
|
|
@ -27,9 +28,9 @@ namespace Microsoft.Framework.Localization
|
|||
/// <param name="resourceAssembly">The <see cref="Assembly"/> that contains the strings as embedded resources.</param>
|
||||
/// <param name="baseName">The base name of the embedded resource in the <see cref="Assembly"/> that contains the strings.</param>
|
||||
public ResourceManagerStringLocalizer(
|
||||
ResourceManager resourceManager,
|
||||
Assembly resourceAssembly,
|
||||
string baseName)
|
||||
[NotNull] ResourceManager resourceManager,
|
||||
[NotNull] Assembly resourceAssembly,
|
||||
[NotNull] string baseName)
|
||||
{
|
||||
ResourceManager = resourceManager;
|
||||
ResourceAssembly = resourceAssembly;
|
||||
|
|
@ -52,20 +53,20 @@ namespace Microsoft.Framework.Localization
|
|||
protected string ResourceBaseName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual LocalizedString this[string name] => GetString(name);
|
||||
public virtual LocalizedString this[[NotNull] string name] => GetString(name);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual LocalizedString this[string name, params object[] arguments] => GetString(name, arguments);
|
||||
public virtual LocalizedString this[[NotNull] string name, params object[] arguments] => GetString(name, arguments);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual LocalizedString GetString(string name)
|
||||
public virtual LocalizedString GetString([NotNull] string name)
|
||||
{
|
||||
var value = GetStringSafely(name, null);
|
||||
return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual LocalizedString GetString(string name, params object[] arguments)
|
||||
public virtual LocalizedString GetString([NotNull] string name, params object[] arguments)
|
||||
{
|
||||
var format = GetStringSafely(name, null);
|
||||
var value = string.Format(format ?? name, arguments);
|
||||
|
|
@ -95,7 +96,7 @@ namespace Microsoft.Framework.Localization
|
|||
/// <param name="name">The name of the string resource.</param>
|
||||
/// <param name="culture">The <see cref="CultureInfo"/> to get the string for.</param>
|
||||
/// <returns>The resource string, or <c>null</c> if none was found.</returns>
|
||||
protected string GetStringSafely(string name, CultureInfo culture)
|
||||
protected string GetStringSafely([NotNull] string name, [NotNull] CultureInfo culture)
|
||||
{
|
||||
var cacheKey = new MissingManifestCacheKey(name, culture);
|
||||
if (_missingManifestCache.ContainsKey(cacheKey))
|
||||
|
|
@ -133,7 +134,7 @@ namespace Microsoft.Framework.Localization
|
|||
/// </summary>
|
||||
/// <param name="culture">The <see cref="CultureInfo"/> to get strings for.</param>
|
||||
/// <returns>The <see cref="IEnumerator{LocalizedString}"/>.</returns>
|
||||
protected IEnumerator<LocalizedString> GetEnumerator(CultureInfo culture)
|
||||
protected IEnumerator<LocalizedString> GetEnumerator([NotNull] CultureInfo culture)
|
||||
{
|
||||
// TODO: I'm sure something here should be cached, probably the whole result
|
||||
var resourceNames = GetResourceNamesFromCultureHierarchy(culture);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.Runtime;
|
||||
|
||||
namespace Microsoft.Framework.Localization
|
||||
|
|
@ -19,7 +20,7 @@ namespace Microsoft.Framework.Localization
|
|||
/// Creates a new <see cref="ResourceManagerStringLocalizer"/>.
|
||||
/// </summary>
|
||||
/// <param name="applicationEnvironment"></param>
|
||||
public ResourceManagerStringLocalizerFactory(IApplicationEnvironment applicationEnvironment)
|
||||
public ResourceManagerStringLocalizerFactory([NotNull] IApplicationEnvironment applicationEnvironment)
|
||||
{
|
||||
_applicationEnvironment = applicationEnvironment;
|
||||
}
|
||||
|
|
@ -30,7 +31,7 @@ namespace Microsoft.Framework.Localization
|
|||
/// </summary>
|
||||
/// <param name="resourceSource">The <see cref="Type"/>.</param>
|
||||
/// <returns>The <see cref="ResourceManagerStringLocalizer"/>.</returns>
|
||||
public IStringLocalizer Create(Type resourceSource)
|
||||
public IStringLocalizer Create([NotNull] Type resourceSource)
|
||||
{
|
||||
var typeInfo = resourceSource.GetTypeInfo();
|
||||
var assembly = typeInfo.Assembly;
|
||||
|
|
@ -44,7 +45,7 @@ namespace Microsoft.Framework.Localization
|
|||
/// <param name="baseName">The base name of the resource to load strings from.</param>
|
||||
/// <param name="location">The location to load resources from.</param>
|
||||
/// <returns>The <see cref="ResourceManagerStringLocalizer"/>.</returns>
|
||||
public IStringLocalizer Create(string baseName, string location)
|
||||
public IStringLocalizer Create([NotNull] string baseName, [NotNull] string location)
|
||||
{
|
||||
var assembly = Assembly.Load(new AssemblyName(location ?? _applicationEnvironment.ApplicationName));
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.Framework.Localization
|
||||
{
|
||||
|
|
@ -25,30 +26,30 @@ namespace Microsoft.Framework.Localization
|
|||
/// <param name="baseName">The base name of the embedded resource in the <see cref="Assembly"/> that contains the strings.</param>
|
||||
/// <param name="culture">The specific <see cref="CultureInfo"/> to use.</param>
|
||||
public ResourceManagerWithCultureStringLocalizer(
|
||||
ResourceManager resourceManager,
|
||||
Assembly assembly,
|
||||
string baseName,
|
||||
CultureInfo culture)
|
||||
[NotNull] ResourceManager resourceManager,
|
||||
[NotNull] Assembly assembly,
|
||||
[NotNull] string baseName,
|
||||
[NotNull] CultureInfo culture)
|
||||
: base(resourceManager, assembly, baseName)
|
||||
{
|
||||
_culture = culture;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override LocalizedString this[string name] => GetString(name);
|
||||
public override LocalizedString this[[NotNull] string name] => GetString(name);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override LocalizedString this[string name, params object[] arguments] => GetString(name, arguments);
|
||||
public override LocalizedString this[[NotNull] string name, params object[] arguments] => GetString(name, arguments);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override LocalizedString GetString(string name)
|
||||
public override LocalizedString GetString([NotNull] string name)
|
||||
{
|
||||
var value = GetStringSafely(name, _culture);
|
||||
return new LocalizedString(name, value ?? name);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override LocalizedString GetString(string name, params object[] arguments)
|
||||
public override LocalizedString GetString([NotNull] string name, params object[] arguments)
|
||||
{
|
||||
var format = GetStringSafely(name, _culture);
|
||||
var value = string.Format(_culture, format ?? name, arguments);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"dependencies": {
|
||||
"Microsoft.Framework.DependencyInjection.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Framework.Localization.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" },
|
||||
"Microsoft.Framework.Runtime.Abstractions": "1.0.0-*",
|
||||
"System.Resources.ReaderWriter": "4.0.0-*"
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue