diff --git a/src/Microsoft.AspNet.Localization/AcceptLanguageHeaderRequestCultureStrategy.cs b/src/Microsoft.AspNet.Localization/AcceptLanguageHeaderRequestCultureStrategy.cs
new file mode 100644
index 0000000000..1a90e5332a
--- /dev/null
+++ b/src/Microsoft.AspNet.Localization/AcceptLanguageHeaderRequestCultureStrategy.cs
@@ -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
+{
+ ///
+ /// Determines the culture information for a request via the value of the Accept-Language header.
+ ///
+ ///
+ ///
+ ///
+ public class AcceptLanguageHeaderRequestCultureStrategy : IRequestCultureStrategy
+ {
+ ///
+ /// The maximum number of values in the Accept-Language header to attempt to create a
+ /// from for the current request.
+ /// Defaults to 3.
+ ///
+ public int MaximumAcceptLanguageHeaderValuesToTry { get; set; } = 3;
+
+ ///
+ 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;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Localization/CookieRequestCultureStrategy.cs b/src/Microsoft.AspNet.Localization/CookieRequestCultureStrategy.cs
new file mode 100644
index 0000000000..902d5819dd
--- /dev/null
+++ b/src/Microsoft.AspNet.Localization/CookieRequestCultureStrategy.cs
@@ -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;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Localization/CustomRequestCultureStrategy.cs b/src/Microsoft.AspNet.Localization/CustomRequestCultureStrategy.cs
new file mode 100644
index 0000000000..629862c1e5
--- /dev/null
+++ b/src/Microsoft.AspNet.Localization/CustomRequestCultureStrategy.cs
@@ -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 _strategy;
+
+ public CustomRequestCultureStrategy([NotNull] Func strategy)
+ {
+ _strategy = strategy;
+ }
+
+ public RequestCulture DetermineRequestCulture([NotNull] HttpContext httpContext)
+ {
+ return _strategy(httpContext);
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Localization/IApplicationBuilderExtensions.cs b/src/Microsoft.AspNet.Localization/IApplicationBuilderExtensions.cs
index 96330b7bd6..d3d7a65077 100644
--- a/src/Microsoft.AspNet.Localization/IApplicationBuilderExtensions.cs
+++ b/src/Microsoft.AspNet.Localization/IApplicationBuilderExtensions.cs
@@ -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
{
///
/// Adds the 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.
///
/// The .
/// The .
- public static IApplicationBuilder UseRequestLocalization(this IApplicationBuilder builder)
+ public static IApplicationBuilder UseRequestLocalization([NotNull] this IApplicationBuilder builder)
{
- return builder.UseMiddleware();
+ var options = new RequestLocalizationMiddlewareOptions();
+
+ return UseRequestLocalization(builder, options);
+ }
+
+ ///
+ /// Adds the to automatically set culture information for
+ /// requests based on information provided by the client.
+ ///
+ /// The .
+ /// The options to configure the middleware with.
+ /// The .
+ public static IApplicationBuilder UseRequestLocalization(
+ [NotNull] this IApplicationBuilder builder,
+ [NotNull] RequestLocalizationMiddlewareOptions options)
+ {
+ return builder.UseMiddleware(options);
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Localization/IRequestCultureFeature.cs b/src/Microsoft.AspNet.Localization/IRequestCultureFeature.cs
index 65417e228d..73cd046f50 100644
--- a/src/Microsoft.AspNet.Localization/IRequestCultureFeature.cs
+++ b/src/Microsoft.AspNet.Localization/IRequestCultureFeature.cs
@@ -12,5 +12,12 @@ namespace Microsoft.AspNet.Localization
/// The of the request.
///
RequestCulture RequestCulture { get; }
+
+ ///
+ /// The that determined the request's culture information.
+ /// If the value is null then no strategy was used and the request's culture was set to the value of
+ /// .
+ ///
+ IRequestCultureStrategy Strategy { get; }
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Localization/IRequestCultureStrategy.cs b/src/Microsoft.AspNet.Localization/IRequestCultureStrategy.cs
new file mode 100644
index 0000000000..93f943488b
--- /dev/null
+++ b/src/Microsoft.AspNet.Localization/IRequestCultureStrategy.cs
@@ -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);
+ }
+}
diff --git a/src/Microsoft.AspNet.Localization/Internal/CultureUtilities.cs b/src/Microsoft.AspNet.Localization/Internal/CultureUtilities.cs
new file mode 100644
index 0000000000..bea6d2145d
--- /dev/null
+++ b/src/Microsoft.AspNet.Localization/Internal/CultureUtilities.cs
@@ -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;
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Localization/QueryStringRequestCultureStrategy.cs b/src/Microsoft.AspNet.Localization/QueryStringRequestCultureStrategy.cs
new file mode 100644
index 0000000000..c7cfdb77e7
--- /dev/null
+++ b/src/Microsoft.AspNet.Localization/QueryStringRequestCultureStrategy.cs
@@ -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
+{
+ ///
+ /// Determines the culture information for a request via values in the query string.
+ ///
+ public class QueryStringRequestCultureStrategy : IRequestCultureStrategy
+ {
+ ///
+ /// The key that contains the culture name.
+ /// Defaults to "culture".
+ ///
+ public string QueryStringKey { get; set; } = "culture";
+
+ ///
+ /// The key that contains the UI culture name. If not specified or no value is found,
+ /// will be used.
+ /// Defaults to "ui-culture".
+ ///
+ public string UIQueryStringKey { get; set; } = "ui-culture";
+
+ ///
+ 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));
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Localization/RequestCulture.cs b/src/Microsoft.AspNet.Localization/RequestCulture.cs
index c0dc4a5680..ec109e6d8e 100644
--- a/src/Microsoft.AspNet.Localization/RequestCulture.cs
+++ b/src/Microsoft.AspNet.Localization/RequestCulture.cs
@@ -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 value.
///
/// The for the request.
- public RequestCulture(CultureInfo culture)
+ public RequestCulture([NotNull] CultureInfo culture)
: this (culture, culture)
{
@@ -27,7 +28,7 @@ namespace Microsoft.AspNet.Localization
///
/// The for the request to be used for formatting.
/// The for the request to be used for text, i.e. language.
- public RequestCulture(CultureInfo culture, CultureInfo uiCulture)
+ public RequestCulture([NotNull] CultureInfo culture, [NotNull] CultureInfo uiCulture)
{
Culture = culture;
UICulture = uiCulture;
diff --git a/src/Microsoft.AspNet.Localization/RequestCultureFeature.cs b/src/Microsoft.AspNet.Localization/RequestCultureFeature.cs
index 730145bd30..76505b4759 100644
--- a/src/Microsoft.AspNet.Localization/RequestCultureFeature.cs
+++ b/src/Microsoft.AspNet.Localization/RequestCultureFeature.cs
@@ -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
{
///
@@ -12,12 +14,16 @@ namespace Microsoft.AspNet.Localization
/// Creates a new with the specified .
///
/// The .
- public RequestCultureFeature(RequestCulture requestCulture)
+ public RequestCultureFeature([NotNull] RequestCulture requestCulture, IRequestCultureStrategy strategy)
{
RequestCulture = requestCulture;
+ Strategy = strategy;
}
///
public RequestCulture RequestCulture { get; }
+
+ ///
+ public IRequestCultureStrategy Strategy { get; }
}
}
diff --git a/src/Microsoft.AspNet.Localization/RequestLocalizationMiddleware.cs b/src/Microsoft.AspNet.Localization/RequestLocalizationMiddleware.cs
index 3be800652f..2064690662 100644
--- a/src/Microsoft.AspNet.Localization/RequestLocalizationMiddleware.cs
+++ b/src/Microsoft.AspNet.Localization/RequestLocalizationMiddleware.cs
@@ -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;
+
///
/// Creates a new .
///
/// The representing the next middleware in the pipeline.
- public RequestLocalizationMiddleware(RequestDelegate next)
+ ///
+ public RequestLocalizationMiddleware([NotNull] RequestDelegate next, [NotNull] RequestLocalizationMiddlewareOptions options)
{
_next = next;
+ _options = options;
}
///
@@ -31,42 +35,35 @@ namespace Microsoft.AspNet.Localization
///
/// The .
/// A that completes when the middleware has completed processing.
- 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(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(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;
diff --git a/src/Microsoft.AspNet.Localization/RequestLocalizationMiddlewareOptions.cs b/src/Microsoft.AspNet.Localization/RequestLocalizationMiddlewareOptions.cs
new file mode 100644
index 0000000000..cfa8e6e196
--- /dev/null
+++ b/src/Microsoft.AspNet.Localization/RequestLocalizationMiddlewareOptions.cs
@@ -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
+{
+ ///
+ /// Specifies options for the .
+ ///
+ public class RequestLocalizationMiddlewareOptions
+ {
+ ///
+ /// Creates a new with default values.
+ ///
+ public RequestLocalizationMiddlewareOptions()
+ {
+ DefaultRequestCulture = new RequestCulture(CultureInfo.DefaultThreadCurrentCulture, CultureInfo.DefaultThreadCurrentUICulture);
+
+ RequestCultureStrategies = new List
+ {
+ new QueryStringRequestCultureStrategy(),
+ new CookieRequestCultureStrategy(),
+ new AcceptLanguageHeaderRequestCultureStrategy { MaximumAcceptLanguageHeaderValuesToTry = MaximumAcceptLanguageHeaderValuesToTry }
+ };
+ }
+
+ ///
+ /// The maximum number of values in the Accept-Language header to attempt to create a
+ /// from for the current request.
+ /// Defaults to 3.
+ ///
+ public int MaximumAcceptLanguageHeaderValuesToTry { get; set; } = 3;
+
+ ///
+ /// The default to use. This value will be used if none of the configured
+ /// options result in a non-null result.
+ /// Defaults to set to
+ /// and set to .
+ ///
+ public RequestCulture DefaultRequestCulture { get; set; }
+
+ ///
+ /// The cultures supported by the application. If this value is non-null, the
+ /// will only set the current request culture to an entry in this
+ /// list. A value of null means all cultures are supported.
+ /// Defaults to null.
+ ///
+ [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Improves usability")]
+ public IList SupportedCultures { get; set; }
+
+ ///
+ /// The UI cultures supported by the application. If this value is non-null, the
+ /// will only set the current request culture to an entry in this
+ /// list. A value of null means all cultures are supported.
+ /// Defaults to null.
+ ///
+ [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Improves usability")]
+ public IList SupportedUICultures { get; set; }
+
+ ///
+ /// An ordered list of strategies used to determine a request's culture information. The first strategy that
+ /// returns a non-null result for a given request will be used.
+ /// Defaults to the following:
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Improves usability")]
+ public IList RequestCultureStrategies { get; set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.Localization/project.json b/src/Microsoft.AspNet.Localization/project.json
index 7561196f6f..a6d3910968 100644
--- a/src/Microsoft.AspNet.Localization/project.json
+++ b/src/Microsoft.AspNet.Localization/project.json
@@ -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-*"
}
diff --git a/src/Microsoft.Framework.Localization.Abstractions/LocalizedString.cs b/src/Microsoft.Framework.Localization.Abstractions/LocalizedString.cs
index 4faf864309..4549457ff1 100644
--- a/src/Microsoft.Framework.Localization.Abstractions/LocalizedString.cs
+++ b/src/Microsoft.Framework.Localization.Abstractions/LocalizedString.cs
@@ -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
{
///
@@ -13,7 +15,7 @@ namespace Microsoft.Framework.Localization
///
/// The name of the string in the resource it was loaded from.
/// The actual string.
- 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
/// The name of the string in the resource it was loaded from.
/// The actual string.
/// Whether the string was found in a resource. Set this to false to indicate an alternate string value was used.
- public LocalizedString(string name, string value, bool resourceNotFound)
+ public LocalizedString([NotNull] string name, [NotNull] string value, bool resourceNotFound)
{
Name = name;
Value = value;
diff --git a/src/Microsoft.Framework.Localization.Abstractions/StringLocalizerOfT.cs b/src/Microsoft.Framework.Localization.Abstractions/StringLocalizerOfT.cs
index f222bf93b3..8801cdf234 100644
--- a/src/Microsoft.Framework.Localization.Abstractions/StringLocalizerOfT.cs
+++ b/src/Microsoft.Framework.Localization.Abstractions/StringLocalizerOfT.cs
@@ -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 .
///
/// The to use.
- 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);
///
- public virtual LocalizedString this[string key] => _localizer[key];
+ public virtual LocalizedString this[[NotNull] string key] => _localizer[key];
///
- 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];
///
- public virtual LocalizedString GetString(string key) => _localizer.GetString(key);
+ public virtual LocalizedString GetString([NotNull] string key) => _localizer.GetString(key);
///
- public virtual LocalizedString GetString(string key, params object[] arguments) =>
+ public virtual LocalizedString GetString([NotNull] string key, params object[] arguments) =>
_localizer.GetString(key, arguments);
///
diff --git a/src/Microsoft.Framework.Localization.Abstractions/project.json b/src/Microsoft.Framework.Localization.Abstractions/project.json
index 87aa883bfd..63eb5f2524 100644
--- a/src/Microsoft.Framework.Localization.Abstractions/project.json
+++ b/src/Microsoft.Framework.Localization.Abstractions/project.json
@@ -3,7 +3,7 @@
"description": "Abstractions of application localization services.",
"dependencies": {
-
+ "Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" }
},
"frameworks": {
diff --git a/src/Microsoft.Framework.Localization/LocalizationServiceCollectionExtensions.cs b/src/Microsoft.Framework.Localization/LocalizationServiceCollectionExtensions.cs
index 9b4a0079fc..fe6f4694f2 100644
--- a/src/Microsoft.Framework.Localization/LocalizationServiceCollectionExtensions.cs
+++ b/src/Microsoft.Framework.Localization/LocalizationServiceCollectionExtensions.cs
@@ -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
///
/// The to add the services to.
/// The .
- public static IServiceCollection AddLocalization(this IServiceCollection services)
+ public static IServiceCollection AddLocalization([NotNull] this IServiceCollection services)
{
services.TryAdd(new ServiceDescriptor(
typeof(IStringLocalizerFactory),
diff --git a/src/Microsoft.Framework.Localization/ResourceManagerStringLocalizer.cs b/src/Microsoft.Framework.Localization/ResourceManagerStringLocalizer.cs
index b6db0b6d13..526b16ab99 100644
--- a/src/Microsoft.Framework.Localization/ResourceManagerStringLocalizer.cs
+++ b/src/Microsoft.Framework.Localization/ResourceManagerStringLocalizer.cs
@@ -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
/// The that contains the strings as embedded resources.
/// The base name of the embedded resource in the that contains the strings.
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; }
///
- public virtual LocalizedString this[string name] => GetString(name);
+ public virtual LocalizedString this[[NotNull] string name] => GetString(name);
///
- 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);
///
- 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);
}
///
- 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
/// The name of the string resource.
/// The to get the string for.
/// The resource string, or null if none was found.
- 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
///
/// The to get strings for.
/// The .
- protected IEnumerator GetEnumerator(CultureInfo culture)
+ protected IEnumerator GetEnumerator([NotNull] CultureInfo culture)
{
// TODO: I'm sure something here should be cached, probably the whole result
var resourceNames = GetResourceNamesFromCultureHierarchy(culture);
diff --git a/src/Microsoft.Framework.Localization/ResourceManagerStringLocalizerFactory.cs b/src/Microsoft.Framework.Localization/ResourceManagerStringLocalizerFactory.cs
index 801f6acef5..3039a9d377 100644
--- a/src/Microsoft.Framework.Localization/ResourceManagerStringLocalizerFactory.cs
+++ b/src/Microsoft.Framework.Localization/ResourceManagerStringLocalizerFactory.cs
@@ -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 .
///
///
- public ResourceManagerStringLocalizerFactory(IApplicationEnvironment applicationEnvironment)
+ public ResourceManagerStringLocalizerFactory([NotNull] IApplicationEnvironment applicationEnvironment)
{
_applicationEnvironment = applicationEnvironment;
}
@@ -30,7 +31,7 @@ namespace Microsoft.Framework.Localization
///
/// The .
/// The .
- 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
/// The base name of the resource to load strings from.
/// The location to load resources from.
/// The .
- 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));
diff --git a/src/Microsoft.Framework.Localization/ResourceManagerWithCultureStringLocalizer.cs b/src/Microsoft.Framework.Localization/ResourceManagerWithCultureStringLocalizer.cs
index 7b988b04ba..8e9027af76 100644
--- a/src/Microsoft.Framework.Localization/ResourceManagerWithCultureStringLocalizer.cs
+++ b/src/Microsoft.Framework.Localization/ResourceManagerWithCultureStringLocalizer.cs
@@ -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
/// The base name of the embedded resource in the that contains the strings.
/// The specific to use.
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;
}
///
- public override LocalizedString this[string name] => GetString(name);
+ public override LocalizedString this[[NotNull] string name] => GetString(name);
///
- 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);
///
- public override LocalizedString GetString(string name)
+ public override LocalizedString GetString([NotNull] string name)
{
var value = GetStringSafely(name, _culture);
return new LocalizedString(name, value ?? name);
}
///
- 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);
diff --git a/src/Microsoft.Framework.Localization/project.json b/src/Microsoft.Framework.Localization/project.json
index 39a74a1e5a..c0ad0046fd 100644
--- a/src/Microsoft.Framework.Localization/project.json
+++ b/src/Microsoft.Framework.Localization/project.json
@@ -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-*"
},