diff --git a/.github/workflows/cloudscribe-develop.yml b/.github/workflows/cloudscribe-develop.yml
index 9438bc8..aa6e915 100644
--- a/.github/workflows/cloudscribe-develop.yml
+++ b/.github/workflows/cloudscribe-develop.yml
@@ -1,39 +1,39 @@
-# This workflow will build a .NET project
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
-
-name: cloudscribe-localization-develop-nuget-build
-
-on:
- push:
- branches: [ "develop" ]
- workflow_dispatch:
-# pull_request:
-# branches: [ "develop" ]
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v4
- - name: Setup .NET
- uses: actions/setup-dotnet@v4
- with:
- dotnet-version: 8.0.x
- - name: Setup NuGet
- run: dotnet nuget add source ${{ secrets.NUGET_SOURCE_URL }} -u ${{secrets.NUGET_USERNAME }} -p ${{ secrets.NUGET_PASSWORD }} --store-password-in-clear-text
- - name: Restore dependencies
- run: dotnet restore
- - name: Build
- run: dotnet build -c Release
- - name: Create NuGet package
- run: dotnet pack -c Release
- - name: Publish NuGet package
- run: dotnet nuget push **/*.nupkg --source ${{ secrets.NUGET_SOURCE_URL }}
- - name: Remote Repository Dispatch
- uses: peter-evans/repository-dispatch@v3
- with:
- token: ${{ secrets.GHB_PAT }}
- repository: GreatHouseBarn/cloudscribe-testing
- event-type: cs.Web.Localization
+# This workflow will build a .NET project
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
+
+name: cloudscribe-localization-develop-nuget-build
+
+on:
+ push:
+ branches: [ "develop" ]
+ workflow_dispatch:
+# pull_request:
+# branches: [ "develop" ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+ - name: Setup NuGet
+ run: dotnet nuget add source ${{ secrets.NUGET_SOURCE_URL }} -u ${{secrets.NUGET_USERNAME }} -p ${{ secrets.NUGET_PASSWORD }} --store-password-in-clear-text
+ - name: Restore dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build -c Release
+ - name: Create NuGet package
+ run: dotnet pack -c Release
+ - name: Publish NuGet package
+ run: dotnet nuget push **/*.nupkg --source ${{ secrets.NUGET_SOURCE_URL }}
+ - name: Remote Repository Dispatch
+ uses: peter-evans/repository-dispatch@v3
+ with:
+ token: ${{ secrets.GHB_PAT }}
+ repository: GreatHouseBarn/cloudscribe-testing
+ event-type: cs.Web.Localization
diff --git a/.github/workflows/nuget-push-to-production.yml b/.github/workflows/nuget-push-to-production.yml
index 269e626..de40787 100644
--- a/.github/workflows/nuget-push-to-production.yml
+++ b/.github/workflows/nuget-push-to-production.yml
@@ -1,56 +1,56 @@
-name: NuGet Push to Production - ESDM Nexus and nuget.org
-
-on:
- workflow_dispatch:
-
-jobs:
- push-nuget:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Setup .NET
- uses: actions/setup-dotnet@v4
- with:
- dotnet-version: 8.0.x
- - name: Exit if the branch is not master
- run: |
- if [[ "${{ github.ref }}" != "refs/heads/master" ]]; then
- echo "Branch is not master, exiting."
- exit 1
- fi
- - name: Setup NuGet
- run: dotnet nuget add source ${{ secrets.NUGET_SOURCE_URL }} -u ${{ secrets.NUGET_USERNAME }} -p ${{ secrets.NUGET_PASSWORD }} --store-password-in-clear-text --name esdm-nuget-testing
- - name: Restore dependencies
- run: dotnet restore
- - name: Build
- run: dotnet build -c Release
- - name: Create NuGet package
- run: dotnet pack -c Release
- - name: Auth to other Nexus repo
- run: dotnet nuget add source ${{ secrets.ESDM_NUGET_HOSTED_URL }} -u ${{ secrets.NUGET_USERNAME }} -p ${{ secrets.NUGET_PASSWORD }} --store-password-in-clear-text --name esdm-nuget-hosted
- - name: Find and Push NuGet packages to Nexus
- run: |
- PACKAGES=$(find . -name "*.nupkg" | grep -E "cloudscribe|sts\.")
- if [ -z "$PACKAGES" ]; then
- echo "No matching package found. Exiting."
- exit 1
- fi
- echo "Found packages: $PACKAGES"
- for PACKAGE in $PACKAGES; do
- echo "Pushing $PACKAGE to Nexus"
- dotnet nuget push "$PACKAGE" --source esdm-nuget-hosted --skip-duplicate || echo "WARNING - skipping duplicate package: $PACKAGE"
- done
- - name: Find and Push NuGet packages to nuget.org
- env:
- NUGET_ORG_API_KEY: ${{ secrets.NUGET_ORG_API_KEY }}
- run: |
- PACKAGES=$(find . -name "*.nupkg" | grep -E "cloudscribe|sts\.Common")
- if [ -z "$PACKAGES" ]; then
- echo "No matching package found. Exiting."
- exit 1
- fi
- echo "Found packages: $PACKAGES"
- for PACKAGE in $PACKAGES; do
- echo "Pushing $PACKAGE to nuget.org"
- dotnet nuget push "$PACKAGE" --api-key "$NUGET_ORG_API_KEY" --source "https://api.nuget.org/v3/index.json" --skip-duplicate || { echo "WARNING - failed to upload package: $PACKAGE"; exit 1; }
- done
+name: NuGet Push to Production - ESDM Nexus and nuget.org
+
+on:
+ workflow_dispatch:
+
+jobs:
+ push-nuget:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+ - name: Exit if the branch is not master
+ run: |
+ if [[ "${{ github.ref }}" != "refs/heads/master" ]]; then
+ echo "Branch is not master, exiting."
+ exit 1
+ fi
+ - name: Setup NuGet
+ run: dotnet nuget add source ${{ secrets.NUGET_SOURCE_URL }} -u ${{ secrets.NUGET_USERNAME }} -p ${{ secrets.NUGET_PASSWORD }} --store-password-in-clear-text --name esdm-nuget-testing
+ - name: Restore dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build -c Release
+ - name: Create NuGet package
+ run: dotnet pack -c Release
+ - name: Auth to other Nexus repo
+ run: dotnet nuget add source ${{ secrets.ESDM_NUGET_HOSTED_URL }} -u ${{ secrets.NUGET_USERNAME }} -p ${{ secrets.NUGET_PASSWORD }} --store-password-in-clear-text --name esdm-nuget-hosted
+ - name: Find and Push NuGet packages to Nexus
+ run: |
+ PACKAGES=$(find . -name "*.nupkg" | grep -E "cloudscribe|sts\.")
+ if [ -z "$PACKAGES" ]; then
+ echo "No matching package found. Exiting."
+ exit 1
+ fi
+ echo "Found packages: $PACKAGES"
+ for PACKAGE in $PACKAGES; do
+ echo "Pushing $PACKAGE to Nexus"
+ dotnet nuget push "$PACKAGE" --source esdm-nuget-hosted --skip-duplicate || echo "WARNING - skipping duplicate package: $PACKAGE"
+ done
+ - name: Find and Push NuGet packages to nuget.org
+ env:
+ NUGET_ORG_API_KEY: ${{ secrets.NUGET_ORG_API_KEY }}
+ run: |
+ PACKAGES=$(find . -name "*.nupkg" | grep -E "cloudscribe|sts\.Common")
+ if [ -z "$PACKAGES" ]; then
+ echo "No matching package found. Exiting."
+ exit 1
+ fi
+ echo "Found packages: $PACKAGES"
+ for PACKAGE in $PACKAGES; do
+ echo "Pushing $PACKAGE to nuget.org"
+ dotnet nuget push "$PACKAGE" --api-key "$NUGET_ORG_API_KEY" --source "https://api.nuget.org/v3/index.json" --skip-duplicate || { echo "WARNING - failed to upload package: $PACKAGE"; exit 1; }
+ done
diff --git a/.gitignore b/.gitignore
index 25e4844..2cceb9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,239 +1,239 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-bld/
-[Bb]in/
-[Oo]bj/
-
-# Visual Studio 2015 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# DNX
-project.lock.json
-artifacts/
-
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding add-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# NuGet Packages
-*.nupkg
-# The packages folder can be ignored because of Package Restore
-**/packages/*
-# except build/, which is used as an MSBuild target.
-!**/packages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/packages/repositories.config
-# NuGet v3's project.json files produces more ignoreable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Microsoft Azure ApplicationInsights config file
-ApplicationInsights.config
-
-# Windows Store app package directory
-AppPackages/
-BundleArtifacts/
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.pfx
-*.publishsettings
-node_modules/
-orleans.codegen.cs
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-*.mdf
-*.ldf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-
-# FAKE - F# Make
-.fake/
-
-src/localization.WebApp/wwwroot/lib*
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Microsoft Azure ApplicationInsights config file
+ApplicationInsights.config
+
+# Windows Store app package directory
+AppPackages/
+BundleArtifacts/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+
+# FAKE - F# Make
+.fake/
+
+src/localization.WebApp/wwwroot/lib*
src/localization.WebApp/Properties/PublishProfiles*
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index a5a483e..9533dd3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,16 +1,16 @@
-language: csharp
-solution: cloudscribe.Web.Localization.sln
-sudo: false
-dist: xenial
-mono: none
-dotnet: 3.0.100
-env:
- global:
- - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- - DOTNET_CLI_TELEMETRY_OPTOUT: 1
-os:
- - linux
-script:
- - if test "$TRAVIS_OS_NAME" == "linux"; then dotnet restore; fi
- - if test "$TRAVIS_OS_NAME" == "osx"; then dotnet restore --disable-parallel; fi
- - dotnet build -c Release
+language: csharp
+solution: cloudscribe.Web.Localization.sln
+sudo: false
+dist: xenial
+mono: none
+dotnet: 3.0.100
+env:
+ global:
+ - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+ - DOTNET_CLI_TELEMETRY_OPTOUT: 1
+os:
+ - linux
+script:
+ - if test "$TRAVIS_OS_NAME" == "linux"; then dotnet restore; fi
+ - if test "$TRAVIS_OS_NAME" == "osx"; then dotnet restore --disable-parallel; fi
+ - dotnet build -c Release
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 43f12a5..6bfa1d8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,6 +1,6 @@
-# Contributing to cloudscribe
-
-This project is part of the cloudscribe set of projects which are all being managed under the same policies.
-See the CONTRIBUTING.md file in the main cloudscribe repository:
-https://github.com/joeaudette/cloudscribe/blob/master/CONTRIBUTING.md
-
+# Contributing to cloudscribe
+
+This project is part of the cloudscribe set of projects which are all being managed under the same policies.
+See the CONTRIBUTING.md file in the main cloudscribe repository:
+https://github.com/joeaudette/cloudscribe/blob/master/CONTRIBUTING.md
+
diff --git a/LICENSE b/LICENSE
index 8dada3e..c0ee812 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,201 +1,201 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "{}"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright {yyyy} {name of copyright owner}
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/NuGetReadmePlan.md b/NuGetReadmePlan.md
new file mode 100644
index 0000000..a1bd424
--- /dev/null
+++ b/NuGetReadmePlan.md
@@ -0,0 +1,33 @@
+# Persistent Plan: Add README to NuGet Packages
+
+## Overview
+This plan describes the steps to ensure all NuGet packages in a solution include a README file and are properly configured for NuGet.org. It is reusable for any .NET solution.
+
+## Steps
+1. **Create a Feature Branch**
+ - Work within the context of the existing current git branch.
+
+2. **Identify NuGet Projects**
+ - List all projects in the solution that are packed and published as NuGet packages.
+
+3. **README.md Creation**
+ - For each NuGet project, create a `README.md` file in the project root.
+ - Ensure each README contains a project description, usage instructions, and license.
+
+4. **Update .csproj Files**
+ - Add `README.md` to each `.csproj`.
+ - Add `` to ensure README is included in the package.
+
+5. **Test Packaging**
+ - Run `dotnet pack --no-build -o ../nupkg` for each project.
+ - Confirm the README is included in the resulting `.nupkg` file.
+
+6. **Leave Changes Local**
+ - Do not commit or push changes until review is complete.
+
+7. **Repeatable**
+ - Use this plan for any other solution by following the same steps.
+
+---
+
+*This file can be copied to any solution and reused as a checklist for preparing NuGet packages with README files.*
diff --git a/README.md b/README.md
index 0a7c14e..7468604 100644
--- a/README.md
+++ b/README.md
@@ -1,98 +1,98 @@
-# cloudscribe.Web.Localization - more flexible localization for ASP.NET Core
-
-I developed this project to meet my localization goals for [cloudscribe.Core](https://github.com/joeaudette/cloudscribe) and [cloudscribe.SimpleContent](https://github.com/joeaudette/cloudscribe.SimpleContent). However it has no dependencies on other cloudscribe components and can be used by anyone who wants the provided functionality. Get the big picture on cloudscribe projects at [cloudscribe.com](https://www.cloudscribe.com)
-
-If you have questions please visit our community forums https://www.cloudscribe.com/forum
-
-### Build Status
-
-
-
-[](https://github.com/cloudscribe/cloudscribe.Web.Localization/actions/workflows/cloudscribe-develop.yml)
-
-
-## Rationale
-
-My vision for composing web applications is to build separate components for each feature or purpose in separate class library projects, packaged as nugets that one can bring into their main web application to add functionality. The main web application may or may not have its own features that it implements, but much or most of the functionality will come from class library projects that are pulled in as nuget dependencies.
-
-The [new localization system for ASP.NET Core](https://docs.asp.net/en/latest/fundamentals/localization.html) allows you to configure a folder where resx files can be dropped in to localize for different languages. However this new system currently [doesn't play nice with class libraries](https://github.com/aspnet/Localization/issues/157), it only works well for localizing things that are part of the main web application.
-
-Given my vision for building apps from class library/nuget components this new system doesn't really do what I want even if the bugs affecting class libraries were fixed. I want to be able to drop resx files into the main application to localize any of my components no matter whether they are pulled in from nuget or baked right into the main web application, I want something more like the old App_GlobalResources folder. I want to be able to embed localized resources into my class library projects of course, but if I don't have an embedded resx for a particular language I want it to be possible to drop one into the main application and have it work so that it is easy for people who speak other languages to create and add their own resx files, and ideally share them back with me so I can share them with others who may need them.
-
-In fact, when it comes to strings for buttons and labels, people often want to customize them in addition to localizing them, so if someone wants different labels or doesn't like the current translations I have embedded, they should be able to override them by dropping in their own custom resx file.
-
-To make this possible I have implemented [GlobalResourceManagerStringLocalizerFactory](https://github.com/joeaudette/cloudscribe.Web.Localization/blob/master/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizerFactory.cs), and [GlobalResourceManagerStringLocalizer](https://github.com/joeaudette/cloudscribe.Web.Localization/blob/master/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizer.cs). By default this will check the global resources in the application resource folder first for a localized string and if not found it will fall back to checking for embedded resources in the class library. If you don't care about customizing, it is also possible by configuration to make it use embedded resources first and fall back to global resources. For the main web application it only checks the configured application resource folder, so it has the same behavior as the standard ResourceManagerStringLocalizerFactory when it comes to resources within the main web application.
-
-For those who may not want global resources like I do but who just want a workaround for the [rc2 class library bugs in ResourceManagerStringLocalizerFactory](https://github.com/aspnet/Localization/issues/157), this project also includes [PatchedResourceManagerStringLocalizerFactory](https://github.com/joeaudette/cloudscribe.Web.Localization/blob/master/src/cloudscribe.Web.Localization/PatchedResourceManagerStringLocalizerFactory.cs)
-
-## Installation
-
-In your project.json file add a dependency
-
- "cloudscribe.Web.Localization": "1.0.0-*"
-
-In your Startup.cs in ConfigureServices add this:
-
- // these 2 lines are the only part unique to this project and must be added first
- services.Configure(Configuration.GetSection("GlobalResourceOptions"));
- services.AddSingleton();
-
- // you must configure a folder where the resx files will live, it can be named as you like
- services.AddLocalization(options => options.ResourcesPath = "Resources" );
- services.Configure(options =>
- {
- var supportedCultures = new[]
- {
- new CultureInfo("en-US"),
- new CultureInfo("en"),
- new CultureInfo("fr-FR"),
- new CultureInfo("fr"),
- };
-
- // State what the default culture for your application is. This will be used if no specific culture
- // can be determined for a given request.
- options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
-
- // You must explicitly state which cultures your application supports.
- // These are the cultures the app supports for formatting numbers, dates, etc.
- options.SupportedCultures = supportedCultures;
-
- // These are the cultures the app supports for UI strings, i.e. we have localized resources for.
- options.SupportedUICultures = supportedCultures;
-
- // You can change which providers are configured to determine the culture for requests, or even add a custom
- // provider with your own logic. The providers will be asked in order to provide a culture for each request,
- // and the first to provide a non-null result that is in the configured supported cultures list will be used.
- // By default, the following built-in providers are configured:
- // - QueryStringRequestCultureProvider, sets culture via "culture" and "ui-culture" query string values, useful for testing
- // - CookieRequestCultureProvider, sets culture via "ASPNET_CULTURE" cookie
- // - AcceptLanguageHeaderRequestCultureProvider, sets culture via the "Accept-Language" request header
- //options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
- //{
- // // My custom request culture logic
- // return new ProviderCultureResult("en");
- //}));
- });
-
-In the main Configure method of Startup.cs you need this:
-
- // this gets the options we configured above
- var locOptions = app.ApplicationServices.GetService>();
- // make sure this is before app.UseMvc
- app.UseRequestLocalization(locOptions.Value);
-
-If you don't want to use global resources in preference to embedded resources in class libraries, but only want fallback to global resources change this to false in your appSettings.json, the default is true to allow customization in addition to localization.
-
- "GlobalResourceOptions": {
- "TryGlobalFirst": "true"
- }
-
-Now if you develop class library projects with Controllers that you want to localize, you can add resx files into the main web application to localize your controllers even though they live in a class library.
-
-Note that adding new resx files to your application requires re-publishing the web application. This is not as ideal as I would like it to be, but I adding a new language is an infrequent activity so having to re-publish is probably not a huge burden in most cases, and it makes sense that the framework is not optimized for infrequent activities. The end result is that resx files are all pre-compiled which means they need no post deployment compilation and therefore adding more languages should not impact application startup performance like it did in the old days with App_GlobalResources folder when the ASP.NET Compiler had to compile all the .resx files at startup time.
-
-To more fully understand ASP.NET Core localization be sure to [read the docs](https://docs.asp.net/en/latest/fundamentals/localization.html), to more fully understand cloudscribe.Web.Localization, study the localization.WebApp project in this repository which has examples showing how to localize a class library and how to override the class library localization from the main web application.
+# cloudscribe.Web.Localization - more flexible localization for ASP.NET Core
+
+I developed this project to meet my localization goals for [cloudscribe.Core](https://github.com/joeaudette/cloudscribe) and [cloudscribe.SimpleContent](https://github.com/joeaudette/cloudscribe.SimpleContent). However it has no dependencies on other cloudscribe components and can be used by anyone who wants the provided functionality. Get the big picture on cloudscribe projects at [cloudscribe.com](https://www.cloudscribe.com)
+
+If you have questions please visit our community forums https://www.cloudscribe.com/forum
+
+### Build Status
+
+
+
+[](https://github.com/cloudscribe/cloudscribe.Web.Localization/actions/workflows/cloudscribe-develop.yml)
+
+
+## Rationale
+
+My vision for composing web applications is to build separate components for each feature or purpose in separate class library projects, packaged as nugets that one can bring into their main web application to add functionality. The main web application may or may not have its own features that it implements, but much or most of the functionality will come from class library projects that are pulled in as nuget dependencies.
+
+The [new localization system for ASP.NET Core](https://docs.asp.net/en/latest/fundamentals/localization.html) allows you to configure a folder where resx files can be dropped in to localize for different languages. However this new system currently [doesn't play nice with class libraries](https://github.com/aspnet/Localization/issues/157), it only works well for localizing things that are part of the main web application.
+
+Given my vision for building apps from class library/nuget components this new system doesn't really do what I want even if the bugs affecting class libraries were fixed. I want to be able to drop resx files into the main application to localize any of my components no matter whether they are pulled in from nuget or baked right into the main web application, I want something more like the old App_GlobalResources folder. I want to be able to embed localized resources into my class library projects of course, but if I don't have an embedded resx for a particular language I want it to be possible to drop one into the main application and have it work so that it is easy for people who speak other languages to create and add their own resx files, and ideally share them back with me so I can share them with others who may need them.
+
+In fact, when it comes to strings for buttons and labels, people often want to customize them in addition to localizing them, so if someone wants different labels or doesn't like the current translations I have embedded, they should be able to override them by dropping in their own custom resx file.
+
+To make this possible I have implemented [GlobalResourceManagerStringLocalizerFactory](https://github.com/joeaudette/cloudscribe.Web.Localization/blob/master/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizerFactory.cs), and [GlobalResourceManagerStringLocalizer](https://github.com/joeaudette/cloudscribe.Web.Localization/blob/master/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizer.cs). By default this will check the global resources in the application resource folder first for a localized string and if not found it will fall back to checking for embedded resources in the class library. If you don't care about customizing, it is also possible by configuration to make it use embedded resources first and fall back to global resources. For the main web application it only checks the configured application resource folder, so it has the same behavior as the standard ResourceManagerStringLocalizerFactory when it comes to resources within the main web application.
+
+For those who may not want global resources like I do but who just want a workaround for the [rc2 class library bugs in ResourceManagerStringLocalizerFactory](https://github.com/aspnet/Localization/issues/157), this project also includes [PatchedResourceManagerStringLocalizerFactory](https://github.com/joeaudette/cloudscribe.Web.Localization/blob/master/src/cloudscribe.Web.Localization/PatchedResourceManagerStringLocalizerFactory.cs)
+
+## Installation
+
+In your project.json file add a dependency
+
+ "cloudscribe.Web.Localization": "1.0.0-*"
+
+In your Startup.cs in ConfigureServices add this:
+
+ // these 2 lines are the only part unique to this project and must be added first
+ services.Configure(Configuration.GetSection("GlobalResourceOptions"));
+ services.AddSingleton();
+
+ // you must configure a folder where the resx files will live, it can be named as you like
+ services.AddLocalization(options => options.ResourcesPath = "Resources" );
+ services.Configure(options =>
+ {
+ var supportedCultures = new[]
+ {
+ new CultureInfo("en-US"),
+ new CultureInfo("en"),
+ new CultureInfo("fr-FR"),
+ new CultureInfo("fr"),
+ };
+
+ // State what the default culture for your application is. This will be used if no specific culture
+ // can be determined for a given request.
+ options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
+
+ // You must explicitly state which cultures your application supports.
+ // These are the cultures the app supports for formatting numbers, dates, etc.
+ options.SupportedCultures = supportedCultures;
+
+ // These are the cultures the app supports for UI strings, i.e. we have localized resources for.
+ options.SupportedUICultures = supportedCultures;
+
+ // You can change which providers are configured to determine the culture for requests, or even add a custom
+ // provider with your own logic. The providers will be asked in order to provide a culture for each request,
+ // and the first to provide a non-null result that is in the configured supported cultures list will be used.
+ // By default, the following built-in providers are configured:
+ // - QueryStringRequestCultureProvider, sets culture via "culture" and "ui-culture" query string values, useful for testing
+ // - CookieRequestCultureProvider, sets culture via "ASPNET_CULTURE" cookie
+ // - AcceptLanguageHeaderRequestCultureProvider, sets culture via the "Accept-Language" request header
+ //options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
+ //{
+ // // My custom request culture logic
+ // return new ProviderCultureResult("en");
+ //}));
+ });
+
+In the main Configure method of Startup.cs you need this:
+
+ // this gets the options we configured above
+ var locOptions = app.ApplicationServices.GetService>();
+ // make sure this is before app.UseMvc
+ app.UseRequestLocalization(locOptions.Value);
+
+If you don't want to use global resources in preference to embedded resources in class libraries, but only want fallback to global resources change this to false in your appSettings.json, the default is true to allow customization in addition to localization.
+
+ "GlobalResourceOptions": {
+ "TryGlobalFirst": "true"
+ }
+
+Now if you develop class library projects with Controllers that you want to localize, you can add resx files into the main web application to localize your controllers even though they live in a class library.
+
+Note that adding new resx files to your application requires re-publishing the web application. This is not as ideal as I would like it to be, but I adding a new language is an infrequent activity so having to re-publish is probably not a huge burden in most cases, and it makes sense that the framework is not optimized for infrequent activities. The end result is that resx files are all pre-compiled which means they need no post deployment compilation and therefore adding more languages should not impact application startup performance like it did in the old days with App_GlobalResources folder when the ASP.NET Compiler had to compile all the .resx files at startup time.
+
+To more fully understand ASP.NET Core localization be sure to [read the docs](https://docs.asp.net/en/latest/fundamentals/localization.html), to more fully understand cloudscribe.Web.Localization, study the localization.WebApp project in this repository which has examples showing how to localize a class library and how to override the class library localization from the main web application.
diff --git a/appveyor.yml b/appveyor.yml
index 1bbd937..d3a24f6 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,17 +1,17 @@
-image: Visual Studio 2022
-environment:
- nodejs_version: "13.0.1"
-# Install scripts. (runs after repo cloning)
-install:
- # Get the latest stable version of Node.js or io.js
- - ps: Install-Product node $env:nodejs_version
- - ps: $env:BuildNumber= $env:APPVEYOR_BUILD_NUMBER
-init:
- - git config --global core.autocrlf true
-build_script:
- - dotnet restore
- - dotnet build -c Release
-test: off
-
-
+image: Visual Studio 2022
+environment:
+ nodejs_version: "13.0.1"
+# Install scripts. (runs after repo cloning)
+install:
+ # Get the latest stable version of Node.js or io.js
+ - ps: Install-Product node $env:nodejs_version
+ - ps: $env:BuildNumber= $env:APPVEYOR_BUILD_NUMBER
+init:
+ - git config --global core.autocrlf true
+build_script:
+ - dotnet restore
+ - dotnet build -c Release
+test: off
+
+
\ No newline at end of file
diff --git a/cloudscribe.Web.Localization.sln b/cloudscribe.Web.Localization.sln
index 19e36a6..ab7e528 100644
--- a/cloudscribe.Web.Localization.sln
+++ b/cloudscribe.Web.Localization.sln
@@ -1,43 +1,43 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26228.4
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0C7E9264-4D14-4C55-9977-BF059274911C}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7ABB5493-BB15-4693-BD7D-2F189E5C74DA}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "localization.WebApp", "src\localization.WebApp\localization.WebApp.csproj", "{638EEC84-755B-47A4-B952-A220082C4224}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebLib", "src\WebLib\WebLib.csproj", "{70D6D992-BC7E-4EBA-9D22-601D5892A88D}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cloudscribe.Web.Localization", "src\cloudscribe.Web.Localization\cloudscribe.Web.Localization.csproj", "{BAFDA9D4-64A4-43CA-8F33-E6BF44824608}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {638EEC84-755B-47A4-B952-A220082C4224}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {638EEC84-755B-47A4-B952-A220082C4224}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {638EEC84-755B-47A4-B952-A220082C4224}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {638EEC84-755B-47A4-B952-A220082C4224}.Release|Any CPU.Build.0 = Release|Any CPU
- {70D6D992-BC7E-4EBA-9D22-601D5892A88D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {70D6D992-BC7E-4EBA-9D22-601D5892A88D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {70D6D992-BC7E-4EBA-9D22-601D5892A88D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {70D6D992-BC7E-4EBA-9D22-601D5892A88D}.Release|Any CPU.Build.0 = Release|Any CPU
- {BAFDA9D4-64A4-43CA-8F33-E6BF44824608}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BAFDA9D4-64A4-43CA-8F33-E6BF44824608}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BAFDA9D4-64A4-43CA-8F33-E6BF44824608}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BAFDA9D4-64A4-43CA-8F33-E6BF44824608}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {638EEC84-755B-47A4-B952-A220082C4224} = {0C7E9264-4D14-4C55-9977-BF059274911C}
- {70D6D992-BC7E-4EBA-9D22-601D5892A88D} = {0C7E9264-4D14-4C55-9977-BF059274911C}
- {BAFDA9D4-64A4-43CA-8F33-E6BF44824608} = {0C7E9264-4D14-4C55-9977-BF059274911C}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.4
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0C7E9264-4D14-4C55-9977-BF059274911C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7ABB5493-BB15-4693-BD7D-2F189E5C74DA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "localization.WebApp", "src\localization.WebApp\localization.WebApp.csproj", "{638EEC84-755B-47A4-B952-A220082C4224}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebLib", "src\WebLib\WebLib.csproj", "{70D6D992-BC7E-4EBA-9D22-601D5892A88D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cloudscribe.Web.Localization", "src\cloudscribe.Web.Localization\cloudscribe.Web.Localization.csproj", "{BAFDA9D4-64A4-43CA-8F33-E6BF44824608}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {638EEC84-755B-47A4-B952-A220082C4224}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {638EEC84-755B-47A4-B952-A220082C4224}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {638EEC84-755B-47A4-B952-A220082C4224}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {638EEC84-755B-47A4-B952-A220082C4224}.Release|Any CPU.Build.0 = Release|Any CPU
+ {70D6D992-BC7E-4EBA-9D22-601D5892A88D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {70D6D992-BC7E-4EBA-9D22-601D5892A88D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {70D6D992-BC7E-4EBA-9D22-601D5892A88D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {70D6D992-BC7E-4EBA-9D22-601D5892A88D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAFDA9D4-64A4-43CA-8F33-E6BF44824608}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAFDA9D4-64A4-43CA-8F33-E6BF44824608}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAFDA9D4-64A4-43CA-8F33-E6BF44824608}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAFDA9D4-64A4-43CA-8F33-E6BF44824608}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {638EEC84-755B-47A4-B952-A220082C4224} = {0C7E9264-4D14-4C55-9977-BF059274911C}
+ {70D6D992-BC7E-4EBA-9D22-601D5892A88D} = {0C7E9264-4D14-4C55-9977-BF059274911C}
+ {BAFDA9D4-64A4-43CA-8F33-E6BF44824608} = {0C7E9264-4D14-4C55-9977-BF059274911C}
+ EndGlobalSection
+EndGlobal
diff --git a/src/WebLib/Controllers.BarController.fr.resx b/src/WebLib/Controllers.BarController.fr.resx
index 7913add..ec9a3bf 100644
--- a/src/WebLib/Controllers.BarController.fr.resx
+++ b/src/WebLib/Controllers.BarController.fr.resx
@@ -1,123 +1,123 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- mon dieux, dis le controller du bar - embedded resource
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ mon dieux, dis le controller du bar - embedded resource
+
\ No newline at end of file
diff --git a/src/WebLib/Controllers.OtherController.fr.resx b/src/WebLib/Controllers.OtherController.fr.resx
index 7c7b037..ce16951 100644
--- a/src/WebLib/Controllers.OtherController.fr.resx
+++ b/src/WebLib/Controllers.OtherController.fr.resx
@@ -1,126 +1,126 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- outrez vous
-
-
- outrez moi - this is an embedded resx file
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ outrez vous
+
+
+ outrez moi - this is an embedded resx file
+
\ No newline at end of file
diff --git a/src/WebLib/Controllers/BarController.cs b/src/WebLib/Controllers/BarController.cs
index 2d5fee0..76f5911 100644
--- a/src/WebLib/Controllers/BarController.cs
+++ b/src/WebLib/Controllers/BarController.cs
@@ -1,29 +1,29 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Localization;
-
-namespace WebLib.Controllers
-{
- public class BarController : Controller
- {
- public BarController(
- IStringLocalizer localizer)
- {
- _localizer = localizer;
- }
-
- private readonly IStringLocalizer _localizer;
-
- public IActionResult Index()
- {
- ViewData["Title"] = _localizer["bar"];
- ViewData["Message"] = _localizer["this is the bar controller"];
-
- return View();
- }
-
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Localization;
+
+namespace WebLib.Controllers
+{
+ public class BarController : Controller
+ {
+ public BarController(
+ IStringLocalizer localizer)
+ {
+ _localizer = localizer;
+ }
+
+ private readonly IStringLocalizer _localizer;
+
+ public IActionResult Index()
+ {
+ ViewData["Title"] = _localizer["bar"];
+ ViewData["Message"] = _localizer["this is the bar controller"];
+
+ return View();
+ }
+
+ }
+}
diff --git a/src/WebLib/Controllers/BazController.cs b/src/WebLib/Controllers/BazController.cs
index fe573d4..20ab5d8 100644
--- a/src/WebLib/Controllers/BazController.cs
+++ b/src/WebLib/Controllers/BazController.cs
@@ -1,28 +1,28 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Localization;
-
-namespace WebLib.Controllers
-{
- public class BazController : Controller
- {
- public BazController(
- IStringLocalizerFactory localizerFactory)
- {
- _localizer = localizerFactory.Create("Controllers.BazController", "WebLib");
- }
-
- private readonly IStringLocalizer _localizer;
-
- public IActionResult Index()
- {
- ViewData["Title"] = _localizer["Baz"];
- ViewData["Message"] = _localizer["Greetings from Baz"];
-
- return View();
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Localization;
+
+namespace WebLib.Controllers
+{
+ public class BazController : Controller
+ {
+ public BazController(
+ IStringLocalizerFactory localizerFactory)
+ {
+ _localizer = localizerFactory.Create("Controllers.BazController", "WebLib");
+ }
+
+ private readonly IStringLocalizer _localizer;
+
+ public IActionResult Index()
+ {
+ ViewData["Title"] = _localizer["Baz"];
+ ViewData["Message"] = _localizer["Greetings from Baz"];
+
+ return View();
+ }
+ }
+}
diff --git a/src/WebLib/Controllers/FooController.cs b/src/WebLib/Controllers/FooController.cs
index 643f988..c79989f 100644
--- a/src/WebLib/Controllers/FooController.cs
+++ b/src/WebLib/Controllers/FooController.cs
@@ -1,25 +1,25 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Localization;
-
-namespace WebLib.Controllers
-{
- public class FooController : Controller
- {
- public FooController(
- IStringLocalizerFactory localizerFactory
- )
- {
- _localizer = localizerFactory.Create("MyResources.Controllers.FooController", "WebLib");
- }
-
- private readonly IStringLocalizer _localizer;
-
- public IActionResult Index()
- {
- ViewData["Title"] = _localizer["Foo"];
- ViewData["Message"] = _localizer["Greetings ya'll"];
-
- return View();
- }
- }
-}
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Localization;
+
+namespace WebLib.Controllers
+{
+ public class FooController : Controller
+ {
+ public FooController(
+ IStringLocalizerFactory localizerFactory
+ )
+ {
+ _localizer = localizerFactory.Create("MyResources.Controllers.FooController", "WebLib");
+ }
+
+ private readonly IStringLocalizer _localizer;
+
+ public IActionResult Index()
+ {
+ ViewData["Title"] = _localizer["Foo"];
+ ViewData["Message"] = _localizer["Greetings ya'll"];
+
+ return View();
+ }
+ }
+}
diff --git a/src/WebLib/Controllers/MessageController.cs b/src/WebLib/Controllers/MessageController.cs
index d7a46fc..1323514 100644
--- a/src/WebLib/Controllers/MessageController.cs
+++ b/src/WebLib/Controllers/MessageController.cs
@@ -1,23 +1,23 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Localization;
-using WebLib.ViewModels;
-
-namespace WebLib.Controllers
-{
- public class MessageController : Controller
- {
-
- public IActionResult Index()
- {
- ViewData["Title"] = "Message";
-
- var model = new ContactMessageViewModel();
-
- return View(model);
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Localization;
+using WebLib.ViewModels;
+
+namespace WebLib.Controllers
+{
+ public class MessageController : Controller
+ {
+
+ public IActionResult Index()
+ {
+ ViewData["Title"] = "Message";
+
+ var model = new ContactMessageViewModel();
+
+ return View(model);
+ }
+ }
+}
diff --git a/src/WebLib/Controllers/OtherController.cs b/src/WebLib/Controllers/OtherController.cs
index 0ec6df4..70ef4ce 100644
--- a/src/WebLib/Controllers/OtherController.cs
+++ b/src/WebLib/Controllers/OtherController.cs
@@ -1,25 +1,25 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Localization;
-
-namespace WebLib.Controllers
-{
- public class OtherController : Controller
- {
- public OtherController(
- IStringLocalizer localizer
- )
- {
- _localizer = localizer;
- }
-
- private readonly IStringLocalizer _localizer;
-
- public IActionResult Index()
- {
- ViewData["Title"] = _localizer["Otherwise"];
- ViewData["Message"] = _localizer["this is the other one"];
-
- return View();
- }
- }
-}
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Localization;
+
+namespace WebLib.Controllers
+{
+ public class OtherController : Controller
+ {
+ public OtherController(
+ IStringLocalizer localizer
+ )
+ {
+ _localizer = localizer;
+ }
+
+ private readonly IStringLocalizer _localizer;
+
+ public IActionResult Index()
+ {
+ ViewData["Title"] = _localizer["Otherwise"];
+ ViewData["Message"] = _localizer["this is the other one"];
+
+ return View();
+ }
+ }
+}
diff --git a/src/WebLib/MyResources/Controllers.FooController.fr.resx b/src/WebLib/MyResources/Controllers.FooController.fr.resx
index 543cb41..dcb6c62 100644
--- a/src/WebLib/MyResources/Controllers.FooController.fr.resx
+++ b/src/WebLib/MyResources/Controllers.FooController.fr.resx
@@ -1,126 +1,126 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Fooeh
-
-
- Comment allez vouz ya'll frenchies - this is embedded in webLib
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Fooeh
+
+
+ Comment allez vouz ya'll frenchies - this is embedded in webLib
+
\ No newline at end of file
diff --git a/src/WebLib/ViewModels/ContactMessageViewModel.cs b/src/WebLib/ViewModels/ContactMessageViewModel.cs
index ad55994..9aa5370 100644
--- a/src/WebLib/ViewModels/ContactMessageViewModel.cs
+++ b/src/WebLib/ViewModels/ContactMessageViewModel.cs
@@ -1,24 +1,24 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace WebLib.ViewModels
-{
- public class ContactMessageViewModel
- {
-
- [Required(ErrorMessage = "The Name field is required.")]
- public string Name { get; set; }
-
- [Required(ErrorMessage = "The Email field is required.")]
- [EmailAddress]
- public string Email { get; set; }
-
- public string Subject { get; set; }
-
- [Required(ErrorMessage = "The Message field is required.")]
- public string Message { get; set; }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace WebLib.ViewModels
+{
+ public class ContactMessageViewModel
+ {
+
+ [Required(ErrorMessage = "The Name field is required.")]
+ public string Name { get; set; }
+
+ [Required(ErrorMessage = "The Email field is required.")]
+ [EmailAddress]
+ public string Email { get; set; }
+
+ public string Subject { get; set; }
+
+ [Required(ErrorMessage = "The Message field is required.")]
+ public string Message { get; set; }
+ }
+}
diff --git a/src/WebLib/Views/Bar/Index.cshtml b/src/WebLib/Views/Bar/Index.cshtml
index 04ef453..4f33aa7 100644
--- a/src/WebLib/Views/Bar/Index.cshtml
+++ b/src/WebLib/Views/Bar/Index.cshtml
@@ -1,7 +1,7 @@
-@*
- For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
-*@
-@{
-}
-
+@*
+ For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
+*@
+@{
+}
+
@ViewData["Message"]
\ No newline at end of file
diff --git a/src/WebLib/Views/Baz/Index.cshtml b/src/WebLib/Views/Baz/Index.cshtml
index 04ef453..4f33aa7 100644
--- a/src/WebLib/Views/Baz/Index.cshtml
+++ b/src/WebLib/Views/Baz/Index.cshtml
@@ -1,7 +1,7 @@
-@*
- For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
-*@
-@{
-}
-
+@*
+ For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
+*@
+@{
+}
+
@ViewData["Message"]
\ No newline at end of file
diff --git a/src/WebLib/Views/Foo/Index.cshtml b/src/WebLib/Views/Foo/Index.cshtml
index 0d5ee88..6f32df5 100644
--- a/src/WebLib/Views/Foo/Index.cshtml
+++ b/src/WebLib/Views/Foo/Index.cshtml
@@ -1,7 +1,7 @@
-@using Microsoft.Extensions.Localization
-@inject IStringLocalizer sr
-
-
-
Hello there from Foo!
-
@ViewData["Message"]
+@using Microsoft.Extensions.Localization
+@inject IStringLocalizer sr
+
+
+
Hello there from Foo!
+
@ViewData["Message"]
@sr["how do I love thee, let me count the ways"]
\ No newline at end of file
diff --git a/src/WebLib/Views/Other/Index.cshtml b/src/WebLib/Views/Other/Index.cshtml
index d4ae117..4e57bd1 100644
--- a/src/WebLib/Views/Other/Index.cshtml
+++ b/src/WebLib/Views/Other/Index.cshtml
@@ -1,8 +1,8 @@
-@*
- For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
-*@
-@{
-}
-
-
Hello there from Other controller!
+@*
+ For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
+*@
+@{
+}
+
+
Hello there from Other controller!
@ViewData["Message"]
\ No newline at end of file
diff --git a/src/WebLib/WebLib.csproj b/src/WebLib/WebLib.csproj
index 7b1a773..b91d061 100644
--- a/src/WebLib/WebLib.csproj
+++ b/src/WebLib/WebLib.csproj
@@ -1,19 +1,19 @@
-
-
-
- net8.0
- true
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ net8.0
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/WebLib/WebLibSharedResources.cs b/src/WebLib/WebLibSharedResources.cs
index cd0b41b..033d80f 100644
--- a/src/WebLib/WebLibSharedResources.cs
+++ b/src/WebLib/WebLibSharedResources.cs
@@ -1,15 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace WebLib
-{
- ///
- /// the only purpose of this class is as a placeholder for shared resources
- /// ie by asking for IStringLocalizer
- ///
- public class WebLibSharedResources
- {
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace WebLib
+{
+ ///
+ /// the only purpose of this class is as a placeholder for shared resources
+ /// ie by asking for IStringLocalizer
+ ///
+ public class WebLibSharedResources
+ {
+ }
+}
diff --git a/src/cloudscribe.Web.Localization/CultureSegmentRouteConstraint.cs b/src/cloudscribe.Web.Localization/CultureSegmentRouteConstraint.cs
index 3014660..aba1ce3 100644
--- a/src/cloudscribe.Web.Localization/CultureSegmentRouteConstraint.cs
+++ b/src/cloudscribe.Web.Localization/CultureSegmentRouteConstraint.cs
@@ -1,102 +1,102 @@
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Routing;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace cloudscribe.Web.Localization
-{
- public class CultureSegmentRouteConstraint : IRouteConstraint
- {
- public CultureSegmentRouteConstraint(bool useSecondSegment = false)
- {
- _useSecondSegment = useSecondSegment;
- }
-
- private bool _useSecondSegment;
-
- public bool Match(
- HttpContext httpContext,
- IRouter route,
- string routeKey,
- RouteValueDictionary values,
- RouteDirection routeDirection)
- {
- if (httpContext == null) { return false; }
-
-
-
- string requestFolder = GetStartingSegment(httpContext.Request.Path);
-
- if (!string.IsNullOrWhiteSpace(requestFolder))
- {
- var logger = httpContext.RequestServices.GetService>();
-
- var cultureSettingsAccessor = httpContext.RequestServices.GetService>();
- var cultureSettings = cultureSettingsAccessor.Value;
- var found = cultureSettings.SupportedUICultures.Where(x =>
- x.Name.Equals(requestFolder,System.StringComparison.InvariantCultureIgnoreCase)
- || x.TwoLetterISOLanguageName.Equals(requestFolder, System.StringComparison.InvariantCultureIgnoreCase )
- ).Any();
-
- var isDefaultCulture = cultureSettings.DefaultRequestCulture.UICulture.Name.Equals(requestFolder, System.StringComparison.InvariantCultureIgnoreCase)
- || cultureSettings.DefaultRequestCulture.UICulture.TwoLetterISOLanguageName.Equals(requestFolder, System.StringComparison.InvariantCultureIgnoreCase);
-
-
-
- //don't match default culture because we don't want the culture segment in the url for the default culture
- if (found && !isDefaultCulture)
- {
- logger.LogDebug($"matched culture route constraint for path {httpContext.Request.Path}");
-
- return true;
- }
-
- logger.LogDebug($"did not match culture route constraint for path {httpContext.Request.Path}");
- }
-
-
- return false;
- }
-
- private string GetStartingSegment(string requestPath)
- {
- if (string.IsNullOrEmpty(requestPath)) return requestPath;
- if (!requestPath.Contains("/")) return requestPath;
-
- var segments = SplitOnCharAndTrim(requestPath, '/');
- if(_useSecondSegment)
- {
- if(segments.Count > 1)
- {
- return segments[1]; //second segment
- }
-
- return null;
- }
- else
- {
- return segments.FirstOrDefault();
- }
-
- }
-
- private List SplitOnCharAndTrim(string s, char c)
- {
- List list = new List();
- if (string.IsNullOrWhiteSpace(s)) { return list; }
-
- string[] a = s.Split(c);
- foreach (string item in a)
- {
- if (!string.IsNullOrWhiteSpace(item)) { list.Add(item.Trim()); }
- }
-
-
- return list;
- }
- }
-}
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace cloudscribe.Web.Localization
+{
+ public class CultureSegmentRouteConstraint : IRouteConstraint
+ {
+ public CultureSegmentRouteConstraint(bool useSecondSegment = false)
+ {
+ _useSecondSegment = useSecondSegment;
+ }
+
+ private bool _useSecondSegment;
+
+ public bool Match(
+ HttpContext httpContext,
+ IRouter route,
+ string routeKey,
+ RouteValueDictionary values,
+ RouteDirection routeDirection)
+ {
+ if (httpContext == null) { return false; }
+
+
+
+ string requestFolder = GetStartingSegment(httpContext.Request.Path);
+
+ if (!string.IsNullOrWhiteSpace(requestFolder))
+ {
+ var logger = httpContext.RequestServices.GetService>();
+
+ var cultureSettingsAccessor = httpContext.RequestServices.GetService>();
+ var cultureSettings = cultureSettingsAccessor.Value;
+ var found = cultureSettings.SupportedUICultures.Where(x =>
+ x.Name.Equals(requestFolder,System.StringComparison.InvariantCultureIgnoreCase)
+ || x.TwoLetterISOLanguageName.Equals(requestFolder, System.StringComparison.InvariantCultureIgnoreCase )
+ ).Any();
+
+ var isDefaultCulture = cultureSettings.DefaultRequestCulture.UICulture.Name.Equals(requestFolder, System.StringComparison.InvariantCultureIgnoreCase)
+ || cultureSettings.DefaultRequestCulture.UICulture.TwoLetterISOLanguageName.Equals(requestFolder, System.StringComparison.InvariantCultureIgnoreCase);
+
+
+
+ //don't match default culture because we don't want the culture segment in the url for the default culture
+ if (found && !isDefaultCulture)
+ {
+ logger.LogDebug($"matched culture route constraint for path {httpContext.Request.Path}");
+
+ return true;
+ }
+
+ logger.LogDebug($"did not match culture route constraint for path {httpContext.Request.Path}");
+ }
+
+
+ return false;
+ }
+
+ private string GetStartingSegment(string requestPath)
+ {
+ if (string.IsNullOrEmpty(requestPath)) return requestPath;
+ if (!requestPath.Contains("/")) return requestPath;
+
+ var segments = SplitOnCharAndTrim(requestPath, '/');
+ if(_useSecondSegment)
+ {
+ if(segments.Count > 1)
+ {
+ return segments[1]; //second segment
+ }
+
+ return null;
+ }
+ else
+ {
+ return segments.FirstOrDefault();
+ }
+
+ }
+
+ private List SplitOnCharAndTrim(string s, char c)
+ {
+ List list = new List();
+ if (string.IsNullOrWhiteSpace(s)) { return list; }
+
+ string[] a = s.Split(c);
+ foreach (string item in a)
+ {
+ if (!string.IsNullOrWhiteSpace(item)) { list.Add(item.Trim()); }
+ }
+
+
+ return list;
+ }
+ }
+}
diff --git a/src/cloudscribe.Web.Localization/FirstUrlSegmentRequestCultureProvider.cs b/src/cloudscribe.Web.Localization/FirstUrlSegmentRequestCultureProvider.cs
index 7ccbd11..de77ffe 100644
--- a/src/cloudscribe.Web.Localization/FirstUrlSegmentRequestCultureProvider.cs
+++ b/src/cloudscribe.Web.Localization/FirstUrlSegmentRequestCultureProvider.cs
@@ -1,78 +1,78 @@
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Localization;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace cloudscribe.Web.Localization
-{
- public class FirstUrlSegmentRequestCultureProvider : RequestCultureProvider
- {
- public FirstUrlSegmentRequestCultureProvider(
- IList supportedUICultures,
- IList supportedCultures = null
- )
- {
- _supportedUICultures = supportedUICultures;
- _supportedCultures = supportedCultures;
- }
-
- private readonly IList _supportedUICultures;
- private readonly IList _supportedCultures;
-
- public override Task DetermineProviderCultureResult(HttpContext httpContext)
- {
- var pathStartingSegment = GetStartingSegment(httpContext.Request.Path);
-
- if (!string.IsNullOrWhiteSpace(pathStartingSegment))
- {
- var matchingUICulture = _supportedUICultures.Where(x => x.Name.Equals(pathStartingSegment, System.StringComparison.InvariantCultureIgnoreCase)
- || x.TwoLetterISOLanguageName.Equals(pathStartingSegment, System.StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
-
- CultureInfo mainCulture = null;
- if (_supportedCultures != null)
- {
- mainCulture = _supportedCultures.Where(x => x.Name.Equals(pathStartingSegment, System.StringComparison.InvariantCultureIgnoreCase)
- || x.TwoLetterISOLanguageName.Equals(pathStartingSegment, System.StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
- }
- if (matchingUICulture != null)
- {
- if (mainCulture != null)
- {
- return Task.FromResult(new ProviderCultureResult(mainCulture.Name, matchingUICulture.Name));
- }
- return Task.FromResult(new ProviderCultureResult(matchingUICulture.Name, matchingUICulture.Name));
- }
- }
-
- //nothing matched
- return NullProviderCultureResult;
-
- }
-
- private string GetStartingSegment(string requestPath)
- {
- if (string.IsNullOrEmpty(requestPath)) return requestPath;
- if (!requestPath.Contains("/")) return requestPath;
-
- var segments = SplitOnCharAndTrim(requestPath, '/');
- return segments.FirstOrDefault();
- }
-
- private List SplitOnCharAndTrim(string s, char c)
- {
- List list = new List();
- if (string.IsNullOrWhiteSpace(s)) { return list; }
-
- string[] a = s.Split(c);
- foreach (string item in a)
- {
- if (!string.IsNullOrWhiteSpace(item)) { list.Add(item.Trim()); }
- }
-
-
- return list;
- }
- }
-}
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Localization;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace cloudscribe.Web.Localization
+{
+ public class FirstUrlSegmentRequestCultureProvider : RequestCultureProvider
+ {
+ public FirstUrlSegmentRequestCultureProvider(
+ IList supportedUICultures,
+ IList supportedCultures = null
+ )
+ {
+ _supportedUICultures = supportedUICultures;
+ _supportedCultures = supportedCultures;
+ }
+
+ private readonly IList _supportedUICultures;
+ private readonly IList _supportedCultures;
+
+ public override Task DetermineProviderCultureResult(HttpContext httpContext)
+ {
+ var pathStartingSegment = GetStartingSegment(httpContext.Request.Path);
+
+ if (!string.IsNullOrWhiteSpace(pathStartingSegment))
+ {
+ var matchingUICulture = _supportedUICultures.Where(x => x.Name.Equals(pathStartingSegment, System.StringComparison.InvariantCultureIgnoreCase)
+ || x.TwoLetterISOLanguageName.Equals(pathStartingSegment, System.StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
+
+ CultureInfo mainCulture = null;
+ if (_supportedCultures != null)
+ {
+ mainCulture = _supportedCultures.Where(x => x.Name.Equals(pathStartingSegment, System.StringComparison.InvariantCultureIgnoreCase)
+ || x.TwoLetterISOLanguageName.Equals(pathStartingSegment, System.StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
+ }
+ if (matchingUICulture != null)
+ {
+ if (mainCulture != null)
+ {
+ return Task.FromResult(new ProviderCultureResult(mainCulture.Name, matchingUICulture.Name));
+ }
+ return Task.FromResult(new ProviderCultureResult(matchingUICulture.Name, matchingUICulture.Name));
+ }
+ }
+
+ //nothing matched
+ return NullProviderCultureResult;
+
+ }
+
+ private string GetStartingSegment(string requestPath)
+ {
+ if (string.IsNullOrEmpty(requestPath)) return requestPath;
+ if (!requestPath.Contains("/")) return requestPath;
+
+ var segments = SplitOnCharAndTrim(requestPath, '/');
+ return segments.FirstOrDefault();
+ }
+
+ private List SplitOnCharAndTrim(string s, char c)
+ {
+ List list = new List();
+ if (string.IsNullOrWhiteSpace(s)) { return list; }
+
+ string[] a = s.Split(c);
+ foreach (string item in a)
+ {
+ if (!string.IsNullOrWhiteSpace(item)) { list.Add(item.Trim()); }
+ }
+
+
+ return list;
+ }
+ }
+}
diff --git a/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizer.cs b/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizer.cs
index 0726e5e..7cadc13 100644
--- a/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizer.cs
+++ b/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizer.cs
@@ -1,313 +1,313 @@
-using System;
-using System.Collections;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Reflection;
-using System.Resources;
-
-//https://github.com/aspnet/Localization/blob/dev/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizer.cs
-
-namespace Microsoft.Extensions.Localization
-{
- ///
- /// An that uses the and
- /// to provide localized strings.
- ///
- /// This type is thread-safe.
- public class GlobalResourceManagerStringLocalizer : IStringLocalizer
- {
- private readonly ConcurrentDictionary _missingManifestCache = new ConcurrentDictionary();
- private readonly IResourceNamesCache _resourceNamesCache;
- private readonly ResourceManager _resourceManager;
- private readonly Assembly _resourceAssembly;
- private readonly string _resourceBaseName;
-
- private readonly ResourceManager _globalResourceManager;
- private readonly GlobalResourceOptions _globalResourceOptions;
-
-
-
- ///
- /// Creates a new .
- ///
- /// The to read strings from.
- /// The that contains the strings as embedded resources.
- /// The base name of the embedded resource in the that contains the strings.
- /// Cache of the list of strings for a given resource assembly name.
- /// The
- /// The global to read strings from.
- public GlobalResourceManagerStringLocalizer(
- ResourceManager resourceManager,
- Assembly resourceAssembly,
- string baseName,
- IResourceNamesCache resourceNamesCache,
- GlobalResourceOptions globalResourceOptions,
- ResourceManager globalResourceManager = null
- )
- {
- if (resourceManager == null)
- {
- throw new ArgumentNullException(nameof(resourceManager));
- }
-
- if (resourceAssembly == null)
- {
- throw new ArgumentNullException(nameof(resourceAssembly));
- }
-
- if (baseName == null)
- {
- throw new ArgumentNullException(nameof(baseName));
- }
-
- if (resourceNamesCache == null)
- {
- throw new ArgumentNullException(nameof(resourceNamesCache));
- }
-
- _resourceAssembly = resourceAssembly;
- _resourceManager = resourceManager;
- _resourceBaseName = baseName;
- _resourceNamesCache = resourceNamesCache;
-
- _globalResourceManager = globalResourceManager;
- _globalResourceOptions = globalResourceOptions;
-
-
- }
-
- ///
- public virtual LocalizedString this[string name]
- {
- get
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- var value = GetStringSafely(name, null);
- return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
- }
- }
-
- ///
- public virtual LocalizedString this[string name, params object[] arguments]
- {
- get
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- var format = GetStringSafely(name, null);
- var value = string.Format(format ?? name, arguments);
- return new LocalizedString(name, value, resourceNotFound: format == null);
- }
- }
-
- ///
- /// Creates a new for a specific .
- ///
- /// The to use.
- /// A culture-specific .
- public IStringLocalizer WithCulture(CultureInfo culture)
- {
- return culture == null
- ? new GlobalResourceManagerStringLocalizer(
- _resourceManager,
- _resourceAssembly,
- _resourceBaseName,
- _resourceNamesCache,
- _globalResourceOptions,
- _globalResourceManager
- )
- : new GlobalResourceManagerWithCultureStringLocalizer(
- _resourceManager,
- _resourceAssembly,
- _resourceBaseName,
- _resourceNamesCache,
- culture,
- _globalResourceOptions,
- _globalResourceManager
- );
- }
-
- ///
- public virtual IEnumerable GetAllStrings(bool includeParentCultures) =>
- GetAllStrings(includeParentCultures, CultureInfo.CurrentUICulture);
-
- ///
- /// Returns all strings in the specified culture.
- ///
- ///
- /// The to get strings for.
- /// The strings.
- protected IEnumerable GetAllStrings(bool includeParentCultures, CultureInfo culture)
- {
- if (culture == null)
- {
- throw new ArgumentNullException(nameof(culture));
- }
-
- var resourceNames = includeParentCultures
- ? GetResourceNamesFromCultureHierarchy(culture)
- : GetResourceNamesForCulture(culture);
-
- if (resourceNames == null && !includeParentCultures)
- {
- var resourceStreamName = GetResourceStreamName(culture);
- var message = string.Format("The manifest '{0}' was not found.", resourceStreamName);
- throw new MissingManifestResourceException(message);
- }
-
- foreach (var name in resourceNames)
- {
- var value = GetStringSafely(name, culture);
- yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
- }
- }
-
- ///
- /// Gets a resource string from the and returns null instead of
- /// throwing exceptions if a match isn't found.
- ///
- /// The name of the string resource.
- /// The to get the string for.
- /// The resource string, or null if none was found.
- protected string GetStringSafely(string name, CultureInfo culture)
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- var cacheKey = $"name={name}&culture={(culture ?? CultureInfo.CurrentUICulture).Name}";
-
- if (_missingManifestCache.ContainsKey(cacheKey))
- {
- return null;
- }
-
- if(_globalResourceOptions.TryGlobalFirst)
- {
- if (_globalResourceManager != null)
- {
- try
- {
- return culture == null ? _globalResourceManager.GetString(name) : _globalResourceManager.GetString(name, culture);
- }
- catch (MissingManifestResourceException) { }
-
- }
- }
-
- try
- {
- return culture == null ? _resourceManager.GetString(name) : _resourceManager.GetString(name, culture);
- }
- catch (MissingManifestResourceException)
- {
- if (!_globalResourceOptions.TryGlobalFirst)
- {
- if (_globalResourceManager != null)
- {
- try
- {
- return culture == null ? _globalResourceManager.GetString(name) : _globalResourceManager.GetString(name, culture);
- }
- catch (MissingManifestResourceException) { }
-
- }
- }
-
- _missingManifestCache.TryAdd(cacheKey, null);
- return null;
- }
- }
-
- private IEnumerable GetResourceNamesFromCultureHierarchy(CultureInfo startingCulture)
- {
- var currentCulture = startingCulture;
- var resourceNames = new HashSet();
-
- var hasAnyCultures = false;
-
- while (true)
- {
-
- var cultureResourceNames = GetResourceNamesForCulture(currentCulture);
-
- if (cultureResourceNames != null)
- {
- foreach (var resourceName in cultureResourceNames)
- {
- resourceNames.Add(resourceName);
- }
- hasAnyCultures = true;
- }
-
- if (currentCulture == currentCulture.Parent)
- {
- // currentCulture begat currentCulture, probably time to leave
- break;
- }
-
- currentCulture = currentCulture.Parent;
- }
-
- if (!hasAnyCultures)
- {
- throw new MissingManifestResourceException("No manifests exist for the current culture.");
- }
-
- return resourceNames;
- }
-
- private string GetResourceStreamName(CultureInfo culture)
- {
- var resourceStreamName = _resourceBaseName;
- if (!string.IsNullOrEmpty(culture.Name))
- {
- resourceStreamName += "." + culture.Name;
- }
- resourceStreamName += ".resources";
-
- return resourceStreamName;
- }
-
- private IList GetResourceNamesForCulture(CultureInfo culture)
- {
- var resourceStreamName = GetResourceStreamName(culture);
-
- var cacheKey = $"assembly={_resourceAssembly.FullName};resourceStreamName={resourceStreamName}";
-
- var cultureResourceNames = _resourceNamesCache.GetOrAdd(cacheKey, _ =>
- {
- using (var cultureResourceStream = _resourceAssembly.GetManifestResourceStream(resourceStreamName))
- {
- if (cultureResourceStream == null)
- {
- return null;
- }
-
- using (var resources = new ResourceReader(cultureResourceStream))
- {
- var names = new List();
- foreach (DictionaryEntry entry in resources)
- {
- var resourceName = (string)entry.Key;
- names.Add(resourceName);
- }
- return names;
- }
- }
-
- });
-
- return cultureResourceNames;
- }
- }
-}
+using System;
+using System.Collections;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Resources;
+
+//https://github.com/aspnet/Localization/blob/dev/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizer.cs
+
+namespace Microsoft.Extensions.Localization
+{
+ ///
+ /// An that uses the and
+ /// to provide localized strings.
+ ///
+ /// This type is thread-safe.
+ public class GlobalResourceManagerStringLocalizer : IStringLocalizer
+ {
+ private readonly ConcurrentDictionary _missingManifestCache = new ConcurrentDictionary();
+ private readonly IResourceNamesCache _resourceNamesCache;
+ private readonly ResourceManager _resourceManager;
+ private readonly Assembly _resourceAssembly;
+ private readonly string _resourceBaseName;
+
+ private readonly ResourceManager _globalResourceManager;
+ private readonly GlobalResourceOptions _globalResourceOptions;
+
+
+
+ ///
+ /// Creates a new .
+ ///
+ /// The to read strings from.
+ /// The that contains the strings as embedded resources.
+ /// The base name of the embedded resource in the that contains the strings.
+ /// Cache of the list of strings for a given resource assembly name.
+ /// The
+ /// The global to read strings from.
+ public GlobalResourceManagerStringLocalizer(
+ ResourceManager resourceManager,
+ Assembly resourceAssembly,
+ string baseName,
+ IResourceNamesCache resourceNamesCache,
+ GlobalResourceOptions globalResourceOptions,
+ ResourceManager globalResourceManager = null
+ )
+ {
+ if (resourceManager == null)
+ {
+ throw new ArgumentNullException(nameof(resourceManager));
+ }
+
+ if (resourceAssembly == null)
+ {
+ throw new ArgumentNullException(nameof(resourceAssembly));
+ }
+
+ if (baseName == null)
+ {
+ throw new ArgumentNullException(nameof(baseName));
+ }
+
+ if (resourceNamesCache == null)
+ {
+ throw new ArgumentNullException(nameof(resourceNamesCache));
+ }
+
+ _resourceAssembly = resourceAssembly;
+ _resourceManager = resourceManager;
+ _resourceBaseName = baseName;
+ _resourceNamesCache = resourceNamesCache;
+
+ _globalResourceManager = globalResourceManager;
+ _globalResourceOptions = globalResourceOptions;
+
+
+ }
+
+ ///
+ public virtual LocalizedString this[string name]
+ {
+ get
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ var value = GetStringSafely(name, null);
+ return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
+ }
+ }
+
+ ///
+ public virtual LocalizedString this[string name, params object[] arguments]
+ {
+ get
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ var format = GetStringSafely(name, null);
+ var value = string.Format(format ?? name, arguments);
+ return new LocalizedString(name, value, resourceNotFound: format == null);
+ }
+ }
+
+ ///
+ /// Creates a new for a specific .
+ ///
+ /// The to use.
+ /// A culture-specific .
+ public IStringLocalizer WithCulture(CultureInfo culture)
+ {
+ return culture == null
+ ? new GlobalResourceManagerStringLocalizer(
+ _resourceManager,
+ _resourceAssembly,
+ _resourceBaseName,
+ _resourceNamesCache,
+ _globalResourceOptions,
+ _globalResourceManager
+ )
+ : new GlobalResourceManagerWithCultureStringLocalizer(
+ _resourceManager,
+ _resourceAssembly,
+ _resourceBaseName,
+ _resourceNamesCache,
+ culture,
+ _globalResourceOptions,
+ _globalResourceManager
+ );
+ }
+
+ ///
+ public virtual IEnumerable GetAllStrings(bool includeParentCultures) =>
+ GetAllStrings(includeParentCultures, CultureInfo.CurrentUICulture);
+
+ ///
+ /// Returns all strings in the specified culture.
+ ///
+ ///
+ /// The to get strings for.
+ /// The strings.
+ protected IEnumerable GetAllStrings(bool includeParentCultures, CultureInfo culture)
+ {
+ if (culture == null)
+ {
+ throw new ArgumentNullException(nameof(culture));
+ }
+
+ var resourceNames = includeParentCultures
+ ? GetResourceNamesFromCultureHierarchy(culture)
+ : GetResourceNamesForCulture(culture);
+
+ if (resourceNames == null && !includeParentCultures)
+ {
+ var resourceStreamName = GetResourceStreamName(culture);
+ var message = string.Format("The manifest '{0}' was not found.", resourceStreamName);
+ throw new MissingManifestResourceException(message);
+ }
+
+ foreach (var name in resourceNames)
+ {
+ var value = GetStringSafely(name, culture);
+ yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
+ }
+ }
+
+ ///
+ /// Gets a resource string from the and returns null instead of
+ /// throwing exceptions if a match isn't found.
+ ///
+ /// The name of the string resource.
+ /// The to get the string for.
+ /// The resource string, or null if none was found.
+ protected string GetStringSafely(string name, CultureInfo culture)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ var cacheKey = $"name={name}&culture={(culture ?? CultureInfo.CurrentUICulture).Name}";
+
+ if (_missingManifestCache.ContainsKey(cacheKey))
+ {
+ return null;
+ }
+
+ if(_globalResourceOptions.TryGlobalFirst)
+ {
+ if (_globalResourceManager != null)
+ {
+ try
+ {
+ return culture == null ? _globalResourceManager.GetString(name) : _globalResourceManager.GetString(name, culture);
+ }
+ catch (MissingManifestResourceException) { }
+
+ }
+ }
+
+ try
+ {
+ return culture == null ? _resourceManager.GetString(name) : _resourceManager.GetString(name, culture);
+ }
+ catch (MissingManifestResourceException)
+ {
+ if (!_globalResourceOptions.TryGlobalFirst)
+ {
+ if (_globalResourceManager != null)
+ {
+ try
+ {
+ return culture == null ? _globalResourceManager.GetString(name) : _globalResourceManager.GetString(name, culture);
+ }
+ catch (MissingManifestResourceException) { }
+
+ }
+ }
+
+ _missingManifestCache.TryAdd(cacheKey, null);
+ return null;
+ }
+ }
+
+ private IEnumerable GetResourceNamesFromCultureHierarchy(CultureInfo startingCulture)
+ {
+ var currentCulture = startingCulture;
+ var resourceNames = new HashSet();
+
+ var hasAnyCultures = false;
+
+ while (true)
+ {
+
+ var cultureResourceNames = GetResourceNamesForCulture(currentCulture);
+
+ if (cultureResourceNames != null)
+ {
+ foreach (var resourceName in cultureResourceNames)
+ {
+ resourceNames.Add(resourceName);
+ }
+ hasAnyCultures = true;
+ }
+
+ if (currentCulture == currentCulture.Parent)
+ {
+ // currentCulture begat currentCulture, probably time to leave
+ break;
+ }
+
+ currentCulture = currentCulture.Parent;
+ }
+
+ if (!hasAnyCultures)
+ {
+ throw new MissingManifestResourceException("No manifests exist for the current culture.");
+ }
+
+ return resourceNames;
+ }
+
+ private string GetResourceStreamName(CultureInfo culture)
+ {
+ var resourceStreamName = _resourceBaseName;
+ if (!string.IsNullOrEmpty(culture.Name))
+ {
+ resourceStreamName += "." + culture.Name;
+ }
+ resourceStreamName += ".resources";
+
+ return resourceStreamName;
+ }
+
+ private IList GetResourceNamesForCulture(CultureInfo culture)
+ {
+ var resourceStreamName = GetResourceStreamName(culture);
+
+ var cacheKey = $"assembly={_resourceAssembly.FullName};resourceStreamName={resourceStreamName}";
+
+ var cultureResourceNames = _resourceNamesCache.GetOrAdd(cacheKey, _ =>
+ {
+ using (var cultureResourceStream = _resourceAssembly.GetManifestResourceStream(resourceStreamName))
+ {
+ if (cultureResourceStream == null)
+ {
+ return null;
+ }
+
+ using (var resources = new ResourceReader(cultureResourceStream))
+ {
+ var names = new List();
+ foreach (DictionaryEntry entry in resources)
+ {
+ var resourceName = (string)entry.Key;
+ names.Add(resourceName);
+ }
+ return names;
+ }
+ }
+
+ });
+
+ return cultureResourceNames;
+ }
+ }
+}
diff --git a/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizerFactory.cs b/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizerFactory.cs
index 101d0fc..9b5a54f 100644
--- a/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizerFactory.cs
+++ b/src/cloudscribe.Web.Localization/GlobalResourceManagerStringLocalizerFactory.cs
@@ -1,179 +1,179 @@
-using System;
-using System.Collections.Concurrent;
-using System.IO;
-using System.Reflection;
-using System.Resources;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Options;
-
-// http://stackoverflow.com/questions/34890555/asp-net-5-localization-using-view-components-in-a-separate-assembly
-
-namespace Microsoft.Extensions.Localization
-{
- // https://github.com/aspnet/Localization/blob/dev/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizerFactory.cs
- // https://github.com/dotnet/corefx/blob/master/src/System.Resources.ResourceManager/src/System/Resources/ResourceManager.cs
-
- ///
- /// An that creates instances of .
- ///
- public class GlobalResourceManagerStringLocalizerFactory : IStringLocalizerFactory
- {
- private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache();
- private readonly ConcurrentDictionary _localizerCache =
- new ConcurrentDictionary();
- private readonly IWebHostEnvironment _hostingEnvironment;
- private readonly string _resourcesRelativePath;
- private readonly GlobalResourceOptions globalResourceOptions;
-
- ///
- /// Creates a new .
- ///
- /// The .
- /// The .
- public GlobalResourceManagerStringLocalizerFactory(
- IWebHostEnvironment hostingEnvironment,
- IOptions localizationOptions,
- IOptions globalResourceOptionsAccessor
- )
- {
- if (hostingEnvironment == null)
- {
- throw new ArgumentNullException(nameof(hostingEnvironment));
- }
-
- if (localizationOptions == null)
- {
- throw new ArgumentNullException(nameof(localizationOptions));
- }
-
- _hostingEnvironment = hostingEnvironment;
- _resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty;
- if (!string.IsNullOrEmpty(_resourcesRelativePath))
- {
- _resourcesRelativePath = _resourcesRelativePath.Replace(Path.AltDirectorySeparatorChar, '.')
- .Replace(Path.DirectorySeparatorChar, '.') + ".";
- }
-
- globalResourceOptions = globalResourceOptionsAccessor.Value;
- }
-
- ///
- /// Creates a using the and
- /// of the specified .
- ///
- /// The .
- /// The .
- public IStringLocalizer Create(Type resourceSource)
- {
- if (resourceSource == null)
- {
- throw new ArgumentNullException(nameof(resourceSource));
- }
-
- var typeInfo = resourceSource.GetTypeInfo();
- var assembly = typeInfo.Assembly;
-
- Assembly appAssembly = null;
- ResourceManager appResourceManager = null;
- string appBaseName = null;
-
- // Re-root the base name if a resources path is set
- string baseName;
- if (assembly.FullName.StartsWith(_hostingEnvironment.ApplicationName))
- {
- baseName = string.IsNullOrEmpty(_resourcesRelativePath)
- ? typeInfo.FullName
- : _hostingEnvironment.ApplicationName + "." + _resourcesRelativePath
- + TrimPrefix(typeInfo.FullName, _hostingEnvironment.ApplicationName + ".");
- }
- else
- {
- var libName = TrimOnFirstComma(assembly.FullName);
- appAssembly = Assembly.GetEntryAssembly();
- appBaseName = _hostingEnvironment.ApplicationName
- + "." + _resourcesRelativePath + TrimPrefix(typeInfo.FullName, libName + ".");
- appResourceManager = new ResourceManager(appBaseName, appAssembly);
-
- baseName = libName + "." + TrimPrefix(typeInfo.FullName, libName + ".");
- }
-
- return _localizerCache.GetOrAdd(baseName, _ =>
- new GlobalResourceManagerStringLocalizer(
- new ResourceManager(baseName, assembly),
- assembly,
- baseName,
- _resourceNamesCache,
- globalResourceOptions,
- appResourceManager
- )
- );
-
-
- }
-
-
- ///
- /// Creates a .
- ///
- /// The base name of the resource to load strings from.
- /// The location to load resources from.
- /// The .
- public IStringLocalizer Create(string baseName, string location)
- {
- if (baseName == null)
- {
- throw new ArgumentNullException(nameof(baseName));
- }
-
- location = location ?? _hostingEnvironment.ApplicationName;
-
- Assembly appAssembly = null;
- ResourceManager appResourceManager = null;
- string appBaseName = null;
-
- if (location.StartsWith(_hostingEnvironment.ApplicationName))
- {
- baseName = location + "." + _resourcesRelativePath + TrimPrefix(baseName, location + ".");
- }
- else
- {
-
- appAssembly = Assembly.GetEntryAssembly();
- appBaseName = _hostingEnvironment.ApplicationName
- + "." + _resourcesRelativePath + TrimPrefix(baseName, location + ".");
- appResourceManager = new ResourceManager(appBaseName, appAssembly);
-
- baseName = location + "." + TrimPrefix(baseName, location + ".");
- }
-
- return _localizerCache.GetOrAdd($"B={baseName},L={location}", _ =>
- {
-
- var assembly = Assembly.Load(new AssemblyName(location));
- return new GlobalResourceManagerStringLocalizer(
- new ResourceManager(baseName, assembly),
- assembly,
- baseName,
- _resourceNamesCache,
- globalResourceOptions,
- appResourceManager
- );
- });
- }
-
- private static string TrimPrefix(string name, string prefix)
- {
- if (name.StartsWith(prefix, StringComparison.Ordinal))
- {
- return name.Substring(prefix.Length);
- }
-
- return name;
- }
-
- private static string TrimOnFirstComma(string name)
- {
- return name.Substring(0, name.IndexOf(","));
- }
- }
-}
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Options;
+
+// http://stackoverflow.com/questions/34890555/asp-net-5-localization-using-view-components-in-a-separate-assembly
+
+namespace Microsoft.Extensions.Localization
+{
+ // https://github.com/aspnet/Localization/blob/dev/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizerFactory.cs
+ // https://github.com/dotnet/corefx/blob/master/src/System.Resources.ResourceManager/src/System/Resources/ResourceManager.cs
+
+ ///
+ /// An that creates instances of .
+ ///
+ public class GlobalResourceManagerStringLocalizerFactory : IStringLocalizerFactory
+ {
+ private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache();
+ private readonly ConcurrentDictionary _localizerCache =
+ new ConcurrentDictionary();
+ private readonly IWebHostEnvironment _hostingEnvironment;
+ private readonly string _resourcesRelativePath;
+ private readonly GlobalResourceOptions globalResourceOptions;
+
+ ///
+ /// Creates a new .
+ ///
+ /// The .
+ /// The .
+ public GlobalResourceManagerStringLocalizerFactory(
+ IWebHostEnvironment hostingEnvironment,
+ IOptions localizationOptions,
+ IOptions globalResourceOptionsAccessor
+ )
+ {
+ if (hostingEnvironment == null)
+ {
+ throw new ArgumentNullException(nameof(hostingEnvironment));
+ }
+
+ if (localizationOptions == null)
+ {
+ throw new ArgumentNullException(nameof(localizationOptions));
+ }
+
+ _hostingEnvironment = hostingEnvironment;
+ _resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty;
+ if (!string.IsNullOrEmpty(_resourcesRelativePath))
+ {
+ _resourcesRelativePath = _resourcesRelativePath.Replace(Path.AltDirectorySeparatorChar, '.')
+ .Replace(Path.DirectorySeparatorChar, '.') + ".";
+ }
+
+ globalResourceOptions = globalResourceOptionsAccessor.Value;
+ }
+
+ ///
+ /// Creates a using the and
+ /// of the specified .
+ ///
+ /// The .
+ /// The .
+ public IStringLocalizer Create(Type resourceSource)
+ {
+ if (resourceSource == null)
+ {
+ throw new ArgumentNullException(nameof(resourceSource));
+ }
+
+ var typeInfo = resourceSource.GetTypeInfo();
+ var assembly = typeInfo.Assembly;
+
+ Assembly appAssembly = null;
+ ResourceManager appResourceManager = null;
+ string appBaseName = null;
+
+ // Re-root the base name if a resources path is set
+ string baseName;
+ if (assembly.FullName.StartsWith(_hostingEnvironment.ApplicationName))
+ {
+ baseName = string.IsNullOrEmpty(_resourcesRelativePath)
+ ? typeInfo.FullName
+ : _hostingEnvironment.ApplicationName + "." + _resourcesRelativePath
+ + TrimPrefix(typeInfo.FullName, _hostingEnvironment.ApplicationName + ".");
+ }
+ else
+ {
+ var libName = TrimOnFirstComma(assembly.FullName);
+ appAssembly = Assembly.GetEntryAssembly();
+ appBaseName = _hostingEnvironment.ApplicationName
+ + "." + _resourcesRelativePath + TrimPrefix(typeInfo.FullName, libName + ".");
+ appResourceManager = new ResourceManager(appBaseName, appAssembly);
+
+ baseName = libName + "." + TrimPrefix(typeInfo.FullName, libName + ".");
+ }
+
+ return _localizerCache.GetOrAdd(baseName, _ =>
+ new GlobalResourceManagerStringLocalizer(
+ new ResourceManager(baseName, assembly),
+ assembly,
+ baseName,
+ _resourceNamesCache,
+ globalResourceOptions,
+ appResourceManager
+ )
+ );
+
+
+ }
+
+
+ ///
+ /// Creates a .
+ ///
+ /// The base name of the resource to load strings from.
+ /// The location to load resources from.
+ /// The .
+ public IStringLocalizer Create(string baseName, string location)
+ {
+ if (baseName == null)
+ {
+ throw new ArgumentNullException(nameof(baseName));
+ }
+
+ location = location ?? _hostingEnvironment.ApplicationName;
+
+ Assembly appAssembly = null;
+ ResourceManager appResourceManager = null;
+ string appBaseName = null;
+
+ if (location.StartsWith(_hostingEnvironment.ApplicationName))
+ {
+ baseName = location + "." + _resourcesRelativePath + TrimPrefix(baseName, location + ".");
+ }
+ else
+ {
+
+ appAssembly = Assembly.GetEntryAssembly();
+ appBaseName = _hostingEnvironment.ApplicationName
+ + "." + _resourcesRelativePath + TrimPrefix(baseName, location + ".");
+ appResourceManager = new ResourceManager(appBaseName, appAssembly);
+
+ baseName = location + "." + TrimPrefix(baseName, location + ".");
+ }
+
+ return _localizerCache.GetOrAdd($"B={baseName},L={location}", _ =>
+ {
+
+ var assembly = Assembly.Load(new AssemblyName(location));
+ return new GlobalResourceManagerStringLocalizer(
+ new ResourceManager(baseName, assembly),
+ assembly,
+ baseName,
+ _resourceNamesCache,
+ globalResourceOptions,
+ appResourceManager
+ );
+ });
+ }
+
+ private static string TrimPrefix(string name, string prefix)
+ {
+ if (name.StartsWith(prefix, StringComparison.Ordinal))
+ {
+ return name.Substring(prefix.Length);
+ }
+
+ return name;
+ }
+
+ private static string TrimOnFirstComma(string name)
+ {
+ return name.Substring(0, name.IndexOf(","));
+ }
+ }
+}
diff --git a/src/cloudscribe.Web.Localization/GlobalResourceManagerWithCultureStringLocalizer.cs b/src/cloudscribe.Web.Localization/GlobalResourceManagerWithCultureStringLocalizer.cs
index c99b57d..96b565c 100644
--- a/src/cloudscribe.Web.Localization/GlobalResourceManagerWithCultureStringLocalizer.cs
+++ b/src/cloudscribe.Web.Localization/GlobalResourceManagerWithCultureStringLocalizer.cs
@@ -1,108 +1,108 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Reflection;
-using System.Resources;
-
-namespace Microsoft.Extensions.Localization
-{
- ///
- /// An that uses the and
- /// to provide localized strings for a specific .
- ///
- public class GlobalResourceManagerWithCultureStringLocalizer : GlobalResourceManagerStringLocalizer
- {
- private readonly CultureInfo _culture;
-
- ///
- /// Creates a new .
- ///
- /// The to read strings from.
- /// The that contains the strings as embedded resources.
- /// The base name of the embedded resource in the that contains the strings.
- /// Cache of the list of strings for a given resource assembly name.
- /// The specific to use.
- /// The
- /// The global to read strings from.
- public GlobalResourceManagerWithCultureStringLocalizer(
- ResourceManager resourceManager,
- Assembly resourceAssembly,
- string baseName,
- IResourceNamesCache resourceNamesCache,
- CultureInfo culture,
- GlobalResourceOptions globalResourceOptions,
- ResourceManager globalResourceManager = null
- )
- : base(
- resourceManager,
- resourceAssembly,
- baseName,
- resourceNamesCache,
- globalResourceOptions,
- globalResourceManager
- )
- {
- if (resourceManager == null)
- {
- throw new ArgumentNullException(nameof(resourceManager));
- }
-
- if (resourceAssembly == null)
- {
- throw new ArgumentNullException(nameof(resourceAssembly));
- }
-
- if (baseName == null)
- {
- throw new ArgumentNullException(nameof(baseName));
- }
-
- if (resourceNamesCache == null)
- {
- throw new ArgumentNullException(nameof(resourceNamesCache));
- }
-
- if (culture == null)
- {
- throw new ArgumentNullException(nameof(culture));
- }
-
- _culture = culture;
- }
-
- ///
- public override LocalizedString this[string name]
- {
- get
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- var value = GetStringSafely(name, _culture);
- return new LocalizedString(name, value ?? name);
- }
- }
-
- ///
- public override LocalizedString this[string name, params object[] arguments]
- {
- get
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- var format = GetStringSafely(name, _culture);
- var value = string.Format(_culture, format ?? name, arguments);
- return new LocalizedString(name, value ?? name, resourceNotFound: format == null);
- }
- }
-
- ///
- public override IEnumerable GetAllStrings(bool includeParentCultures) =>
- GetAllStrings(includeParentCultures, _culture);
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Resources;
+
+namespace Microsoft.Extensions.Localization
+{
+ ///
+ /// An that uses the and
+ /// to provide localized strings for a specific .
+ ///
+ public class GlobalResourceManagerWithCultureStringLocalizer : GlobalResourceManagerStringLocalizer
+ {
+ private readonly CultureInfo _culture;
+
+ ///
+ /// Creates a new .
+ ///
+ /// The to read strings from.
+ /// The that contains the strings as embedded resources.
+ /// The base name of the embedded resource in the that contains the strings.
+ /// Cache of the list of strings for a given resource assembly name.
+ /// The specific to use.
+ /// The
+ /// The global to read strings from.
+ public GlobalResourceManagerWithCultureStringLocalizer(
+ ResourceManager resourceManager,
+ Assembly resourceAssembly,
+ string baseName,
+ IResourceNamesCache resourceNamesCache,
+ CultureInfo culture,
+ GlobalResourceOptions globalResourceOptions,
+ ResourceManager globalResourceManager = null
+ )
+ : base(
+ resourceManager,
+ resourceAssembly,
+ baseName,
+ resourceNamesCache,
+ globalResourceOptions,
+ globalResourceManager
+ )
+ {
+ if (resourceManager == null)
+ {
+ throw new ArgumentNullException(nameof(resourceManager));
+ }
+
+ if (resourceAssembly == null)
+ {
+ throw new ArgumentNullException(nameof(resourceAssembly));
+ }
+
+ if (baseName == null)
+ {
+ throw new ArgumentNullException(nameof(baseName));
+ }
+
+ if (resourceNamesCache == null)
+ {
+ throw new ArgumentNullException(nameof(resourceNamesCache));
+ }
+
+ if (culture == null)
+ {
+ throw new ArgumentNullException(nameof(culture));
+ }
+
+ _culture = culture;
+ }
+
+ ///
+ public override LocalizedString this[string name]
+ {
+ get
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ var value = GetStringSafely(name, _culture);
+ return new LocalizedString(name, value ?? name);
+ }
+ }
+
+ ///
+ public override LocalizedString this[string name, params object[] arguments]
+ {
+ get
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ var format = GetStringSafely(name, _culture);
+ var value = string.Format(_culture, format ?? name, arguments);
+ return new LocalizedString(name, value ?? name, resourceNotFound: format == null);
+ }
+ }
+
+ ///
+ public override IEnumerable GetAllStrings(bool includeParentCultures) =>
+ GetAllStrings(includeParentCultures, _culture);
+ }
+}
diff --git a/src/cloudscribe.Web.Localization/GlobalResourceOptions.cs b/src/cloudscribe.Web.Localization/GlobalResourceOptions.cs
index f195ba3..b5d3329 100644
--- a/src/cloudscribe.Web.Localization/GlobalResourceOptions.cs
+++ b/src/cloudscribe.Web.Localization/GlobalResourceOptions.cs
@@ -1,15 +1,15 @@
-namespace Microsoft.Extensions.Localization
-{
- public class GlobalResourceOptions
- {
- ///
- /// if true (the default) then the GlobalResourceStringLocalizer will first try to get the localized string from global resources,
- /// ie stored in the resx folder of the main web app, only if it is not found will it fallback to try to get the resource from embedded resources inside the
- /// class library. This allow snot only localization but customization because you can drop in a resx file to set the strings
- /// and it will be used in preference to any embedded resource.
- /// set to false if you only want to use global resources as fallback, in that case it will try first to get the resource from resx embedded in the lib and only
- /// if not found will it try the global resources
- ///
- public bool TryGlobalFirst { get; set; } = true;
- }
-}
+namespace Microsoft.Extensions.Localization
+{
+ public class GlobalResourceOptions
+ {
+ ///
+ /// if true (the default) then the GlobalResourceStringLocalizer will first try to get the localized string from global resources,
+ /// ie stored in the resx folder of the main web app, only if it is not found will it fallback to try to get the resource from embedded resources inside the
+ /// class library. This allow snot only localization but customization because you can drop in a resx file to set the strings
+ /// and it will be used in preference to any embedded resource.
+ /// set to false if you only want to use global resources as fallback, in that case it will try first to get the resource from resx embedded in the lib and only
+ /// if not found will it try the global resources
+ ///
+ public bool TryGlobalFirst { get; set; } = true;
+ }
+}
diff --git a/src/cloudscribe.Web.Localization/PatchedResourceManagerStringLocalizerFactory.cs b/src/cloudscribe.Web.Localization/PatchedResourceManagerStringLocalizerFactory.cs
index 70dcc04..b0c0f01 100644
--- a/src/cloudscribe.Web.Localization/PatchedResourceManagerStringLocalizerFactory.cs
+++ b/src/cloudscribe.Web.Localization/PatchedResourceManagerStringLocalizerFactory.cs
@@ -1,146 +1,146 @@
-//using System;
-//using System.Collections.Concurrent;
-//using System.IO;
-//using System.Reflection;
-//using System.Resources;
-//using Microsoft.AspNetCore.Hosting;
-//using Microsoft.Extensions.Options;
-
-////https://github.com/aspnet/Localization/issues/139
-
-//namespace Microsoft.Extensions.Localization
-//{
-// ///
-// /// An that creates instances of .
-// ///
-// public class PatchedResourceManagerStringLocalizerFactory : IStringLocalizerFactory
-// {
-// private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache();
-// private readonly ConcurrentDictionary _localizerCache =
-// new ConcurrentDictionary();
-// private readonly IHostingEnvironment _hostingEnvironment;
-// private readonly string _resourcesRelativePath;
-
-// ///
-// /// Creates a new .
-// ///
-// /// The .
-// /// The .
-// public PatchedResourceManagerStringLocalizerFactory(
-// IHostingEnvironment hostingEnvironment,
-// IOptions localizationOptions)
-// {
-// if (hostingEnvironment == null)
-// {
-// throw new ArgumentNullException(nameof(hostingEnvironment));
-// }
-
-// if (localizationOptions == null)
-// {
-// throw new ArgumentNullException(nameof(localizationOptions));
-// }
-
-// _hostingEnvironment = hostingEnvironment;
-// _resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty;
-// if (!string.IsNullOrEmpty(_resourcesRelativePath))
-// {
-// _resourcesRelativePath = _resourcesRelativePath.Replace(Path.AltDirectorySeparatorChar, '.')
-// .Replace(Path.DirectorySeparatorChar, '.') + ".";
-// }
-// }
-
-// ///
-// /// Creates a using the and
-// /// of the specified .
-// ///
-// /// The .
-// /// The .
-// public IStringLocalizer Create(Type resourceSource)
-// {
-// if (resourceSource == null)
-// {
-// throw new ArgumentNullException(nameof(resourceSource));
-// }
-
-// var typeInfo = resourceSource.GetTypeInfo();
-// var assembly = typeInfo.Assembly;
-
-// // Re-root the base name if a resources path is set
-// string baseName;
-// if (assembly.FullName.StartsWith(_hostingEnvironment.ApplicationName))
-// {
-// baseName = string.IsNullOrEmpty(_resourcesRelativePath)
-// ? typeInfo.FullName
-// : _hostingEnvironment.ApplicationName + "." + _resourcesRelativePath
-// + TrimPrefix(typeInfo.FullName, _hostingEnvironment.ApplicationName + ".");
-// }
-// else
-// {
-// var libName = TrimOnFirstComma(assembly.FullName);
-// baseName = libName + "." + TrimPrefix(typeInfo.FullName, libName + ".");
-// }
-
-// return _localizerCache.GetOrAdd(baseName, _ =>
-// new ResourceManagerStringLocalizer(
-// new ResourceManager(baseName, assembly),
-// assembly,
-// baseName,
-// _resourceNamesCache)
-// );
-
-
-// }
-
-// ///
-// /// Creates a .
-// ///
-// /// The base name of the resource to load strings from.
-// /// The location to load resources from.
-// /// The .
-// public IStringLocalizer Create(string baseName, string location)
-// {
-// if (baseName == null)
-// {
-// throw new ArgumentNullException(nameof(baseName));
-// }
-
-// location = location ?? _hostingEnvironment.ApplicationName;
-
-// if (location.StartsWith(_hostingEnvironment.ApplicationName))
-// {
-// baseName = location + "." + _resourcesRelativePath + TrimPrefix(baseName, location + ".");
-// }
-// else
-// {
-// baseName = location + "." + TrimPrefix(baseName, location + ".");
-// }
-
-// return _localizerCache.GetOrAdd($"B={baseName},L={location}", _ =>
-// {
-// var assembly = Assembly.Load(new AssemblyName(location));
-// return new ResourceManagerStringLocalizer(
-// new ResourceManager(baseName, assembly),
-// assembly,
-// baseName,
-// _resourceNamesCache);
-// });
-// }
-
-// private static string TrimPrefix(string name, string prefix)
-// {
-// if (name.StartsWith(prefix, StringComparison.Ordinal))
-// {
-// return name.Substring(prefix.Length);
-// }
-
-// return name;
-// }
-
-// private static string TrimOnFirstComma(string name)
-// {
-
-// return name.Substring(0, name.IndexOf(","));
-
-// }
-// }
-//}
+//using System;
+//using System.Collections.Concurrent;
+//using System.IO;
+//using System.Reflection;
+//using System.Resources;
+//using Microsoft.AspNetCore.Hosting;
+//using Microsoft.Extensions.Options;
+
+////https://github.com/aspnet/Localization/issues/139
+
+//namespace Microsoft.Extensions.Localization
+//{
+// ///
+// /// An that creates instances of .
+// ///
+// public class PatchedResourceManagerStringLocalizerFactory : IStringLocalizerFactory
+// {
+// private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache();
+// private readonly ConcurrentDictionary _localizerCache =
+// new ConcurrentDictionary();
+// private readonly IHostingEnvironment _hostingEnvironment;
+// private readonly string _resourcesRelativePath;
+
+// ///
+// /// Creates a new .
+// ///
+// /// The .
+// /// The .
+// public PatchedResourceManagerStringLocalizerFactory(
+// IHostingEnvironment hostingEnvironment,
+// IOptions localizationOptions)
+// {
+// if (hostingEnvironment == null)
+// {
+// throw new ArgumentNullException(nameof(hostingEnvironment));
+// }
+
+// if (localizationOptions == null)
+// {
+// throw new ArgumentNullException(nameof(localizationOptions));
+// }
+
+// _hostingEnvironment = hostingEnvironment;
+// _resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty;
+// if (!string.IsNullOrEmpty(_resourcesRelativePath))
+// {
+// _resourcesRelativePath = _resourcesRelativePath.Replace(Path.AltDirectorySeparatorChar, '.')
+// .Replace(Path.DirectorySeparatorChar, '.') + ".";
+// }
+// }
+
+// ///
+// /// Creates a using the and
+// /// of the specified .
+// ///
+// /// The .
+// /// The .
+// public IStringLocalizer Create(Type resourceSource)
+// {
+// if (resourceSource == null)
+// {
+// throw new ArgumentNullException(nameof(resourceSource));
+// }
+
+// var typeInfo = resourceSource.GetTypeInfo();
+// var assembly = typeInfo.Assembly;
+
+// // Re-root the base name if a resources path is set
+// string baseName;
+// if (assembly.FullName.StartsWith(_hostingEnvironment.ApplicationName))
+// {
+// baseName = string.IsNullOrEmpty(_resourcesRelativePath)
+// ? typeInfo.FullName
+// : _hostingEnvironment.ApplicationName + "." + _resourcesRelativePath
+// + TrimPrefix(typeInfo.FullName, _hostingEnvironment.ApplicationName + ".");
+// }
+// else
+// {
+// var libName = TrimOnFirstComma(assembly.FullName);
+// baseName = libName + "." + TrimPrefix(typeInfo.FullName, libName + ".");
+// }
+
+// return _localizerCache.GetOrAdd(baseName, _ =>
+// new ResourceManagerStringLocalizer(
+// new ResourceManager(baseName, assembly),
+// assembly,
+// baseName,
+// _resourceNamesCache)
+// );
+
+
+// }
+
+// ///
+// /// Creates a .
+// ///
+// /// The base name of the resource to load strings from.
+// /// The location to load resources from.
+// /// The .
+// public IStringLocalizer Create(string baseName, string location)
+// {
+// if (baseName == null)
+// {
+// throw new ArgumentNullException(nameof(baseName));
+// }
+
+// location = location ?? _hostingEnvironment.ApplicationName;
+
+// if (location.StartsWith(_hostingEnvironment.ApplicationName))
+// {
+// baseName = location + "." + _resourcesRelativePath + TrimPrefix(baseName, location + ".");
+// }
+// else
+// {
+// baseName = location + "." + TrimPrefix(baseName, location + ".");
+// }
+
+// return _localizerCache.GetOrAdd($"B={baseName},L={location}", _ =>
+// {
+// var assembly = Assembly.Load(new AssemblyName(location));
+// return new ResourceManagerStringLocalizer(
+// new ResourceManager(baseName, assembly),
+// assembly,
+// baseName,
+// _resourceNamesCache);
+// });
+// }
+
+// private static string TrimPrefix(string name, string prefix)
+// {
+// if (name.StartsWith(prefix, StringComparison.Ordinal))
+// {
+// return name.Substring(prefix.Length);
+// }
+
+// return name;
+// }
+
+// private static string TrimOnFirstComma(string name)
+// {
+
+// return name.Substring(0, name.IndexOf(","));
+
+// }
+// }
+//}
diff --git a/src/cloudscribe.Web.Localization/README.md b/src/cloudscribe.Web.Localization/README.md
index cb56e7c..3da2621 100644
--- a/src/cloudscribe.Web.Localization/README.md
+++ b/src/cloudscribe.Web.Localization/README.md
@@ -1,16 +1,16 @@
-# cloudscribe.Web.Localization
-
-A .NET library for more flexible localization in ASP.NET Core applications. Provides advanced resource management and custom localizer factories.
-
-## Usage
-
-1. Install the NuGet package:
- ```sh
- dotnet add package cloudscribe.Web.Localization
- ```
-2. Configure localization in your ASP.NET Core app.
-3. Use the provided localizer services in your controllers and views.
-
-## License
-
-This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
+# cloudscribe.Web.Localization
+
+A .NET library for more flexible localization in ASP.NET Core applications. Provides advanced resource management and custom localizer factories.
+
+## Usage
+
+1. Install the NuGet package:
+ ```sh
+ dotnet add package cloudscribe.Web.Localization
+ ```
+2. Configure localization in your ASP.NET Core app.
+3. Use the provided localizer services in your controllers and views.
+
+## License
+
+This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
diff --git a/src/cloudscribe.Web.Localization/SharedResources.cs b/src/cloudscribe.Web.Localization/SharedResources.cs
index a2e733d..4ef442b 100644
--- a/src/cloudscribe.Web.Localization/SharedResources.cs
+++ b/src/cloudscribe.Web.Localization/SharedResources.cs
@@ -1,11 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace cloudscribe.Web.Localization
-{
- public class SharedResources
- {
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace cloudscribe.Web.Localization
+{
+ public class SharedResources
+ {
+ }
+}
diff --git a/src/cloudscribe.Web.Localization/cloudscribe.Web.Localization.csproj b/src/cloudscribe.Web.Localization/cloudscribe.Web.Localization.csproj
index 7e6d11e..ca0fba9 100644
--- a/src/cloudscribe.Web.Localization/cloudscribe.Web.Localization.csproj
+++ b/src/cloudscribe.Web.Localization/cloudscribe.Web.Localization.csproj
@@ -1,35 +1,35 @@
-
-
-
- more flexible localization for ASP.NET Core
- 8.5.0
- net8.0
- Joe Audette
- cloudscribe.Web.Localization
- cloudscribe;localization;resx
- icon.png
- https://github.com/joeaudette/cloudscribe.Web.Localization
- Apache-2.0
- https://github.com/cloudscribe/cloudscribe.Web.Localization.git
- git
-
- README.md
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ more flexible localization for ASP.NET Core
+ 8.6.0
+ net8.0
+ Joe Audette
+ cloudscribe.Web.Localization
+ cloudscribe;localization;resx
+ icon.png
+ https://github.com/joeaudette/cloudscribe.Web.Localization
+ Apache-2.0
+ https://github.com/cloudscribe/cloudscribe.Web.Localization.git
+ git
+
+ README.md
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/localization.WebApp/.bowerrc b/src/localization.WebApp/.bowerrc
index 6406626..78d4e9d 100644
--- a/src/localization.WebApp/.bowerrc
+++ b/src/localization.WebApp/.bowerrc
@@ -1,3 +1,3 @@
-{
- "directory": "wwwroot/lib"
-}
+{
+ "directory": "wwwroot/lib"
+}
diff --git a/src/localization.WebApp/Controllers/HomeController.cs b/src/localization.WebApp/Controllers/HomeController.cs
index 5d124d2..f046b08 100644
--- a/src/localization.WebApp/Controllers/HomeController.cs
+++ b/src/localization.WebApp/Controllers/HomeController.cs
@@ -1,59 +1,59 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Localization;
-using Microsoft.AspNetCore.Localization;
-using Microsoft.AspNetCore.Http;
-
-namespace localization.WebApp.Controllers
-{
- public class HomeController : Controller
- {
- public HomeController(
- IStringLocalizer localizer
- )
- {
- _localizer = localizer;
- }
-
- private readonly IStringLocalizer _localizer;
-
- public IActionResult Index()
- {
- return View();
- }
-
- public IActionResult About()
- {
- ViewData["Message"] = _localizer["Your application description page."];
-
- return View();
- }
-
- public IActionResult Contact()
- {
- ViewData["Message"] = _localizer["Your contact page."];
-
- return View();
- }
-
- [HttpPost]
- public IActionResult SetLanguage(string culture, string returnUrl)
- {
- Response.Cookies.Append(
- CookieRequestCultureProvider.DefaultCookieName,
- CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
- new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
- );
-
- return LocalRedirect(returnUrl);
- }
-
- public IActionResult Error()
- {
- return View();
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Localization;
+using Microsoft.AspNetCore.Localization;
+using Microsoft.AspNetCore.Http;
+
+namespace localization.WebApp.Controllers
+{
+ public class HomeController : Controller
+ {
+ public HomeController(
+ IStringLocalizer localizer
+ )
+ {
+ _localizer = localizer;
+ }
+
+ private readonly IStringLocalizer _localizer;
+
+ public IActionResult Index()
+ {
+ return View();
+ }
+
+ public IActionResult About()
+ {
+ ViewData["Message"] = _localizer["Your application description page."];
+
+ return View();
+ }
+
+ public IActionResult Contact()
+ {
+ ViewData["Message"] = _localizer["Your contact page."];
+
+ return View();
+ }
+
+ [HttpPost]
+ public IActionResult SetLanguage(string culture, string returnUrl)
+ {
+ Response.Cookies.Append(
+ CookieRequestCultureProvider.DefaultCookieName,
+ CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
+ new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
+ );
+
+ return LocalRedirect(returnUrl);
+ }
+
+ public IActionResult Error()
+ {
+ return View();
+ }
+ }
+}
diff --git a/src/localization.WebApp/GlobalResources/Controllers.BarController.fr.resx b/src/localization.WebApp/GlobalResources/Controllers.BarController.fr.resx
index 5511251..e4e56a8 100644
--- a/src/localization.WebApp/GlobalResources/Controllers.BarController.fr.resx
+++ b/src/localization.WebApp/GlobalResources/Controllers.BarController.fr.resx
@@ -1,123 +1,123 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- oui oui oui le controller de bar - from resx in the web app
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ oui oui oui le controller de bar - from resx in the web app
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/Controllers.BazController.fr.resx b/src/localization.WebApp/GlobalResources/Controllers.BazController.fr.resx
index 974e242..fd27386 100644
--- a/src/localization.WebApp/GlobalResources/Controllers.BazController.fr.resx
+++ b/src/localization.WebApp/GlobalResources/Controllers.BazController.fr.resx
@@ -1,123 +1,123 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Comment allez vous from Baz - from resx file in the main web app
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Comment allez vous from Baz - from resx file in the main web app
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/Controllers.HomeController.fr.resx b/src/localization.WebApp/GlobalResources/Controllers.HomeController.fr.resx
index 5bc1370..9001c93 100644
--- a/src/localization.WebApp/GlobalResources/Controllers.HomeController.fr.resx
+++ b/src/localization.WebApp/GlobalResources/Controllers.HomeController.fr.resx
@@ -1,126 +1,126 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Votre page de description de l'application .
-
-
- Votre page de contact .
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Votre page de description de l'application .
+
+
+ Votre page de contact .
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/ViewModels.ContactMessageViewModel.fr.resx b/src/localization.WebApp/GlobalResources/ViewModels.ContactMessageViewModel.fr.resx
index 85dca8a..631e503 100644
--- a/src/localization.WebApp/GlobalResources/ViewModels.ContactMessageViewModel.fr.resx
+++ b/src/localization.WebApp/GlobalResources/ViewModels.ContactMessageViewModel.fr.resx
@@ -1,129 +1,129 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Le champ E-mail est obligatoire.
-
-
- Le champ Message est obligatoire.
-
-
- Il est requis de compléter le champ correspondant au nom.
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Le champ E-mail est obligatoire.
+
+
+ Le champ Message est obligatoire.
+
+
+ Il est requis de compléter le champ correspondant au nom.
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/Views.Home.About.fr.resx b/src/localization.WebApp/GlobalResources/Views.Home.About.fr.resx
index 9648a59..1005aa7 100644
--- a/src/localization.WebApp/GlobalResources/Views.Home.About.fr.resx
+++ b/src/localization.WebApp/GlobalResources/Views.Home.About.fr.resx
@@ -1,126 +1,126 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Sur
-
-
- Utilisez cette zone pour fournir des informations supplémentaires .
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Sur
+
+
+ Utilisez cette zone pour fournir des informations supplémentaires .
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/Views.Shared._Layout.fr.resx b/src/localization.WebApp/GlobalResources/Views.Shared._Layout.fr.resx
index 031507a..a2a845e 100644
--- a/src/localization.WebApp/GlobalResources/Views.Shared._Layout.fr.resx
+++ b/src/localization.WebApp/GlobalResources/Views.Shared._Layout.fr.resx
@@ -1,132 +1,132 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Sur
-
-
- Contact
-
-
- Accueil
-
-
- Basculer la navigation
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Sur
+
+
+ Contact
+
+
+ Accueil
+
+
+ Basculer la navigation
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/Views.Shared._LoginPartial.fr.resx b/src/localization.WebApp/GlobalResources/Views.Shared._LoginPartial.fr.resx
index 2897c8d..5531d0a 100644
--- a/src/localization.WebApp/GlobalResources/Views.Shared._LoginPartial.fr.resx
+++ b/src/localization.WebApp/GlobalResources/Views.Shared._LoginPartial.fr.resx
@@ -1,135 +1,135 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Bonjour {0} !
-
-
- S'identifier
-
-
- Déconnecter
-
-
- Faire en sorte
-
-
- Enregistrez
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Bonjour {0} !
+
+
+ S'identifier
+
+
+ Déconnecter
+
+
+ Faire en sorte
+
+
+ Enregistrez
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/Views.Shared._SelectLanguagePartial.fr.resx b/src/localization.WebApp/GlobalResources/Views.Shared._SelectLanguagePartial.fr.resx
index 3c75b52..b4e516d 100644
--- a/src/localization.WebApp/GlobalResources/Views.Shared._SelectLanguagePartial.fr.resx
+++ b/src/localization.WebApp/GlobalResources/Views.Shared._SelectLanguagePartial.fr.resx
@@ -1,126 +1,126 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Langue:
-
-
- Demande fournisseur de la culture:
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Langue:
+
+
+ Demande fournisseur de la culture:
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/Views/Home/Index.fr.resx b/src/localization.WebApp/GlobalResources/Views/Home/Index.fr.resx
index 7a149c8..05a26bd 100644
--- a/src/localization.WebApp/GlobalResources/Views/Home/Index.fr.resx
+++ b/src/localization.WebApp/GlobalResources/Views/Home/Index.fr.resx
@@ -1,222 +1,222 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- <a href="http://go.microsoft.com/fwlink/?LinkId=518007">Gulp</a> et <a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> pour la gestion des bibliothèques côté client
-
-
- Ajouter un contrôleur et Vue
-
-
- Utilisations d'application
-
-
- Apportez dans les bibliothèques de NuGet , Bower , et NPM , et automatiser les tâches à l'aide Grunt ou Gulp .
-
-
- Page D'accueil
-
-
- Comment
-
-
- Découvrez comment la plate-forme Azure cloud de Microsoft vous permet de construire, déployer et applications Web à grande échelle .
-
-
- Apprenez à créer des applications ASP.NET qui peuvent fonctionner n'importe où .
-
-
- Apprendre Encore Plus
-
-
- Prochain
-
-
- Gestion des Paquetages
-
-
- Précédent
-
-
- Pages échantillon en utilisant ASP.NET MVC 6
-
-
- Thématisation aide <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a>
-
-
- Il ya de puissantes nouvelles fonctionnalités de Visual Studio pour la création d'applications web modernes .
-
-
- Ajoutez un appsetting dans la configuration et y accéder à l'application .
-
-
- Ajouter des packages de clients à l'aide Bower.
-
-
- Ajouter paquets en utilisant NuGet.
-
-
- Le développement côté client
-
-
- Aperçu conceptuel de ce qui est ASP.NET 5
-
-
- Développer sur différentes plateformes
-
-
- Notions de base ASP.NET 5 tels que le démarrage et middleware.
-
-
- Gérer Secrets de l'utilisateur à l'aide de Secret Manager.
-
-
- Vue D'ensemble
-
-
- Publier sur Microsoft Azure Web Apps
-
-
- Lire la suite sur le site de documentation
-
-
- Déployer & Exécuter
-
-
- Exécuter des commandes dans votre project.json
-
-
- Exécutez votre application
-
-
- Exécutez votre application sur .NET de base
-
-
- Sécurité
-
-
- Cibler le développement, la mise en scène ou de l'environnement de production.
-
-
- Utilisez la journalisation pour enregistrer un message.
-
-
- Utilisation des données
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ <a href="http://go.microsoft.com/fwlink/?LinkId=518007">Gulp</a> et <a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> pour la gestion des bibliothèques côté client
+
+
+ Ajouter un contrôleur et Vue
+
+
+ Utilisations d'application
+
+
+ Apportez dans les bibliothèques de NuGet , Bower , et NPM , et automatiser les tâches à l'aide Grunt ou Gulp .
+
+
+ Page D'accueil
+
+
+ Comment
+
+
+ Découvrez comment la plate-forme Azure cloud de Microsoft vous permet de construire, déployer et applications Web à grande échelle .
+
+
+ Apprenez à créer des applications ASP.NET qui peuvent fonctionner n'importe où .
+
+
+ Apprendre Encore Plus
+
+
+ Prochain
+
+
+ Gestion des Paquetages
+
+
+ Précédent
+
+
+ Pages échantillon en utilisant ASP.NET MVC 6
+
+
+ Thématisation aide <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a>
+
+
+ Il ya de puissantes nouvelles fonctionnalités de Visual Studio pour la création d'applications web modernes .
+
+
+ Ajoutez un appsetting dans la configuration et y accéder à l'application .
+
+
+ Ajouter des packages de clients à l'aide Bower.
+
+
+ Ajouter paquets en utilisant NuGet.
+
+
+ Le développement côté client
+
+
+ Aperçu conceptuel de ce qui est ASP.NET 5
+
+
+ Développer sur différentes plateformes
+
+
+ Notions de base ASP.NET 5 tels que le démarrage et middleware.
+
+
+ Gérer Secrets de l'utilisateur à l'aide de Secret Manager.
+
+
+ Vue D'ensemble
+
+
+ Publier sur Microsoft Azure Web Apps
+
+
+ Lire la suite sur le site de documentation
+
+
+ Déployer & Exécuter
+
+
+ Exécuter des commandes dans votre project.json
+
+
+ Exécutez votre application
+
+
+ Exécutez votre application sur .NET de base
+
+
+ Sécurité
+
+
+ Cibler le développement, la mise en scène ou de l'environnement de production.
+
+
+ Utilisez la journalisation pour enregistrer un message.
+
+
+ Utilisation des données
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/WebLib.Controllers.FooController.fr.resx b/src/localization.WebApp/GlobalResources/WebLib.Controllers.FooController.fr.resx
index 480d436..1c4b325 100644
--- a/src/localization.WebApp/GlobalResources/WebLib.Controllers.FooController.fr.resx
+++ b/src/localization.WebApp/GlobalResources/WebLib.Controllers.FooController.fr.resx
@@ -1,123 +1,123 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Comment allez vouz ya'll
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Comment allez vouz ya'll
+
\ No newline at end of file
diff --git a/src/localization.WebApp/GlobalResources/WebLibSharedResources.fr.resx b/src/localization.WebApp/GlobalResources/WebLibSharedResources.fr.resx
index d959ae7..c8f3816 100644
--- a/src/localization.WebApp/GlobalResources/WebLibSharedResources.fr.resx
+++ b/src/localization.WebApp/GlobalResources/WebLibSharedResources.fr.resx
@@ -1,126 +1,126 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- comment puis-je te aime , permettez-moi de compter les façons
-
-
- cette chaîne provient de ressources partagées
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ comment puis-je te aime , permettez-moi de compter les façons
+
+
+ cette chaîne provient de ressources partagées
+
\ No newline at end of file
diff --git a/src/localization.WebApp/Program.cs b/src/localization.WebApp/Program.cs
index f7935f2..7b7d6b1 100644
--- a/src/localization.WebApp/Program.cs
+++ b/src/localization.WebApp/Program.cs
@@ -1,28 +1,28 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-
-namespace localization.WebApp
-{
- public class Program
- {
- public static void Main(string[] args)
- {
- CreateHostBuilder(args).Build().Run();
- }
-
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.UseStartup();
- });
- }
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace localization.WebApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/localization.WebApp/Properties/launchSettings.json b/src/localization.WebApp/Properties/launchSettings.json
index 4e1dc1a..33a8e61 100644
--- a/src/localization.WebApp/Properties/launchSettings.json
+++ b/src/localization.WebApp/Properties/launchSettings.json
@@ -1,27 +1,27 @@
-{
- "iisSettings": {
- "windowsAuthentication": false,
- "anonymousAuthentication": true,
- "iisExpress": {
- "applicationUrl": "http://localhost:51296/",
- "sslPort": 44310
- }
- },
- "profiles": {
- "IIS Express": {
- "commandName": "IISExpress",
- "launchBrowser": true,
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- },
- "localization.WebApp": {
- "commandName": "Project",
- "launchBrowser": true,
- "launchUrl": "http://localhost:5000",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- }
- }
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:51296/",
+ "sslPort": 44310
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "localization.WebApp": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "launchUrl": "http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/localization.WebApp/Startup.cs b/src/localization.WebApp/Startup.cs
index ff4fe23..d6280fd 100644
--- a/src/localization.WebApp/Startup.cs
+++ b/src/localization.WebApp/Startup.cs
@@ -1,172 +1,172 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-//using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
-//using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.AspNetCore.Mvc.Razor;
-using System.Globalization;
-using Microsoft.AspNetCore.Localization;
-using Microsoft.Extensions.Options;
-using Microsoft.Extensions.Localization;
-using cloudscribe.Web.Localization;
-using Microsoft.Extensions.Hosting;
-
-//https://github.com/aspnet/Localization/issues/157
-
-namespace localization.WebApp
-{
- public class Startup
- {
-
- public Startup(IConfiguration configuration)
- {
- Configuration =configuration;
-
- }
-
- public IConfiguration Configuration { get; }
-
- // This method gets called by the runtime. Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
-
- services.AddControllersWithViews();
- services.AddRazorPages();
-
- services.Configure(Configuration.GetSection("GlobalResourceOptions"));
- services.AddSingleton();
- //services.AddSingleton();
-
- //services.AddLocalization();
- services.AddLocalization(options => options.ResourcesPath = "GlobalResources" );
-
- services.AddRouting(options =>
- {
- options.LowercaseUrls = true;
- });
-
- services.AddMvc()
- .AddRazorOptions(options =>
- {
- //options.AddEmbeddedViewsForWebLib();
- })
- .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
- .AddDataAnnotationsLocalization()
- ;
-
- var supportedCultures = new[]
- {
- new CultureInfo("en-US"),
- //new CultureInfo("en"),
- new CultureInfo("fr-FR"),
- // new CultureInfo("fr"),
- };
-
- var routeSegmentLocalizationProvider = new FirstUrlSegmentRequestCultureProvider(supportedCultures.ToList());
-
- // this seems in conflict with middleware config below where we new up the options
- // but without this the language dropdown in layout only shows english
- services.Configure(options =>
- {
-
-
- // State what the default culture for your application is. This will be used if no specific culture
- // can be determined for a given request.
- options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
-
- // You must explicitly state which cultures your application supports.
- // These are the cultures the app supports for formatting numbers, dates, etc.
- options.SupportedCultures = supportedCultures;
-
- // These are the cultures the app supports for UI strings, i.e. we have localized resources for.
- options.SupportedUICultures = supportedCultures;
-
- // You can change which providers are configured to determine the culture for requests, or even add a custom
- // provider with your own logic. The providers will be asked in order to provide a culture for each request,
- // and the first to provide a non-null result that is in the configured supported cultures list will be used.
- // By default, the following built-in providers are configured:
- // - QueryStringRequestCultureProvider, sets culture via "culture" and "ui-culture" query string values, useful for testing
- // - CookieRequestCultureProvider, sets culture via "ASPNET_CULTURE" cookie
- // - AcceptLanguageHeaderRequestCultureProvider, sets culture via the "Accept-Language" request header
- //options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
- //{
- // // My custom request culture logic
- // return new ProviderCultureResult("en");
- //}));
- options.RequestCultureProviders.Insert(0, routeSegmentLocalizationProvider);
-
- });
- }
-
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(
- IApplicationBuilder app,
- IWebHostEnvironment env,
- IOptions locOptions
- )
- {
-
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- //app.UseDatabaseErrorPage();
-
- }
- else
- {
- app.UseExceptionHandler("/Home/Error");
- }
-
- app.UseStaticFiles();
-
-
- app.UseRequestLocalization(locOptions.Value);
-
- app.UseHttpsRedirection();
- //app.UseStaticFiles();
-
- app.UseRouting();
-
- app.UseAuthentication();
- app.UseAuthorization();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllerRoute(
- name: "default-localized",
- pattern: "{culture}/{controller}/{action}/{id?}",
- defaults: new { controller = "Home", action = "Index" },
- constraints: new { culture = new CultureSegmentRouteConstraint() }
- );
-
- endpoints.MapControllerRoute(
- name: "default",
- pattern: "{controller=Home}/{action=Index}/{id?}");
-
- endpoints.MapRazorPages();
- });
-
-
- //app.UseMvc(routes =>
- //{
- // routes.MapRoute(
- // name: "default-localized",
- // template: "{culture}/{controller}/{action}/{id?}",
- // defaults: new { controller = "Home", action = "Index" },
- // constraints: new { culture = new CultureSegmentRouteConstraint() }
- // );
-
-
- // routes.MapRoute(
- // name: "default",
- // template: "{controller=Home}/{action=Index}/{id?}");
- //});
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+//using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
+//using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.AspNetCore.Mvc.Razor;
+using System.Globalization;
+using Microsoft.AspNetCore.Localization;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Localization;
+using cloudscribe.Web.Localization;
+using Microsoft.Extensions.Hosting;
+
+//https://github.com/aspnet/Localization/issues/157
+
+namespace localization.WebApp
+{
+ public class Startup
+ {
+
+ public Startup(IConfiguration configuration)
+ {
+ Configuration =configuration;
+
+ }
+
+ public IConfiguration Configuration { get; }
+
+ // This method gets called by the runtime. Use this method to add services to the container.
+ public void ConfigureServices(IServiceCollection services)
+ {
+
+ services.AddControllersWithViews();
+ services.AddRazorPages();
+
+ services.Configure(Configuration.GetSection("GlobalResourceOptions"));
+ services.AddSingleton();
+ //services.AddSingleton();
+
+ //services.AddLocalization();
+ services.AddLocalization(options => options.ResourcesPath = "GlobalResources" );
+
+ services.AddRouting(options =>
+ {
+ options.LowercaseUrls = true;
+ });
+
+ services.AddMvc()
+ .AddRazorOptions(options =>
+ {
+ //options.AddEmbeddedViewsForWebLib();
+ })
+ .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
+ .AddDataAnnotationsLocalization()
+ ;
+
+ var supportedCultures = new[]
+ {
+ new CultureInfo("en-US"),
+ //new CultureInfo("en"),
+ new CultureInfo("fr-FR"),
+ // new CultureInfo("fr"),
+ };
+
+ var routeSegmentLocalizationProvider = new FirstUrlSegmentRequestCultureProvider(supportedCultures.ToList());
+
+ // this seems in conflict with middleware config below where we new up the options
+ // but without this the language dropdown in layout only shows english
+ services.Configure(options =>
+ {
+
+
+ // State what the default culture for your application is. This will be used if no specific culture
+ // can be determined for a given request.
+ options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
+
+ // You must explicitly state which cultures your application supports.
+ // These are the cultures the app supports for formatting numbers, dates, etc.
+ options.SupportedCultures = supportedCultures;
+
+ // These are the cultures the app supports for UI strings, i.e. we have localized resources for.
+ options.SupportedUICultures = supportedCultures;
+
+ // You can change which providers are configured to determine the culture for requests, or even add a custom
+ // provider with your own logic. The providers will be asked in order to provide a culture for each request,
+ // and the first to provide a non-null result that is in the configured supported cultures list will be used.
+ // By default, the following built-in providers are configured:
+ // - QueryStringRequestCultureProvider, sets culture via "culture" and "ui-culture" query string values, useful for testing
+ // - CookieRequestCultureProvider, sets culture via "ASPNET_CULTURE" cookie
+ // - AcceptLanguageHeaderRequestCultureProvider, sets culture via the "Accept-Language" request header
+ //options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
+ //{
+ // // My custom request culture logic
+ // return new ProviderCultureResult("en");
+ //}));
+ options.RequestCultureProviders.Insert(0, routeSegmentLocalizationProvider);
+
+ });
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(
+ IApplicationBuilder app,
+ IWebHostEnvironment env,
+ IOptions locOptions
+ )
+ {
+
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ //app.UseDatabaseErrorPage();
+
+ }
+ else
+ {
+ app.UseExceptionHandler("/Home/Error");
+ }
+
+ app.UseStaticFiles();
+
+
+ app.UseRequestLocalization(locOptions.Value);
+
+ app.UseHttpsRedirection();
+ //app.UseStaticFiles();
+
+ app.UseRouting();
+
+ app.UseAuthentication();
+ app.UseAuthorization();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllerRoute(
+ name: "default-localized",
+ pattern: "{culture}/{controller}/{action}/{id?}",
+ defaults: new { controller = "Home", action = "Index" },
+ constraints: new { culture = new CultureSegmentRouteConstraint() }
+ );
+
+ endpoints.MapControllerRoute(
+ name: "default",
+ pattern: "{controller=Home}/{action=Index}/{id?}");
+
+ endpoints.MapRazorPages();
+ });
+
+
+ //app.UseMvc(routes =>
+ //{
+ // routes.MapRoute(
+ // name: "default-localized",
+ // template: "{culture}/{controller}/{action}/{id?}",
+ // defaults: new { controller = "Home", action = "Index" },
+ // constraints: new { culture = new CultureSegmentRouteConstraint() }
+ // );
+
+
+ // routes.MapRoute(
+ // name: "default",
+ // template: "{controller=Home}/{action=Index}/{id?}");
+ //});
+ }
+ }
+}
diff --git a/src/localization.WebApp/Views/Home/About.cshtml b/src/localization.WebApp/Views/Home/About.cshtml
index fdd2f44..ec1e585 100644
--- a/src/localization.WebApp/Views/Home/About.cshtml
+++ b/src/localization.WebApp/Views/Home/About.cshtml
@@ -1,11 +1,11 @@
-@using Microsoft.Extensions.Localization
-@inject IStringLocalizer sr
-
-@{
- ViewData["Title"] = "About";
-}
-
@ViewData["Title"].
-
@ViewData["Message"]
-
-
Use this area to provide additional information.
-@sr["this string comes from shared resources"]
+@using Microsoft.Extensions.Localization
+@inject IStringLocalizer sr
+
+@{
+ ViewData["Title"] = "About";
+}
+
@ViewData["Title"].
+
@ViewData["Message"]
+
+
Use this area to provide additional information.
+@sr["this string comes from shared resources"]
diff --git a/src/localization.WebApp/Views/Home/Contact.cshtml b/src/localization.WebApp/Views/Home/Contact.cshtml
index 15c12c6..9d10bf9 100644
--- a/src/localization.WebApp/Views/Home/Contact.cshtml
+++ b/src/localization.WebApp/Views/Home/Contact.cshtml
@@ -1,17 +1,17 @@
-@{
- ViewData["Title"] = "Contact";
-}
-
@ViewData["Title"].
-
@ViewData["Message"]
-
-
- One Microsoft Way
- Redmond, WA 98052-6399
- P:
- 425.555.0100
-
-
-
- Support:Support@example.com
- Marketing:Marketing@example.com
-
+@{
+ ViewData["Title"] = "Contact";
+}
+
@ViewData["Title"].
+
@ViewData["Message"]
+
+
+ One Microsoft Way
+ Redmond, WA 98052-6399
+ P:
+ 425.555.0100
+
+
+
+ Support:Support@example.com
+ Marketing:Marketing@example.com
+
diff --git a/src/localization.WebApp/Views/Home/Index.cshtml b/src/localization.WebApp/Views/Home/Index.cshtml
index 146ccc3..7bd5cea 100644
--- a/src/localization.WebApp/Views/Home/Index.cshtml
+++ b/src/localization.WebApp/Views/Home/Index.cshtml
@@ -1,109 +1,109 @@
-@{
- ViewData["Title"] = "Home Page";
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
- Learn how to build ASP.NET apps that can run anywhere.
-
- Learn More
-
-
-
-
-
-
-
-
- There are powerful new features in Visual Studio for building modern web apps.
-
- Learn More
-
-
-
-
-
-
-
-
- Bring in libraries from NuGet, Bower, and npm, and automate tasks using Grunt or Gulp.
-
- Learn More
-
-
-
-
-
-
-
-
- Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps.
-
- Learn More
-
-
- Swapping to Development environment will display more detailed information about the error that occurred.
-
-
- Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application.
-
+@{
+ ViewData["Title"] = "Error";
+}
+
+
Error.
+
An error occurred while processing your request.
+
+
Development Mode
+
+ Swapping to Development environment will display more detailed information about the error that occurred.
+
+
+ Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application.
+