{"id":13430710,"url":"https://github.com/RickStrahl/Westwind.Globalization","last_synced_at":"2025-03-16T06:31:03.805Z","repository":{"id":8814314,"uuid":"10511995","full_name":"RickStrahl/Westwind.Globalization","owner":"RickStrahl","description":"Database driven resource localization for .NET applications","archived":false,"fork":false,"pushed_at":"2023-03-19T01:42:27.000Z","size":27529,"stargazers_count":543,"open_issues_count":74,"forks_count":135,"subscribers_count":56,"default_branch":"master","last_synced_at":"2024-10-30T05:57:58.276Z","etag":null,"topics":["database-provider","dotnet","dotnet-core","localization","resx-resources"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RickStrahl.png","metadata":{"files":{"readme":"Readme.md","changelog":"ChangeLog.md","contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"github":"RickStrahl","custom":"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=K677THUA2MJSE\u0026source=url"}},"created_at":"2013-06-05T20:21:21.000Z","updated_at":"2024-10-07T08:37:05.000Z","dependencies_parsed_at":"2023-01-13T15:15:25.226Z","dependency_job_id":"f3467fd8-c679-4976-8181-25f70a7ef79e","html_url":"https://github.com/RickStrahl/Westwind.Globalization","commit_stats":{"total_commits":374,"total_committers":9,"mean_commits":41.55555555555556,"dds":0.03475935828877008,"last_synced_commit":"4d0ceb8251dfe34cc0018058afac69c07c13d2f2"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickStrahl%2FWestwind.Globalization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickStrahl%2FWestwind.Globalization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickStrahl%2FWestwind.Globalization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickStrahl%2FWestwind.Globalization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RickStrahl","download_url":"https://codeload.github.com/RickStrahl/Westwind.Globalization/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243835952,"owners_count":20355611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database-provider","dotnet","dotnet-core","localization","resx-resources"],"created_at":"2024-07-31T02:00:56.989Z","updated_at":"2025-03-16T06:31:03.798Z","avatar_url":"https://github.com/RickStrahl.png","language":"C#","readme":"# West Wind Globalization\n### Database Resource Localization for .NET\n\n**Westwind.Globalization (.NET Standard, .NET 4.5+):**   \n[![NuGet](https://img.shields.io/nuget/v/Westwind.Globalization.svg)](https://www.nuget.org/packages/Westwind.Globalization/)\n![](https://img.shields.io/nuget/dt/Westwind.Globalization.svg)\n\n**Westwind.Globalization.AspNetCore (.NET Core 6.0, 5.0):**  \n[![NuGet](https://img.shields.io/nuget/v/Westwind.Globalization.AspNetCore.svg)](https://www.nuget.org/packages/Westwind.Globalization.AspNetCore/)\n![](https://img.shields.io/nuget/dt/Westwind.Globalization.AspNetCore.svg)\n\n**Westwind.Globalization.Web (.NET 4.5+):**  \n[![NuGet](https://img.shields.io/nuget/v/Westwind.Globalization.Web.svg)](https://www.nuget.org/packages/Westwind.Globalization.Web/)\n![](https://img.shields.io/nuget/dt/Westwind.Globalization.Web.svg)\n\n\nThis library and tooling provides easy to use database resource managers and providers that allow you to use a database for storing localization resources. Unlike static Resx resources, database resources are dynamic, can be changed at runtime and are editable by multiple users at the same time. The custom resource managers, providers and ASP.NET Core StringLocalizers use the standard .NET resource infrastructure, so other than startup configuration there are no code changes when switching from using traditional Resx resources. \n\nIt's also possible to import resources into a database, edit them dynamically, and then export them back out into Resx and optionally strongly typed classes so your deployed applications can run with Resx resources, while you can use dynamic Database resources during development.\n\nA rich, Web based resource editor is also provided that makes it easy to create resource content and translate it interactively in a running application where you can see resource changes immediately applied without recompilation. You can import and export Resx resources, generate strongly typed classes and serve resources to JavaScript applications using the database resources. \n![Web Resource Editor](WebResourceLocalizationForm.png)\n\n### Quick Links\n\n* [Nuget Packages](#nuget)\n* [Features](#features)\n* [Documentation](https://west-wind.com/westwind.globalization/docs)\n* [Installation and Configuration for .NET Core](#installation-netcore)\n* [Installation and Configuration for .NET 4.5+](#installation-fullframework)\n* [Using Resources in your Application](#resource-usage)\n* [The Web Resource Editor](#web-resource-editor)\n\n### Requirements:\n* works .NET Standard 2.0/.NET Core 2.0 or .NET 4.5 or later\n* SQL Server 2008-2019, SQL Server Express, SQL Compact 4, MySql, SqLite\n* .NET Core Sample Project uses .NET Core 2.2 and needs VS 2019\n\n### .NET Version Support\nVersion 3.0 adds support for the 2.0 versions of .NET Standard, .NET Core and ASP.NET Core. The following versions are provided:\n\n* Westwind.Globalization \u003csmall\u003e*(net45 and netstandard2.0)*\u003c/small\u003e  \n[![NuGet](https://img.shields.io/nuget/v/Westwind.Globalization.svg)](https://www.nuget.org/packages/Westwind.Globalization/)\n![](https://img.shields.io/nuget/dt/Westwind.Globalization.svg)\n* Westwind.Globalization.AspNetCore \u003csmall\u003e*(net5.0, net6.0)*\u003c/small\u003e  \n[![NuGet](https://img.shields.io/nuget/v/Westwind.Globalization.AspNetCore.svg)](https://www.nuget.org/packages/Westwind.Globalization.AspNetCore/)\n![](https://img.shields.io/nuget/dt/Westwind.Globalization.AspNetCore.svg)\n* Westwind.Globalization.Web \u003csmall\u003e*(net45)*\u003c/small\u003e  \n[![NuGet](https://img.shields.io/nuget/v/Westwind.Globalization.Web.svg)](https://www.nuget.org/packages/Westwind.Globalization.Web/)\n![](https://img.shields.io/nuget/dt/Westwind.Globalization.Web.svg)\n* Westwind.Globalization.Sample \u003csmall\u003e*(net45)*\u003c/small\u003e\n* Westwind.Globalization.Sample.AspNetCore \u003csmall\u003e*(netcore3.1+, netcore2.1+)*\u003c/small\u003e\n\n\u003ca name=\"nuget\"\u003e\u003c/a\u003e\n### Installation\nInstallation is different depending on which version of .NET you are running under **.NET Core** and **Full Framework** use different project types and NuGet Packages for the Web support.\n\n\u003e #### Limited non-Windows Support for Admin Features\n\u003e The admin features of this package have not been fully ported to non-Windows platforms. Specifically, any of the RESX and Import Export features will not work on non-windows platforms currently. However runtime database access is fully functional.\n\nFor installation use NuGet.\n\n#### To Install for .NET Core\nPlease read the installation instructions below to configure once you've installed the project. You will need to configure startup settings in order for the Db Providers to run.\n \n```\nPM\u003e Install-Package Westwind.Globalization.AspNetCore\n```\nIf you're not using a Web Project you can just use the base package:\n\n```\nPM\u003e Install-Package Westwind.Globalization\n```\n\n\u003e #### ASP.NET Core Administration Web UI: Separate Download\n\u003e Due to changes in NuGet support in .NET Core we can no longer package static HTML, CSS and JS as part of NuGet packages. As a result a **separate download is required** to add the Localization Admin UI. You can download it from:\n\u003e \n\u003e * [Documentation for installing Localization Admin Files](https://github.com/RickStrahl/Westwind.Globalization/tree/master/DownloadableAssets)\n\u003e * [Localization Admin  Html Assets Download](https://github.com/RickStrahl/Westwind.Globalization/blob/master/DownloadableAssets/LocalizationAdministrationHtml_AspNetCore.zip?raw=true)\n\u003e\n\u003e Unzip the contents of the Zip file into your project folder root, which creates the `./wwwroot/LocalizationAdmin` Web folder and adds related resources to `./Properties`.\n\n#### To Install on .NET Framework\nPlease read the Installation Section below or watch the [Getting Started Video](https://youtu.be/ABR7ISppB1k), which describes how to install the packages, configure the project, import existing resources.\n\n```\nPM\u003e Install-Package Westwind.Globalization.Web.Starter\n```\nor if you don't want sample resources and a test page, simply use:\n```\nPM\u003e Install-Package Westwind.Globalization.Web\n```\n\nIf you're not using a Web Project or you're using MVC/Web API **and** don't need the Web Resource Editor you can just use the core package:\n```\nPM\u003e Install-Package Westwind.Globalization\n```\n\n### Resources:\n* [Westwind.Globalization Home Page](http://west-wind.com/westwind.globalization/)\n* [Nuget Package](https://www.nuget.org/packages?q=westwind.globalization)\n* [Video: Getting Started with West Wind Globalization 2.0](https://youtu.be/ABR7ISppB1k)\n* [Wiki Documentation and FAQ](http://west-wind.com/westwind.globalization/docs/)\n* [Original Article for Database Driven Resource Provider](http://www.west-wind.com/presentations/wwdbresourceprovider/)\n* [Westwind-Globalization on StackOverFlow](http://stackoverflow.com/questions/tagged/westwind-globalization)\n* [Class Reference](http://west-wind.com/westwind.globalization/docs/?page=_40y0vh66q.htm)\n* [Change Log](ChangeLog.md)\n* [License](#license)\n\n\n\u003ca name=\"Features\"\u003e\u003c/a\u003e\n### Features\n* .NET Resources in Sql Server, SqlCe, MySql and SqLite   \n* Injectable .NET Core StringLocalizers (ASP.NET Core)\n* ASP.NET Database ResourceProviders (ASP.NET/WebForms) \n* .NET  ResourceManager (ASP.NET MVC,non-Web apps)\n* Uses standard .NET Resource infrastructure and caching\n* Or: Use our dynamic DbRes string based helper (works anywhere)\n* Interactive Web Resource Editor to edit Resources\n* Keyboard optimized resources editing\n* Translate text resources with Google or Bing\n* Use Markdown in your text resources\n* Import and export Resx resources \n* Generate strongly typed classes from the Db resources\n* Release and reload resources in running Web apps\n* Serve .NET Resources to JavaScript as JSON\n* Create your own custom DbResourceManagers\n* Directly access and manage DbResources with code \n\n\nBecause this library uses the standard .NET resource infrastructure using the DbResourceProvider or DbResourceManager requires no code changes from ResX resources, other than provider configuration in your .config file and potentially a few lines of startup code.  You can import existing Resx resources and edit them interactively. Serve your resources either with the DbResourceProvider or DbResourceManager, or if you chose export them back out to Resx files for your final application code. Importing and exporting is a easily done from the Web admin interface or can be fired using code including as part of your build process.\n\n\u003e **Note**: The database is accessed only once per ResourceSet and per Locale, using the\n\u003e standard .NET Resource caching architecture used in Resource Providers and\n\u003e Resource Managers, so database access and usage is minimal. You can use these \n\u003e Providers/Manager in MVC, WebForms and even in non Web applications.\n\n\u003ca name=\"web-resource-editor\"\u003e\u003c/a\u003e\n### Web Resource Editor\nOne of the main reasons people want to use Database resources rather\nthan Resx resources is that it allows for dynamic updates of resources. Resx\nresources are static and compiled into an application and so are typically\ntied to the development process, while dynamic resources can be updated\nseparately even after the application has been completed and deployed.\n\nSince data is stored in a database it's easy to create editing front ends\nor programmatic tools that simply manipulate the database. This library\nships with a Web interface that allows editing of resources interactively\nand an easy to use data API to update resources programmatically.\n\n![Web Resource Editor](WebResourceLocalizationForm.png)\n\n![Web Resource Translator Dialog](WebResourceTranslateDialog.png)\n\nThe resource editor is an easy way to localize resources interactively,\nbut it's not the only way you can do this of course. Since you have access \nto the data API underneath it as well as the database itself, it's \neasy to create your own customized UI or data driven API that suits your\napplication needs exactly.\n\n\u003e **Markdown Support** The resource edit form allows you to optionally use Markdown for resource editing which in addition to localization makes it possible to use this libary as a basic CMS to manage user manageable content in your applications.\n\n\n### How the database Providers work\nThis library implements a custom .NET `ResourceManager` and \nASP.NET `ResourceProvider` (for .NET 4.x) that are tied to a database provider interface (although you can implement non-data providers as well). This means you  can access resources using the same mechanisms that you use with standard Resx Resources in your .NET applications. It also means although resources are initially loaded from the database for the first load of each `ResourceSet`. .NET then caches resources for each individual `ResourceSet` and locale the same way that Resx resources are read from the assembly resources and then cached. \n\n\u003e The database is hit only for the first read of a given \nResourceSet/Locale combination - not every resource access\nhits the database!\n\nThe `DbResourceManager` can be used in any type of .NET application using the `DbRes` or `DbResInstance` class methods, generated strongly typed classes, or using the Resource\nManager directly. The DbResourceProvider classes can be used in ASP.NET applications - especially for WebForms with support for local and global resources, implicit resources and control meta tags. MVC applications typically use the ResourceManager with strongly typed resources or the\n`DbRes` classes or by exporting resources back into RESX. \n\nUnderneath the .NET providers lies a the `Westwind.Globalization` data\naccess layer (IDbResourceDataManager) that provides the data interface \nto provide access to various providers. The default provider uses **SQL Server**\nas a data source with additional providers available for **MySql**, **SqLite** and\n**SqlCompact**. This API is accessed by the Resource Provider and Resource Manager\nimplementations to read the resources from the database.\n\nAdditionally the API can be directly accessed to provide resource access, and the DbRes helper class provides very easy access to these resources using the DbRes.T() method which can be thought of as a high level translation method.\n\nThis interface is also directly accessible and allows your code as well as support code like the UI Web Resource editor to easily access and manipulate resources in real-time at runtime.\n\nThis library includes quite a proliferation of classes most of it due to the implementation requirements for the .NET providers which require implementation of a host of interface based classes for customization. \n\nThere are three distinct resource access mechanisms supported:\n\n* ASP.NET Resource Provider (best used with WebForms)\n* .NET Resource Manager and strongly typed resources \n  (Non-Web apps, ASP.NET Core, classic MVC apps or anywhere where you already use Resx)\n* Direct Db Provider access using `DbRes` and `DbResInstance` helpers  \n(easiest overall - works everywhere)\n\n## Running the Sample Application\nTo run the sample application you have to set up a database to provide the resources. The following assumes you are using the default configuration which uses SQL Server and a database named *Localizations* - you can  change this via web.config settings (see the following section for more details). \n \n* Create a SQL Server/Express Database called `Localizations`\n* Make sure the Web User using **has rights** to create a Table in this DB\n* Open `http://localhost:xxxxx/LocalizationAdmin/index.html` in your browser\n* You'll get an error message like: \u003cbr/\u003e\n  *ResourceLoadingFailed: Invalid Object Name Localizations*\n* Use the `Create Table` button to create the *Localizations* table\n* Use `Import or Export Resx` button to import resources from the project into the db\n* Select `Import Resources`\tfrom the dropdown\n* Use the path of `~/Properties/` for Resx Import Folder\n* Click on the Import Resources button\n* You should now have all the sample and LocalizationForm resources in the db\n\n\n## Installation and Configuration\nThe easiest way to use this library in your own applications is to install the NuGet package into an ASP.NET application.\n\n\u003ca name=\"installation-netcore\"\u003e\u003c/a\u003e\n### ASP.NET Core Packages\n```\npm\u003e Install-Package Westwind.Globalization.AspNetCore\n```\n\n\u003e #### @icon-info-circle Download the Localization Admin UI Files\n\u003e Nuget no longer allows distribution of static content, so in order to use the Localization Admin UI you also need to download the resources for the Localization Admin UI if you want to integrate the Localization interface into your application.\n\u003e \n\u003e * [Localization Admin Html Assets](https://github.com/RickStrahl/Westwind.Globalization/blob/master/DownloadableAssets/LocalizationAdministrationHtml_AspNetCore.zip?raw=true)\n\u003e * [Documentation for installing Localization Admin Files](DownloadableAssets/Readme.md) \n\u003e\n\u003e Once you've downloaded the Localization Admin UI zip file, unzip the entire content into the project's root folder.\n\n\nFor non-Web applications or if you use only the DbRes based localization features, you can just install the base package.\n\n```\npm\u003e Install-Package Westwind.Globalization\n```\nASP.NET Core integration works in combination with ASP.NET Core new Localization features. Westwind.Globalization builds on top of this, or you can just use its native features. West Wind Globalization supports:\n\n* `IStringLocalizer` DI via custom `IDbResourceStringLocalizer`\n* `appSettings.json` configuration (optional)\n\n### ASP.NET Core Configuration\nConfiguration can be accomplished in 3 ways:\n\n1. Using a standalone `dbResourceConfiguration.json` file\n2. Using `appsettings.json` in a `DbResourceProvider` section\n3. Additional ASP.NET Core `IConfiguration` functionality configured\n(ie. Environment variables, user secrets)\n4. Explicit configuration via `AddWestwindGlobalization(opt =\u003e return true)`\n\nConfiguration values are applied in the order listed, with later assignments over-writing earlier settings.\n\n#### DbResourceConfiguration.json\nYou can create a standalone `DbResourceConfiguration.json` file for configuration that works both in full framework and .NET Core:\n```json\n{\n  \"ResourceAccessMode\": \"DbResourceManager\",\n  \"ConnectionString\": \"server=.;database=localizations;integrated security=true;\",\n  \"DataProvider\": \"SqlServer\",\n  \"ResourceTableName\": \"Localizations\",\n  \"ResxExportProjectType\": \"Project\",\n  \"ResxBaseFolder\": \"~/Properties/\",\n  \"StronglyTypedGlobalResource\": \"~/Properties/Resources.cs\",\n  \"ResourceBaseNamespace\": \"AppResources\",\n  \"AddMissingResources\": true,\n  \"LocalizationFormWebPath\": \"~/LocalizationAdmin/\",\n  \"GoogleApiKey\": \"XXXfaSyDcvmGhGN7FlynP9QUZOLF8_4K8iF9ChWo\",\n  \"BingClientId\": \"12345-4b99-47ed-be7e-caf733526020\"\n}\n```\nIf this file exists configuration values are read from it.\n\n\u003e #### @icon-warning Copy to Output Directory\n\u003e If you want to use `DbResourceConfiguration.json` for configuration storage make sure you set the **Copy to Output Directory** option to **Copy if newer** or **Copy always** to ensure the file is copied into the published output folder.\n\u003e\n\u003e ![](images/DbResourceConfigurationJsonCopy.png)\n\n#### ASP.NET Core IConfiguration\nFor ASP.NET Core operation Westwind.Globalization also registers the `DbResourceConfiguration` instance as `IOptions\u003cDbResourceConfiguration\u003e` which gives strongly typed access to the configuration via depedency injection. \n\nThis means you can use any configured configuration providers - most commonly:\n\n* appsettings.json using a `DbResourceConfiguration` object\n* Environment variables\n* User Secrets store\n\nYou can store configuration settings in `appsettings.json` like this:\n\n```json\n{\n  \"Logging\": {...},\n  \"DbResourceConfiguration\": {\n    \"ResourceAccessMode\": \"DbResourceManager\",\n    \"ConnectionString\": \"server=.;database=localizations;integrated security=true;\",\n    \"DataProvider\": \"SqlServer\",\n    \"ResourceTableName\": \"Localizations\",\n    \"StronglyTypedGlobalResource\": \"~/Properties/Resources.cs\",\n    \"ResourceBaseNamespace\": \"AppResources\",\n    \"ResxExportProjectType\": \"Project\",\n    \"ResxBaseFolder\": \"~/Properties/\",\n    \"AddMissingResources\": true,\n    \"LocalizationFormWebPath\": \"~/LocalizationAdmin/\",\n    \"BingClientId\": \"12345-4b99-47ed-be7e-caf733526020\",\n    \"GoogleApiKey\": \"XXXfaSyDcvmGhGN7FlynP9QUZOLF8_4K8iF9ChWo\"\n  }\n}\n```\nIf provided the `appsettings.json` file overrides `DbResourceConfiguration.json`. \n\nWe recommend you only use one of the files to avoid confusion. For ASP.NET Core projects we recommend you store settings in `appsettings.json` since that gives you dependency injection for `IOptions\u003cDbResourceConfiguration\u003e` as well as putting configuration settings into a well-known location.\n\n### Enabling West Wind Globalization in ASP.NET Core\nYou also need to explicitly enable localization features in ASP.NET Core using the following code in the `Startup.cs` file's `ConfigureServices()` method:\n\n```cs\npublic void ConfigureServices(IServiceCollection services)\n{\n    // Standard ASP.NET Localization features are recommended\n    // Make sure this is done FIRST!\n    services.AddLocalization(options =\u003e\n    {\n        // I prefer Properties over the default `Resources` folder\n        // due to namespace issues if you have a Resources type as\n        // most people do for shared resources.\n        options.ResourcesPath = \"Properties\";\n    });\n    \n\n    // Replace StringLocalizers with Db Resource Implementation\n    services.AddSingleton(typeof(IStringLocalizerFactory), \n                          typeof(DbResStringLocalizerFactory));\n    services.AddSingleton(typeof(IHtmlLocalizerFactory),\n                          typeof(DbResHtmlLocalizerFactory));\n                          \n    \n    // Required: Enable Westwind.Globalization (opt parm is optional)\n    // shown here with optional manual configuration code\n    services.AddWestwindGlobalization(opt =\u003e\n    {                \n        // the default settings comme from DbResourceConfiguration.json if exists\n        // you can override the settings here, the config you create is added\n        // to the DI system (DbResourceConfiguration)\n\n        // Resource Mode - from Database (or Resx for serving from Resources)\n        opt.ResourceAccessMode = ResourceAccessMode.DbResourceManager;  // .Resx\n        \n        // Make sure the database you connect to exists\n        opt.ConnectionString = \"server=.;database=localizations;uid=localizations;pwd=local\";\n        \n        // Database provider used - Sql Server is the default\n        opt.DataProvider = DbResourceProviderTypes.SqlServer;\n\n        // The table in which resources are stored\n        opt.ResourceTableName = \"localizations\";\n        \n        opt.AddMissingResources = false;\n        opt.ResxBaseFolder = \"~/Properties/\";\n\n        // Set up security for Localization Administration form\n        opt.ConfigureAuthorizeLocalizationAdministration(actionContext =\u003e\n        {\n            // return true or false whether this request is authorized\n            return true;   //actionContext.HttpContext.User.Identity.IsAuthenticated;\n        });\n\n    });\n\n    ...\n    \n    // .NET Core 2.x\n    // services.AddMvc()\n    //         .AddViewLocalization()\n    //         .AddDataAnnotationsLocalization();\n    //         .AddApplicationPart(typeof(DbResViewLocalizer).Assembly);\n    \n    // .NET Core 3.1\n    services.AddMvc(opt =\u003e  \n        // required for the Administration interface for dynamic serialization\n        .AddNewtonsoftJson();\n        // for MVC/RazorPages localization\n        .AddViewLocalization()\n        // for ViewModel Error Annotation Localization\n        .AddDataAnnotationsLocalization();\n\n    // this *has to go here* after view localization has been initialized\n    // so that Pages can localize - note required even if you're not using\n    // the DbResource manager.\n    services.AddTransient\u003cIViewLocalizer, DbResViewLocalizer\u003e();\n}\n```\n\nAny code changes made override any of the file values. You can also replace the entire `DbResourceConfiguration` object entirely in this handler.\n\nIn addition you probablywant to add standard ASP.NET Core Localization features to the `Configure()` method in `Startup.cs`:\n\n```cs\npublic void Configure(IApplicationBuilder app) \n{\n    ..\n  \n    var supportedCultures = new[]\n    {\n        new CultureInfo(\"en-US\"),\n        new CultureInfo(\"en\"),\n        new CultureInfo(\"de-DE\"),\n        new CultureInfo(\"de\"),\n        new CultureInfo(\"fr\")\n    };\n    app.UseRequestLocalization(new RequestLocalizationOptions\n    {\n        DefaultRequestCulture = new RequestCulture(\"en-US\"),\n        SupportedCultures = supportedCultures,\n        SupportedUICultures = supportedCultures                 \n    });\n    \n    ..\n    \n    // .NET Core 3.1\n    app.UseRouting();\n\n    app.UseDefaultFiles();\n    app.UseStaticFiles();\n\n    // .NET Core 3.1 required for Endpoints\n    app.UseEndpoints(endpoints =\u003e\n    {\n        endpoints.MapRazorPages();\n        endpoints.MapDefaultControllerRoute();\n    });\n    \n    // .NET Core 2.x only needs this\n    //app.UseMvc()\n}\n```   \n\n\u003e Note\n#### Dependency Injection for DbResourceConfiguration\nYou can get access to DbResourceConfiguration in a number of ways:\n\n* Via DI by asking for `DbResourceConfiguration`\n* Via DI by asking for `IOptions\u003cDbResourceConfig\u003e` (if loaded through IConfiguration)\n* Static `DbResourceConfiguration.Current` \n\n#### Dependency Injection for IDbResStringLocalizer\nOne of the base features of ASP.NET Core's Localization is `IStringLocalizer` which provides the provides an interface to map type signatures to instances of Resx resources. `DbResStringLocalizer` uses the `DbResourceManager` (which supports switchable Db or Resx resource access).\n\nTo use the DbRes localizer, override the default `IStringLocalizer` with:\n\n```cs\nservices.AddSingleton(typeof(IStringLocalizerFactory), typeof(DbResStringLocalizerFactory));\n```  \n\nOnce this is done you can use standard ASP.NET localization to use data from the configured localization provider (Db or Resx typically).\n\n\u003e #### Use of IStringLocalizer is optional. \n\u003e You can use `DbRes.T()` or strongly typed resources directly if you prefer. However, for `DataAnnotation` localization `IStringLocalizer` is required in ASP.NET Core (shrug), so generally you'll want to add `DbResStringLocalizer` in `ConfigureServices()`.\n\n\u003ca name=\"installation-fullframework\"\u003e\u003c/a\u003e\n### Full Framework Configuration\n```txt\npm\u003e Install-Package Westwind.Globalization.Web\n```\n\nIf you're not using a Web Project, or an MVC/Web API project that doesn't use the Web Resource Editor you can use the core package:\n\n```txt\npm\u003e Install-Package Westwind.Globalization\n```\nwhich doesn't install the web related components and HTML resources. \n\nThe .Web version installs the required assemblies, adds a few configuration entries in web.config and enables the resource provider by default. The Starter package adds sample resources and a couple of test pages. I recommend you use the .Starter package so you can ensure the provider is working and serving resources - once up and running you can remove the starter package, leaving the dependent assemblies in place.\n\n\n### Full Framework Configuration\nASP.NET Classic uses the web.config Configuration file for configuration\n\n```xml\n\u003cconfiguration\u003e\n  \u003cconfigSections\u003e\n    \u003csection name=\"DbResourceConfiguration\" requirePermission=\"false\" \n\t\t\t type=\"System.Configuration.NameValueSectionHandler,System,Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" /\u003e\n  \u003c/configSections\u003e  \n\n  \u003cDbResourceConfiguration\u003e\n    \u003cadd key=\"ConnectionString\" value=\"server=.;database=Localizations;integrated security=true;\" /\u003e\n    \u003cadd key=\"ResourceTableName\" value=\"Localizations\" /\u003e\n    \u003cadd key=\"AddMissingResources\" value=\"False\" /\u003e\n\n    \u003c!-- Resource Imports and Exports --\u003e\n    \u003cadd key=\"ResxExportProjectType\" value=\"Project\" /\u003e\n    \u003cadd key=\"StronglyTypedGlobalResource\" value=\"~/Properties/Resources.cs\" /\u003e\n    \u003cadd key=\"ResourceBaseNamespace\" value=\"WebApplication1.Properties\" /\u003e    \n    \u003cadd key=\"ResxBaseFolder\" value=\"~/Properties\" /\u003e\n\n    \u003c!-- WebForms specific only --\u003e\n    \u003cadd key=\"LocalizationFormWebPath\" value=\"~/LocalizationAdmin/\" /\u003e\n    \u003cadd key=\"DesignTimeVirtualPath\" value=\"\" /\u003e\n    \u003cadd key=\"ShowLocalizationControlOptions\" value=\"False\" /\u003e\n    \u003cadd key=\"ShowControlIcons\" value=\"False\" /\u003e\n\n    \u003c!-- Google Translate API --\u003e\n    \u003cadd key=\"GoogleApiKey\" value=\"\" /\u003e\n\n    \u003c!-- Bing Translation --\u003e\n    \u003cadd key=\"BingClientId\" value=\"\" /\u003e\n  \u003c/DbResourceConfiguration\u003e\n\n  \u003c!-- Enable ASP.NET Resource Provider  --\u003e\n  \u003csystem.web\u003e\n    \u003cglobalization resourceProviderFactoryType=\n     \"Westwind.Globalization.DbSimpleResourceProviderFactory,Westwind.Globalization.Web\" /\u003e\n  \u003c/system.web\u003e\n\u003c/configuration\u003e\n```\n#### Overriding Configuration Settings (Full Framework)\nTo override configuration settings that are set in `web.config` you can access the DbResourceConfiguration.Current instance that's used to configure the application. \n\n```cs\nprotected void Application_Start()\n{                       \n    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);\n    RouteConfig.RegisterRoutes(RouteTable.Routes);\n\n    // Specify where config information comes from (config file is default - can be separate Json/Xml)\n    //DbResourceConfiguration.ConfigurationMode = ConfigurationModes.ConfigFile;\n    \n    var config = DbResourceConfiguration.Current;\n    \n    config.ConnectionString = \"SqlServerLocalizations\";\n    config.DbResourceDataManagerType = typeof(DbResourceSqlServerDataManager);\n\n    //DbResourceConfiguration.Current.ConnectionString = \"MySqlLocalizations\";\n    //DbResourceConfiguration.Current.DbResourceDataManagerType = typeof(DbResourceMySqlDataManager);\n\n    // force ResourceMode explicitly. Default is AspNetResourceProvider\n    GeneratedResourceSettings.ResourceAccessMode = ResourceAccessMode.DbResourceManager;\n    //GeneratedResourceSettings.ResourceAccessMode = ResourceAccessMode.Resx;\n\n    // *** Remove or Add custom resource converters\n    // *** By default the MarkdownResourceConverter is provided\n    //DbResourceConfiguration.Current.ResourceSetValueConverters.Clear();\n    //DbResourceConfiguration.Current.ResourceSetValueConverters.Add(new MarkdownResourceSetValueConverter());\n}\n```\n\nSettings made here occur before any requests are made to the providers, so `Application_Start` is a good way to initialize settings, including selecting a provider. Any of the Configuration values can be set here, or anywhere else by using the static `DbResourceConfiguration.Current` instance.\n\n#### Setting ASP.NET Locale based on Browser Locale (Full Framework)\nIn order to do automatic localization based on a browser's language used you can sniff the browser's default language and set the UiCulture in the Begin_Request handler of your ASP.NET application class. A helper method to provide this functionality automatically is provided.\n\n```C#\nprotected void Application_BeginRequest()\n{\n    // Automatically set the user's locale to what the browser returns\n    // and optionally only allow certain locales/locale-prefixes\n    WebUtils.SetUserLocale(allowLocales: \"en,de\");\n}\n```\n\nThis forces the user's Culture and UI Culture to whatever the browser is using,\nand explicitly. Now when a page is rendered it will use the UiCulture of the browser.\nThe optional allowLocales enforces that only certain locales can be set - anything\nnot matched is defaulted to the server's default locale.\n\nThe way .NET resource managers work, if there's no match for the locale the user\nprovides, resources fall back to the closest matching locale or the invariant locale.\nSo if the user comes in with it-IT but you don't support it or it-IT in your resources\nthe user will see resources for invariant. Likewise if a user comes in with \nde-CH (Swiss german) and you de (without a locale specific suffix) the de German\nversion will be returned. Resource Fallback tries to ensure that always something\nis returned.\n\n### Configuration Settings (.NET Core and Full Framework)\n\n**ConnectionString and ResourceTableName**   \nThe two most important keys are the connectionString and resourceTableName which point at your database and a table that holds resources. On full framework you can use either a raw connection string or a Connection String Name defined in `\u003cConnectionStrings\u003e` of your `web.config` file.\n\n**AddMissingResources**  \nWhen set to true causes any resource lookup that fails to produce matching resource ID to write the invariant resource into the database. Use with caution - as this might slow down your application significantly as you now write to the database on any missing resources. Use only during development and testing to get resources into the system for easier debugging later.\n\n**ResxExportProjectType**  \nThis option determines how the Resx export feature works. The two options are `Project` or `WebForms`. Project exports all resource files into \\Properties folder underneath the resxBasePath and excludes any resource sets that include a . in their name (assumed to be ASP.NET resources). WebForms writes out resources into folder specific App_LocalResources and App_GlobalResources folders based on the root folder\n\n**ResxBaseFolder**  \nThe base folder that's used for all Resx Import and Export operations. The default is ~/ which is the root web folder, but you can specify a full OS path here. Note that this allows you to read/write resources in other non-web projects - as long as your Web application has writes to the folder specified.\n\n**StronglyTypeGlobalResource and ResourceBaseNamespace**\nIf you do a strongly typed class export from the admin manager all resources will be created in a single file in the this file using the ResourceBaseNameSpace as the namespace in the generated class.\n\n#### Run the Web Resource Editor\nIn order to use database resources you'll actually have to create some resources in a database. Make sure you've first added a valid connection string in the config file in the last step! Then open the `/LocalizationAdmin/index.html` in your browser and click on the *Create Table* button in the toolbar.\n\nOnce the table's been created you can now start creating resources interactively, by directly\nadding values to the database table, or by using the DbResourceDataManager API to manipulate the\ndata programmatically.\n\nBy default a `Resources` ResourceSet has been provided for you the resources of which are used in the test page. You can remove those resources or the resource set as needed once you know the provider works. ResourceSets are logical groups of resources that belong together - I like to use one ResourceSet per form or per application feature depending on how much content is involved. But you can also use a single ResourceSet for your entire application if you want. Whatever works for you to make it easy to find resources.\n\n#### Import Existing Resources\nI also recommend that you first perform an *Import Resx* step to pull any existing Resx resources from the `~/Properties/` folder (or whereever) into your project. This will also import the Localization form's resources into your database so that the localization form properly localizes when running with the DbResource Provider.\n\n\u003ca name=\"resource-usage\"\u003e\u003c/a\u003e\n## Using Resources in your Application\nThere are a number of different ways to access resources from this provider.\n\n* Direct access with DbRes \n* ASP.NET Resource provider\n* .NET Resource Manager\n* Strongly Typed Resources\n\n### DbRes Helper Class\nThe `DbRes` and `DbResInstance` Helper class are wrappers around the `DbResourceManager` and `DbResouceDataManager` object. The DbRes class contains a handful of common use methods that are used to retrieve and manipulate resources by name and resource set.\n\nIn an ASP.NET Web MVC (or WebPages) application you can use:\n\n```C#\n// Using current UiCulture - empty resource set uses default (Resources)\nDbRes.T(\"HelloWorld\")\n\n// Exact match with resource - Hallo Welt\nDbRes.T(\"HelloWorld\",\"Resources\",\"de\")\n\n// Resource Fallback to de if de-CH doesn't exist - Hallo Welt\nDbRes.T(\"HelloWorld\",\"Resources\",\"de-CH\")\n```\n\nThis is an easy mechanism that's tied closely to the database\nresources created and can be applied with minimal fuss in any\nkind of .NET application.\n\n### ASP.NET MVC or ASP.NET WebPages\n```HTML\nSay Hello: @DbRes.T(\"HelloWorld\") at @DateTime.Now\n```\n\n### ASP.NET WebForms\n```HTML\nSay Hello: \u003c%: DbRes.T(\"HelloWorld\") %\u003e at \u003c%= DateTime.Now %\u003e\n```\n\n### In .NET code\n```HTML\nstring value = DbRes.T(\"HelloWorld\");\n```\n\nThe `DbRes.T()` method returns the ResourceId passed in if a resource is missing in the ResourceSet which can be useful for providing 'default' text. Some people like to use full resource strings as their resource Ids so default values are always available even if a resource is missing or the provider is not available. \n\n## Using the ASP.NET Resource Provider  (Full Framework, WebForms)\nIf you're using an existing WebForms application or you want to\nuse the ASP.NET based Resource Provider model for accessing resources\nyou can use the DbSimpleResourceProvider. This implementation is an\nASP.NET Resource Provider implementation that directly accesses the\nDbResourceDataManager to retrieve resources. A second Resource Provider\nimplementation that uses the DbResourceProvider uses the DbResourceManager\nto indirectly access resources. Typically the DbSimpleResourceProvider is\nthe more efficient interface.\n\nTo use this provider you have to enable it in web.config. To do so:\n\n```XML\n\u003cconfiguration\u003e  \n  \u003csystem.web\u003e\n       \u003cglobalization resourceProviderFactoryType=\"Westwind.Globalization.DbSimpleResourceProviderFactory,Westwind.Globalization.Web\" /\u003e    \n       \u003c!--\u003cglobalization resourceProviderFactoryType=\"Westwind.Globalization.DbResourceProviderFactory,Westwind.Globalization\" /\u003e--\u003e    \n  \u003c/system.web\u003e\n\u003c/configuration\u003e\n```\n\nOnce enabled you can use all the standard ASP.NET Resource Provider\nfeatures:\n\n* GetGlobalResourceObject, GetLocalResourceObject on Page and HttpContext\n* Using meta:resourcekey attributes on Web Controls\n\n### Page.GetGlobalResourceObject() or HttpContext.GetGlobalResourceObject() \n```HTML\n\u003clegend\u003eASP.NET ResourceProvider\u003c/legend\u003e\n\u003clabel\u003eGet GlobalResource Object (default locale):\u003c/label\u003e\n\u003c%: Page.GetGlobalResourceObject(\"Resources\",\"HelloWorld\") %\u003e\n```\n\n### Page.GetLocalResourceObject()\n```HTML\n\u003clabel\u003eGetLocalResourceObject via Expression:\u003c/label\u003e                 \n\u003c%: GetLocalResourceObject(\"lblHelloWorldLabel.Text\") %\u003e\n```\n\n### WebForms Control meta:resourcekey attribute\n```HTML\n\u003clabel\u003eMeta Tag (key lblHelloWorldLabel.Text):\u003c/label\u003e\n\u003casp:Label ID=\"lblHelloLabel\" runat=\"server\" meta:resourcekey=\"lblHelloWorldLabel\"\u003e\u003c/asp:Label\u003e\n```\n\n### WebForms Resource Expressions\n```HTML\n\u003clabel\u003eResource Expressions (Global Resources):\u003c/label\u003e\n\u003casp:Label ID=\"Label1\" runat=\"server\" Text=\"\u003c%$ Resources:Resources,HelloWorld %\u003e\"\u003e\u003c/asp:Label\u003e\n```\n\n\n## Strongly typed Resources\nThe Web Resource Editor form allows you to create strongly typed resources\nfor any global resources in your application. Basically it'll go through all the \nnon-local resources in your file and create strongly type .NET classes in a file that\nis specified in the DbResourceProvider configuration settings.\n\n```\n\u003cadd key=\"StronglyTypedGlobalResource\" value=\"~/Properties/Resources.cs\" /\u003e\n\u003cadd key=\"ResourceBaseNamespace\" value=\"WebApplication1.Properties\" /\u003e\n```\nYou specify the namespace and filename to generate it to. Once you've generated the strongly typed resource file with the embedded resource class(es), you need to recompile your application to make the resource properties available to it.\n \nThe generated resources can use either the ASP.NET resource provider (which uses\nwhatever provider is configured - Resx or DbResourceProvider) or the \nDbResourceManager which only uses the DbResourceManager. Using the latter allows\nyou to also generate resources for use in non-Web applications.\n\nHere's what generated resources look like:\n```C#\nnamespace WebApplication1.Properties\n{\n    public class GeneratedResourceSettings\n    {\n        // You can change the ResourceAccess Mode globally in Application_Start  \n        // AspNetResourceProvider, Project (MVC, Windows), Resx      \n        public static ResourceAccessMode ResourceAccessMode = ResourceAccessMode.AspNetResourceProvider;\n    }\n\n\tpublic class Commonwords\n\t{\n\t\tpublic static System.String Ready\n\t\t{\n\t\t\tget\n\t\t\t{\n\t\t\t\tif (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider)\n\t\t\t\t\treturn (System.String) HttpContext.GetGlobalResourceObject(\"Commonwords\",\"Ready\");\n\t\t\t\treturn DbRes.T(\"Ready\",\"Commonwords\");\n\t\t\t}\n\t\t}\n\n\t\tpublic static System.String ThisIsALongLineOfText\n\t\t{\n\t\t\tget\n\t\t\t{\n\t\t\t\tif (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider)\n\t\t\t\t\treturn (System.String) HttpContext.GetGlobalResourceObject(\"Commonwords\",\"This is a long line of text\");\n\t\t\t\treturn DbRes.T(\"This is a long line of text\",\"Commonwords\");\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\nThese can then be used in any ASP.NET application:\n\n##### ASP.NET MVC or WebPages\n```HTML\n\u003cdiv class=\"statusbar\"\u003e@CommonWords.Ready\u003c/div\u003e\n```\n\n##### ASP.NET WebForms\n```HTML\n\u003cdiv class=\"statusbar\"\u003e\u003c%: WebApplication1.CommonWords.Ready %\u003e\u003c/div\u003e\n```\n#### .NET Code\n```C#\nstring ready = CommonWords.Ready;\n```\n\nNote that strongly typed resources must be re-generated whenever you add new\nresources, so this is an ongoing process. As with the Resx Generator if\nyou remove or rename a resource you may break your code. \n\nStrongly typed resources are generated into a single file for all the resource sets exported in order to not clutter up your application with unnecessary generated files.  \n\n## ASP.NET MVC ModelValidation (Full Framework)\nASP.NET and Entity Framework support model validation and you can also use the database provider to localize these validation messages. To do so **you have to generate strongly typed resources**, or export to Resx and then enable strong resource typing. ASP.NET/EntityFramework Model validation works based on class property access so in order to use it a type has to exist.\n\nTo do this:\n\n* Open the Localization Administration form \n* Use *Export Class* to export create a class\n* Or: Use *Export to Resx* to export Resx files (in Project mode)\u003cbr/\u003e\nthen make sure to enable the strong type generation on the Resx and choose *Public class*\n\nOnce you've done this you can create your validation classes like you always would:\n\n```c#\npublic class ViewModelWithLocalizedAttributes\n{\n    [Required(ErrorMessageResourceName = \"NameIsRequired\", ErrorMessageResourceType = typeof(Resources))]\n    public string Name { get; set;  }\n\n    [Required(ErrorMessageResourceName = \"AddressIsRequired\", ErrorMessageResourceType = typeof(Resources))]\n    public string Address { get; set;  }\n}\n```\n\nThe type will be your exported class or generated Resx class and the name is the name of the property on the generated object. DataAnnotations use Reflection to lookup the property name, so if for some reason the validation does not work check the following:\n\n* Make sure the property name is typed correctly and matches a property name.\n* Try writing out the actual property using @Resources.AddressIsRequired to ensure the value is valid (on a simple test page perferrably). \n\n\n## Model Validation ASP.NET Core Mvc\nASP.NET MVC uses a completely different model for Model validation based on `IStringLocalizer`. In this initial .NET Core release we don't have support for this yet, but we're working on it. It's coming in an update soon.\n\n\n## Switching Database Providers\nBy default the resource providers and manager use **SQL Server** to hold the database resources. If you don't do any custom configuration in code to specify the `DbResourceConfiguration.DbResourceDataManagerType` you'll get the Sql Server provider/manager. \n\nThe following providers are supported:\n\n* Sql Server (2008-2016, Sql Azure)\n* MySql\n* SqLite\n* Sql Server Compact (no .NET Core support)\n\nTo use a specific provider, assign the `DbResourceConfiguration.DbResourceDataManagerType` to the appropriate engine you want to use during startup configuration.\n\n* typeof(DbResourceSqlServerDataManager)\n* typeof(DbResourceMySqlDataManager)\n* typeof(DbResourceSqLiteDataManager)\n* typeof(DbResourceSqlCompactDataManager)\n\nIn .NET Core you set the value in the `AddDbResourceLocalization(opt)` configuration:\n\n```cs\nservices.AddWestwindGlobalization(opt =\u003e\n    ...\n    opt.DbResourceDataManagerType = typeof(DbResourceMySqlDataManager);\n    opt.ConnectionString = \"server=localhost;uid=testuser;pwd=super10seekrit;\" + \n                           \"database=Localizations;charset=utf8\"\n```\n\nFor full framework you can set the value in the `Application_Start` handler and set the singleton configuration value:\n\n```cs\nDbResourceConfiguration.Current.DbResourceDataManagerType =\n                  typeof(DbResourceSqLiteDataManager);\nDbResourceConfiguration.Current.ConnectionString = \n    \"server=localhost;database=Localizations;\" +\n    \"uid=testuser;pwd=super10seekrit;charset=utf8\" \n```                  \n\nNote that the connection string can be set in configuration files (`app/web.config` in full framework, `DbResourceConfiguration.json` or `appsettings.json` in .NET Core), but the provider configuration has to be set in code.\n\nHere's a little more info on how to specify each provider and the dependencies that are required.\n\n### Sql Server\n*no additional package needed*\n\n.NET Core:\n```\nopt.ConnectionString = \"server=.;database=localizations;integrated security=true\";\n// not required since it's the default\nopt.DbResourceManagerType = typeof(DbResourceSqlServerManager);\n```\n\nweb.config file connection String Example:\n\n```xml\n\u003cadd name=\"SqlServerLocalizations\"\n    connectionString=\"server=.;database=localizations;integrated security=true;\"\n    providerName=\"System.Data.SqlClient\" /\u003e\n```\n\n### MySql\n\n*add NuGet Package: **MySql.Data***\n\nCode Configuration:\n```c#\nopt.ConnectionString = \"server=localhost;uid=testuser;pwd=super10seekrit;database=Localizations;charset=utf8\";\nopt.DbResourceDataManagerType = typeof(DbResourceMySqlDataManager);                \n```\n\nweb.config file connection String Example:\n\n```xml\n\u003cadd name=\"MySqlLocalizations\"\n    connectionString=\"server=localhost;uid=testuser;pwd=super10seekrit;database=Localizations;charset=utf8\" \n    providerName=\"MySql.Data.MySqlClient\" /\u003e\n```\n\n### SqLite\n*.NET Core add Nuget Package:* **Microsoft.Data.SqLite**\n\n*Full Framework add NuGet Package:* **System.Data.SQLite**\n\nCode Configuration:\n```c#\nopt.ConnectionString = \"Data Source=./data/SqLiteLocalizations.db\";\nopt.DbResourceDataManagerType = typeof(DbResourceSqLiteDataManager);\n```  \n\n\u003e Make sure to use a valid path where the database file can be found and used.\n\nweb.config file connection String Example:\n```xml\n\u003cadd name=\"SqLiteLocalizations\"\n    connectionString=\"Data Source=|DataDirectory|\\SqLiteLocalizations.db\"\n    providerName=\"System.Data.SQLite\" /\u003e\n```\n\n### Sql Server Compact\n*add NuGet Package: **Microsoft.SqlServer.Compact***\n\n**not supported on .NET Core**\n\n```c#\nDbResourceConfiguration.Current.DbResourceDataManagerType = typeof(DbResourceSqlServerCeDataManager);\n```\nweb.config connection string example:\n\n```xml\n\u003cadd name=\"SqlServerCeLocalizations\" \n     connectionString=\"Data Source=|DataDirectory|\\Localizations.sdf;Persist Security Info=False;\" \n     providerName=\"System.Data.SqlServerCe.4.0\" /\u003e\n```\n\n### Global Data Manager Configuration\nThis code configures the data manager globally so every time a data access operation occurs it instantiates the data manager configured here. It's important that you add the appropriate assembly first, otherwise these provider types will not be available and your code won't compile.\n\n\n## JavaScript Resource Handler\nIf you're building applications that include JavaScript logic it's likely that you also need to access localized resources on the client. This library provides a JavaScript Resource Handler that can serve resources in the proper localized locale to your client application.\n\nThe resource handler allows you to specify which resources to serve and which locale - or auto-detected locale - to serve the data to your JavaScript client application.\n\nThe handler produces a JavaScript object map that is exposed as a global variable with properties for each of the resource keys:\n\n```javascript\nresources = {\n\t\"HelloWorld\": \"Hallo schn\\u00F6de Welt\",\n\t\"Ready\": \"Los\",\n\t\"Today\": \"Heute\",\n\t\"Yesterday\": \"Gestern\",\n    \"dbRes\": function dbRes(resId) { return resources[resId] || resId; }    \n};\n```\n\nResource values are normalized, meaning if a localized doesn't exist, resource fallback is used to fill the value. A `dbRes()` function is added to the object to allow returning the resource ID if a value can't be matched or if the resources for some reason fail to load.\n\nResources can be accessed in client code:\n\n```html\n\u003cscript\u003e\n    var hello = resources.HelloWorld;\n    var hello2 = resources.dbRes(\"HelloWorld\");\n\u003c/script\u003e\n```\n\nThe latter will always return **some** value (HelloWorld) even if there's no matching property value to return.\n\n### Configuration and Usage (ASP.NET Core)\nFor ASP.NET Core the JavaScript resource handling does not have to be configured - it's always available as long as ASP.NET MVC is active and running on the Web site. The handler is hooked in via custom routing that lives at a fixed URL.\n\nTo add client side script to the `api/JavaScriptLocalizationResources` endpoint (all in one line):\n\n```html\n\u003cscript src=\"/api/JavaScriptLocalizationResources?  \n                ResourceSet=LocalizationForm\u0026\n                VarName=resources\u0026\n                localeId=auto\u0026\n                ResourceMode=ResDb\"\u003e\u003c/script\u003e\n```\n\nThe following parameters are passed:\n\n* **resourceSet** - The ResourceSet name to serve resources to serve.\n* **varName** - The name of the global variable to declare the map on. This can also be a property value of an existing object like `page.resources` to avoid cluttering up global scope.\n* **localeId** - Optional locale id like `de-DE` or `de`. If not passed the value is `auto` which reads the value from the users `accept-language` header.\n* **resourceMode** - Either `ResDb` or `Resx` which determines whether resources are served from the database or resx. If not passed or `auto` the DbResourceConfig setting is used.\n\n\n#### Configuration (.NET Framework)\nTo configure the Resource Handler for classic ASP.NET it has to be registered in web.config as follows:\n\n```xml\n\u003cconfiguration\u003e\n\u003csystem.webServer\u003e\n\u003chandlers\u003e\n    \u003cadd name=\"JavaScriptResourceHandler\"\n        verb=\"GET\"\n        path=\"JavascriptResourceHandler.axd\"\n        type=\"Westwind.Globalization.JavaScriptResourceHandler,Westwind.Globalization.Web\" /\u003e\n\u003c/handlers\u003e\n\u003c/system.webServer\u003e\n\u003c/configuration\u003e\n```\n\nNote this entry is automatically made for you when you install the NuGet package.\n\n#### Usage\nThe resource handler is then accessed as a script resource in your code by calling the\nstatic JavaScriptResourceHandler.GetJavaScriptResourcesUrl() method:\n\n```html\n\u003cscript src=\"@JavaScriptResourceHandler.GetJavaScriptResourcesUrl(\"resources\",\"Resources\")\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n    document.querySelector(\"#JavaScriptHelloWorld\").innerText = resources.HelloWorld;\n    document.querySelector(\"#JavaScriptYesterday\").innerText = resources.dbRes(\"Yesterday\");\n\u003c/script\u003e\n```\n\n\nor if you're using a plain HTML page (all one line):\n\n```html\n\u003cscript src=\"JavaScriptResourceHandler.axd?ResourceSet=Resources\u0026\n                            LocaleId=auto\u0026\n                            VarName=resources\u0026\n                            ResourceType=resdb\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n    document.querySelector(\"#JavaScriptHelloWorld\").innerText = resources.HelloWorld;\n\u003c/script\u003e\n```\n\nEither of the above generate the following script code (shown here localized in German):\n\n```javascript\nresources = {\n\t\"HelloWorld\": \"Hallo schn\\u00F6de Welt\",\n\t\"Ready\": \"Los\",\n\t\"Today\": \"Heute\",\n\t\"Yesterday\": \"Gestern\",\n    \"dbRes\": function dbRes(resId) { return resources[resId] || resId; }    \n};\n```\n\n### Handler Url Formatting\nA full JavaScript resource handler URL looks like this:\n\n```\nJavaScriptResourceHandler.axd?ResourceSet=Resources\u0026LocaleId=auto\u0026VarName=resources\u0026ResourceType=resdb\u0026ResourceMode=1\n```\n\nThe QueryString parameters on the URL are used as follows:\n\n##### ResourceSet\nThe ResourceSet name as defined in the database or the name of the ResX file relative to the ResxBaseFolder defined in the configuration.\n\n##### LocaleId\nThis can be either a specific localeId like `de`, or `de-de`. Or it can be `auto` in which ASP.NET will use its default locale, which you can override to match the browser's locale as described in [Auto-detecting browser locale](Auto-Detecting-and-Setting-ASP.NET-Locale-based-on-Browser-Locale). The recommendation is to use `auto` and have IIS detect the browser locale and switch the thread UiCulture.\n\n##### ResourceType - resdb,resx\nYou can specify what type of resources are loaded with this Resource handler. The options are `resdb`, which uses the dbResourceProvider/Manager or `resx` which uses Resx resources. Again in order for Resx resources to work the ResxBaseFolder must be set.\n\n##### ResourceMode  0 (WebForms), 1 (Project/folder)\nDetermines how Resx Resources are loaded using either *project* (1) or *WebForms* (0) style resources. If *project* (0) resources are used make sure the ResxBaseFolder points to the path where your Resx resources like. If you use *WebForms* mode, resources are located using App_GlobalResources and App_LocalResources folders.\n\n\n## Project Sponsors\nThe following people/organizations have provided sponsorship to this project by way of direct donations or for paid development as part of a development project using these tools:\n\n* **Frank Lutz - Monosynth**\u003cbr/\u003e\nFrank provided a sizable donation to the project and valuable feedback for a host of improvements and bug fixes.\n\n* **Craig Tucker - Alabama Software**\u003cbr/\u003e\nCraig offered early support and feedback for this project and billed project time for a number of additions to the library as part of a larger project.\n\n* **Dan Martin - WeatherMaker**\u003cbr/\u003e\nDan and his company provided a block of my billable hours dedicated to this project for adding support for MySql.\n\nWant to sponsor this project, need customization or make a donation? You can contact me directly at rstrahl@west-wind.com or you can also make a donation online via PayPal.\n\n* [Make a donation for Westwind.Globalization using PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=ERVCP2CMPS4QL)\n\n## License\nThe Westwind.Globalization library is licensed under the\n[MIT License](http://opensource.org/licenses/MIT) and there's no charge to use, \nintegrate or modify the code for this project. You are free to use it in personal, \ncommercial, government and any other type of application. \n\n[Commercial Licenses](http://west-wind.com/Westwind.Globalization/docs/?page=_2lp0u0i9b.htm) are \nalso available as an option. If you are using these tools in a commercial application\nplease consider purchasing one of our reasonably priced commercial licenses that help support this project's development.\n\nAll source code is copyright West Wind Technologies, regardless of changes made to them. Any source code modifications must leave the original copyright code headers intact.\n\n\n#### Warranty Disclaimer: No Warranty!\nIN NO EVENT SHALL THE AUTHOR, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE \nTHIS PROGRAM AND DOCUMENTATION, BE LIABLE FOR ANY COMMERCIAL, SPECIAL, INCIDENTAL, \nOR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM \nINCLUDING, BUT NOT LIMITED TO, LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR \nLOSSES SUSTAINED BY YOU OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE \nPROGRAM TO OPERATE WITH ANY OTHER PROGRAMS, EVEN IF YOU OR OTHER PARTIES HAVE \nBEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.","funding_links":["https://github.com/sponsors/RickStrahl","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=K677THUA2MJSE\u0026source=url","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=ERVCP2CMPS4QL"],"categories":["Frameworks, Libraries and Tools","框架, 库和工具","C# #","C\\#"],"sub_categories":["Internationalization","国际化"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRickStrahl%2FWestwind.Globalization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRickStrahl%2FWestwind.Globalization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRickStrahl%2FWestwind.Globalization/lists"}