Merge source code from aspnet/Localization
This commit is contained in:
commit
7e0f561425
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Product>Microsoft ASP.NET Core</Product>
|
||||
<Description>Provides a request culture provider which gets culture and ui-culture from request's route data.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;localization</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Localization" />
|
||||
<Reference Include="Microsoft.AspNetCore.Routing.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the culture information for a request via values in the route data.
|
||||
/// </summary>
|
||||
public class RouteDataRequestCultureProvider : RequestCultureProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The key that contains the culture name.
|
||||
/// Defaults to "culture".
|
||||
/// </summary>
|
||||
public string RouteDataStringKey { get; set; } = "culture";
|
||||
|
||||
/// <summary>
|
||||
/// The key that contains the UI culture name. If not specified or no value is found,
|
||||
/// <see cref="RouteDataStringKey"/> will be used.
|
||||
/// Defaults to "ui-culture".
|
||||
/// </summary>
|
||||
public string UIRouteDataStringKey { get; set; } = "ui-culture";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
|
||||
{
|
||||
if (httpContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpContext));
|
||||
}
|
||||
|
||||
string culture = null;
|
||||
string uiCulture = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(RouteDataStringKey))
|
||||
{
|
||||
culture = httpContext.GetRouteValue(RouteDataStringKey)?.ToString();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(UIRouteDataStringKey))
|
||||
{
|
||||
uiCulture = httpContext.GetRouteValue(UIRouteDataStringKey)?.ToString();
|
||||
}
|
||||
|
||||
if (culture == null && uiCulture == null)
|
||||
{
|
||||
// No values specified for either so no match
|
||||
return NullProviderCultureResult;
|
||||
}
|
||||
|
||||
if (culture != null && uiCulture == null)
|
||||
{
|
||||
// Value for culture but not for UI culture so default to culture value for both
|
||||
uiCulture = culture;
|
||||
}
|
||||
|
||||
if (culture == null && uiCulture != null)
|
||||
{
|
||||
// Value for UI culture but not for culture so default to UI culture value for both
|
||||
culture = uiCulture;
|
||||
}
|
||||
|
||||
var providerResultCulture = new ProviderCultureResult(culture, uiCulture);
|
||||
|
||||
return Task.FromResult(providerResultCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"AssemblyIdentity": "Microsoft.AspNetCore.Localization.Routing, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
||||
"Types": [
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.Routing.RouteDataRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"BaseType": "Microsoft.AspNetCore.Localization.RequestCultureProvider",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "DetermineProviderCultureResult",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "httpContext",
|
||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>",
|
||||
"Virtual": true,
|
||||
"Override": true,
|
||||
"ImplementedInterface": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_RouteDataStringKey",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.String",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_RouteDataStringKey",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_UIRouteDataStringKey",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.String",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_UIRouteDataStringKey",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Localization.Routing" />
|
||||
<Reference Include="Microsoft.AspNetCore.Routing" />
|
||||
<Reference Include="Microsoft.AspNetCore.TestHost" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
// 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 System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization.Routing
|
||||
{
|
||||
public class RouteDataRequestCultureProviderTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("{culture}/{ui-culture}/hello", "ar-SA/ar-YE/hello", "ar-SA", "ar-YE")]
|
||||
[InlineData("{CULTURE}/{UI-CULTURE}/hello", "ar-SA/ar-YE/hello", "ar-SA", "ar-YE")]
|
||||
[InlineData("{culture}/{ui-culture}/hello", "unsupported/unsupported/hello", "en-US", "en-US")]
|
||||
[InlineData("{culture}/hello", "ar-SA/hello", "ar-SA", "en-US")]
|
||||
[InlineData("hello", "hello", "en-US", "en-US")]
|
||||
[InlineData("{ui-culture}/hello", "ar-YE/hello", "en-US", "ar-YE")]
|
||||
public async Task GetCultureInfo_FromRouteData(
|
||||
string routeTemplate,
|
||||
string requestUrl,
|
||||
string expectedCulture,
|
||||
string expectedUICulture)
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRouter(routes =>
|
||||
{
|
||||
routes.MapMiddlewareRoute(routeTemplate, fork =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
}
|
||||
};
|
||||
options.RequestCultureProviders = new[]
|
||||
{
|
||||
new RouteDataRequestCultureProvider()
|
||||
{
|
||||
Options = options
|
||||
}
|
||||
};
|
||||
fork.UseRequestLocalization(options);
|
||||
|
||||
fork.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
return context.Response.WriteAsync(
|
||||
$"{requestCulture.Culture.Name},{requestCulture.UICulture.Name}");
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddRouting();
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync(requestUrl);
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var data = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal($"{expectedCulture},{expectedUICulture}", data);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetDefaultCultureInfo_IfCultureKeysAreMissing()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US")
|
||||
};
|
||||
options.RequestCultureProviders = new[]
|
||||
{
|
||||
new RouteDataRequestCultureProvider()
|
||||
{
|
||||
Options = options
|
||||
}
|
||||
};
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
|
||||
return context.Response.WriteAsync(
|
||||
$"{requestCulture.Culture.Name},{requestCulture.UICulture.Name}");
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page");
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var data = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal("en-US,en-US", data);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{c}/{uic}/hello", "ar-SA/ar-YE/hello", "ar-SA", "ar-YE")]
|
||||
[InlineData("{C}/{UIC}/hello", "ar-SA/ar-YE/hello", "ar-SA", "ar-YE")]
|
||||
[InlineData("{c}/hello", "ar-SA/hello", "ar-SA", "en-US")]
|
||||
[InlineData("hello", "hello", "en-US", "en-US")]
|
||||
[InlineData("{uic}/hello", "ar-YE/hello", "en-US", "ar-YE")]
|
||||
public async Task GetCultureInfo_FromRouteData_WithCustomKeys(
|
||||
string routeTemplate,
|
||||
string requestUrl,
|
||||
string expectedCulture,
|
||||
string expectedUICulture)
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRouter(routes =>
|
||||
{
|
||||
routes.MapMiddlewareRoute(routeTemplate, fork =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
}
|
||||
};
|
||||
options.RequestCultureProviders = new[]
|
||||
{
|
||||
new RouteDataRequestCultureProvider()
|
||||
{
|
||||
Options = options,
|
||||
RouteDataStringKey = "c",
|
||||
UIRouteDataStringKey = "uic"
|
||||
}
|
||||
};
|
||||
fork.UseRequestLocalization(options);
|
||||
|
||||
fork.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
|
||||
return context.Response.WriteAsync(
|
||||
$"{requestCulture.Culture.Name},{requestCulture.UICulture.Name}");
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddRouting();
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync(requestUrl);
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var data = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal($"{expectedCulture},{expectedUICulture}", data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
Localization
|
||||
============
|
||||
|
||||
### Localization Samples
|
||||
|
||||
Here are a few samples that demonstrate different localization features including: localized views, localized strings in data annotations, creating custom localization resources ... etc.
|
||||
|
||||
* [Localization.StarterWeb](https://github.com/aspnet/Entropy/tree/dev/samples/Localization.StarterWeb) - comprehensive localization sample demonstrates almost all of the localization features
|
||||
* [Localization.EntityFramework](https://github.com/aspnet/Entropy/tree/dev/samples/Localization.EntityFramework) - localization sample that uses an EntityFramework based localization provider for resources
|
||||
* [Localization.CustomResourceManager](https://github.com/aspnet/Entropy/tree/dev/samples/Localization.CustomResourceManager) - localization sample that uses a custom `ResourceManagerStringLocalizer`
|
||||
|
||||
### Localization Providers
|
||||
|
||||
Community projects adapt _RequestCultureProvider_ for determining the culture information of an `HttpRequest`.
|
||||
|
||||
* [My.AspNetCore.Localization.Json](https://github.com/hishamco/My.AspNetCore.Localization.Json) - determines the culture information for a request from a JSON file.
|
||||
* [My.AspNetCore.Localization.Session](https://github.com/hishamco/My.AspNetCore.Localization.Session) - determines the culture information for a request via values in the session state.
|
||||
|
||||
### Localization Resources
|
||||
|
||||
Community projects adapt _IStringLocalizer_ for fetching the localiztion resources.
|
||||
|
||||
* [My.Extensions.Localization.Json](https://github.com/hishamco/My.Extensions.Localization.Json) - fetches the localization resources from JSON file(s).
|
||||
* [OrchardCore.Localization.PortableObject](https://github.com/OrchardCMS/OrchardCore/tree/dev/src/OrchardCore/OrchardCore.Localization.Core/PortableObject) - fetches the localization resources from PO file(s).
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp2.1;netcoreapp2.0;net461</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Localization" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||
<Reference Include="Microsoft.Extensions.Configuration.CommandLine" />
|
||||
<Reference Include="Microsoft.Extensions.Localization" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Hola</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>こんにちは</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>您好</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>您好</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
// 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.Globalization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LocalizationSample
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLocalization(options => options.ResourcesPath = "My/Resources");
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IStringLocalizer<Startup> SR)
|
||||
{
|
||||
var supportedCultures = new [] { "en-US", "en-AU", "en-GB", "es-ES", "ja-JP", "fr-FR", "zh", "zh-CN" };
|
||||
app.UseRequestLocalization(options =>
|
||||
options
|
||||
.AddSupportedCultures(supportedCultures)
|
||||
.AddSupportedUICultures(supportedCultures)
|
||||
.SetDefaultCulture(supportedCultures[0])
|
||||
// Optionally create an app-specific provider with just a delegate, e.g. look up user preference from DB.
|
||||
// Inserting it as position 0 ensures it has priority over any of the default providers.
|
||||
//.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
|
||||
//{
|
||||
|
||||
//}));
|
||||
);
|
||||
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
if (context.Request.Path.Value.EndsWith("favicon.ico"))
|
||||
{
|
||||
// Pesky browsers
|
||||
context.Response.StatusCode = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
context.Response.StatusCode = 200;
|
||||
context.Response.ContentType = "text/html; charset=utf-8";
|
||||
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
|
||||
await context.Response.WriteAsync(
|
||||
$@"<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{SR["Request Localization"]}</title>
|
||||
<style>
|
||||
body {{ font-family: 'Segoe UI', Helvetica, Sans-Serif }}
|
||||
h1, h2, h3, h4, th {{ font-family: 'Segoe UI Light', Helvetica, Sans-Serif }}
|
||||
th {{ text-align: left }}
|
||||
</style>
|
||||
<script>
|
||||
function useCookie() {{
|
||||
var culture = document.getElementById('culture');
|
||||
var uiCulture = document.getElementById('uiCulture');
|
||||
var cookieValue = '{CookieRequestCultureProvider.DefaultCookieName}=c='+culture.options[culture.selectedIndex].value+'|uic='+uiCulture.options[uiCulture.selectedIndex].value;
|
||||
document.cookie = cookieValue;
|
||||
window.location = window.location.href.split('?')[0];
|
||||
}}
|
||||
|
||||
function clearCookie() {{
|
||||
document.cookie='{CookieRequestCultureProvider.DefaultCookieName}=""""';
|
||||
}}
|
||||
</script>
|
||||
</head>
|
||||
<body>");
|
||||
await context.Response.WriteAsync($"<h1>{SR["Request Localization Sample"]}</h1>");
|
||||
await context.Response.WriteAsync($"<h1>{SR["Hello"]}</h1>");
|
||||
await context.Response.WriteAsync("<form id=\"theForm\" method=\"get\">");
|
||||
await context.Response.WriteAsync($"<label for=\"culture\">{SR["Culture"]}: </label>");
|
||||
await context.Response.WriteAsync("<select id=\"culture\" name=\"culture\">");
|
||||
await WriteCultureSelectOptions(context);
|
||||
await context.Response.WriteAsync("</select><br />");
|
||||
await context.Response.WriteAsync($"<label for=\"uiCulture\">{SR["UI Culture"]}: </label>");
|
||||
await context.Response.WriteAsync("<select id=\"uiCulture\" name=\"ui-culture\">");
|
||||
await WriteCultureSelectOptions(context);
|
||||
await context.Response.WriteAsync("</select><br />");
|
||||
await context.Response.WriteAsync("<input type=\"submit\" value=\"go QS\" /> ");
|
||||
await context.Response.WriteAsync($"<input type=\"button\" value=\"go cookie\" onclick='useCookie();' /> ");
|
||||
await context.Response.WriteAsync($"<a href=\"/\" onclick='clearCookie();'>{SR["reset"]}</a>");
|
||||
await context.Response.WriteAsync("</form>");
|
||||
await context.Response.WriteAsync("<br />");
|
||||
await context.Response.WriteAsync("<table><tbody>");
|
||||
await context.Response.WriteAsync($"<tr><th>Winning provider:</th><td>{requestCultureFeature.Provider.GetType().Name}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current request culture:"]}</th><td>{requestCulture.Culture.DisplayName} ({requestCulture.Culture})</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current request UI culture:"]}</th><td>{requestCulture.UICulture.DisplayName} ({requestCulture.UICulture})</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current thread culture:"]}</th><td>{CultureInfo.CurrentCulture.DisplayName} ({CultureInfo.CurrentCulture})</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current thread UI culture:"]}</th><td>{CultureInfo.CurrentUICulture.DisplayName} ({CultureInfo.CurrentUICulture})</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current date (invariant full):"]}</th><td>{DateTime.Now.ToString("F", CultureInfo.InvariantCulture)}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current date (invariant):"]}</th><td>{DateTime.Now.ToString(CultureInfo.InvariantCulture)}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current date (request full):"]}</th><td>{DateTime.Now.ToString("F")}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current date (request):"]}</th><td>{DateTime.Now.ToString()}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current time (invariant):"]}</th><td>{DateTime.Now.ToString("T", CultureInfo.InvariantCulture)}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Current time (request):"]}</th><td>{DateTime.Now.ToString("T")}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Big number (invariant):"]}</th><td>{(Math.Pow(2, 42) + 0.42).ToString("N", CultureInfo.InvariantCulture)}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Big number (request):"]}</th><td>{(Math.Pow(2, 42) + 0.42).ToString("N")}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Big number negative (invariant):"]}</th><td>{(-Math.Pow(2, 42) + 0.42).ToString("N", CultureInfo.InvariantCulture)}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Big number negative (request):"]}</th><td>{(-Math.Pow(2, 42) + 0.42).ToString("N")}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Money (invariant):"]}</th><td>{2199.50.ToString("C", CultureInfo.InvariantCulture)}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Money (request):"]}</th><td>{2199.50.ToString("C")}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Money negative (invariant):"]}</th><td>{(-2199.50).ToString("C", CultureInfo.InvariantCulture)}</td></tr>");
|
||||
await context.Response.WriteAsync($"<tr><th>{SR["Money negative (request):"]}</th><td>{(-2199.50).ToString("C")}</td></tr>");
|
||||
await context.Response.WriteAsync("</tbody></table>");
|
||||
await context.Response.WriteAsync(
|
||||
@"</body>
|
||||
</html>");
|
||||
});
|
||||
}
|
||||
|
||||
private static async System.Threading.Tasks.Task WriteCultureSelectOptions(HttpContext context)
|
||||
{
|
||||
await context.Response.WriteAsync($" <option value=\"\">-- select --</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("en-US").Name}\">{new CultureInfo("en-US").DisplayName}</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("en-AU").Name}\">{new CultureInfo("en-AU").DisplayName}</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("en-GB").Name}\">{new CultureInfo("en-GB").DisplayName}</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("fr-FR").Name}\">{new CultureInfo("fr-FR").DisplayName}</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("es-ES").Name}\">{new CultureInfo("es-ES").DisplayName}</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("ja-JP").Name}\">{new CultureInfo("ja-JP").DisplayName}</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("zh").Name}\">{new CultureInfo("zh").DisplayName}</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"{new CultureInfo("zh-CN").Name}\">{new CultureInfo("zh-CN").DisplayName}</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"en-NOTREAL\">English (Not a real locale)</option>");
|
||||
await context.Response.WriteAsync($" <option value=\"pp-NOTREAL\">Made-up (Not a real anything)</option>");
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddCommandLine(args)
|
||||
.Build();
|
||||
|
||||
var host = new WebHostBuilder()
|
||||
.ConfigureLogging(factory => factory.AddConsole())
|
||||
.UseKestrel()
|
||||
.UseConfiguration(config)
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// 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.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the culture information for a request via the value of the Accept-Language header.
|
||||
/// </summary>
|
||||
public class AcceptLanguageHeaderRequestCultureProvider : RequestCultureProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum number of values in the Accept-Language header to attempt to create a <see cref="System.Globalization.CultureInfo"/>
|
||||
/// from for the current request.
|
||||
/// Defaults to <c>3</c>.
|
||||
/// </summary>
|
||||
public int MaximumAcceptLanguageHeaderValuesToTry { get; set; } = 3;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
|
||||
{
|
||||
if (httpContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpContext));
|
||||
}
|
||||
|
||||
var acceptLanguageHeader = httpContext.Request.GetTypedHeaders().AcceptLanguage;
|
||||
|
||||
if (acceptLanguageHeader == null || acceptLanguageHeader.Count == 0)
|
||||
{
|
||||
return NullProviderCultureResult;
|
||||
}
|
||||
|
||||
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)
|
||||
.Select(x => x.Value).ToList();
|
||||
|
||||
if (orderedLanguages.Count > 0)
|
||||
{
|
||||
return Task.FromResult(new ProviderCultureResult(orderedLanguages));
|
||||
}
|
||||
|
||||
return NullProviderCultureResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
// 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.AspNetCore.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for adding the <see cref="RequestLocalizationMiddleware"/> to an application.
|
||||
/// </summary>
|
||||
public static class ApplicationBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the <see cref="RequestLocalizationMiddleware"/> to automatically set culture information for
|
||||
/// requests based on information provided by the client.
|
||||
/// </summary>
|
||||
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
||||
public static IApplicationBuilder UseRequestLocalization(this IApplicationBuilder app)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
return app.UseMiddleware<RequestLocalizationMiddleware>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the <see cref="RequestLocalizationMiddleware"/> to automatically set culture information for
|
||||
/// requests based on information provided by the client.
|
||||
/// </summary>
|
||||
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <param name="options">The <see cref="RequestLocalizationOptions"/> to configure the middleware with.</param>
|
||||
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
||||
public static IApplicationBuilder UseRequestLocalization(
|
||||
this IApplicationBuilder app,
|
||||
RequestLocalizationOptions options)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
return app.UseMiddleware<RequestLocalizationMiddleware>(Options.Create(options));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the <see cref="RequestLocalizationMiddleware"/> to automatically set culture information for
|
||||
/// requests based on information provided by the client.
|
||||
/// </summary>
|
||||
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <param name="optionsAction"></param>
|
||||
/// <remarks>
|
||||
/// This will going to instantiate a new <see cref="RequestLocalizationOptions"/> that doesn't come from the services.
|
||||
/// </remarks>
|
||||
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
||||
public static IApplicationBuilder UseRequestLocalization(
|
||||
this IApplicationBuilder app,
|
||||
Action<RequestLocalizationOptions> optionsAction)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
if (optionsAction == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(optionsAction));
|
||||
}
|
||||
|
||||
var options = new RequestLocalizationOptions();
|
||||
optionsAction.Invoke(options);
|
||||
|
||||
return app.UseMiddleware<RequestLocalizationMiddleware>(Options.Create(options));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the <see cref="RequestLocalizationMiddleware"/> to automatically set culture information for
|
||||
/// requests based on information provided by the client.
|
||||
/// </summary>
|
||||
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <param name="cultures">The culture names to be added by the application, which is represents both supported cultures and UI cultures.</param>
|
||||
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
||||
/// <remarks>
|
||||
/// Note that the first culture is the default culture name.
|
||||
/// </remarks>
|
||||
public static IApplicationBuilder UseRequestLocalization(
|
||||
this IApplicationBuilder app,
|
||||
params string[] cultures)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
if (cultures == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(cultures));
|
||||
}
|
||||
|
||||
if (cultures.Length == 0)
|
||||
{
|
||||
throw new ArgumentException(Resources.Exception_CulturesShouldNotBeEmpty);
|
||||
}
|
||||
|
||||
var options = new RequestLocalizationOptions()
|
||||
.AddSupportedCultures(cultures)
|
||||
.AddSupportedUICultures(cultures)
|
||||
.SetDefaultCulture(cultures[0]);
|
||||
|
||||
return app.UseMiddleware<RequestLocalizationMiddleware>(Options.Create(options));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the culture information for a request via the value of a cookie.
|
||||
/// </summary>
|
||||
public class CookieRequestCultureProvider : RequestCultureProvider
|
||||
{
|
||||
private static readonly char[] _cookieSeparator = new[] { '|' };
|
||||
private static readonly string _culturePrefix = "c=";
|
||||
private static readonly string _uiCulturePrefix = "uic=";
|
||||
|
||||
/// <summary>
|
||||
/// Represent the default cookie name used to track the user's preferred culture information, which is ".AspNetCore.Culture".
|
||||
/// </summary>
|
||||
public static readonly string DefaultCookieName = ".AspNetCore.Culture";
|
||||
|
||||
/// <summary>
|
||||
/// The name of the cookie that contains the user's preferred culture information.
|
||||
/// Defaults to <see cref="DefaultCookieName"/>.
|
||||
/// </summary>
|
||||
public string CookieName { get; set; } = DefaultCookieName;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
|
||||
{
|
||||
if (httpContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpContext));
|
||||
}
|
||||
|
||||
var cookie = httpContext.Request.Cookies[CookieName];
|
||||
|
||||
if (string.IsNullOrEmpty(cookie))
|
||||
{
|
||||
return NullProviderCultureResult;
|
||||
}
|
||||
|
||||
var providerResultCulture = ParseCookieValue(cookie);
|
||||
|
||||
return Task.FromResult(providerResultCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a string representation of a <see cref="RequestCulture"/> for placement in a cookie.
|
||||
/// </summary>
|
||||
/// <param name="requestCulture">The <see cref="RequestCulture"/>.</param>
|
||||
/// <returns>The cookie value.</returns>
|
||||
public static string MakeCookieValue(RequestCulture requestCulture)
|
||||
{
|
||||
if (requestCulture == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(requestCulture));
|
||||
}
|
||||
|
||||
var seperator = _cookieSeparator[0].ToString();
|
||||
|
||||
return string.Join(seperator,
|
||||
$"{_culturePrefix}{requestCulture.Culture.Name}",
|
||||
$"{_uiCulturePrefix}{requestCulture.UICulture.Name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a <see cref="RequestCulture"/> from the specified cookie value.
|
||||
/// Returns <c>null</c> if parsing fails.
|
||||
/// </summary>
|
||||
/// <param name="value">The cookie value to parse.</param>
|
||||
/// <returns>The <see cref="RequestCulture"/> or <c>null</c> if parsing fails.</returns>
|
||||
public static ProviderCultureResult ParseCookieValue(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var parts = value.Split(_cookieSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var potentialCultureName = parts[0];
|
||||
var potentialUICultureName = parts[1];
|
||||
|
||||
if (!potentialCultureName.StartsWith(_culturePrefix) || !potentialUICultureName.StartsWith(_uiCulturePrefix))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var cultureName = potentialCultureName.Substring(_culturePrefix.Length);
|
||||
var uiCultureName = potentialUICultureName.Substring(_uiCulturePrefix.Length);
|
||||
|
||||
if (cultureName == null && uiCultureName == null)
|
||||
{
|
||||
// No values specified for either so no match
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cultureName != null && uiCultureName == null)
|
||||
{
|
||||
// Value for culture but not for UI culture so default to culture value for both
|
||||
uiCultureName = cultureName;
|
||||
}
|
||||
|
||||
if (cultureName == null && uiCultureName != null)
|
||||
{
|
||||
// Value for UI culture but not for culture so default to UI culture value for both
|
||||
cultureName = uiCultureName;
|
||||
}
|
||||
|
||||
return new ProviderCultureResult(cultureName, uiCultureName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the culture information for a request via the configured delegate.
|
||||
/// </summary>
|
||||
public class CustomRequestCultureProvider : RequestCultureProvider
|
||||
{
|
||||
private readonly Func<HttpContext, Task<ProviderCultureResult>> _provider;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="CustomRequestCultureProvider"/> using the specified delegate.
|
||||
/// </summary>
|
||||
/// <param name="provider">The provider delegate.</param>
|
||||
public CustomRequestCultureProvider(Func<HttpContext, Task<ProviderCultureResult>> provider)
|
||||
{
|
||||
if (provider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(provider));
|
||||
}
|
||||
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
|
||||
{
|
||||
if (httpContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpContext));
|
||||
}
|
||||
|
||||
return _provider(httpContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the feature that provides the current request's culture information.
|
||||
/// </summary>
|
||||
public interface IRequestCultureFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="Localization.RequestCulture"/> of the request.
|
||||
/// </summary>
|
||||
RequestCulture RequestCulture { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IRequestCultureProvider"/> that determined the request's culture information.
|
||||
/// If the value is <c>null</c> then no provider was used and the request's culture was set to the value of
|
||||
/// <see cref="Builder.RequestLocalizationOptions.DefaultRequestCulture"/>.
|
||||
/// </summary>
|
||||
IRequestCultureProvider Provider { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a provider for determining the culture information of an <see cref="HttpRequest"/>.
|
||||
/// </summary>
|
||||
public interface IRequestCultureProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the provider to determine the culture of the given request.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The <see cref="HttpContext"/> for the request.</param>
|
||||
/// <returns>
|
||||
/// The determined <see cref="ProviderCultureResult"/>.
|
||||
/// Returns <c>null</c> if the provider couldn't determine a <see cref="ProviderCultureResult"/>.
|
||||
/// </returns>
|
||||
Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization.Internal
|
||||
{
|
||||
internal static class RequestCultureProviderLoggerExtensions
|
||||
{
|
||||
private static readonly Action<ILogger, string, IList<StringSegment>, Exception> _unsupportedCulture;
|
||||
private static readonly Action<ILogger, string, IList<StringSegment>, Exception> _unsupportedUICulture;
|
||||
|
||||
static RequestCultureProviderLoggerExtensions()
|
||||
{
|
||||
_unsupportedCulture = LoggerMessage.Define<string, IList<StringSegment>>(
|
||||
LogLevel.Warning,
|
||||
1,
|
||||
"{requestCultureProvider} returned the following unsupported cultures '{cultures}'.");
|
||||
_unsupportedUICulture = LoggerMessage.Define<string, IList<StringSegment>>(
|
||||
LogLevel.Warning,
|
||||
2,
|
||||
"{requestCultureProvider} returned the following unsupported UI Cultures '{uiCultures}'.");
|
||||
}
|
||||
|
||||
public static void UnsupportedCultures(this ILogger logger, string requestCultureProvider, IList<StringSegment> cultures)
|
||||
{
|
||||
_unsupportedCulture(logger, requestCultureProvider, cultures, null);
|
||||
}
|
||||
|
||||
public static void UnsupportedUICultures(this ILogger logger, string requestCultureProvider, IList<StringSegment> uiCultures)
|
||||
{
|
||||
_unsupportedUICulture(logger, requestCultureProvider, uiCultures, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Product>Microsoft ASP.NET Core</Product>
|
||||
<Description>ASP.NET Core middleware for automatically applying culture information to HTTP requests. Culture information can be specified in the HTTP header, query string, cookie, or custom source.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;localization</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Http.Extensions" />
|
||||
<Reference Include="Microsoft.Extensions.Localization.Abstractions" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
<Reference Include="Microsoft.Extensions.Options" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// <auto-generated />
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
internal static class Resources
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNetCore.Localization.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Please provide at least one culture.
|
||||
/// </summary>
|
||||
internal static string Exception_CulturesShouldNotBeEmpty
|
||||
{
|
||||
get { return GetString("Exception_CulturesShouldNotBeEmpty"); }
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
||||
System.Diagnostics.Debug.Assert(value != null);
|
||||
|
||||
if (formatterNames != null)
|
||||
{
|
||||
for (var i = 0; i < formatterNames.Length; i++)
|
||||
{
|
||||
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Collections.Generic;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Details about the cultures obtained from <see cref="IRequestCultureProvider"/>.
|
||||
/// </summary>
|
||||
public class ProviderCultureResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ProviderCultureResult"/> object that has its <see cref="Cultures"/> and
|
||||
/// <see cref="UICultures"/> properties set to the same culture value.
|
||||
/// </summary>
|
||||
/// <param name="culture">The name of the culture to be used for formatting, text, i.e. language.</param>
|
||||
public ProviderCultureResult(StringSegment culture)
|
||||
: this(new List<StringSegment> { culture }, new List<StringSegment> { culture })
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ProviderCultureResult"/> object has its <see cref="Cultures"/> and
|
||||
/// <see cref="UICultures"/> properties set to the respective culture values provided.
|
||||
/// </summary>
|
||||
/// <param name="culture">The name of the culture to be used for formatting.</param>
|
||||
/// <param name="uiCulture"> The name of the ui culture to be used for text, i.e. language.</param>
|
||||
public ProviderCultureResult(StringSegment culture, StringSegment uiCulture)
|
||||
: this(new List<StringSegment> { culture }, new List<StringSegment> { uiCulture })
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ProviderCultureResult"/> object that has its <see cref="Cultures"/> and
|
||||
/// <see cref="UICultures"/> properties set to the same culture value.
|
||||
/// </summary>
|
||||
/// <param name="cultures">The list of cultures to be used for formatting, text, i.e. language.</param>
|
||||
public ProviderCultureResult(IList<StringSegment> cultures)
|
||||
: this(cultures, cultures)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ProviderCultureResult"/> object has its <see cref="Cultures"/> and
|
||||
/// <see cref="UICultures"/> properties set to the respective culture values provided.
|
||||
/// </summary>
|
||||
/// <param name="cultures">The list of cultures to be used for formatting.</param>
|
||||
/// <param name="uiCultures">The list of ui cultures to be used for text, i.e. language.</param>
|
||||
public ProviderCultureResult(IList<StringSegment> cultures, IList<StringSegment> uiCultures)
|
||||
{
|
||||
Cultures = cultures;
|
||||
UICultures = uiCultures;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of cultures to be used for formatting.
|
||||
/// </summary>
|
||||
public IList<StringSegment> Cultures { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of ui cultures to be used for text, i.e. language;
|
||||
/// </summary>
|
||||
public IList<StringSegment> UICultures { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the culture information for a request via values in the query string.
|
||||
/// </summary>
|
||||
public class QueryStringRequestCultureProvider : RequestCultureProvider
|
||||
{
|
||||
/// <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 override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
|
||||
{
|
||||
if (httpContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpContext));
|
||||
}
|
||||
|
||||
var request = httpContext.Request;
|
||||
if (!request.QueryString.HasValue)
|
||||
{
|
||||
return NullProviderCultureResult;
|
||||
}
|
||||
|
||||
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 NullProviderCultureResult;
|
||||
}
|
||||
|
||||
if (queryCulture != null && queryUICulture == null)
|
||||
{
|
||||
// Value for culture but not for UI culture so default to culture value for both
|
||||
queryUICulture = queryCulture;
|
||||
}
|
||||
|
||||
if (queryCulture == null && queryUICulture != null)
|
||||
{
|
||||
// Value for UI culture but not for culture so default to UI culture value for both
|
||||
queryCulture = queryUICulture;
|
||||
}
|
||||
|
||||
var providerResultCulture = new ProviderCultureResult(queryCulture, queryUICulture);
|
||||
|
||||
return Task.FromResult(providerResultCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// 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.Globalization;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Details about the culture for an <see cref="Http.HttpRequest"/>.
|
||||
/// </summary>
|
||||
public class RequestCulture
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestCulture"/> object has its <see cref="Culture"/> and <see cref="UICulture"/>
|
||||
/// 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)
|
||||
: this(culture, culture)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestCulture"/> object has its <see cref="Culture"/> and <see cref="UICulture"/>
|
||||
/// properties set to the same <see cref="CultureInfo"/> value.
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture for the request.</param>
|
||||
public RequestCulture(string culture)
|
||||
: this(culture, culture)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestCulture"/> object has its <see cref="Culture"/> and <see cref="UICulture"/>
|
||||
/// properties set to the respective <see cref="CultureInfo"/> values provided.
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture for the request to be used for formatting.</param>
|
||||
/// <param name="uiCulture">The culture for the request to be used for text, i.e. language.</param>
|
||||
public RequestCulture(string culture, string uiCulture)
|
||||
: this (new CultureInfo(culture), new CultureInfo(uiCulture))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestCulture"/> object has its <see cref="Culture"/> and <see cref="UICulture"/>
|
||||
/// properties set to the respective <see cref="CultureInfo"/> values provided.
|
||||
/// </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)
|
||||
{
|
||||
if (culture == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(culture));
|
||||
}
|
||||
|
||||
if (uiCulture == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uiCulture));
|
||||
}
|
||||
|
||||
Culture = culture;
|
||||
UICulture = uiCulture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CultureInfo"/> for the request to be used for formatting.
|
||||
/// </summary>
|
||||
public CultureInfo Culture { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CultureInfo"/> for the request to be used for text, i.e. language;
|
||||
/// </summary>
|
||||
public CultureInfo UICulture { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the current request's culture information.
|
||||
/// </summary>
|
||||
public class RequestCultureFeature : IRequestCultureFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestCultureFeature"/> with the specified <see cref="Localization.RequestCulture"/>.
|
||||
/// </summary>
|
||||
/// <param name="requestCulture">The <see cref="Localization.RequestCulture"/>.</param>
|
||||
/// <param name="provider">The <see cref="IRequestCultureProvider"/>.</param>
|
||||
public RequestCultureFeature(RequestCulture requestCulture, IRequestCultureProvider provider)
|
||||
{
|
||||
if (requestCulture == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(requestCulture));
|
||||
}
|
||||
|
||||
RequestCulture = requestCulture;
|
||||
Provider = provider;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public RequestCulture RequestCulture { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestCultureProvider Provider { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// An abstract base class provider for determining the culture information of an <see cref="HttpRequest"/>.
|
||||
/// </summary>
|
||||
public abstract class RequestCultureProvider : IRequestCultureProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Result that indicates that this instance of <see cref="RequestCultureProvider" /> could not determine the
|
||||
/// request culture.
|
||||
/// </summary>
|
||||
protected static readonly Task<ProviderCultureResult> NullProviderCultureResult = Task.FromResult(default(ProviderCultureResult));
|
||||
|
||||
/// <summary>
|
||||
/// The current options for the <see cref="RequestLocalizationMiddleware"/>.
|
||||
/// </summary>
|
||||
public RequestLocalizationOptions Options { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
// 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;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables automatic setting of the culture for <see cref="HttpRequest"/>s based on information
|
||||
/// sent by the client in headers and logic provided by the application.
|
||||
/// </summary>
|
||||
public class RequestLocalizationMiddleware
|
||||
{
|
||||
private static readonly int MaxCultureFallbackDepth = 5;
|
||||
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly RequestLocalizationOptions _options;
|
||||
private ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestLocalizationMiddleware"/>.
|
||||
/// </summary>
|
||||
/// <param name="next">The <see cref="RequestDelegate"/> representing the next middleware in the pipeline.</param>
|
||||
/// <param name="options">The <see cref="RequestLocalizationOptions"/> representing the options for the
|
||||
/// <see cref="RequestLocalizationMiddleware"/>.</param>
|
||||
public RequestLocalizationMiddleware(RequestDelegate next, IOptions<RequestLocalizationOptions> options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
_next = next ?? throw new ArgumentNullException(nameof(next));
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the logic of the middleware.
|
||||
/// </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)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var requestCulture = _options.DefaultRequestCulture;
|
||||
|
||||
IRequestCultureProvider winningProvider = null;
|
||||
|
||||
if (_options.RequestCultureProviders != null)
|
||||
{
|
||||
foreach (var provider in _options.RequestCultureProviders)
|
||||
{
|
||||
var providerResultCulture = await provider.DetermineProviderCultureResult(context);
|
||||
if (providerResultCulture == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var cultures = providerResultCulture.Cultures;
|
||||
var uiCultures = providerResultCulture.UICultures;
|
||||
|
||||
CultureInfo cultureInfo = null;
|
||||
CultureInfo uiCultureInfo = null;
|
||||
if (_options.SupportedCultures != null)
|
||||
{
|
||||
cultureInfo = GetCultureInfo(
|
||||
cultures,
|
||||
_options.SupportedCultures,
|
||||
_options.FallBackToParentCultures);
|
||||
|
||||
if (cultureInfo == null)
|
||||
{
|
||||
EnsureLogger(context);
|
||||
_logger?.UnsupportedCultures(provider.GetType().Name, cultures);
|
||||
}
|
||||
}
|
||||
|
||||
if (_options.SupportedUICultures != null)
|
||||
{
|
||||
uiCultureInfo = GetCultureInfo(
|
||||
uiCultures,
|
||||
_options.SupportedUICultures,
|
||||
_options.FallBackToParentUICultures);
|
||||
|
||||
if (uiCultureInfo == null)
|
||||
{
|
||||
EnsureLogger(context);
|
||||
_logger?.UnsupportedUICultures(provider.GetType().Name, uiCultures);
|
||||
}
|
||||
}
|
||||
|
||||
if (cultureInfo == null && uiCultureInfo == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cultureInfo == null && uiCultureInfo != null)
|
||||
{
|
||||
cultureInfo = _options.DefaultRequestCulture.Culture;
|
||||
}
|
||||
|
||||
if (cultureInfo != null && uiCultureInfo == null)
|
||||
{
|
||||
uiCultureInfo = _options.DefaultRequestCulture.UICulture;
|
||||
}
|
||||
|
||||
var result = new RequestCulture(cultureInfo, uiCultureInfo);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
requestCulture = result;
|
||||
winningProvider = provider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.Features.Set<IRequestCultureFeature>(new RequestCultureFeature(requestCulture, winningProvider));
|
||||
|
||||
SetCurrentThreadCulture(requestCulture);
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
|
||||
private void EnsureLogger(HttpContext context)
|
||||
{
|
||||
_logger = _logger ?? context.RequestServices.GetService<ILogger<RequestLocalizationMiddleware>>();
|
||||
}
|
||||
|
||||
private static void SetCurrentThreadCulture(RequestCulture requestCulture)
|
||||
{
|
||||
CultureInfo.CurrentCulture = requestCulture.Culture;
|
||||
CultureInfo.CurrentUICulture = requestCulture.UICulture;
|
||||
}
|
||||
|
||||
private static CultureInfo GetCultureInfo(
|
||||
IList<StringSegment> cultureNames,
|
||||
IList<CultureInfo> supportedCultures,
|
||||
bool fallbackToParentCultures)
|
||||
{
|
||||
foreach (var cultureName in cultureNames)
|
||||
{
|
||||
// Allow empty string values as they map to InvariantCulture, whereas null culture values will throw in
|
||||
// the CultureInfo ctor
|
||||
if (cultureName != null)
|
||||
{
|
||||
var cultureInfo = GetCultureInfo(cultureName, supportedCultures, fallbackToParentCultures, currentDepth: 0);
|
||||
if (cultureInfo != null)
|
||||
{
|
||||
return cultureInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CultureInfo GetCultureInfo(StringSegment name, IList<CultureInfo> supportedCultures)
|
||||
{
|
||||
// Allow only known culture names as this API is called with input from users (HTTP requests) and
|
||||
// creating CultureInfo objects is expensive and we don't want it to throw either.
|
||||
if (name == null || supportedCultures == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var culture = supportedCultures.FirstOrDefault(
|
||||
supportedCulture => StringSegment.Equals(supportedCulture.Name, name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (culture == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return CultureInfo.ReadOnly(culture);
|
||||
}
|
||||
|
||||
private static CultureInfo GetCultureInfo(
|
||||
StringSegment cultureName,
|
||||
IList<CultureInfo> supportedCultures,
|
||||
bool fallbackToParentCultures,
|
||||
int currentDepth)
|
||||
{
|
||||
var culture = GetCultureInfo(cultureName, supportedCultures);
|
||||
|
||||
if (culture == null && fallbackToParentCultures && currentDepth < MaxCultureFallbackDepth)
|
||||
{
|
||||
var lastIndexOfHyphen = cultureName.LastIndexOf('-');
|
||||
|
||||
if (lastIndexOfHyphen > 0)
|
||||
{
|
||||
// Trim the trailing section from the culture name, e.g. "fr-FR" becomes "fr"
|
||||
var parentCultureName = cultureName.Subsegment(0, lastIndexOfHyphen);
|
||||
|
||||
culture = GetCultureInfo(parentCultureName, supportedCultures, fallbackToParentCultures, currentDepth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return culture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
// 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;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies options for the <see cref="RequestLocalizationMiddleware"/>.
|
||||
/// </summary>
|
||||
public class RequestLocalizationOptions
|
||||
{
|
||||
private RequestCulture _defaultRequestCulture =
|
||||
new RequestCulture(CultureInfo.CurrentCulture, CultureInfo.CurrentUICulture);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RequestLocalizationOptions"/> with default values.
|
||||
/// </summary>
|
||||
public RequestLocalizationOptions()
|
||||
{
|
||||
RequestCultureProviders = new List<IRequestCultureProvider>
|
||||
{
|
||||
new QueryStringRequestCultureProvider { Options = this },
|
||||
new CookieRequestCultureProvider { Options = this },
|
||||
new AcceptLanguageHeaderRequestCultureProvider { Options = this }
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default culture to use for requests when a supported culture could not be determined by
|
||||
/// one of the configured <see cref="IRequestCultureProvider"/>s.
|
||||
/// Defaults to <see cref="CultureInfo.CurrentCulture"/> and <see cref="CultureInfo.CurrentUICulture"/>.
|
||||
/// </summary>
|
||||
public RequestCulture DefaultRequestCulture
|
||||
{
|
||||
get
|
||||
{
|
||||
return _defaultRequestCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
_defaultRequestCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to set a request culture to an parent culture in the case the
|
||||
/// culture determined by the configured <see cref="IRequestCultureProvider"/>s is not in the
|
||||
/// <see cref="SupportedCultures"/> list but a parent culture is.
|
||||
/// Defaults to <c>true</c>;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that the parent culture check is done using only the culture name.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// If this property is <c>true</c> and the application is configured to support the culture "fr", but not the
|
||||
/// culture "fr-FR", and a configured <see cref="IRequestCultureProvider"/> determines a request's culture is
|
||||
/// "fr-FR", then the request's culture will be set to the culture "fr", as it is a parent of "fr-FR".
|
||||
/// </example>
|
||||
public bool FallBackToParentCultures { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to set a request UI culture to a parent culture in the case the
|
||||
/// UI culture determined by the configured <see cref="IRequestCultureProvider"/>s is not in the
|
||||
/// <see cref="SupportedUICultures"/> list but a parent culture is.
|
||||
/// Defaults to <c>true</c>;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that the parent culture check is done using ony the culture name.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// If this property is <c>true</c> and the application is configured to support the UI culture "fr", but not
|
||||
/// the UI culture "fr-FR", and a configured <see cref="IRequestCultureProvider"/> determines a request's UI
|
||||
/// culture is "fr-FR", then the request's UI culture will be set to the culture "fr", as it is a parent of
|
||||
/// "fr-FR".
|
||||
/// </example>
|
||||
public bool FallBackToParentUICultures { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// The cultures supported by the application. The <see cref="RequestLocalizationMiddleware"/> will only set
|
||||
/// the current request culture to an entry in this list.
|
||||
/// Defaults to <see cref="CultureInfo.CurrentCulture"/>.
|
||||
/// </summary>
|
||||
public IList<CultureInfo> SupportedCultures { get; set; } = new List<CultureInfo> { CultureInfo.CurrentCulture };
|
||||
|
||||
/// <summary>
|
||||
/// The UI cultures supported by the application. The <see cref="RequestLocalizationMiddleware"/> will only set
|
||||
/// the current request culture to an entry in this list.
|
||||
/// Defaults to <see cref="CultureInfo.CurrentUICulture"/>.
|
||||
/// </summary>
|
||||
public IList<CultureInfo> SupportedUICultures { get; set; } = new List<CultureInfo> { CultureInfo.CurrentUICulture };
|
||||
|
||||
/// <summary>
|
||||
/// An ordered list of providers used to determine a request's culture information. The first provider 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="QueryStringRequestCultureProvider"/></description></item>
|
||||
/// <item><description><see cref="CookieRequestCultureProvider"/></description></item>
|
||||
/// <item><description><see cref="AcceptLanguageHeaderRequestCultureProvider"/></description></item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public IList<IRequestCultureProvider> RequestCultureProviders { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds the set of the supported cultures by the application.
|
||||
/// </summary>
|
||||
/// <param name="cultures">The cultures to be added.</param>
|
||||
/// <returns>The <see cref="RequestLocalizationOptions"/>.</returns>
|
||||
public RequestLocalizationOptions AddSupportedCultures(params string[] cultures)
|
||||
{
|
||||
var supportedCultures = new List<CultureInfo>();
|
||||
|
||||
foreach (var culture in cultures)
|
||||
{
|
||||
supportedCultures.Add(new CultureInfo(culture));
|
||||
}
|
||||
|
||||
SupportedCultures = supportedCultures;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the set of the supported UI cultures by the application.
|
||||
/// </summary>
|
||||
/// <param name="uiCultures">The UI cultures to be added.</param>
|
||||
/// <returns>The <see cref="RequestLocalizationOptions"/>.</returns>
|
||||
public RequestLocalizationOptions AddSupportedUICultures(params string[] uiCultures)
|
||||
{
|
||||
var supportedUICultures = new List<CultureInfo>();
|
||||
foreach (var culture in uiCultures)
|
||||
{
|
||||
supportedUICultures.Add(new CultureInfo(culture));
|
||||
}
|
||||
|
||||
SupportedUICultures = supportedUICultures;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the default culture which is used by the application when a supported culture could not be determined by
|
||||
/// one of the configured <see cref="IRequestCultureProvider"/>s.
|
||||
/// </summary>
|
||||
/// <param name="defaultCulture">The default culture to be set.</param>
|
||||
/// <returns>The <see cref="RequestLocalizationOptions"/>.</returns>
|
||||
public RequestLocalizationOptions SetDefaultCulture(string defaultCulture)
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture(defaultCulture);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Exception_CulturesShouldNotBeEmpty" xml:space="preserve">
|
||||
<value>Please provide at least one culture.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,893 @@
|
|||
{
|
||||
"AssemblyIdentity": "Microsoft.AspNetCore.Localization, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
||||
"Types": [
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Builder.ApplicationBuilderExtensions",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"Abstract": true,
|
||||
"Static": true,
|
||||
"Sealed": true,
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "UseRequestLocalization",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "app",
|
||||
"Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
|
||||
}
|
||||
],
|
||||
"ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
|
||||
"Static": true,
|
||||
"Extension": true,
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "UseRequestLocalization",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "app",
|
||||
"Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
|
||||
},
|
||||
{
|
||||
"Name": "options",
|
||||
"Type": "Microsoft.AspNetCore.Builder.RequestLocalizationOptions"
|
||||
}
|
||||
],
|
||||
"ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
|
||||
"Static": true,
|
||||
"Extension": true,
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "UseRequestLocalization",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "app",
|
||||
"Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
|
||||
},
|
||||
{
|
||||
"Name": "optionsAction",
|
||||
"Type": "System.Action<Microsoft.AspNetCore.Builder.RequestLocalizationOptions>"
|
||||
}
|
||||
],
|
||||
"ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
|
||||
"Static": true,
|
||||
"Extension": true,
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "UseRequestLocalization",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "app",
|
||||
"Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
|
||||
},
|
||||
{
|
||||
"Name": "cultures",
|
||||
"Type": "System.String[]",
|
||||
"IsParams": true
|
||||
}
|
||||
],
|
||||
"ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
|
||||
"Static": true,
|
||||
"Extension": true,
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Builder.RequestLocalizationOptions",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_DefaultRequestCulture",
|
||||
"Parameters": [],
|
||||
"ReturnType": "Microsoft.AspNetCore.Localization.RequestCulture",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_DefaultRequestCulture",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "Microsoft.AspNetCore.Localization.RequestCulture"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_FallBackToParentCultures",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Boolean",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_FallBackToParentCultures",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.Boolean"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_FallBackToParentUICultures",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Boolean",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_FallBackToParentUICultures",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.Boolean"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_SupportedCultures",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Collections.Generic.IList<System.Globalization.CultureInfo>",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_SupportedCultures",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.Collections.Generic.IList<System.Globalization.CultureInfo>"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_SupportedUICultures",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Collections.Generic.IList<System.Globalization.CultureInfo>",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_SupportedUICultures",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.Collections.Generic.IList<System.Globalization.CultureInfo>"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_RequestCultureProviders",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Collections.Generic.IList<Microsoft.AspNetCore.Localization.IRequestCultureProvider>",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_RequestCultureProviders",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.Collections.Generic.IList<Microsoft.AspNetCore.Localization.IRequestCultureProvider>"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "AddSupportedCultures",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "cultures",
|
||||
"Type": "System.String[]",
|
||||
"IsParams": true
|
||||
}
|
||||
],
|
||||
"ReturnType": "Microsoft.AspNetCore.Builder.RequestLocalizationOptions",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "AddSupportedUICultures",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "uiCultures",
|
||||
"Type": "System.String[]",
|
||||
"IsParams": true
|
||||
}
|
||||
],
|
||||
"ReturnType": "Microsoft.AspNetCore.Builder.RequestLocalizationOptions",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "SetDefaultCulture",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "defaultCulture",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"ReturnType": "Microsoft.AspNetCore.Builder.RequestLocalizationOptions",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.AcceptLanguageHeaderRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"BaseType": "Microsoft.AspNetCore.Localization.RequestCultureProvider",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "DetermineProviderCultureResult",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "httpContext",
|
||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>",
|
||||
"Virtual": true,
|
||||
"Override": true,
|
||||
"ImplementedInterface": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_MaximumAcceptLanguageHeaderValuesToTry",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Int32",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_MaximumAcceptLanguageHeaderValuesToTry",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.Int32"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.CookieRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"BaseType": "Microsoft.AspNetCore.Localization.RequestCultureProvider",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "DetermineProviderCultureResult",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "httpContext",
|
||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>",
|
||||
"Virtual": true,
|
||||
"Override": true,
|
||||
"ImplementedInterface": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_CookieName",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.String",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_CookieName",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "MakeCookieValue",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "requestCulture",
|
||||
"Type": "Microsoft.AspNetCore.Localization.RequestCulture"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.String",
|
||||
"Static": true,
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "ParseCookieValue",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"ReturnType": "Microsoft.AspNetCore.Localization.ProviderCultureResult",
|
||||
"Static": true,
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Field",
|
||||
"Name": "DefaultCookieName",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.String",
|
||||
"Static": true,
|
||||
"ReadOnly": true,
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.CustomRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"BaseType": "Microsoft.AspNetCore.Localization.RequestCultureProvider",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "DetermineProviderCultureResult",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "httpContext",
|
||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>",
|
||||
"Virtual": true,
|
||||
"Override": true,
|
||||
"ImplementedInterface": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "provider",
|
||||
"Type": "System.Func<Microsoft.AspNetCore.Http.HttpContext, System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>>"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.IRequestCultureFeature",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Interface",
|
||||
"Abstract": true,
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_RequestCulture",
|
||||
"Parameters": [],
|
||||
"ReturnType": "Microsoft.AspNetCore.Localization.RequestCulture",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_Provider",
|
||||
"Parameters": [],
|
||||
"ReturnType": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Interface",
|
||||
"Abstract": true,
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "DetermineProviderCultureResult",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "httpContext",
|
||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.ProviderCultureResult",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_Cultures",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Collections.Generic.IList<Microsoft.Extensions.Primitives.StringSegment>",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_UICultures",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Collections.Generic.IList<Microsoft.Extensions.Primitives.StringSegment>",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "culture",
|
||||
"Type": "Microsoft.Extensions.Primitives.StringSegment"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "culture",
|
||||
"Type": "Microsoft.Extensions.Primitives.StringSegment"
|
||||
},
|
||||
{
|
||||
"Name": "uiCulture",
|
||||
"Type": "Microsoft.Extensions.Primitives.StringSegment"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "cultures",
|
||||
"Type": "System.Collections.Generic.IList<Microsoft.Extensions.Primitives.StringSegment>"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "cultures",
|
||||
"Type": "System.Collections.Generic.IList<Microsoft.Extensions.Primitives.StringSegment>"
|
||||
},
|
||||
{
|
||||
"Name": "uiCultures",
|
||||
"Type": "System.Collections.Generic.IList<Microsoft.Extensions.Primitives.StringSegment>"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.QueryStringRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"BaseType": "Microsoft.AspNetCore.Localization.RequestCultureProvider",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "DetermineProviderCultureResult",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "httpContext",
|
||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>",
|
||||
"Virtual": true,
|
||||
"Override": true,
|
||||
"ImplementedInterface": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_QueryStringKey",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.String",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_QueryStringKey",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_UIQueryStringKey",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.String",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_UIQueryStringKey",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.RequestCulture",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_Culture",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Globalization.CultureInfo",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_UICulture",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Globalization.CultureInfo",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "culture",
|
||||
"Type": "System.Globalization.CultureInfo"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "culture",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "culture",
|
||||
"Type": "System.String"
|
||||
},
|
||||
{
|
||||
"Name": "uiCulture",
|
||||
"Type": "System.String"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "culture",
|
||||
"Type": "System.Globalization.CultureInfo"
|
||||
},
|
||||
{
|
||||
"Name": "uiCulture",
|
||||
"Type": "System.Globalization.CultureInfo"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.RequestCultureFeature",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"ImplementedInterfaces": [
|
||||
"Microsoft.AspNetCore.Localization.IRequestCultureFeature"
|
||||
],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_RequestCulture",
|
||||
"Parameters": [],
|
||||
"ReturnType": "Microsoft.AspNetCore.Localization.RequestCulture",
|
||||
"Sealed": true,
|
||||
"Virtual": true,
|
||||
"ImplementedInterface": "Microsoft.AspNetCore.Localization.IRequestCultureFeature",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_Provider",
|
||||
"Parameters": [],
|
||||
"ReturnType": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"Sealed": true,
|
||||
"Virtual": true,
|
||||
"ImplementedInterface": "Microsoft.AspNetCore.Localization.IRequestCultureFeature",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "requestCulture",
|
||||
"Type": "Microsoft.AspNetCore.Localization.RequestCulture"
|
||||
},
|
||||
{
|
||||
"Name": "provider",
|
||||
"Type": "Microsoft.AspNetCore.Localization.IRequestCultureProvider"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.RequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"Abstract": true,
|
||||
"ImplementedInterfaces": [
|
||||
"Microsoft.AspNetCore.Localization.IRequestCultureProvider"
|
||||
],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "DetermineProviderCultureResult",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "httpContext",
|
||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>",
|
||||
"Virtual": true,
|
||||
"Abstract": true,
|
||||
"ImplementedInterface": "Microsoft.AspNetCore.Localization.IRequestCultureProvider",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "get_Options",
|
||||
"Parameters": [],
|
||||
"ReturnType": "Microsoft.AspNetCore.Builder.RequestLocalizationOptions",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "set_Options",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "value",
|
||||
"Type": "Microsoft.AspNetCore.Builder.RequestLocalizationOptions"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Void",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [],
|
||||
"Visibility": "Protected",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Field",
|
||||
"Name": "NullProviderCultureResult",
|
||||
"Parameters": [],
|
||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.AspNetCore.Localization.ProviderCultureResult>",
|
||||
"Static": true,
|
||||
"ReadOnly": true,
|
||||
"Visibility": "Protected",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware",
|
||||
"Visibility": "Public",
|
||||
"Kind": "Class",
|
||||
"ImplementedInterfaces": [],
|
||||
"Members": [
|
||||
{
|
||||
"Kind": "Method",
|
||||
"Name": "Invoke",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "context",
|
||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
||||
}
|
||||
],
|
||||
"ReturnType": "System.Threading.Tasks.Task",
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
},
|
||||
{
|
||||
"Kind": "Constructor",
|
||||
"Name": ".ctor",
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "next",
|
||||
"Type": "Microsoft.AspNetCore.Http.RequestDelegate"
|
||||
},
|
||||
{
|
||||
"Name": "options",
|
||||
"Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.RequestLocalizationOptions>"
|
||||
}
|
||||
],
|
||||
"Visibility": "Public",
|
||||
"GenericParameter": []
|
||||
}
|
||||
],
|
||||
"GenericParameters": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using LocalizationSample;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization.FunctionalTests
|
||||
{
|
||||
public class LocalizationSampleTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task LocalizationSampleSmokeTest()
|
||||
{
|
||||
// Arrange
|
||||
var webHostBuilder = new WebHostBuilder().UseStartup(typeof(Startup));
|
||||
var testHost = new TestServer(webHostBuilder);
|
||||
var locale = "fr-FR";
|
||||
var client = testHost.CreateClient();
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "My/Resources");
|
||||
var cookieValue = $"c={locale}|uic={locale}";
|
||||
request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}");
|
||||
|
||||
// Act
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Contains("<h1>Bonjour</h1>", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
// 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;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using LocalizationWebsite;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization.FunctionalTests
|
||||
{
|
||||
public class LocalizationTest
|
||||
{
|
||||
[Fact]
|
||||
public Task Localization_CustomCulture()
|
||||
{
|
||||
return RunTest(
|
||||
typeof(StartupCustomCulturePreserved),
|
||||
"en-US",
|
||||
"kr10.00");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Localization_GetAllStrings()
|
||||
{
|
||||
return RunTest(
|
||||
typeof(StartupGetAllStrings),
|
||||
"fr-FR",
|
||||
"1 Bonjour from Customer in resources folder");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Localization_ResourcesInClassLibrary_ReturnLocalizedValue()
|
||||
{
|
||||
return RunTest(
|
||||
typeof(StartupResourcesInClassLibrary),
|
||||
"fr-FR",
|
||||
"Bonjour from ResourcesClassLibraryNoAttribute Bonjour from ResourcesClassLibraryNoAttribute Bonjour from ResourcesClassLibraryWithAttribute Bonjour from ResourcesClassLibraryWithAttribute");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Localization_ResourcesInFolder_ReturnLocalizedValue()
|
||||
{
|
||||
return RunTest(
|
||||
typeof(StartupResourcesInFolder),
|
||||
"fr-FR",
|
||||
"Bonjour from StartupResourcesInFolder Bonjour from Test in resources folder Bonjour from Customer in resources folder Hello");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Localization_ResourcesInFolder_ReturnLocalizedValue_WithCultureFallback()
|
||||
{
|
||||
return RunTest(
|
||||
typeof(StartupResourcesInFolder),
|
||||
"fr-FR-test",
|
||||
"Bonjour from StartupResourcesInFolder Bonjour from Test in resources folder Bonjour from Customer in resources folder Hello");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Localization_ResourcesInFolder_ReturnNonLocalizedValue_CultureHierarchyTooDeep()
|
||||
{
|
||||
return RunTest(
|
||||
typeof(StartupResourcesInFolder),
|
||||
"fr-FR-test-again-too-deep-to-work",
|
||||
"Hello Hello Hello Hello");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Localization_ResourcesAtRootFolder_ReturnLocalizedValue()
|
||||
{
|
||||
return RunTest(
|
||||
typeof(StartupResourcesAtRootFolder),
|
||||
"fr-FR",
|
||||
"Bonjour from StartupResourcesAtRootFolder Bonjour from Test in root folder Bonjour from Customer in Models folder");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task Localization_BuilderAPIs()
|
||||
{
|
||||
return RunTest(
|
||||
typeof(StartupBuilderAPIs),
|
||||
"ar-YE",
|
||||
"Hello");
|
||||
}
|
||||
|
||||
private async Task RunTest(Type startupType, string culture, string expected)
|
||||
{
|
||||
var webHostBuilder = new WebHostBuilder().UseStartup(startupType);
|
||||
var testHost = new TestServer(webHostBuilder);
|
||||
|
||||
var client = testHost.CreateClient();
|
||||
var request = new HttpRequestMessage();
|
||||
var cookieValue = $"c={culture}|uic={culture}";
|
||||
request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}");
|
||||
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expected, await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\sample\LocalizationSample.csproj" />
|
||||
<ProjectReference Include="..\..\testassets\LocalizationWebsite\LocalizationWebsite.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Localization" />
|
||||
<Reference Include="Microsoft.AspNetCore.TestHost" />
|
||||
<Reference Include="Microsoft.Extensions.Logging" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
// 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 System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Extensions.Localization
|
||||
{
|
||||
public class AcceptLanguageHeaderRequestCultureProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetFallbackLanguage_ReturnsFirstNonNullCultureFromSupportedCultureList()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA"),
|
||||
new CultureInfo("en-US")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("ar-SA", requestCulture.Culture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
client.DefaultRequestHeaders.AcceptLanguage.ParseAdd("jp,ar-SA,en-US");
|
||||
var count = client.DefaultRequestHeaders.AcceptLanguage.Count;
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
Assert.Equal(3, count);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetFallbackLanguage_ReturnsFromSupportedCulture_AcceptLanguageListContainsSupportedCultures()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("fr-FR"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA"),
|
||||
new CultureInfo("en-US")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("ar-SA", requestCulture.Culture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
client.DefaultRequestHeaders.AcceptLanguage.ParseAdd("en-GB,ar-SA,en-US");
|
||||
var count = client.DefaultRequestHeaders.AcceptLanguage.Count;
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetFallbackLanguage_ReturnsDefault_AcceptLanguageListDoesnotContainSupportedCultures()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("fr-FR"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA"),
|
||||
new CultureInfo("af-ZA")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("fr-FR", requestCulture.Culture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
client.DefaultRequestHeaders.AcceptLanguage.ParseAdd("en-GB,ar-MA,en-US");
|
||||
var count = client.DefaultRequestHeaders.AcceptLanguage.Count;
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
Assert.Equal(3, count);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OmitDefaultRequestCultureShouldNotThrowNullReferenceException_And_ShouldGetTheRightCulture()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
|
||||
Assert.Equal("ar-YE", requestCulture.Culture.Name);
|
||||
Assert.Equal("ar-YE", requestCulture.UICulture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
client.DefaultRequestHeaders.AcceptLanguage.ParseAdd("en-GB,ar-YE,en-US");
|
||||
var count = client.DefaultRequestHeaders.AcceptLanguage.Count;
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
Assert.Equal(3, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
// 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 System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Extensions.Localization
|
||||
{
|
||||
public class CookieRequestCultureProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetCultureInfoFromPersistentCookie()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
}
|
||||
};
|
||||
var provider = new CookieRequestCultureProvider
|
||||
{
|
||||
CookieName = "Preferences"
|
||||
};
|
||||
options.RequestCultureProviders.Insert(0, provider);
|
||||
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("ar-SA", requestCulture.Culture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var culture = new CultureInfo("ar-SA");
|
||||
var requestCulture = new RequestCulture(culture);
|
||||
var value = CookieRequestCultureProvider.MakeCookieValue(requestCulture);
|
||||
client.DefaultRequestHeaders.Add("Cookie", new CookieHeaderValue("Preferences", value).ToString());
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
Assert.Equal("c=ar-SA|uic=ar-SA", value);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetDefaultCultureInfoIfCultureKeysAreMissingOrInvalid()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
}
|
||||
};
|
||||
var provider = new CookieRequestCultureProvider
|
||||
{
|
||||
CookieName = "Preferences"
|
||||
};
|
||||
options.RequestCultureProviders.Insert(0, provider);
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("en-US", requestCulture.Culture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
|
||||
client.DefaultRequestHeaders.Add("Cookie", new CookieHeaderValue("Preferences", "uic=ar-SA").ToString());
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetDefaultCultureInfoIfCookieDoesNotExist()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
}
|
||||
};
|
||||
var provider = new CookieRequestCultureProvider
|
||||
{
|
||||
CookieName = "Preferences"
|
||||
};
|
||||
options.RequestCultureProviders.Insert(0, provider);
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("en-US", requestCulture.Culture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RequestLocalizationMiddleware_LogsWarningsForUnsupportedCultures()
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<RequestLocalizationMiddleware>,
|
||||
TestSink.EnableWithTypeName<RequestLocalizationMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
}
|
||||
};
|
||||
var provider = new CookieRequestCultureProvider
|
||||
{
|
||||
CookieName = "Preferences"
|
||||
};
|
||||
options.RequestCultureProviders.Insert(0, provider);
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context => Task.CompletedTask);
|
||||
})
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton(typeof(ILoggerFactory), loggerFactory);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var culture = "??";
|
||||
var uiCulture = "ar-YE";
|
||||
client.DefaultRequestHeaders.Add("Cookie", new CookieHeaderValue("Preferences", $"c={culture}|uic={uiCulture}").ToString());
|
||||
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
var expectedMessage = $"{nameof(CookieRequestCultureProvider)} returned the following unsupported cultures '??'.";
|
||||
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal(LogLevel.Warning, write.LogLevel);
|
||||
Assert.Equal(expectedMessage, write.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RequestLocalizationMiddleware_LogsWarningsForUnsupportedUICultures()
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<RequestLocalizationMiddleware>,
|
||||
TestSink.EnableWithTypeName<RequestLocalizationMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
}
|
||||
};
|
||||
var provider = new CookieRequestCultureProvider
|
||||
{
|
||||
CookieName = "Preferences"
|
||||
};
|
||||
options.RequestCultureProviders.Insert(0, provider);
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context => Task.CompletedTask);
|
||||
})
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton(typeof(ILoggerFactory), loggerFactory);
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var culture = "ar-YE";
|
||||
var uiCulture = "??";
|
||||
client.DefaultRequestHeaders.Add("Cookie", new CookieHeaderValue("Preferences", $"c={culture}|uic={uiCulture}").ToString());
|
||||
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
var expectedMessage = $"{nameof(CookieRequestCultureProvider)} returned the following unsupported UI Cultures '??'.";
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal(LogLevel.Warning, write.LogLevel);
|
||||
Assert.Equal(expectedMessage, write.State.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// 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;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Extensions.Localization
|
||||
{
|
||||
public class CustomRequestCultureProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task CustomRequestCultureProviderThatGetsCultureInfoFromUrl()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar")
|
||||
}
|
||||
};
|
||||
options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(context =>
|
||||
{
|
||||
var culture = GetCultureInfoFromUrl(context, options.SupportedCultures);
|
||||
var requestCulture = new ProviderCultureResult(culture);
|
||||
return Task.FromResult(requestCulture);
|
||||
}));
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("ar", requestCulture.Culture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/ar/page");
|
||||
}
|
||||
}
|
||||
|
||||
private string GetCultureInfoFromUrl(HttpContext context, IList<CultureInfo> supportedCultures)
|
||||
{
|
||||
var currentCulture = "en";
|
||||
var segments = context.Request.Path.Value.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (segments.Length > 1 && segments[0].Length == 2)
|
||||
{
|
||||
currentCulture = segments[0];
|
||||
}
|
||||
|
||||
return currentCulture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Localization" />
|
||||
<Reference Include="Microsoft.AspNetCore.TestHost" />
|
||||
<Reference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<Reference Include="Microsoft.Extensions.Logging" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
// 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 System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Extensions.Localization
|
||||
{
|
||||
public class QueryStringRequestCultureProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetCultureInfoFromQueryString()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("ar-SA", requestCulture.Culture.Name);
|
||||
Assert.Equal("ar-YE", requestCulture.UICulture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page?culture=ar-SA&ui-culture=ar-YE");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetDefaultCultureInfoIfCultureKeysAreMissing()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US")
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("en-US", requestCulture.Culture.Name);
|
||||
Assert.Equal("en-US", requestCulture.UICulture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetDefaultCultureInfoIfCultureIsInSupportedCultureList()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("en-US", requestCulture.Culture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page?culture=ar-XY&ui-culture=ar-SA");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetDefaultCultureInfoIfUICultureIsNotInSupportedList()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("en-US", requestCulture.UICulture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page?culture=ar-SA&ui-culture=ar-XY");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSameCultureInfoIfCultureKeyIsMissing()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("ar-SA", requestCulture.Culture.Name);
|
||||
Assert.Equal("ar-SA", requestCulture.UICulture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page?ui-culture=ar-SA");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSameCultureInfoIfUICultureKeyIsMissing()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
}
|
||||
});
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("ar-SA", requestCulture.Culture.Name);
|
||||
Assert.Equal("ar-SA", requestCulture.UICulture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page?culture=ar-SA");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetCultureInfoFromQueryStringWithCustomKeys()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-SA")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("ar-YE")
|
||||
}
|
||||
};
|
||||
var provider = new QueryStringRequestCultureProvider();
|
||||
provider.QueryStringKey = "c";
|
||||
provider.UIQueryStringKey = "uic";
|
||||
options.RequestCultureProviders.Insert(0, provider);
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("ar-SA", requestCulture.Culture.Name);
|
||||
Assert.Equal("ar-YE", requestCulture.UICulture.Name);
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page?c=ar-SA&uic=ar-YE");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTheRightCultureInfoRegardlessOfCultureNameCasing()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("FR")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("FR")
|
||||
}
|
||||
};
|
||||
var provider = new QueryStringRequestCultureProvider();
|
||||
|
||||
provider.QueryStringKey = "c";
|
||||
provider.UIQueryStringKey = "uic";
|
||||
options.RequestCultureProviders.Insert(0, provider);
|
||||
app.UseRequestLocalization(options);
|
||||
app.Run(context =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
Assert.Equal("fr", requestCulture.Culture.ToString());
|
||||
Assert.Equal("fr", requestCulture.UICulture.ToString());
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
using (var server = new TestServer(builder))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("/page?c=FR&uic=FR");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
// 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.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Localization
|
||||
{
|
||||
public class RequestLocalizationOptionsTest : IDisposable
|
||||
{
|
||||
private readonly CultureInfo _initialCulture;
|
||||
private readonly CultureInfo _initialUICulture;
|
||||
|
||||
public RequestLocalizationOptionsTest()
|
||||
{
|
||||
_initialCulture = CultureInfo.CurrentCulture;
|
||||
_initialUICulture = CultureInfo.CurrentUICulture;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultRequestCulture_DefaultsToCurrentCulture()
|
||||
{
|
||||
// Arrange/Act
|
||||
var options = new RequestLocalizationOptions();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(options.DefaultRequestCulture);
|
||||
Assert.Equal(CultureInfo.CurrentCulture, options.DefaultRequestCulture.Culture);
|
||||
Assert.Equal(CultureInfo.CurrentUICulture, options.DefaultRequestCulture.UICulture);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultRequestCulture_DefaultsToCurrentCultureWhenExplicitlySet()
|
||||
{
|
||||
// Arrange
|
||||
var explicitCulture = new CultureInfo("fr-FR");
|
||||
CultureInfo.CurrentCulture = explicitCulture;
|
||||
CultureInfo.CurrentUICulture = explicitCulture;
|
||||
|
||||
// Act
|
||||
var options = new RequestLocalizationOptions();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(explicitCulture, options.DefaultRequestCulture.Culture);
|
||||
Assert.Equal(explicitCulture, options.DefaultRequestCulture.UICulture);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultRequestCulture_ThrowsWhenTryingToSetToNull()
|
||||
{
|
||||
// Arrange
|
||||
var options = new RequestLocalizationOptions();
|
||||
|
||||
// Act/Assert
|
||||
Assert.Throws<ArgumentNullException>(() => options.DefaultRequestCulture = null);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SupportedCultures_DefaultsToCurrentCulture()
|
||||
{
|
||||
// Arrange/Act
|
||||
var options = new RequestLocalizationOptions();
|
||||
|
||||
// Assert
|
||||
Assert.Collection(options.SupportedCultures, item => Assert.Equal(CultureInfo.CurrentCulture, item));
|
||||
Assert.Collection(options.SupportedUICultures, item => Assert.Equal(CultureInfo.CurrentUICulture, item));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SupportedCultures_DefaultsToCurrentCultureWhenExplicitlySet()
|
||||
{
|
||||
// Arrange
|
||||
var explicitCulture = new CultureInfo("fr-FR");
|
||||
CultureInfo.CurrentCulture = explicitCulture;
|
||||
CultureInfo.CurrentUICulture = explicitCulture;
|
||||
|
||||
// Act
|
||||
var options = new RequestLocalizationOptions();
|
||||
|
||||
// Assert
|
||||
Assert.Collection(options.SupportedCultures, item => Assert.Equal(explicitCulture, item));
|
||||
Assert.Collection(options.SupportedUICultures, item => Assert.Equal(explicitCulture, item));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuilderAPIs_AddSupportedCultures()
|
||||
{
|
||||
// Arrange
|
||||
var supportedCultures = new[] { "en-US", "ar-YE" };
|
||||
|
||||
// Act
|
||||
var options = new RequestLocalizationOptions()
|
||||
.AddSupportedCultures(supportedCultures);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(supportedCultures, options.SupportedCultures.Select(c => c.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuilderAPIs_AddSupportedUICultures()
|
||||
{
|
||||
// Arrange
|
||||
var supportedUICultures = new[] { "en-US", "ar-YE" };
|
||||
|
||||
// Act
|
||||
var options = new RequestLocalizationOptions()
|
||||
.AddSupportedUICultures(supportedUICultures);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(supportedUICultures, options.SupportedUICultures.Select(c => c.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuilderAPIs_SetDefaultCulture()
|
||||
{
|
||||
// Arrange
|
||||
var defaultCulture = "ar-YE";
|
||||
|
||||
// Act
|
||||
var options = new RequestLocalizationOptions()
|
||||
.SetDefaultCulture(defaultCulture);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(defaultCulture, options.DefaultRequestCulture.Culture.Name);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
CultureInfo.CurrentCulture = _initialCulture;
|
||||
CultureInfo.CurrentUICulture = _initialUICulture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ResourcesClassLibraryNoAttribute\ResourcesClassLibraryNoAttribute.csproj" />
|
||||
<ProjectReference Include="..\ResourcesClassLibraryWithAttribute\ResourcesClassLibraryWithAttribute.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Localization" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||
<Reference Include="Microsoft.AspNetCore.Testing" />
|
||||
<Reference Include="Microsoft.Extensions.Configuration.CommandLine" />
|
||||
<Reference Include="Microsoft.Extensions.Localization" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// 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.
|
||||
|
||||
namespace LocalizationWebsite.Models
|
||||
{
|
||||
public class Customer
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour from Customer in Models folder</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// 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.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LocalizationWebsite
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddCommandLine(args)
|
||||
.Build();
|
||||
|
||||
var host = new WebHostBuilder()
|
||||
.ConfigureLogging((_, factory) =>
|
||||
{
|
||||
factory.AddConsole();
|
||||
factory.AddFilter("Console", level => level >= LogLevel.Warning);
|
||||
})
|
||||
.UseKestrel()
|
||||
.UseConfiguration(config)
|
||||
.UseStartup("LocalizationWebsite")
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour from Customer in resources folder</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>We shouldn't get the english hello!</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour from StartupResourcesInFolder</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour from Test in resources folder</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// 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 LocalizationWebsite.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LocalizationWebsite
|
||||
{
|
||||
public class StartupBuilderAPIs
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
IApplicationBuilder app,
|
||||
ILoggerFactory loggerFactory,
|
||||
IStringLocalizer<Customer> customerStringLocalizer)
|
||||
{
|
||||
var supportedCultures = new[] { "en-US", "fr-FR" };
|
||||
app.UseRequestLocalization(options =>
|
||||
options
|
||||
.AddSupportedCultures(supportedCultures)
|
||||
.AddSupportedUICultures(supportedCultures)
|
||||
.SetDefaultCulture("ar-YE")
|
||||
);
|
||||
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
|
||||
var requestCulture = requestCultureFeature.RequestCulture;
|
||||
await context.Response.WriteAsync(customerStringLocalizer["Hello"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// 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;
|
||||
|
||||
namespace LocalizationWebsite
|
||||
{
|
||||
public class StartupCustomCulturePreserved
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLocalization();
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
IApplicationBuilder app)
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("en-US") { NumberFormat= { CurrencySymbol = "kr" } }
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("en-US") { NumberFormat= { CurrencySymbol = "kr" } }
|
||||
}
|
||||
});
|
||||
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
await context.Response.WriteAsync(10.ToString("C"));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// 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 System.Linq;
|
||||
using LocalizationWebsite.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LocalizationWebsite
|
||||
{
|
||||
public class StartupGetAllStrings
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
IApplicationBuilder app,
|
||||
ILoggerFactory loggerFactory,
|
||||
IStringLocalizer<Customer> customerStringLocalizer)
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("fr-FR")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("fr-FR")
|
||||
}
|
||||
});
|
||||
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
var strings = customerStringLocalizer.GetAllStrings();
|
||||
|
||||
await context.Response.WriteAsync(strings.Count().ToString());
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(string.Join(" ", strings));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// 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 System.Reflection;
|
||||
using LocalizationWebsite.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LocalizationWebsite
|
||||
{
|
||||
public class StartupResourcesAtRootFolder
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLocalization();
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
IApplicationBuilder app,
|
||||
ILoggerFactory loggerFactory,
|
||||
IStringLocalizerFactory stringLocalizerFactory,
|
||||
IStringLocalizer<StartupResourcesAtRootFolder> startupStringLocalizer,
|
||||
IStringLocalizer<Customer> customerStringLocalizer)
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("fr-FR")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("fr-FR")
|
||||
}
|
||||
});
|
||||
|
||||
var location = typeof(LocalizationWebsite.StartupResourcesAtRootFolder).GetTypeInfo().Assembly.GetName().Name;
|
||||
var stringLocalizer = stringLocalizerFactory.Create("Test", location: location);
|
||||
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
await context.Response.WriteAsync(startupStringLocalizer["Hello"]);
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(stringLocalizer["Hello"]);
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(customerStringLocalizer["Hello"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour from StartupResourcesAtRootFolder</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// 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 System.Reflection;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LocalizationWebsite
|
||||
{
|
||||
public class StartupResourcesInClassLibrary
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
IApplicationBuilder app,
|
||||
ILoggerFactory loggerFactory,
|
||||
IStringLocalizerFactory stringLocalizerFactory)
|
||||
{
|
||||
var supportedCultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("en-US"),
|
||||
new CultureInfo("fr-FR")
|
||||
};
|
||||
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = supportedCultures,
|
||||
SupportedUICultures = supportedCultures
|
||||
});
|
||||
|
||||
var noAttributeStringLocalizer = stringLocalizerFactory.Create(typeof(ResourcesClassLibraryNoAttribute.Model));
|
||||
var withAttributeStringLocalizer = stringLocalizerFactory.Create(typeof(ResourcesClassLibraryWithAttribute.Model));
|
||||
|
||||
var noAttributeAssembly = typeof(ResourcesClassLibraryNoAttribute.Model).GetTypeInfo().Assembly;
|
||||
var noAttributeName = new AssemblyName(noAttributeAssembly.FullName).Name;
|
||||
var noAttributeNameStringLocalizer = stringLocalizerFactory.Create(
|
||||
nameof(ResourcesClassLibraryNoAttribute.Model),
|
||||
noAttributeName);
|
||||
|
||||
var withAttributeAssembly = typeof(ResourcesClassLibraryWithAttribute.Model).GetTypeInfo().Assembly;
|
||||
var withAttributeName = new AssemblyName(withAttributeAssembly.FullName).Name;
|
||||
var withAttributeNameStringLocalizer = stringLocalizerFactory.Create(
|
||||
nameof(ResourcesClassLibraryWithAttribute.Model),
|
||||
withAttributeName);
|
||||
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
await context.Response.WriteAsync(noAttributeNameStringLocalizer["Hello"]);
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(noAttributeStringLocalizer["Hello"]);
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(withAttributeNameStringLocalizer["Hello"]);
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(withAttributeStringLocalizer["Hello"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// 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 System.Reflection;
|
||||
using LocalizationWebsite.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LocalizationWebsite
|
||||
{
|
||||
public class StartupResourcesInFolder
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
IApplicationBuilder app,
|
||||
ILoggerFactory loggerFactory,
|
||||
IStringLocalizerFactory stringLocalizerFactory,
|
||||
IStringLocalizer<StartupResourcesInFolder> startupStringLocalizer,
|
||||
IStringLocalizer<Customer> custromerStringLocalizer,
|
||||
// This localizer is used in tests to prevent a regression of https://github.com/aspnet/Localization/issues/293
|
||||
// Namely that english was always being returned if it existed.
|
||||
IStringLocalizer<StartupCustomCulturePreserved> customCultureLocalizer)
|
||||
{
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("fr-FR")
|
||||
},
|
||||
SupportedUICultures = new List<CultureInfo>()
|
||||
{
|
||||
new CultureInfo("fr-FR")
|
||||
}
|
||||
});
|
||||
|
||||
var assemblyName = typeof(StartupResourcesInFolder).GetTypeInfo().Assembly.GetName().Name;
|
||||
var stringLocalizer = stringLocalizerFactory.Create("Test", assemblyName);
|
||||
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
await context.Response.WriteAsync(startupStringLocalizer["Hello"]);
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(stringLocalizer["Hello"]);
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(custromerStringLocalizer["Hello"]);
|
||||
await context.Response.WriteAsync(" ");
|
||||
await context.Response.WriteAsync(customCultureLocalizer["Hello"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour from Test in root folder</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// 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.
|
||||
|
||||
namespace ResourcesClassLibraryNoAttribute
|
||||
{
|
||||
public class Model
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour from ResourcesClassLibraryNoAttribute</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +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 System.Reflection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
[assembly: ResourceLocation("ResourceFolder")]
|
||||
[assembly: RootNamespace("Alternate.Namespace")]
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// 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.
|
||||
|
||||
namespace ResourcesClassLibraryWithAttribute
|
||||
{
|
||||
public class Model
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Bonjour from ResourcesClassLibraryWithAttribute</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>Alternate.Namespace</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Extensions.Localization" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loading…
Reference in New Issue