├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── dotnet.yml ├── .gitignore ├── LICENSE ├── README.md ├── ReswPlus.sln ├── docs └── FAQ.md ├── nuget ├── Icon.png ├── README.md ├── ReswPlus.SourceGenerator.NugetPackage.props └── ReswPlus.targets ├── samples ├── UWP │ ├── ReswPlusUWPSample │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Assets │ │ │ ├── LargeTile.scale-100.png │ │ │ ├── LargeTile.scale-125.png │ │ │ ├── LargeTile.scale-150.png │ │ │ ├── LargeTile.scale-200.png │ │ │ ├── LargeTile.scale-400.png │ │ │ ├── LockScreenLogo.scale-200.png │ │ │ ├── SmallTile.scale-100.png │ │ │ ├── SmallTile.scale-125.png │ │ │ ├── SmallTile.scale-150.png │ │ │ ├── SmallTile.scale-200.png │ │ │ ├── SmallTile.scale-400.png │ │ │ ├── SplashScreen.scale-100.png │ │ │ ├── SplashScreen.scale-125.png │ │ │ ├── SplashScreen.scale-150.png │ │ │ ├── SplashScreen.scale-200.png │ │ │ ├── SplashScreen.scale-400.png │ │ │ ├── Square150x150Logo.scale-100.png │ │ │ ├── Square150x150Logo.scale-125.png │ │ │ ├── Square150x150Logo.scale-150.png │ │ │ ├── Square150x150Logo.scale-200.png │ │ │ ├── Square150x150Logo.scale-400.png │ │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ │ │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ │ ├── Square44x44Logo.scale-100.png │ │ │ ├── Square44x44Logo.scale-125.png │ │ │ ├── Square44x44Logo.scale-150.png │ │ │ ├── Square44x44Logo.scale-200.png │ │ │ ├── Square44x44Logo.scale-400.png │ │ │ ├── Square44x44Logo.targetsize-16.png │ │ │ ├── Square44x44Logo.targetsize-24.png │ │ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ │ │ ├── Square44x44Logo.targetsize-256.png │ │ │ ├── Square44x44Logo.targetsize-32.png │ │ │ ├── Square44x44Logo.targetsize-48.png │ │ │ ├── StoreLogo.backup.png │ │ │ ├── StoreLogo.scale-100.png │ │ │ ├── StoreLogo.scale-125.png │ │ │ ├── StoreLogo.scale-150.png │ │ │ ├── StoreLogo.scale-200.png │ │ │ ├── StoreLogo.scale-400.png │ │ │ ├── Wide310x150Logo.scale-100.png │ │ │ ├── Wide310x150Logo.scale-125.png │ │ │ ├── Wide310x150Logo.scale-150.png │ │ │ ├── Wide310x150Logo.scale-200.png │ │ │ └── Wide310x150Logo.scale-400.png │ │ ├── Converters │ │ │ └── ToUpperCaseConverter.cs │ │ ├── MainPage.xaml │ │ ├── MainPage.xaml.cs │ │ ├── Package.appxmanifest │ │ ├── Pages │ │ │ ├── AdvancedPluralizationSamplePage.xaml │ │ │ ├── AdvancedPluralizationSamplePage.xaml.cs │ │ │ ├── BasicPluralizationSamplePage.xaml │ │ │ ├── BasicPluralizationSamplePage.xaml.cs │ │ │ ├── HtmlStringSamplePage.xaml │ │ │ ├── HtmlStringSamplePage.xaml.cs │ │ │ ├── LiteralStringFormatSamplePage.xaml │ │ │ ├── LiteralStringFormatSamplePage.xaml.cs │ │ │ ├── MacroSamplePage.xaml │ │ │ ├── MacroSamplePage.xaml.cs │ │ │ ├── NamedStringFormatSamplePage.xaml │ │ │ ├── NamedStringFormatSamplePage.xaml.cs │ │ │ ├── ReferenceStringFormatSamplePage.xaml │ │ │ ├── ReferenceStringFormatSamplePage.xaml.cs │ │ │ ├── StringFormatSamplePage.xaml │ │ │ ├── StringFormatSamplePage.xaml.cs │ │ │ ├── StronglyTypedSamplePage.xaml │ │ │ ├── StronglyTypedSamplePage.xaml.cs │ │ │ ├── VariantsSamplePage.xaml │ │ │ └── VariantsSamplePage.xaml.cs │ │ ├── Properties │ │ │ ├── AssemblyInfo.cs │ │ │ └── Default.rd.xml │ │ ├── ReswPlusUWPSample.csproj │ │ ├── ReswPlusUWPSample_TemporaryKey.pfx │ │ └── Strings │ │ │ ├── en-US │ │ │ └── Resources.resw │ │ │ └── fr │ │ │ └── Resources.resw │ └── ReswPlusUWPSampleExternalLibrary │ │ ├── Generated │ │ └── ReswPlus.SourceGenerator │ │ │ └── ReswPlus.SourceGenerator.ReswSourceGenerator │ │ │ ├── ResourceStringProvider.cs │ │ │ └── Resources.resw.cs │ │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── ReswPlusSampleExternalLibrary.rd.xml │ │ ├── ReswPlusUWPSampleExternalLibrary.csproj │ │ └── Strings │ │ └── en │ │ └── Resources.resw └── WinAppSDK │ ├── ReswPlusWinAppSDKSample │ ├── App.xaml │ ├── App.xaml.cs │ ├── Assets │ │ ├── Icon.png │ │ ├── LargeTile.scale-100.png │ │ ├── LargeTile.scale-125.png │ │ ├── LargeTile.scale-150.png │ │ ├── LargeTile.scale-200.png │ │ ├── LargeTile.scale-400.png │ │ ├── SmallTile.scale-100.png │ │ ├── SmallTile.scale-125.png │ │ ├── SmallTile.scale-150.png │ │ ├── SmallTile.scale-200.png │ │ ├── SmallTile.scale-400.png │ │ ├── SplashScreen.scale-100.png │ │ ├── SplashScreen.scale-125.png │ │ ├── SplashScreen.scale-150.png │ │ ├── SplashScreen.scale-200.png │ │ ├── SplashScreen.scale-400.png │ │ ├── Square150x150Logo.scale-100.png │ │ ├── Square150x150Logo.scale-125.png │ │ ├── Square150x150Logo.scale-150.png │ │ ├── Square150x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-400.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ ├── Square44x44Logo.scale-100.png │ │ ├── Square44x44Logo.scale-125.png │ │ ├── Square44x44Logo.scale-150.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Square44x44Logo.scale-400.png │ │ ├── Square44x44Logo.targetsize-16.png │ │ ├── Square44x44Logo.targetsize-24.png │ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ │ ├── Square44x44Logo.targetsize-256.png │ │ ├── Square44x44Logo.targetsize-32.png │ │ ├── Square44x44Logo.targetsize-48.png │ │ ├── StoreLogo.ico │ │ ├── StoreLogo.scale-100.png │ │ ├── StoreLogo.scale-125.png │ │ ├── StoreLogo.scale-150.png │ │ ├── StoreLogo.scale-200.png │ │ ├── StoreLogo.scale-400.png │ │ ├── Wide310x150Logo.scale-100.png │ │ ├── Wide310x150Logo.scale-125.png │ │ ├── Wide310x150Logo.scale-150.png │ │ ├── Wide310x150Logo.scale-200.png │ │ └── Wide310x150Logo.scale-400.png │ ├── Converters │ │ └── ToUpperCaseConverter.cs │ ├── MainControl.xaml │ ├── MainControl.xaml.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── Package.appxmanifest │ ├── Pages │ │ ├── AdvancedPluralizationSamplePage.xaml │ │ ├── AdvancedPluralizationSamplePage.xaml.cs │ │ ├── BasicPluralizationSamplePage.xaml │ │ ├── BasicPluralizationSamplePage.xaml.cs │ │ ├── LiteralStringFormatSamplePage.xaml │ │ ├── LiteralStringFormatSamplePage.xaml.cs │ │ ├── MacroSamplePage.xaml │ │ ├── MacroSamplePage.xaml.cs │ │ ├── NamedStringFormatSamplePage.xaml │ │ ├── NamedStringFormatSamplePage.xaml.cs │ │ ├── ReferenceStringFormatSamplePage.xaml │ │ ├── ReferenceStringFormatSamplePage.xaml.cs │ │ ├── StringFormatSamplePage.xaml │ │ ├── StringFormatSamplePage.xaml.cs │ │ ├── StronglyTypedSamplePage.xaml │ │ ├── StronglyTypedSamplePage.xaml.cs │ │ ├── VariantsSamplePage.xaml │ │ └── VariantsSamplePage.xaml.cs │ ├── Properties │ │ ├── PublishProfiles │ │ │ ├── win-arm64.pubxml │ │ │ ├── win-x64.pubxml │ │ │ └── win-x86.pubxml │ │ └── launchSettings.json │ ├── ReswPlusWinAppSDKSample.csproj │ ├── ReswPlusWinAppSDKSample_TemporaryKey.pfx │ ├── Strings │ │ ├── en-US │ │ │ └── Resources.resw │ │ └── fr │ │ │ └── Resources.resw │ └── app.manifest │ └── ReswPlusWinAppSDKSampleExternalLibrary │ ├── ReswPlusWinAppSDKSampleExternalLibrary.csproj │ └── Strings │ └── en │ └── Resources.resw ├── src ├── ReswPlus.CommandLine │ ├── Converters │ │ └── AndroidXMLConverter.cs │ ├── Parameters │ │ ├── AndroidToReswParameters.cs │ │ └── ReswToAndroidParameters.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ └── ReswPlusCmd.csproj ├── ReswPlus.Shared │ ├── Interfaces │ │ └── IErrorLogger.cs │ ├── ResourceParser │ │ ├── FormatTag.cs │ │ ├── ParameterType.cs │ │ ├── ReswFilters.cs │ │ ├── ReswInfo.cs │ │ ├── ReswItem.cs │ │ └── ReswParser.cs │ ├── ReswPlus.Shared.projitems │ └── ReswPlus.Shared.shproj └── ReswPlus.SourceGenerator │ ├── AnalyzerReleases.Shipped.md │ ├── AnalyzerReleases.Unshipped.md │ ├── ClassGenerators │ ├── GenerationResult.cs │ ├── Models │ │ ├── Localization.cs │ │ └── StronglyTypedClass.cs │ ├── PluralFormsRetriever.cs │ └── ReswClassGenerator.cs │ ├── CodeGenerators │ ├── CsharpCodeGenerator.cs │ └── ICodeGenerator.cs │ ├── Images │ └── Icon.png │ ├── Models │ ├── IProject.cs │ ├── Language.cs │ ├── Project.cs │ └── ResourceFileInfo.cs │ ├── ReswGenerator.cs │ ├── ReswPlus.SourceGenerator.csproj │ └── Templates │ ├── Macros │ └── Macros.txt │ ├── Plurals │ ├── ArabicProvider.txt │ ├── BreizhProvider.txt │ ├── CentralAtlasTamazightProvider.txt │ ├── CroatProvider.txt │ ├── CzechProvider.txt │ ├── DanishProvider.txt │ ├── FilipinoProvider.txt │ ├── HebrewProvider.txt │ ├── IPluralProvider.txt │ ├── IcelandicProvider.txt │ ├── IntOneOrZeroProvider.txt │ ├── IrishProvider.txt │ ├── LatvianProvider.txt │ ├── LithuanianProvider.txt │ ├── MacedonianProvider.txt │ ├── MalteseProvider.txt │ ├── ManxProvider.txt │ ├── OneOrTwoProvider.txt │ ├── OneOrZeroProvider.txt │ ├── OneOrZeroToOneExcludedProvider.txt │ ├── OnlyOneProvider.txt │ ├── OtherProvider.txt │ ├── PluralTypeEnum.txt │ ├── PolishProvider.txt │ ├── ResourceLoaderExtension.txt │ ├── RomanianProvider.txt │ ├── ScottishGaelicProvider.txt │ ├── SinhalaProvider.txt │ ├── SlavicProvider.txt │ ├── SlovenianProvider.txt │ ├── TachelhitProvider.txt │ ├── WelshProvider.txt │ ├── ZeroToOneProvider.txt │ └── ZeroToTwoExcludedProvider.txt │ ├── ResourceStringProviders │ ├── MicrosoftResourceStringProvider.txt │ └── WindowsResourceStringProvider.txt │ └── Utils │ ├── DoubleExt.txt │ └── IntExt.txt └── tests └── ReswPlusUnitTests ├── FormatTagLiterals.cs ├── FormatTagMacros.cs ├── FormatTagParsing.cs ├── FormatTagPlurals.cs ├── FormatTagStringRef.cs ├── FormatTagTyped.cs ├── FormatTagVariants.cs └── ReswPlusUnitTests.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | # Don't touch my line endings you git! 2 | * text=auto 3 | 4 | # Ignore all differences in line endings 5 | *.jpg binary 6 | *.png binary 7 | *.gif binary -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: Build, Test, and (Optionally) Publish ReswPlus 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - 'v*' # Runs only when a tag like v1.0.0 is pushed 9 | pull_request: 10 | branches: 11 | - main 12 | workflow_dispatch: # Allows manual trigger via GitHub Actions UI 13 | 14 | jobs: 15 | build: 16 | runs-on: windows-latest 17 | 18 | steps: 19 | - name: Checkout Repository 20 | uses: actions/checkout@v4 21 | 22 | - name: Setup .NET 23 | uses: actions/setup-dotnet@v4 24 | 25 | - name: Setup MSBuild 26 | uses: microsoft/setup-msbuild@v2 27 | 28 | - name: Setup NuGet 29 | uses: nuget/setup-nuget@v2 30 | 31 | - name: Determine Build Configuration 32 | id: config 33 | shell: pwsh 34 | run: | 35 | if ("${{ github.event_name }}" -eq "pull_request") { 36 | echo "BUILD_CONFIG=Debug" | Out-File -FilePath $env:GITHUB_ENV -Append 37 | } else { 38 | echo "BUILD_CONFIG=Release" | Out-File -FilePath $env:GITHUB_ENV -Append 39 | } 40 | 41 | - name: Restore Nuget 42 | run: nuget restore ReswPlus.sln 43 | working-directory: ${{ github.workspace }} 44 | 45 | - name: DotNet Restore 46 | run: dotnet restore ReswPlus.sln 47 | working-directory: ${{ github.workspace }} 48 | 49 | - name: Build Solution 50 | run: msbuild ReswPlus.sln /p:Configuration=${{ env.BUILD_CONFIG }} /p:Platform=x64 /p:PublishReadyToRun=false 51 | working-directory: ${{ github.workspace }} 52 | 53 | - name: Run Unit Tests 54 | run: dotnet test tests/ReswPlusUnitTests/ReswPlusUnitTests.csproj --configuration ${{ env.BUILD_CONFIG }} --no-build --verbosity normal 55 | working-directory: ${{ github.workspace }} 56 | 57 | - name: Pack NuGet Package (Only for Release and explicit request) 58 | if: startsWith(github.ref, 'refs/tags/v') 59 | run: dotnet pack src/ReswPlus.SourceGenerator/ReswPlus.SourceGenerator.csproj --configuration Release --no-build --output nupkg 60 | working-directory: ${{ github.workspace }} 61 | 62 | - name: Push NuGet package 63 | if: startsWith(github.ref, 'refs/tags/v') 64 | run: dotnet nuget push "**/nupkg/*.nupkg" --api-key "${{ secrets.NUGET_API_KEY }}" --source "https://api.nuget.org/v3/index.json" --skip-duplicate 65 | working-directory: ${{ github.workspace }} 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | # User-specific files 6 | *.suo 7 | *.user 8 | *.userosscache 9 | *.sln.docstates 10 | *.nupkg 11 | project.lock.json 12 | 13 | # Visual Studio cache/options directory 14 | .vs/ 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | Generated Files/ 28 | 29 | # ReSharper is a .NET coding add-in 30 | _ReSharper*/ 31 | *.[Rr]e[Ss]harper 32 | *.DotSettings.user 33 | 34 | # DotCover is a Code Coverage Tool 35 | *.dotCover 36 | 37 | # Visual Studio code coverage results 38 | *.coverage 39 | *.coveragexml 40 | 41 | # Windows Store app package directories and files 42 | AppPackages/ 43 | BundleArtifacts/ 44 | Package.StoreAssociation.xml 45 | _pkginfo.txt 46 | 47 | # Visual Studio cache files 48 | # files ending in .cache can be ignored 49 | *.[Cc]ache 50 | # but keep track of directories ending in .cache 51 | !*.[Cc]ache/ 52 | 53 | packages/ 54 | 55 | UpgradeLog.htm 56 | UpgradeLog*.htm -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Rudy Huyn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ReswPlus - Advanced Code Generator for `.resw` Files 4 | ![Type](https://img.shields.io/badge/type-Visual%20Studio%20Extension-blueviolet) 5 | ![Compatibility](https://img.shields.io/badge/compatibility-UWP%2C%20.Net%20Core%2C%20.Net%20Standard%2C%20ASP.Net%20Core-blue) 6 | ![Language Supported](https://img.shields.io/badge/languages-C%23-brightgreen) 7 | ![GitHub](https://img.shields.io/github/license/dotnetplus/reswplus.svg) 8 | 9 | _**Now available as a Source Generator!**_ 10 | 11 | **ReswPlus** is a C# Source Generator for Visual Studio that enhances `.resw` files with a powerful set of features: 12 | 13 | - **Strongly typed static properties** for safer and more efficient string access. 14 | - **Automatic generation of string formatting methods**, supporting: 15 | - Typed and named parameters, literal strings, string references, and macros. 16 | - **Pluralization support** for *196 languages*, including handling empty states when the item count is zero. 17 | - **Variant support** for managing multiple versions of a string. 18 | - **Generation of a markup extension** for accessing strings with **compile-time verification**. 19 | 20 | ## ✅ Feature Comparison 21 | 22 | | Feature | Resw | Resw + ReswPlus | Resx | Android XML (for reference) | 23 | |-----------------------------------------------|------|-----------------|------|-------------| 24 | | Modify UI properties via resource files (x:uid) | ✅ | ✅ | | | 25 | | Generate strongly typed accessors | | ✅ | ✅ | ✅ | 26 | | Generate string formatting methods | | ✅ | | | 27 | | Support pluralization | | ✅ | | ✅ | 28 | | Support empty states | | ✅ | | | 29 | | Auto-generate string formatting methods | | ✅ | | | 30 | | Support literal strings in formatters | | ✅ | | | 31 | | Support macros in formatters | | ✅ | | | 32 | | Support string references in formatters | | ✅ | | | 33 | | Strongly typed string formatting | | ✅ | | | 34 | | Support resources in libraries | | ✅ | ✅ | | 35 | | Support string variants (e.g., gender-based) | | ✅ | | | 36 | 37 | ## 📦 Getting Started 38 | 39 | ⚡ [How to Install ReswPlus](https://github.com/reswplus/ReswPlus/wiki/How-to-install-ReswPlus) – Step-by-step installation guide. 40 | 41 | ## 🔧 Features 42 | 43 | ### Strongly Typed Class Generator 44 | ReswPlus generates a class that exposes all strings from your `.resw` files as **strongly typed static properties**, ensuring **compile-time safety** in both XAML and C#. 45 | 46 | 🗨 [How to Generate a Strongly Typed Class](https://github.com/reswplus/ReswPlus/wiki/Features:-Strongly-typed-properties) 47 | 48 | ### Pluralization Support 49 | Easily add **pluralization** support for *196 languages*, including correct handling of **empty states** when the count is zero. 50 | 51 | 🗨 [How to Add Pluralization](https://github.com/reswplus/ReswPlus/wiki/Features:-Pluralization-support) 52 | ⚙️ [Handling Empty States](https://github.com/reswplus/ReswPlus/wiki/Features:-Pluralization---Empty-states) 53 | ⚙️ [Supported Languages](https://github.com/reswplus/ReswPlus/wiki/Languages-supported-for-pluralization) 54 | 55 | ### String Formatting 56 | ReswPlus simplifies ViewModels and Views by handling string formatting directly and generating **strongly typed methods**. 57 | 58 | 🗨 [How to Use String Formatting](https://github.com/reswplus/ReswPlus/wiki/Features:-String-Formatting) 59 | ⚙️ [Named Parameters](https://github.com/reswplus/ReswPlus/wiki/Features:-Named-parameters-for-String-Formatting) 60 | ⚙️ [Using String References](https://github.com/reswplus/ReswPlus/wiki/Features:-String-References-in-String-Formatting) 61 | ⚙️ [Using Literal Strings](https://github.com/reswplus/ReswPlus/wiki/Features:-Literal-Strings-in-String-Formatting) 62 | ⚙️ [Using Macros](https://github.com/reswplus/ReswPlus/wiki/Features:-Macros-in-String-Formatting) 63 | 64 | ### String Variants 65 | ReswPlus allows multiple variants of a string based on different criteria, such as **gender-based messages** or other conditions. 66 | 67 | 🗨 [How to Use Variants](https://github.com/reswplus/ReswPlus/wiki/Features:-Variants) 68 | 69 | ## Tools 70 | In addition to features to enrich resw files, ReswPlus also provides some interesting tools to improve your productivity or make it easier to use/support resw files in your workflow and localization process. 71 | 72 | ### Convert from/to Android XML files 73 | Unfortunately, not all localization tools and companies support `.resw` files. This becomes even more problematic when dealing with pluralization, as `.resw` does not support it by default. 74 | 75 | To address this, **ReswPlus** includes a converter for **seamless conversion between `.resw` and Android XML**, a format that supports string pluralization and is widely compatible with existing localization tools. 76 | 77 | Simply right click on the resw associated to the default language of your app and select `ReswPlus > Export to Android XML format`. To convert the Android files once localized, you can use the command-line tool provided with the nuget package (packages/ReswPlusLib.xxxx/Tools/ReswPlusCmd\ReswPlusCmd.exe with the following arguments `xml-to-resw -i `. 78 | 79 | If you don't want to use Visual Studio to convert your resw files to Android XML files, you can use the same command-line tool with the following arguments `resw-to-xml -i ` 80 | 81 | ## Other programming languages 82 | 83 | The current Source Generator supports only C#. If your project uses VB.NET, C++/CX, or C++/WinRT, you can use our legacy Visual Studio extension, available [here](https://github.com/DotNetPlus/ReswPlus/tree/legacy/visual-studio-extension) 84 | 85 | ![reswplus](https://user-images.githubusercontent.com/1226538/56525314-a76eb800-64ff-11e9-9e39-1bb4cd2dd012.gif) 86 | -------------------------------------------------------------------------------- /docs/FAQ.md: -------------------------------------------------------------------------------- 1 | ## What's the minimum version of Windows 10 supported for applications using Resw? 2 | 3 | Because ReswPlus uses [MarkupExtension](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.markup.markupextension), the minimum version supported is 4 | Windows 10 Fall Creators Update (1709). 5 | 6 | ## Does it support VB or C++? 7 | 8 | VB support is currently under development. C++/CX and C++/WinRT support are planned for a future update. 9 | 10 | ## Is it free? 11 | 12 | Yes and it won't change. 13 | 14 | ## What's the license of this product? 15 | 16 | This code is under MIT License, you can find the license here: https://github.com/rudyhuyn/ReswPlus/blob/master/LICENSE 17 | 18 | ## How can I ask ReswPlus to ignore a resource item? 19 | 20 | Add the hashtag **#ReswPlusIgnore** in the comment field to ask ReswPlus to ignore the current item. 21 | 22 | ## I have an idea/suggestion, where can I share it? 23 | 24 | [Open a ticket](https://github.com/rudyhuyn/ReswPlus/issues/new), we will study your idea or suggestion and will include it in a next update if approved! 25 | 26 | ## Can I contribute? 27 | 28 | Of course! First [open a ticket](https://github.com/rudyhuyn/ReswPlus/issues/new) and describe your suggestion or the feature you would like to work on, once approved, send a Pull request with your change. 29 | -------------------------------------------------------------------------------- /nuget/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/nuget/Icon.png -------------------------------------------------------------------------------- /nuget/README.md: -------------------------------------------------------------------------------- 1 | **ReswPlus** is a C# Source Generator for Visual Studio that enhances `.resw` files with a powerful set of features, making localization easier, safer, and more efficient. 2 | 3 | ## Features 4 | 5 | - **Strongly typed static properties** for safer and more efficient string access. 6 | - **Automatic generation of string formatting methods**, supporting: 7 | - Typed and named parameters, literal strings, string references, and macros. 8 | - **Pluralization support** for *196 languages*, including handling empty states when the item count is zero. 9 | - **Variant support** for managing multiple versions of a string. 10 | - **Generation of a markup extension** for accessing strings with **compile-time verification**. -------------------------------------------------------------------------------- /nuget/ReswPlus.SourceGenerator.NugetPackage.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.3.1.5 5 | true 6 | ReswPlus - Source Generator 7 | ReswPlus 8 | $(FileVersion) 9 | Rudy Huyn 10 | ReswPlus - Source Generator for Resw files 11 | https://github.com/reswplus/ReswPlus/ 12 | Icon.png 13 | Copyright 2025 14 | dotnet localization resx resw plural pluralization 15 | MIT 16 | README.md 17 | NU5128 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /nuget/ReswPlus.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | $(AdditionalFileItemNames);PRIResource 11 | 12 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | #7B54C0 9 | 10 | 11 | 16 | 17 | 24 | 25 | 33 | 34 | 39 | 40 | 45 | 46 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Windows.ApplicationModel; 3 | using Windows.ApplicationModel.Activation; 4 | using Windows.UI; 5 | using Windows.UI.ViewManagement; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Controls; 8 | using Windows.UI.Xaml.Navigation; 9 | 10 | namespace ReswPlusUWPSample 11 | { 12 | /// 13 | /// Provides application-specific behavior to supplement the default Application class. 14 | /// 15 | public sealed partial class App : Application 16 | { 17 | /// 18 | /// Initializes the singleton application object. This is the first line of authored code 19 | /// executed, and as such is the logical equivalent of main() or WinMain(). 20 | /// 21 | public App() 22 | { 23 | this.InitializeComponent(); 24 | this.Suspending += OnSuspending; 25 | } 26 | 27 | /// 28 | /// Invoked when the application is launched normally by the end user. Other entry points 29 | /// will be used such as when the application is launched to open a specific file. 30 | /// 31 | /// Details about the launch request and process.s 32 | protected override void OnLaunched(LaunchActivatedEventArgs e) 33 | { 34 | var rootFrame = Window.Current.Content as Frame; 35 | 36 | // Do not repeat app initialization when the Window already has content, 37 | // just ensure that the window is active 38 | if (rootFrame == null) 39 | { 40 | // Create a Frame to act as the navigation context and navigate to the first page 41 | rootFrame = new Frame(); 42 | 43 | rootFrame.NavigationFailed += OnNavigationFailed; 44 | 45 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 46 | { 47 | //TODO: Load state from previously suspended application 48 | } 49 | 50 | // Place the frame in the current Window 51 | Window.Current.Content = rootFrame; 52 | } 53 | 54 | if (e.PrelaunchActivated == false) 55 | { 56 | if (rootFrame.Content == null) 57 | { 58 | // When the navigation stack isn't restored navigate to the first page, 59 | // configuring the new page by passing required information as a navigation 60 | // parameter 61 | _ = rootFrame.Navigate(typeof(MainPage), e.Arguments); 62 | } 63 | // Ensure the current window is active 64 | Window.Current.Activate(); 65 | } 66 | 67 | CustomizeTitleBar(); 68 | } 69 | 70 | /// 71 | /// Invoked when Navigation to a certain page fails 72 | /// 73 | /// The Frame which failed navigation 74 | /// Details about the navigation failure 75 | private void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 76 | { 77 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 78 | } 79 | 80 | /// 81 | /// Invoked when application execution is being suspended. Application state is saved 82 | /// without knowing whether the application will be terminated or resumed with the contents 83 | /// of memory still intact. 84 | /// 85 | /// The source of the suspend request. 86 | /// Details about the suspend request. 87 | private void OnSuspending(object sender, SuspendingEventArgs e) 88 | { 89 | var deferral = e.SuspendingOperation.GetDeferral(); 90 | //TODO: Save application state and stop any background activity 91 | deferral.Complete(); 92 | } 93 | 94 | private void CustomizeTitleBar() 95 | { 96 | var titleBar = ApplicationView.GetForCurrentView().TitleBar; 97 | 98 | var backgroundColor = Color.FromArgb(255, 0x7B, 0x54, 0xC0); 99 | var foregroundColor = Colors.White; 100 | 101 | // Set active window colors 102 | titleBar.ButtonForegroundColor = titleBar.ForegroundColor = foregroundColor; 103 | titleBar.ButtonBackgroundColor = titleBar.BackgroundColor = backgroundColor; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-100.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-125.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-150.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-200.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/LargeTile.scale-400.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-100.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-125.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-150.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-200.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SmallTile.scale-400.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.backup.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/Assets/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Converters/ToUpperCaseConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Windows.UI.Xaml.Data; 3 | 4 | namespace ReswPlusUWPSample.Converters 5 | { 6 | internal class ToUpperCaseConverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, string language) 9 | { 10 | return value is string str ? str.ToUpper() : (object)""; 11 | } 12 | 13 | public object ConvertBack(object value, Type targetType, object parameter, string language) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using ReswPlusUWPSample.Pages; 2 | using Windows.UI.Xaml.Controls; 3 | 4 | namespace ReswPlusUWPSample 5 | { 6 | public sealed partial class MainPage : Page 7 | { 8 | public MainPage() 9 | { 10 | InitializeComponent(); 11 | NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems[0]; 12 | _ = NavFrame.Navigate(typeof(StronglyTypedSamplePage), null); 13 | } 14 | 15 | private void NavigationViewControl_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) 16 | { 17 | if (args.InvokedItemContainer?.Tag != null) 18 | { 19 | var navItemTag = args.InvokedItemContainer.Tag.ToString(); 20 | switch (navItemTag) 21 | { 22 | case "StronglyTyped": 23 | { 24 | _ = NavFrame.Navigate(typeof(StronglyTypedSamplePage), null, args.RecommendedNavigationTransitionInfo); 25 | } 26 | break; 27 | case "StringFormat": 28 | { 29 | _ = NavFrame.Navigate(typeof(StringFormatSamplePage), null, args.RecommendedNavigationTransitionInfo); 30 | } 31 | break; 32 | case "LiteralFormat": 33 | { 34 | _ = NavFrame.Navigate(typeof(LiteralStringFormatSamplePage), null, args.RecommendedNavigationTransitionInfo); 35 | break; 36 | } 37 | case "StringReferenceFormat": 38 | { 39 | _ = NavFrame.Navigate(typeof(ReferenceStringFormatSamplePage), null, args.RecommendedNavigationTransitionInfo); 40 | break; 41 | } 42 | case "MacroFormat": 43 | { 44 | _ = NavFrame.Navigate(typeof(MacroSamplePage), null, args.RecommendedNavigationTransitionInfo); 45 | break; 46 | } 47 | case "NamedStringFormat": 48 | { 49 | _ = NavFrame.Navigate(typeof(NamedStringFormatSamplePage), null, args.RecommendedNavigationTransitionInfo); 50 | } 51 | break; 52 | case "Pluralization": 53 | { 54 | _ = NavFrame.Navigate(typeof(BasicPluralizationSamplePage), null, args.RecommendedNavigationTransitionInfo); 55 | } 56 | break; 57 | case "AdvancedPluralization": 58 | { 59 | _ = NavFrame.Navigate(typeof(AdvancedPluralizationSamplePage), null, args.RecommendedNavigationTransitionInfo); 60 | } 61 | break; 62 | case "Variants": 63 | { 64 | _ = NavFrame.Navigate(typeof(VariantsSamplePage), null, args.RecommendedNavigationTransitionInfo); 65 | } 66 | break; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ReswPlusSample 7 | Contoso 8 | Assets\StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/AdvancedPluralizationSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusUWPSample.Pages 4 | { 5 | public sealed partial class AdvancedPluralizationSamplePage : Page 6 | { 7 | public AdvancedPluralizationSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/BasicPluralizationSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusUWPSample.Pages 4 | { 5 | public sealed partial class BasicPluralizationSamplePage : Page 6 | { 7 | public BasicPluralizationSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/HtmlStringSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Rudy Huyn. All rights reserved. 2 | // Licensed under the MIT License. 3 | // Source: https://github.com/DotNetPlus/ReswPlus 4 | 5 | using Windows.UI.Xaml.Controls; 6 | 7 | namespace ReswPlusSample.Pages 8 | { 9 | public sealed partial class HtmlStringSamplePage : Page 10 | { 11 | public HtmlStringSamplePage() 12 | { 13 | this.InitializeComponent(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/LiteralStringFormatSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusUWPSample.Pages 4 | { 5 | public sealed partial class LiteralStringFormatSamplePage : Page 6 | { 7 | public LiteralStringFormatSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/MacroSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusUWPSample.Pages 4 | { 5 | public sealed partial class MacroSamplePage : Page 6 | { 7 | public MacroSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/NamedStringFormatSamplePage.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 39 | 40 | 44 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/NamedStringFormatSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusUWPSample.Pages 4 | { 5 | public sealed partial class NamedStringFormatSamplePage : Page 6 | { 7 | public NamedStringFormatSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/ReferenceStringFormatSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusUWPSample.Pages 4 | { 5 | public sealed partial class ReferenceStringFormatSamplePage : Page 6 | { 7 | public ReferenceStringFormatSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/StringFormatSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusUWPSample.Pages 4 | { 5 | public sealed partial class StringFormatSamplePage : Page 6 | { 7 | public StringFormatSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/StronglyTypedSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusUWPSample.Pages 4 | { 5 | public sealed partial class StronglyTypedSamplePage : Page 6 | { 7 | public StronglyTypedSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Pages/VariantsSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Windows.UI.Xaml.Controls; 3 | 4 | namespace ReswPlusUWPSample.Pages 5 | { 6 | public enum PartDayEnum { MORNING = 1, AFTERNOON, EVENING, NIGHT }; 7 | public enum PetTypeEnum { DOG = 1, CAT }; 8 | 9 | public sealed partial class VariantsSamplePage : Page, INotifyPropertyChanged 10 | { 11 | public VariantsSamplePage() 12 | { 13 | this.InitializeComponent(); 14 | } 15 | 16 | public PartDayEnum DayPart { get; set; } 17 | 18 | private void UpdatePartDay(PartDayEnum part) 19 | { 20 | DayPart = part; 21 | RaisePropertyChanged(nameof(DayPart)); 22 | } 23 | 24 | public PetTypeEnum PetType { get; set; } 25 | 26 | private void UpdatePetType(PetTypeEnum type) 27 | { 28 | PetType = type; 29 | RaisePropertyChanged(nameof(PetType)); 30 | } 31 | 32 | public void RaisePropertyChanged(string name) 33 | { 34 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 35 | } 36 | public event PropertyChangedEventHandler PropertyChanged; 37 | 38 | private void PartDayMorning_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e) 39 | { 40 | UpdatePartDay(PartDayEnum.MORNING); 41 | } 42 | 43 | private void PartDayAfternoon_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e) 44 | { 45 | UpdatePartDay(PartDayEnum.AFTERNOON); 46 | } 47 | 48 | private void PartDayEvening_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e) 49 | { 50 | UpdatePartDay(PartDayEnum.EVENING); 51 | } 52 | 53 | private void PartDayNight_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e) 54 | { 55 | UpdatePartDay(PartDayEnum.NIGHT); 56 | } 57 | 58 | private void PetTypeDog_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e) 59 | { 60 | UpdatePetType(PetTypeEnum.DOG); 61 | } 62 | 63 | private void PetTypeCat_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e) 64 | { 65 | UpdatePetType(PetTypeEnum.CAT); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ReswPlusSample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ReswPlusSample")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] 30 | [assembly: NeutralResourcesLanguage("en-US")] 31 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSample/ReswPlusUWPSample_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/UWP/ReswPlusUWPSample/ReswPlusUWPSample_TemporaryKey.pfx -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSampleExternalLibrary/Generated/ReswPlus.SourceGenerator/ReswPlus.SourceGenerator.ReswSourceGenerator/ResourceStringProvider.cs: -------------------------------------------------------------------------------- 1 | using Windows.ApplicationModel.Resources; 2 | 3 | namespace _ReswPlus_AutoGenerated 4 | { 5 | internal class ResourceStringProvider 6 | { 7 | private readonly ResourceLoader _resourceLoader; 8 | 9 | public ResourceStringProvider(string resourceMapId) 10 | { 11 | _resourceLoader = ResourceLoader.GetForViewIndependentUse(resourceMapId); 12 | } 13 | 14 | public string GetString(string resourceId) => _resourceLoader.GetString(resourceId); 15 | } 16 | } -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSampleExternalLibrary/Generated/ReswPlus.SourceGenerator/ReswPlus.SourceGenerator.ReswSourceGenerator/Resources.resw.cs: -------------------------------------------------------------------------------- 1 | // File generated automatically by ReswPlus. https://github.com/DotNetPlus/ReswPlus 2 | using System; 3 | using Windows.UI.Xaml.Markup; 4 | using Windows.UI.Xaml.Data; 5 | 6 | namespace ReswPlusUWPSampleExternalLibrary.Strings{ 7 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ReswPlus.SourceGenerator", "1.0.0.0")] 8 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 9 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 10 | public static class Resources { 11 | private static _ReswPlus_AutoGenerated.ResourceStringProvider _resourceStringProvider; 12 | static Resources() 13 | { 14 | _resourceStringProvider = new _ReswPlus_AutoGenerated.ResourceStringProvider("ReswPlusUWPSampleExternalLibrary/Resources"); 15 | } 16 | 17 | /// 18 | /// Returns the specified string resource for the specified culture or current UI culture. 19 | /// 20 | public static string GetString(string key) => _resourceStringProvider.GetString(key); 21 | 22 | #region ExternalString 23 | /// 24 | /// Looks up a localized string similar to: This string is from an external library 25 | /// 26 | public static string ExternalString 27 | { 28 | get 29 | { 30 | return _resourceStringProvider.GetString("ExternalString"); 31 | } 32 | } 33 | #endregion 34 | } 35 | 36 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ReswPlus.SourceGenerator", "1.0.0.0")] 37 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 38 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 39 | [MarkupExtensionReturnType(ReturnType = typeof(string))] 40 | public partial class ResourcesExtension : MarkupExtension 41 | { 42 | public enum KeyEnum 43 | { 44 | _Undefined = 0, 45 | ExternalString, 46 | } 47 | 48 | private static _ReswPlus_AutoGenerated.ResourceStringProvider _resourceStringProvider; 49 | static ResourcesExtension() 50 | { 51 | _resourceStringProvider = new _ReswPlus_AutoGenerated.ResourceStringProvider("ReswPlusUWPSampleExternalLibrary/Resources"); 52 | } 53 | public KeyEnum Key { get; set;} 54 | public IValueConverter Converter { get; set;} 55 | public object ConverterParameter { get; set;} 56 | protected override object ProvideValue() 57 | { 58 | var value = Key is KeyEnum._Undefined ? string.Empty : _resourceStringProvider.GetString(Key.ToString()); 59 | return Converter is null ? value : Converter.Convert(value, typeof(String), ConverterParameter, null); 60 | } 61 | } 62 | } //ReswPlusUWPSampleExternalLibrary.Strings 63 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSampleExternalLibrary/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ReswPlusSampleExternalLibrary")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ReswPlusSampleExternalLibrary")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] 30 | [assembly: NeutralResourcesLanguage("en")] 31 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSampleExternalLibrary/Properties/ReswPlusSampleExternalLibrary.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /samples/UWP/ReswPlusUWPSampleExternalLibrary/Strings/en/Resources.resw: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | This string is from an external library 122 | 123 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | #7B54C0 16 | 17 | 18 | 23 | 24 | 31 | 32 | 40 | 41 | 46 | 47 | 52 | 53 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | 3 | // To learn more about WinUI, the WinUI project structure, 4 | // and more about our project templates, see: http://aka.ms/winui-project-info. 5 | 6 | namespace ReswPlusWinAppSDKSample; 7 | /// 8 | /// Provides application-specific behavior to supplement the default Application class. 9 | /// 10 | public partial class App : Application 11 | { 12 | /// 13 | /// Initializes the singleton application object. This is the first line of authored code 14 | /// executed, and as such is the logical equivalent of main() or WinMain(). 15 | /// 16 | public App() 17 | { 18 | this.InitializeComponent(); 19 | } 20 | 21 | /// 22 | /// Invoked when the application is launched. 23 | /// 24 | /// Details about the launch request and process. 25 | protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) 26 | { 27 | m_window = new MainWindow(); 28 | m_window.Activate(); 29 | } 30 | 31 | private Window m_window; 32 | } 33 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Icon.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-100.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-125.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-150.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-200.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/LargeTile.scale-400.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-100.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-125.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-150.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-200.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SmallTile.scale-400.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.ico -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/Assets/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Converters/ToUpperCaseConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.UI.Xaml.Data; 3 | 4 | namespace ReswPlusWinAppSDKSample.Converters; 5 | 6 | internal class ToUpperCaseConverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, string language) 9 | { 10 | return value is string str ? str.ToUpper() : (object)""; 11 | } 12 | 13 | public object ConvertBack(object value, Type targetType, object parameter, string language) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/MainControl.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/MainControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | using ReswPlusWinAppSDKSample.Pages; 3 | 4 | namespace ReswPlusWinAppSDKSample; 5 | 6 | public sealed partial class MainControl : UserControl 7 | { 8 | public MainControl() 9 | { 10 | InitializeComponent(); 11 | NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems[0]; 12 | _ = NavFrame.Navigate(typeof(StronglyTypedSamplePage), null); 13 | } 14 | 15 | private void NavigationViewControl_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) 16 | { 17 | if (args.InvokedItemContainer?.Tag != null) 18 | { 19 | var navItemTag = args.InvokedItemContainer.Tag.ToString(); 20 | switch (navItemTag) 21 | { 22 | case "StronglyTyped": 23 | { 24 | _ = NavFrame.Navigate(typeof(StronglyTypedSamplePage), null, args.RecommendedNavigationTransitionInfo); 25 | } 26 | break; 27 | case "StringFormat": 28 | { 29 | _ = NavFrame.Navigate(typeof(StringFormatSamplePage), null, args.RecommendedNavigationTransitionInfo); 30 | } 31 | break; 32 | case "LiteralFormat": 33 | { 34 | _ = NavFrame.Navigate(typeof(LiteralStringFormatSamplePage), null, args.RecommendedNavigationTransitionInfo); 35 | break; 36 | } 37 | case "StringReferenceFormat": 38 | { 39 | _ = NavFrame.Navigate(typeof(ReferenceStringFormatSamplePage), null, args.RecommendedNavigationTransitionInfo); 40 | break; 41 | } 42 | case "MacroFormat": 43 | { 44 | _ = NavFrame.Navigate(typeof(MacroSamplePage), null, args.RecommendedNavigationTransitionInfo); 45 | break; 46 | } 47 | case "NamedStringFormat": 48 | { 49 | _ = NavFrame.Navigate(typeof(NamedStringFormatSamplePage), null, args.RecommendedNavigationTransitionInfo); 50 | } 51 | break; 52 | case "Pluralization": 53 | { 54 | _ = NavFrame.Navigate(typeof(BasicPluralizationSamplePage), null, args.RecommendedNavigationTransitionInfo); 55 | } 56 | break; 57 | case "AdvancedPluralization": 58 | { 59 | _ = NavFrame.Navigate(typeof(AdvancedPluralizationSamplePage), null, args.RecommendedNavigationTransitionInfo); 60 | } 61 | break; 62 | case "Variants": 63 | { 64 | _ = NavFrame.Navigate(typeof(VariantsSamplePage), null, args.RecommendedNavigationTransitionInfo); 65 | } 66 | break; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | 3 | namespace ReswPlusWinAppSDKSample; 4 | 5 | public sealed partial class MainWindow : Window 6 | { 7 | public MainWindow() 8 | { 9 | AppWindow.SetIcon("Assets/StoreLogo.ico"); 10 | this.InitializeComponent(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | ReswPlusWinAppSDKSample 19 | ruhuynva 20 | Assets\StoreLogo.png 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/AdvancedPluralizationSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusWinAppSDKSample.Pages; 4 | 5 | public sealed partial class AdvancedPluralizationSamplePage : Page 6 | { 7 | public AdvancedPluralizationSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/BasicPluralizationSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusWinAppSDKSample.Pages; 4 | 5 | public sealed partial class BasicPluralizationSamplePage : Page 6 | { 7 | public BasicPluralizationSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/LiteralStringFormatSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusWinAppSDKSample.Pages; 4 | 5 | public sealed partial class LiteralStringFormatSamplePage : Page 6 | { 7 | public LiteralStringFormatSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/MacroSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusWinAppSDKSample.Pages; 4 | 5 | public sealed partial class MacroSamplePage : Page 6 | { 7 | public MacroSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/NamedStringFormatSamplePage.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 39 | 40 | 44 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/NamedStringFormatSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusWinAppSDKSample.Pages; 4 | 5 | public sealed partial class NamedStringFormatSamplePage : Page 6 | { 7 | public NamedStringFormatSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/ReferenceStringFormatSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusWinAppSDKSample.Pages; 4 | 5 | public sealed partial class ReferenceStringFormatSamplePage : Page 6 | { 7 | public ReferenceStringFormatSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/StringFormatSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusWinAppSDKSample.Pages; 4 | 5 | public sealed partial class StringFormatSamplePage : Page 6 | { 7 | public StringFormatSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/StronglyTypedSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace ReswPlusWinAppSDKSample.Pages; 4 | 5 | public sealed partial class StronglyTypedSamplePage : Page 6 | { 7 | public StronglyTypedSamplePage() 8 | { 9 | this.InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Pages/VariantsSamplePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.UI.Xaml.Controls; 3 | 4 | namespace ReswPlusWinAppSDKSample.Pages; 5 | 6 | public enum PartDayEnum { MORNING = 1, AFTERNOON, EVENING, NIGHT }; 7 | public enum PetTypeEnum { DOG = 1, CAT }; 8 | 9 | public sealed partial class VariantsSamplePage : Page, INotifyPropertyChanged 10 | { 11 | public VariantsSamplePage() 12 | { 13 | this.InitializeComponent(); 14 | } 15 | 16 | public PartDayEnum DayPart { get; set; } 17 | 18 | private void UpdatePartDay(PartDayEnum part) 19 | { 20 | DayPart = part; 21 | RaisePropertyChanged(nameof(DayPart)); 22 | } 23 | 24 | public PetTypeEnum PetType { get; set; } 25 | 26 | private void UpdatePetType(PetTypeEnum type) 27 | { 28 | PetType = type; 29 | RaisePropertyChanged(nameof(PetType)); 30 | } 31 | 32 | public void RaisePropertyChanged(string name) 33 | { 34 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 35 | } 36 | public event PropertyChangedEventHandler PropertyChanged; 37 | 38 | private void PartDayMorning_Checked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) 39 | { 40 | UpdatePartDay(PartDayEnum.MORNING); 41 | } 42 | 43 | private void PartDayAfternoon_Checked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) 44 | { 45 | UpdatePartDay(PartDayEnum.AFTERNOON); 46 | } 47 | 48 | private void PartDayEvening_Checked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) 49 | { 50 | UpdatePartDay(PartDayEnum.EVENING); 51 | } 52 | 53 | private void PartDayNight_Checked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) 54 | { 55 | UpdatePartDay(PartDayEnum.NIGHT); 56 | } 57 | 58 | private void PetTypeDog_Checked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) 59 | { 60 | UpdatePetType(PetTypeEnum.DOG); 61 | } 62 | 63 | private void PetTypeCat_Checked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) 64 | { 65 | UpdatePetType(PetTypeEnum.CAT); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Properties/PublishProfiles/win-arm64.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | FileSystem 8 | ARM64 9 | win-arm64 10 | win10-arm64 11 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ 12 | true 13 | False 14 | False 15 | True 16 | False 17 | True 18 | 19 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Properties/PublishProfiles/win-x64.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | FileSystem 8 | x64 9 | win-x64 10 | win10-x64 11 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ 12 | true 13 | False 14 | False 15 | True 16 | False 17 | True 18 | 19 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Properties/PublishProfiles/win-x86.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | FileSystem 8 | x86 9 | win-x86 10 | win10-x86 11 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ 12 | true 13 | False 14 | False 15 | True 16 | False 17 | True 18 | 19 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "ReswPlusWinAppSDKSample (Package)": { 4 | "commandName": "MsixPackage" 5 | }, 6 | "ReswPlusWinAppSDKSample (Unpackaged)": { 7 | "commandName": "Project" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/ReswPlusWinAppSDKSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net9.0-windows10.0.22000.0 6 | 10.0.17763.0 7 | ReswPlusWinAppSDKSample 8 | app.manifest 9 | x86;x64;ARM64 10 | win-$(Platform).pubxml 11 | true 12 | true 13 | Icon.png 14 | ReswPlusWinAppSDKSample_TemporaryKey.pfx 15 | True 16 | 10.0.19041.0 17 | False 18 | SHA256 19 | True 20 | False 21 | True 22 | Always 23 | x86|x64|arm64 24 | 0 25 | win-x86;win-x64;win-arm64 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {44d125b3-6c8a-4f2f-a76f-bffb2ad7e70d} 49 | ReswPlus.SourceGenerator 50 | 51 | 52 | 53 | 54 | 55 | 56 | True 57 | \ 58 | 59 | 60 | 61 | 62 | 63 | Designer 64 | 65 | 66 | Designer 67 | 68 | 69 | Designer 70 | 71 | 72 | Designer 73 | 74 | 75 | Designer 76 | 77 | 78 | Designer 79 | 80 | 81 | Designer 82 | 83 | 84 | Designer 85 | 86 | 87 | Designer 88 | 89 | 90 | Designer 91 | 92 | 93 | 94 | 95 | true 96 | 97 | 98 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/ReswPlusWinAppSDKSample_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/samples/WinAppSDK/ReswPlusWinAppSDKSample/ReswPlusWinAppSDKSample_TemporaryKey.pfx -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSample/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | PerMonitorV2 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSampleExternalLibrary/ReswPlusWinAppSDKSampleExternalLibrary.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0-windows10.0.22000.0 5 | 10.0.17763.0 6 | ReswPlusWinAppSDKSampleExternalLibrary 7 | win-x86;win-x64;win-arm64 8 | win10-x86;win10-x64;win10-arm64 9 | true 10 | en 11 | 10.0.19041.0 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {44d125b3-6c8a-4f2f-a76f-bffb2ad7e70d} 20 | ReswPlus.SourceGenerator 21 | 22 | 23 | -------------------------------------------------------------------------------- /samples/WinAppSDK/ReswPlusWinAppSDKSampleExternalLibrary/Strings/en/Resources.resw: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | This string is from an external library 122 | 123 | -------------------------------------------------------------------------------- /src/ReswPlus.CommandLine/Parameters/AndroidToReswParameters.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | 3 | namespace ReswPlusCmd.Parameters; 4 | 5 | [Verb("xml-to-resw", HelpText = "Convert a android localization XML files to resw")] 6 | public class AndroidToReswParameters 7 | { 8 | [Value(0, HelpText = "Output Directory Path", MetaName = "output")] 9 | public string? OutputPath { get; set; } 10 | 11 | [Option('i', "input", HelpText = "A single XML File or a path of a directory containing xml files", Required = true)] 12 | public string? Input { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/ReswPlus.CommandLine/Parameters/ReswToAndroidParameters.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | 3 | namespace ReswPlusCmd.Parameters; 4 | 5 | [Verb("resw-to-xml", HelpText = "Convert a single resw file to Android XML format")] 6 | public class ReswToAndroidParameters 7 | { 8 | [Value(0, HelpText = "Output File Path", MetaName = "output")] 9 | public string? OutputFilePath { get; set; } 10 | 11 | [Option('i', "input", HelpText = "Resw input file", Required = true)] 12 | public string? Input { get; set; } 13 | 14 | [Option('p', "pluralization", Default = true, HelpText = "boolean indicating if the resw file supports pluralization", Required = false)] 15 | public bool SupportPluralization { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/ReswPlus.CommandLine/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using CommandLine; 4 | using ReswPlus.Core.ResourceParser; 5 | using ReswPlusCmd.Converters; 6 | using ReswPlusCmd.Parameters; 7 | 8 | namespace ReswPlusCmd; 9 | 10 | internal class Program 11 | { 12 | private static int Main(string[] args) 13 | { 14 | var returnValue = 0; 15 | _ = Parser.Default.ParseArguments(args) 16 | .WithParsed((Action)(parameters => 17 | { 18 | returnValue = ReswToAndroidCommand(parameters); 19 | })).WithParsed((Action)(parameters => 20 | { 21 | returnValue = AndroidToReswCommand(parameters); 22 | })); 23 | 24 | return returnValue; 25 | } 26 | 27 | #region Commands 28 | private static int AndroidToReswCommand(AndroidToReswParameters parameters) 29 | { 30 | if (Directory.Exists(parameters.Input)) 31 | { 32 | var success = AndroidXMLConverter.AndroidXMLDirectoryToResw(parameters.Input, parameters.OutputPath!); 33 | if (success) 34 | { 35 | Console.WriteLine($"Directory created: {parameters.OutputPath}"); 36 | return 0; 37 | } 38 | else 39 | { 40 | Console.WriteLine($"Error during the conversion"); 41 | return -1; 42 | } 43 | } 44 | else if (File.Exists(parameters.Input)) 45 | { 46 | var success = AndroidXMLConverter.AndroidXMLFileToResw(parameters.Input, parameters.OutputPath!); 47 | if (success) 48 | { 49 | Console.WriteLine($"File created: {parameters.OutputPath}"); 50 | return 0; 51 | } 52 | else 53 | { 54 | Console.WriteLine($"Error during the conversion"); 55 | return -1; 56 | } 57 | } 58 | else 59 | { 60 | Console.WriteLine($"The file {parameters.Input} doesn't exist"); 61 | return -1; 62 | } 63 | } 64 | 65 | private static int ReswToAndroidCommand(ReswToAndroidParameters parameters) 66 | { 67 | if (!File.Exists(parameters.Input)) 68 | { 69 | Console.WriteLine($"The file {parameters.Input} doesn't exist"); 70 | return -1; 71 | } 72 | 73 | var reswContent = File.ReadAllText(parameters.Input); 74 | var resw = ReswParser.Parse(reswContent); 75 | if (resw == null) 76 | { 77 | Console.WriteLine($"Can't parse the resw file: {parameters.Input}"); 78 | return -1; 79 | } 80 | var androidXML = AndroidXMLConverter.ReswToAndroidXML(resw, parameters.SupportPluralization); 81 | if (androidXML == null) 82 | { 83 | Console.WriteLine($"Error during the conversion of the file: {parameters.Input}"); 84 | return -1; 85 | } 86 | androidXML.Save(parameters.OutputFilePath!); 87 | return 0; 88 | } 89 | #endregion 90 | } 91 | -------------------------------------------------------------------------------- /src/ReswPlus.CommandLine/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "ReswPlusCommand": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/ReswPlus.CommandLine/ReswPlusCmd.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | ReswPlusCmd.Program 7 | ReswPlusCmd 8 | enable 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/ReswPlus.Shared/Interfaces/IErrorLogger.cs: -------------------------------------------------------------------------------- 1 | namespace ReswPlus.Core.Interfaces; 2 | 3 | public interface IErrorLogger 4 | { 5 | void LogError(string message, string? document = null); 6 | void LogWarning(string message, string? document = null); 7 | } 8 | -------------------------------------------------------------------------------- /src/ReswPlus.Shared/ResourceParser/ParameterType.cs: -------------------------------------------------------------------------------- 1 | namespace ReswPlus.Core.ResourceParser; 2 | 3 | public enum ParameterType 4 | { 5 | Object, 6 | Byte, 7 | Int, 8 | Uint, 9 | Long, 10 | String, 11 | Double, 12 | Char, 13 | Ulong, 14 | Decimal 15 | }; 16 | -------------------------------------------------------------------------------- /src/ReswPlus.Shared/ResourceParser/ReswFilters.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text.RegularExpressions; 4 | 5 | namespace ReswPlus.Core.ResourceParser; 6 | 7 | public sealed class VariantedReswItems 8 | { 9 | public List Items { get; } 10 | public string Key { get; } 11 | public bool SupportPlural { get; } 12 | public bool SupportVariants { get; } 13 | 14 | public VariantedReswItems(List items, string key, bool supportPlural, bool supportVariants) 15 | { 16 | Items = items; 17 | Key = key; 18 | SupportPlural = supportPlural; 19 | SupportVariants = supportVariants; 20 | } 21 | } 22 | 23 | public static class ReswFilters 24 | { 25 | private static readonly Regex regexPluralVariantItems = new("(?:_(?Variant\\-?\\d+))?(?:_(?Zero|One|Other|Many|Few|None))?$"); 26 | 27 | public static IEnumerable GetItemsWithVariantOrPlural(this IEnumerable reswItems) 28 | { 29 | 30 | var variantedItems = from item in reswItems 31 | where item.Key.Contains("_") 32 | let match = regexPluralVariantItems.Match(item.Key) 33 | where match.Success && !string.IsNullOrEmpty(match.Value) 34 | let commonKey = item.Key.Substring(0, item.Key.Length - match.Length) 35 | group (item: item, isVariant: match.Groups["variant"].Length > 0, isPlural: match.Groups["plural"].Length > 0) 36 | by commonKey into gr 37 | select gr; 38 | foreach (var variantedItem in variantedItems) 39 | { 40 | // all items must have the same type (pluralization, variants or both), if one of them is different, we reject all of them 41 | var checkPlurals = variantedItem.Select(i => i.isPlural).Distinct(); 42 | var itemsAllPlurals = checkPlurals.Count() == 1 && checkPlurals.First(); 43 | var checkVariants = variantedItem.Select(i => i.isVariant).Distinct(); 44 | var itemsAllVariants = checkVariants.Count() == 1 && checkVariants.First(); 45 | 46 | if (!itemsAllPlurals && !itemsAllVariants) 47 | { 48 | // Ignore if items don't have the same form 49 | continue; 50 | } 51 | 52 | yield return new VariantedReswItems( 53 | variantedItem.Select(i => i.item).ToList(), 54 | variantedItem.Key, 55 | variantedItem.First().isPlural, 56 | variantedItem.First().isVariant 57 | ); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/ReswPlus.Shared/ResourceParser/ReswInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ReswPlus.Core.ResourceParser; 4 | 5 | public sealed class ReswInfo 6 | { 7 | public List Items { get; } 8 | 9 | public ReswInfo() 10 | { 11 | Items = []; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/ReswPlus.Shared/ResourceParser/ReswItem.cs: -------------------------------------------------------------------------------- 1 | namespace ReswPlus.Core.ResourceParser; 2 | 3 | public sealed class ReswItem(string key, string value, string? comment = null) 4 | { 5 | public string Key { get; } = key; 6 | public string Value { get; } = value; 7 | public string? Comment { get; } = comment; 8 | } 9 | -------------------------------------------------------------------------------- /src/ReswPlus.Shared/ResourceParser/ReswParser.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | 3 | namespace ReswPlus.Core.ResourceParser; 4 | 5 | public sealed class ReswParser 6 | { 7 | public static ReswInfo Parse(string content) 8 | { 9 | var res = new ReswInfo(); 10 | 11 | var xml = new XmlDocument(); 12 | xml.LoadXml(content); 13 | 14 | var nodes = xml.DocumentElement?.SelectNodes("//data"); 15 | if (nodes is null) 16 | { 17 | return res; 18 | } 19 | 20 | foreach (XmlElement element in nodes) 21 | { 22 | string? comment = null; 23 | var elementKey = element.Attributes.GetNamedItem("name"); 24 | string key; 25 | if (elementKey != null) 26 | { 27 | key = elementKey.Value ?? string.Empty; 28 | } 29 | else 30 | { 31 | continue; 32 | } 33 | var elementValue = element.SelectSingleNode("value"); 34 | string value; 35 | if (elementValue != null) 36 | { 37 | value = elementValue.InnerText; 38 | } 39 | else 40 | { 41 | continue; 42 | } 43 | 44 | var elementComment = element.SelectSingleNode("comment"); 45 | if (elementComment != null) 46 | { 47 | comment = elementComment.InnerText; 48 | } 49 | 50 | res.Items.Add(new ReswItem(key, value, comment)); 51 | } 52 | return res; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/ReswPlus.Shared/ReswPlus.Shared.projitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 1a6ff0bd-991a-417e-a79d-98ebb4208816 7 | 8 | 9 | ReswPlus.Shared 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/ReswPlus.Shared/ReswPlus.Shared.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1a6ff0bd-991a-417e-a79d-98ebb4208816 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/AnalyzerReleases.Shipped.md: -------------------------------------------------------------------------------- 1 | ## Release 1.0.0 2 | 3 | ### New Rules 4 | 5 | Rule ID | Category | Severity | Notes 6 | --------|----------|----------|-------------------- 7 | RESWP0001 | Compatibility | Error | ReswPlus source generator only supports C#. 8 | RESWP0002 | Compatibility | Error | ReswPlus cannot determine the namespace. 9 | RESWP0003 | Compatibility | Error | Can't retrieve the root path of the project. 10 | RESWP0004 | Compatibility | Info | ReswPlus cannot determine the project type, defaulting to application. 11 | RESWP0005 | Compatibility | Error | ReswPlus only supports UWP and WinAppSDK applications/libraries. -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/AnalyzerReleases.Unshipped.md: -------------------------------------------------------------------------------- 1 | ; Unshipped analyzer release 2 | ; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md 3 | 4 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/ClassGenerators/GenerationResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using ReswPlus.SourceGenerator.CodeGenerators; 3 | 4 | namespace ReswPlus.SourceGenerator.ClassGenerators; 5 | 6 | /// 7 | /// Represents the result of a generation process. 8 | /// 9 | internal sealed class GenerationResult 10 | { 11 | /// 12 | /// Gets or sets the collection of generated files. 13 | /// 14 | public IEnumerable Files { get; set; } 15 | 16 | /// 17 | /// Gets or sets a value indicating whether the result contains plural forms. 18 | /// 19 | public bool ContainsPlural { get; set; } 20 | 21 | /// 22 | /// Gets or sets a value indicating whether the result contains macros. 23 | /// 24 | public bool ContainsMacro { get; set; } 25 | 26 | public GenerationResult(IEnumerable files) 27 | { 28 | Files = files; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/ClassGenerators/Models/Localization.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using ReswPlus.Core.ResourceParser; 4 | 5 | namespace ReswPlus.SourceGenerator.ClassGenerators.Models; 6 | 7 | /// 8 | /// Represents a base class for localization. 9 | /// 10 | internal abstract class Localization 11 | { 12 | protected Localization(string key, string summary) 13 | { 14 | Key = key; 15 | Summary = summary; 16 | } 17 | 18 | /// 19 | /// Gets or sets the key for the localization. 20 | /// 21 | public string Key { get; } 22 | 23 | /// 24 | /// Gets or sets the list of format tag parameters. 25 | /// 26 | public List Parameters { get; set; } = []; 27 | 28 | /// 29 | /// Gets the list of extra function format tag parameters. 30 | /// 31 | public List ExtraParameters { get; } = []; 32 | 33 | /// 34 | /// Gets or sets the summary for the localization. 35 | /// 36 | public string Summary { get; } 37 | 38 | /// 39 | /// Gets or sets a value indicating whether .NET formatting is used. 40 | /// 41 | public bool IsDotNetFormatting { get; set; } 42 | 43 | /// 44 | /// Gets a value indicating whether the localization is a property. 45 | /// 46 | public bool IsProperty => !Parameters.OfType().Any() && !ExtraParameters.Any(); 47 | } 48 | 49 | /// 50 | /// Represents a regular localization. 51 | /// 52 | internal sealed class RegularLocalization : Localization 53 | { 54 | public RegularLocalization(string key, string summary) : base(key, summary) 55 | { 56 | } 57 | } 58 | 59 | /// 60 | /// Represents a plural localization. 61 | /// 62 | internal class PluralLocalization : Localization 63 | { 64 | public PluralLocalization(string key, string summary) : base(key, summary) 65 | { 66 | } 67 | 68 | /// 69 | /// Gets or sets a value indicating whether the none state is supported. 70 | /// 71 | public bool SupportNoneState { get; set; } 72 | 73 | /// 74 | /// Gets or sets the parameter to use for pluralization. 75 | /// 76 | public FunctionFormatTagParameter? ParameterToUseForPluralization { get; set; } 77 | } 78 | 79 | /// 80 | /// Represents an interface for variant localization. 81 | /// 82 | internal interface IVariantLocalization 83 | { 84 | /// 85 | /// Gets or sets the parameter to use for variant. 86 | /// 87 | FunctionFormatTagParameter? ParameterToUseForVariant { get; set; } 88 | } 89 | 90 | /// 91 | /// Represents a plural variant localization. 92 | /// 93 | internal sealed class PluralVariantLocalization : PluralLocalization, IVariantLocalization 94 | { 95 | public PluralVariantLocalization(string key, string summary) : base(key, summary) 96 | { 97 | } 98 | 99 | /// 100 | /// Gets or sets the parameter to use for variant. 101 | /// 102 | public FunctionFormatTagParameter? ParameterToUseForVariant { get; set; } 103 | } 104 | 105 | /// 106 | /// Represents a variant localization. 107 | /// 108 | internal sealed class VariantLocalization : Localization, IVariantLocalization 109 | { 110 | public VariantLocalization(string key, string summary) : base(key, summary) 111 | { 112 | } 113 | 114 | /// 115 | /// Gets or sets the parameter to use for variant. 116 | /// 117 | public FunctionFormatTagParameter? ParameterToUseForVariant { get; set; } 118 | } 119 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/ClassGenerators/Models/StronglyTypedClass.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ReswPlus.SourceGenerator.ClassGenerators.Models; 4 | 5 | internal sealed class StronglyTypedClass 6 | { 7 | public StronglyTypedClass(bool isAdvanced, string[] namespaces, string resoureFile, string className, AppType appType) 8 | { 9 | IsAdvanced = isAdvanced; 10 | Namespaces = namespaces; 11 | ResoureFile = resoureFile; 12 | ClassName = className; 13 | AppType = appType; 14 | Items = []; 15 | } 16 | 17 | public bool IsAdvanced { get; } 18 | public string[] Namespaces { get; } 19 | public string ResoureFile { get; } 20 | public string ClassName { get; } 21 | public AppType AppType { get; } 22 | 23 | public List Items { get; } 24 | } 25 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/CodeGenerators/ICodeGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using ReswPlus.SourceGenerator.ClassGenerators.Models; 3 | using ReswPlus.SourceGenerator.Models; 4 | 5 | namespace ReswPlus.SourceGenerator.CodeGenerators; 6 | 7 | /// 8 | /// Represents a generated file with its filename, content, and supported languages. 9 | /// 10 | internal sealed class GeneratedFile 11 | { 12 | public GeneratedFile(string filename, string content) 13 | { 14 | Filename = filename; 15 | Content = content; 16 | } 17 | 18 | /// 19 | /// Gets or sets the filename of the generated file. 20 | /// 21 | public string Filename { get; } 22 | 23 | /// 24 | /// Gets or sets the content of the generated file. 25 | /// 26 | public string Content { get; } 27 | 28 | /// 29 | /// Gets or sets the languages supported by the generated file. 30 | /// 31 | public string[]? Languages { get; set; } 32 | } 33 | 34 | /// 35 | /// Defines a method to generate files based on the provided information. 36 | /// 37 | internal interface ICodeGenerator 38 | { 39 | /// 40 | /// Generates a collection of files based on the provided base filename, strongly typed class information, and resource file information. 41 | /// 42 | /// The base filename for the generated files. 43 | /// The strongly typed class information. 44 | /// The resource file information. 45 | /// A collection of generated files. 46 | IEnumerable GetGeneratedFiles(string baseFilename, StronglyTypedClass info, ResourceFileInfo projectItem); 47 | } 48 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Images/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetPlus/ReswPlus/e6dafb6d0c297f00c7005e894d542f386674b959/src/ReswPlus.SourceGenerator/Images/Icon.png -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Models/IProject.cs: -------------------------------------------------------------------------------- 1 | namespace ReswPlus.SourceGenerator.Models; 2 | 3 | /// 4 | /// Represents a project with properties and methods to retrieve project-specific information. 5 | /// 6 | internal interface IProject 7 | { 8 | /// 9 | /// Gets a value indicating whether the project is a library. 10 | /// 11 | bool IsLibrary { get; } 12 | 13 | /// 14 | /// Gets the name of the project. 15 | /// 16 | string Name { get; } 17 | 18 | /// 19 | /// Gets the programming language of the project. 20 | /// 21 | Language Language { get; } 22 | } 23 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Models/Language.cs: -------------------------------------------------------------------------------- 1 | namespace ReswPlus.SourceGenerator.Models; 2 | 3 | /// 4 | /// Represents the programming languages supported by the source generator. 5 | /// 6 | internal enum Language 7 | { 8 | /// 9 | /// Unknown language. 10 | /// 11 | Unknown, 12 | 13 | /// 14 | /// C# language. 15 | /// 16 | CSharp 17 | } 18 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Models/Project.cs: -------------------------------------------------------------------------------- 1 | namespace ReswPlus.SourceGenerator.Models; 2 | 3 | /// 4 | /// Represents a project with a name and a flag indicating if it is a library. 5 | /// 6 | internal sealed class Project(string name, bool isLibrary) : IProject 7 | { 8 | /// 9 | /// Gets a value indicating whether the project is a library. 10 | /// 11 | public bool IsLibrary { get; } = isLibrary; 12 | 13 | /// 14 | /// Gets the name of the project. 15 | /// 16 | public string Name { get; } = name; 17 | 18 | /// 19 | /// Gets the language of the project, which is always C#. 20 | /// 21 | public Language Language => Language.CSharp; 22 | } 23 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Models/ResourceFileInfo.cs: -------------------------------------------------------------------------------- 1 | namespace ReswPlus.SourceGenerator.Models; 2 | 3 | /// 4 | /// Represents information about a resource file. 5 | /// 6 | internal sealed class ResourceFileInfo(string path, IProject parentProject) 7 | { 8 | /// 9 | /// Gets the path of the resource file. 10 | /// 11 | public string Path { get; } = path; 12 | 13 | /// 14 | /// Gets the project that contains the resource file. 15 | /// 16 | public IProject Project { get; } = parentProject; 17 | } 18 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/ReswPlus.SourceGenerator.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | enable 6 | 12.0 7 | true 8 | true 9 | false 10 | true 11 | true 12 | Generated 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/ArabicProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class ArabicProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | if (n == 0) 12 | { 13 | return PluralTypeEnum.ZERO; 14 | } 15 | if (n == 1) 16 | { 17 | return PluralTypeEnum.ONE; 18 | } 19 | if (n == 2) 20 | { 21 | return PluralTypeEnum.TWO; 22 | } 23 | if ((n % 100).IsBetween(3, 10)) 24 | { 25 | return PluralTypeEnum.FEW; 26 | } 27 | if ((n % 100).IsBetween(11, 99)) 28 | { 29 | return PluralTypeEnum.MANY; 30 | } 31 | } 32 | return PluralTypeEnum.OTHER; 33 | 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/BreizhProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class BreizhProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | var mod10 = n % 10; 12 | var mod100 = n % 100; 13 | if (mod10 == 1 && mod100 != 11 && mod100 != 71 && mod100 != 91) 14 | { 15 | return PluralTypeEnum.ONE; 16 | } 17 | if (mod10 == 2 && mod100 != 12 && mod100 != 72 && mod100 != 92) 18 | { 19 | return PluralTypeEnum.TWO; 20 | } 21 | var diffMod = mod100 - mod10; 22 | if ((mod10 == 3 || mod10 == 4 || mod10 == 9) && diffMod != 10 && diffMod != 70 && diffMod != 90) 23 | { 24 | return PluralTypeEnum.FEW; 25 | } 26 | if (n != 0 && n % 1000000 == 0) 27 | return PluralTypeEnum.MANY; 28 | } 29 | return PluralTypeEnum.OTHER; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/CentralAtlasTamazightProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class CentralAtlasTamazightProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n == 0 || n == 1 || (n.IsInt() && n.IsBetween(11, 99))) 10 | { 11 | return PluralTypeEnum.ONE; 12 | } 13 | return PluralTypeEnum.OTHER; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/CroatProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class CroatProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | var integer = (int)n; 12 | if (integer % 10 == 1 && integer % 100 != 11) 13 | { 14 | return PluralTypeEnum.ONE; 15 | } 16 | if ((integer % 10).IsBetween(2, 4) && !(integer % 100).IsBetween(12, 14)) 17 | { 18 | return PluralTypeEnum.FEW; 19 | } 20 | } 21 | var f = n.DigitsAfterDecimal(); 22 | if (f % 10 == 1 && f % 100 != 11) 23 | { 24 | return PluralTypeEnum.ONE; 25 | } 26 | 27 | if ((f % 10).IsBetween(2, 4) && !(f % 100).IsBetween(12, 14)) 28 | { 29 | return PluralTypeEnum.FEW; 30 | } 31 | 32 | return PluralTypeEnum.OTHER; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/CzechProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class CzechProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n == 1) 10 | return PluralTypeEnum.ONE; 11 | 12 | if (n.GetNumberOfDigitsAfterDecimal() != 0) 13 | { 14 | return PluralTypeEnum.MANY; 15 | } 16 | 17 | if (n.IsBetween(2, 4)) 18 | return PluralTypeEnum.FEW; 19 | 20 | return PluralTypeEnum.OTHER; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/DanishProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class DanishProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n != 0 && n.IsBetween(0, 1)) 10 | return PluralTypeEnum.ONE; 11 | return PluralTypeEnum.OTHER; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/FilipinoProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class FilipinoProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | var isInt = n.IsInt(); 10 | 11 | if (isInt) 12 | { 13 | if (n.IsBetween(1, 3)) 14 | return PluralTypeEnum.ONE; 15 | var imod10 = n % 10; 16 | if (imod10 != 4 && imod10 != 6 || imod10 != 9) 17 | return PluralTypeEnum.ONE; 18 | } 19 | else 20 | { 21 | var f = n.DigitsAfterDecimal(); 22 | var imod10 = f % 10; 23 | if (imod10 != 4 && imod10 != 6 || imod10 != 9) 24 | return PluralTypeEnum.ONE; 25 | 26 | } 27 | 28 | 29 | return PluralTypeEnum.OTHER; 30 | 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/HebrewProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class HebrewProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | switch ((int)n) 12 | { 13 | case 1: 14 | return PluralTypeEnum.ONE; 15 | case 2: 16 | return PluralTypeEnum.TWO; 17 | } 18 | 19 | if (n != 0 && (n % 10) == 0) 20 | { 21 | return PluralTypeEnum.MANY; 22 | } 23 | } 24 | return PluralTypeEnum.OTHER; 25 | 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/IPluralProvider.txt: -------------------------------------------------------------------------------- 1 | namespace _ReswPlus_AutoGenerated.Plurals 2 | { 3 | public interface IPluralProvider 4 | { 5 | PluralTypeEnum ComputePlural(double n); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/IcelandicProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class IcelandicProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | var integer = (int)n; 12 | if (integer % 10 == 1 && integer % 100 != 11) 13 | { 14 | return PluralTypeEnum.ONE; 15 | } 16 | return PluralTypeEnum.OTHER; 17 | } 18 | else 19 | { 20 | return PluralTypeEnum.ONE; 21 | } 22 | 23 | 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/IntOneOrZeroProvider.txt: -------------------------------------------------------------------------------- 1 | 2 | namespace _ReswPlus_AutoGenerated.Plurals 3 | { 4 | internal sealed class IntOneOrZeroProvider : IPluralProvider 5 | { 6 | public PluralTypeEnum ComputePlural(double n) 7 | { 8 | if (n == 0 || n == 1) 9 | { 10 | return PluralTypeEnum.ONE; 11 | } 12 | else 13 | { 14 | return PluralTypeEnum.OTHER; 15 | } 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/IrishProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class IrishProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | if (n == 1) 12 | { 13 | return PluralTypeEnum.ONE; 14 | } 15 | if (n == 2) 16 | { 17 | return PluralTypeEnum.TWO; 18 | } 19 | if ((n.IsBetween(3, 6))) 20 | { 21 | return PluralTypeEnum.FEW; 22 | } 23 | if ((n.IsBetween(7, 10))) 24 | { 25 | return PluralTypeEnum.MANY; 26 | } 27 | } 28 | return PluralTypeEnum.OTHER; 29 | 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/LatvianProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class LatvianProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n == 0 || (n % 100).IsBetween(11, 19)) 10 | { 11 | return PluralTypeEnum.ZERO; 12 | } 13 | 14 | var f = n.DigitsAfterDecimal(); 15 | if (f.IsBetween(11, 19)) 16 | return PluralTypeEnum.ZERO; 17 | 18 | if (n % 10 == 1 && n % 100 != 11) 19 | return PluralTypeEnum.ONE; 20 | if (f % 10 == 1) 21 | { 22 | if (n.GetNumberOfDigitsAfterDecimal() == 2) 23 | { 24 | if (f % 100 != 11) 25 | return PluralTypeEnum.ONE; 26 | } 27 | else 28 | { 29 | return PluralTypeEnum.ONE; 30 | } 31 | } 32 | return PluralTypeEnum.OTHER; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/LithuanianProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class LithuanianProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if ((n % 10).IsBetween(2, 9) && !(n % 100).IsBetween(11, 19)) 10 | { 11 | return PluralTypeEnum.FEW; 12 | } 13 | if ((n % 10) == 1 && !(n % 100).IsBetween(11, 19)) 14 | { 15 | return PluralTypeEnum.ONE; 16 | } 17 | if (n.GetNumberOfDigitsAfterDecimal() != 0) 18 | return PluralTypeEnum.MANY; 19 | return PluralTypeEnum.OTHER; 20 | 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/MacedonianProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class MacedonianProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | if (n % 10 == 1) 12 | { 13 | return PluralTypeEnum.ONE; 14 | } 15 | } 16 | else 17 | { 18 | var f = n.DigitsAfterDecimal(); 19 | if (f % 10 == 1) 20 | { 21 | return PluralTypeEnum.ONE; 22 | } 23 | } 24 | return PluralTypeEnum.OTHER; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/MalteseProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class MalteseProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | var isInt = n.IsInt(); 10 | if (isInt) 11 | { 12 | var i = (int)n; 13 | if (i == 1) 14 | { 15 | return PluralTypeEnum.ONE; 16 | } 17 | if (i == 0 || (i % 100).IsBetween(2, 10)) 18 | { 19 | return PluralTypeEnum.FEW; 20 | } 21 | if ((i % 100).IsBetween(11, 19)) 22 | { 23 | return PluralTypeEnum.MANY; 24 | } 25 | } 26 | 27 | return PluralTypeEnum.OTHER; 28 | 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/ManxProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class ManxProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | var isInt = n.IsInt(); 10 | var i = (int)n; 11 | if (isInt) 12 | { 13 | if (i % 10 == 1) 14 | return PluralTypeEnum.ONE; 15 | if (i % 10 == 2) 16 | return PluralTypeEnum.TWO; 17 | if (i % 20 == 0) 18 | return PluralTypeEnum.FEW; 19 | return PluralTypeEnum.OTHER; 20 | } 21 | else 22 | { 23 | return PluralTypeEnum.MANY; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/OneOrTwoProvider.txt: -------------------------------------------------------------------------------- 1 | 2 | namespace _ReswPlus_AutoGenerated.Plurals 3 | { 4 | internal sealed class OneOrTwoProvider : IPluralProvider 5 | { 6 | public PluralTypeEnum ComputePlural(double n) 7 | { 8 | if (n == 1) 9 | { 10 | return PluralTypeEnum.ONE; 11 | } 12 | else if (n == 2) 13 | { 14 | return PluralTypeEnum.TWO; 15 | } 16 | else 17 | { 18 | return PluralTypeEnum.OTHER; 19 | } 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/OneOrZeroProvider.txt: -------------------------------------------------------------------------------- 1 | 2 | namespace _ReswPlus_AutoGenerated.Plurals 3 | { 4 | internal sealed class OneOrZeroProvider : IPluralProvider 5 | { 6 | public PluralTypeEnum ComputePlural(double n) 7 | { 8 | if (n == 0) 9 | return PluralTypeEnum.ZERO; 10 | if (n == 1) 11 | { 12 | return PluralTypeEnum.ONE; 13 | } 14 | else 15 | { 16 | return PluralTypeEnum.OTHER; 17 | } 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/OneOrZeroToOneExcludedProvider.txt: -------------------------------------------------------------------------------- 1 | 2 | namespace _ReswPlus_AutoGenerated.Plurals 3 | { 4 | internal sealed class OneOrZeroToOneExcludedProvider : IPluralProvider 5 | { 6 | public PluralTypeEnum ComputePlural(double n) 7 | { 8 | if (n == 0) 9 | return PluralTypeEnum.ZERO; 10 | if ((int)n == 0 || (int)n == 1) 11 | { 12 | return PluralTypeEnum.ONE; 13 | } 14 | else 15 | { 16 | return PluralTypeEnum.OTHER; 17 | } 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/OnlyOneProvider.txt: -------------------------------------------------------------------------------- 1 | 2 | namespace _ReswPlus_AutoGenerated.Plurals 3 | { 4 | internal sealed class OnlyOneProvider : IPluralProvider 5 | { 6 | public PluralTypeEnum ComputePlural(double n) 7 | { 8 | if (n == 1) 9 | { 10 | return PluralTypeEnum.ONE; 11 | } 12 | else 13 | { 14 | return PluralTypeEnum.OTHER; 15 | } 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/OtherProvider.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class OtherProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | return PluralTypeEnum.OTHER; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/PluralTypeEnum.txt: -------------------------------------------------------------------------------- 1 | namespace _ReswPlus_AutoGenerated.Plurals 2 | { 3 | public enum PluralTypeEnum 4 | { 5 | ZERO, 6 | ONE, 7 | TWO, 8 | OTHER, 9 | FEW, 10 | MANY 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/PolishProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class PolishProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if ((n % 10).IsBetween(2, 4) && !(n % 100).IsBetween(12, 14)) 10 | { 11 | return PluralTypeEnum.FEW; 12 | } 13 | if (n != 1 && (n % 10).IsBetween(0, 1) || 14 | (n % 10).IsBetween(5, 9) || 15 | (n % 100).IsBetween(12, 14)) 16 | { 17 | return PluralTypeEnum.MANY; 18 | } 19 | if (n == 1) 20 | { 21 | return PluralTypeEnum.ONE; 22 | } 23 | return PluralTypeEnum.OTHER; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/ResourceLoaderExtension.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | using System.Globalization; 3 | using System; 4 | 5 | namespace _ReswPlus_AutoGenerated.Plurals 6 | { 7 | internal static class ResourceLoaderExtension 8 | { 9 | private static _ReswPlus_AutoGenerated.Plurals.IPluralProvider _pluralProvider; 10 | private static readonly object _objLock = new object(); 11 | 12 | public static string GetPlural(this _ReswPlus_AutoGenerated.ResourceStringProvider resourceStringProvider, string key, double number, bool supportNoneState = false) 13 | { 14 | if (supportNoneState && number == 0) 15 | { 16 | return resourceStringProvider.GetString(key + "_None"); 17 | } 18 | 19 | if (_pluralProvider is null) 20 | { 21 | CreatePluralProvider(); 22 | if (_pluralProvider is null) 23 | { 24 | return ""; 25 | } 26 | } 27 | string selectedSentence = null; 28 | var pluralType = _pluralProvider.ComputePlural(number); 29 | try 30 | { 31 | switch (pluralType) 32 | { 33 | case PluralTypeEnum.ZERO: 34 | selectedSentence = resourceStringProvider.GetString(key + "_Zero"); 35 | break; 36 | case PluralTypeEnum.ONE: 37 | selectedSentence = resourceStringProvider.GetString(key + "_One"); 38 | break; 39 | case PluralTypeEnum.OTHER: 40 | selectedSentence = resourceStringProvider.GetString(key + "_Other"); 41 | break; 42 | case PluralTypeEnum.TWO: 43 | selectedSentence = resourceStringProvider.GetString(key + "_Two"); 44 | break; 45 | case PluralTypeEnum.FEW: 46 | selectedSentence = resourceStringProvider.GetString(key + "_Few"); 47 | break; 48 | case PluralTypeEnum.MANY: 49 | selectedSentence = resourceStringProvider.GetString(key + "_Many"); 50 | break; 51 | } 52 | } 53 | catch { } 54 | return selectedSentence ?? ""; 55 | } 56 | 57 | private static void CreatePluralProvider(string forcedCultureName = null) 58 | { 59 | lock (_objLock) 60 | { 61 | if (_pluralProvider is null) 62 | { 63 | var cultureToUse = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName; 64 | if (!string.IsNullOrEmpty(forcedCultureName)) 65 | { 66 | try 67 | { 68 | var forcedCulture = new CultureInfo(forcedCultureName)?.TwoLetterISOLanguageName; 69 | if (!string.IsNullOrEmpty(forcedCulture)) 70 | { 71 | cultureToUse = forcedCulture; 72 | } 73 | } 74 | catch 75 | { 76 | } 77 | } 78 | _pluralProvider = GetPluralChooser(cultureToUse); 79 | } 80 | } 81 | } 82 | 83 | private static _ReswPlus_AutoGenerated.Plurals.IPluralProvider GetPluralChooser(string culture) 84 | { 85 | switch (culture) 86 | { 87 | {{PluralProviderSelector}} 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/RomanianProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class RomanianProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.GetNumberOfDigitsAfterDecimal() > 0 || n == 0 || (n != 1 && (n % 100).IsBetween(1, 19))) 10 | { 11 | return PluralTypeEnum.FEW; 12 | } 13 | if (n == 1) 14 | { 15 | return PluralTypeEnum.ONE; 16 | } 17 | return PluralTypeEnum.OTHER; 18 | 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/ScottishGaelicProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class ScottishGaelicProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | var i = (int)n; 12 | switch (i) 13 | { 14 | case 1: 15 | case 11: 16 | return PluralTypeEnum.ONE; 17 | case 2: 18 | case 12: 19 | return PluralTypeEnum.TWO; 20 | } 21 | if (i <= 19) 22 | return PluralTypeEnum.FEW; 23 | } 24 | return PluralTypeEnum.OTHER; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/SinhalaProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class SinhalaProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n == 0 || n == 1 || n.DigitsAfterDecimal() == 1) 10 | return PluralTypeEnum.ONE; 11 | return PluralTypeEnum.OTHER; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/SlavicProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class SlavicProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsInt()) 10 | { 11 | if ((n % 10) == 1 && (n % 100) != 11) 12 | { 13 | return PluralTypeEnum.ONE; 14 | } 15 | if ((n % 10).IsBetween(2, 4) && !(n % 100).IsBetween(12, 14)) 16 | { 17 | return PluralTypeEnum.FEW; 18 | } 19 | if ((n % 10) == 0 || 20 | (n % 10).IsBetween(5, 9) || 21 | (n % 100).IsBetween(11, 14)) 22 | { 23 | return PluralTypeEnum.MANY; 24 | } 25 | 26 | } 27 | return PluralTypeEnum.OTHER; 28 | 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/SlovenianProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class SlovenianProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | var isInt = n.IsInt(); 10 | if (isInt) 11 | { 12 | switch ((int)n) 13 | { 14 | case 1: 15 | return PluralTypeEnum.ONE; 16 | case 2: 17 | return PluralTypeEnum.TWO; 18 | case 3: 19 | case 4: 20 | return PluralTypeEnum.TWO; 21 | } 22 | 23 | return PluralTypeEnum.OTHER; 24 | } 25 | else 26 | { 27 | return PluralTypeEnum.FEW; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/TachelhitProvider.txt: -------------------------------------------------------------------------------- 1 | 2 | using _ReswPlus_AutoGenerated.Utils; 3 | 4 | namespace _ReswPlus_AutoGenerated.Plurals 5 | { 6 | internal sealed class TachelhitProvider : IPluralProvider 7 | { 8 | public PluralTypeEnum ComputePlural(double n) 9 | { 10 | if ((int)n == 0 || n == 1) 11 | { 12 | return PluralTypeEnum.ONE; 13 | } 14 | if (n <= 10 && (int)n == n) 15 | return PluralTypeEnum.FEW; 16 | 17 | return PluralTypeEnum.OTHER; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/WelshProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class WelshProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | var isInt = n.IsInt(); 10 | if (isInt) 11 | { 12 | var i = (int)n; 13 | switch (i) 14 | { 15 | case 0: 16 | return PluralTypeEnum.ZERO; 17 | case 1: 18 | return PluralTypeEnum.ONE; 19 | case 2: 20 | return PluralTypeEnum.TWO; 21 | case 3: 22 | return PluralTypeEnum.FEW; 23 | case 6: 24 | return PluralTypeEnum.MANY; 25 | } 26 | } 27 | return PluralTypeEnum.OTHER; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/ZeroToOneProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class ZeroToOneProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsBetween(0, 1)) 10 | { 11 | return PluralTypeEnum.ONE; 12 | } 13 | return PluralTypeEnum.OTHER; 14 | 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Plurals/ZeroToTwoExcludedProvider.txt: -------------------------------------------------------------------------------- 1 | using _ReswPlus_AutoGenerated.Utils; 2 | 3 | namespace _ReswPlus_AutoGenerated.Plurals 4 | { 5 | internal sealed class ZeroToTwoExcludedProvider : IPluralProvider 6 | { 7 | public PluralTypeEnum ComputePlural(double n) 8 | { 9 | if (n.IsBetweenEndNotIncluded(0, 2)) 10 | { 11 | return PluralTypeEnum.ONE; 12 | } 13 | else 14 | { 15 | return PluralTypeEnum.OTHER; 16 | } 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/ResourceStringProviders/MicrosoftResourceStringProvider.txt: -------------------------------------------------------------------------------- 1 | using Microsoft.Windows.ApplicationModel.Resources; 2 | 3 | namespace _ReswPlus_AutoGenerated 4 | { 5 | internal sealed class ResourceStringProvider 6 | { 7 | private readonly ResourceLoader _resourceLoader; 8 | 9 | public ResourceStringProvider(string resourceMapId) 10 | { 11 | _resourceLoader = new ResourceLoader(ResourceLoader.GetDefaultResourceFilePath(), resourceMapId); 12 | } 13 | 14 | public string GetString(string resourceId) => _resourceLoader.GetString(resourceId); 15 | } 16 | } -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/ResourceStringProviders/WindowsResourceStringProvider.txt: -------------------------------------------------------------------------------- 1 | using Windows.ApplicationModel.Resources; 2 | 3 | namespace _ReswPlus_AutoGenerated 4 | { 5 | internal sealed class ResourceStringProvider 6 | { 7 | private readonly ResourceLoader _resourceLoader; 8 | 9 | public ResourceStringProvider(string resourceMapId) 10 | { 11 | _resourceLoader = ResourceLoader.GetForViewIndependentUse(resourceMapId); 12 | } 13 | 14 | public string GetString(string resourceId) => _resourceLoader.GetString(resourceId); 15 | } 16 | } -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Utils/DoubleExt.txt: -------------------------------------------------------------------------------- 1 | namespace _ReswPlus_AutoGenerated.Utils 2 | { 3 | internal static class DoubleExtension 4 | { 5 | public static bool IsBetween(this double number, double start, double end) 6 | { 7 | return start <= number && number <= end; 8 | } 9 | public static bool IsBetweenEndNotIncluded(this double number, double start, double end) 10 | { 11 | return start <= number && number < end; 12 | } 13 | 14 | public static bool IsInt(this double number) 15 | { 16 | return (int)number == number; 17 | } 18 | 19 | public static uint GetNumberOfDigitsAfterDecimal(this double number) 20 | { 21 | return (uint)((number - (int)number).ToString()).Length - 2; 22 | } 23 | 24 | 25 | public static long DigitsAfterDecimal(this double number) 26 | { 27 | try 28 | { 29 | //need optimization 30 | var str = ((number - (int)number).ToString()).Substring(2); 31 | if (str == "") 32 | return 0; 33 | return long.Parse(str); 34 | } 35 | catch 36 | { 37 | return 0; 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/ReswPlus.SourceGenerator/Templates/Utils/IntExt.txt: -------------------------------------------------------------------------------- 1 | namespace _ReswPlus_AutoGenerated.Utils 2 | { 3 | internal static class IntExtension 4 | { 5 | public static bool IsBetween(this int number, int start, int end) 6 | { 7 | return start <= number && number <= end; 8 | } 9 | public static bool IsBetweenEndNotIncluded(this int number, int start, int end) 10 | { 11 | return start <= number && number < end; 12 | } 13 | 14 | public static bool IsBetween(this long number, long start, long end) 15 | { 16 | return start <= number && number <= end; 17 | } 18 | public static bool IsBetweenEndNotIncluded(this long number, long start, long end) 19 | { 20 | return start <= number && number < end; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/ReswPlusUnitTests/FormatTagLiterals.cs: -------------------------------------------------------------------------------- 1 | using ReswPlus.Core.ResourceParser; 2 | using Xunit; 3 | 4 | namespace ReswPlusUnitTests; 5 | 6 | public class FormatTagLiterals 7 | { 8 | [Fact] 9 | public void TestParseParameters_OneLiteral() 10 | { 11 | foreach (var literal in new[] { 12 | "", 13 | " ", 14 | " ", 15 | "test", 16 | "Plural", 17 | "Int", 18 | "LONG_TEXT_AAAAAAAAAAAAAAAAAAAAAAAAA", 19 | "TEXT WITH ] CHAR", 20 | "TEXT WITH \\\" CHAR" 21 | }) 22 | { 23 | var basicLocalizedItems = new ReswItem[0]; 24 | var res = FormatTag.ParseParameters("test", new[] { $"\"{literal}\"" }, basicLocalizedItems, "test", null); 25 | Assert.NotNull(res); 26 | Assert.True(res.Parameters.Count == 1); 27 | _ = Assert.IsType(res.Parameters[0]); 28 | var literalParam = (LiteralStringFormatTagParameter)res.Parameters[0]; 29 | Assert.Equal(literal, literalParam.Value); 30 | Assert.Null(res.PluralizationParameter); 31 | Assert.Null(res.VariantParameter); 32 | } 33 | } 34 | 35 | [Fact] 36 | public void TestParseParameters_LiteralMixed() 37 | { 38 | foreach (var literal in new[] { 39 | "", 40 | " ", 41 | " ", 42 | "lkryweiuf rysiu", 43 | "Lorem Ipsum", 44 | "Int Plural Short", 45 | "LONG_TEXT_AAAAAABBBBBBBBBBBBBBBBBBBBBBB" 46 | }) 47 | { 48 | var basicLocalizedItems = new ReswItem[0]; 49 | var res = FormatTag.ParseParameters("test", new[] { 50 | $"\"{literal}\"", 51 | "Int test" 52 | }, basicLocalizedItems, "test", null); 53 | Assert.NotNull(res); 54 | Assert.True(res.Parameters.Count == 2); 55 | _ = Assert.IsType(res.Parameters[0]); 56 | _ = Assert.IsType(res.Parameters[1]); 57 | var literalParam = (LiteralStringFormatTagParameter)res.Parameters[0]; 58 | Assert.Equal(literal, literalParam.Value); 59 | Assert.Null(res.PluralizationParameter); 60 | Assert.Null(res.VariantParameter); 61 | } 62 | } 63 | 64 | [Fact] 65 | public void TestParseParameters_Multi() 66 | { 67 | var strings = new[] { 68 | "", 69 | " ", 70 | " ", 71 | "lkryweiuf rysiu", 72 | "Lorem Ipsum", 73 | "Int Plural Short", 74 | "LONG_TEXT_AAAAAABBBBBBBBBBBBBBBBBBBBBBB" 75 | }; 76 | foreach (var literal1 in strings) 77 | { 78 | foreach (var literal2 in strings) 79 | { 80 | var basicLocalizedItems = new ReswItem[0]; 81 | var res = FormatTag.ParseParameters("test", new[] { 82 | $"\"{literal1}\"", 83 | $"\"{literal2}\"", 84 | }, basicLocalizedItems, "test", null); 85 | Assert.NotNull(res); 86 | Assert.True(res.Parameters.Count == 2); 87 | for (var i = 0; i < 2; ++i) 88 | { 89 | _ = Assert.IsType(res.Parameters[i]); 90 | var literalParam = (LiteralStringFormatTagParameter)res.Parameters[i]; 91 | Assert.Equal(i == 0 ? literal1 : literal2, literalParam.Value); 92 | Assert.Null(res.PluralizationParameter); 93 | Assert.Null(res.VariantParameter); 94 | } 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /tests/ReswPlusUnitTests/FormatTagMacros.cs: -------------------------------------------------------------------------------- 1 | using ReswPlus.Core.ResourceParser; 2 | using Xunit; 3 | 4 | namespace ReswPlusUnitTests; 5 | 6 | public class FormatTagMacros 7 | { 8 | [Fact] 9 | public void TestParseParameters_OneLiteral() 10 | { 11 | foreach (var macro in FormatTag.MacrosAvailable) 12 | { 13 | var basicLocalizedItems = new ReswItem[0]; 14 | var res = FormatTag.ParseParameters("test", new[] { macro.Key }, basicLocalizedItems, "test", null); 15 | Assert.NotNull(res); 16 | Assert.True(res.Parameters.Count == 1); 17 | _ = Assert.IsType(res.Parameters[0]); 18 | var macroParam = (MacroFormatTagParameter)res.Parameters[0]; 19 | Assert.Equal(macro.Value, macroParam.Id); 20 | Assert.Null(res.PluralizationParameter); 21 | Assert.Null(res.VariantParameter); 22 | } 23 | } 24 | 25 | [Fact] 26 | public void TestParseParameters_LiteralMixed() 27 | { 28 | foreach (var macro in FormatTag.MacrosAvailable) 29 | { 30 | var basicLocalizedItems = new ReswItem[0]; 31 | var res = FormatTag.ParseParameters("test", new[] { 32 | macro.Key, 33 | "Int test" 34 | }, basicLocalizedItems, "test", null); 35 | Assert.NotNull(res); 36 | Assert.True(res.Parameters.Count == 2); 37 | _ = Assert.IsType(res.Parameters[0]); 38 | _ = Assert.IsType(res.Parameters[1]); 39 | var macroParam = (MacroFormatTagParameter)res.Parameters[0]; 40 | Assert.Equal(macro.Value, macroParam.Id); 41 | Assert.Null(res.PluralizationParameter); 42 | Assert.Null(res.VariantParameter); 43 | } 44 | } 45 | 46 | [Fact] 47 | public void TestParseParameters_Multi() 48 | { 49 | foreach (var macro1 in FormatTag.MacrosAvailable) 50 | { 51 | foreach (var macro2 in FormatTag.MacrosAvailable) 52 | { 53 | var basicLocalizedItems = new ReswItem[0]; 54 | var res = FormatTag.ParseParameters("test", new[] { 55 | macro1.Key, 56 | macro2.Key, 57 | }, basicLocalizedItems, "test", null); 58 | Assert.NotNull(res); 59 | Assert.True(res.Parameters.Count == 2); 60 | for (var i = 0; i < 2; ++i) 61 | { 62 | _ = Assert.IsType(res.Parameters[i]); 63 | var macroParam = (MacroFormatTagParameter)res.Parameters[i]; 64 | Assert.Equal(i == 0 ? macro1.Value : macro2.Value, macroParam.Id); 65 | Assert.Null(res.PluralizationParameter); 66 | Assert.Null(res.VariantParameter); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/ReswPlusUnitTests/FormatTagStringRef.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using ReswPlus.Core.ResourceParser; 3 | using Xunit; 4 | 5 | namespace ReswPlusUnitTests; 6 | 7 | public class FormatTagStringRef 8 | { 9 | [Fact] 10 | public void TestParseParameters_StringRef() 11 | { 12 | var localizedItems = new List() 13 | { 14 | new("TestString", "Test"), 15 | new("Hello", "World"), 16 | new("1223", "Number"), 17 | new("Test_String", "TEST"), 18 | }; 19 | 20 | foreach (var item in localizedItems) 21 | { 22 | var res = FormatTag.ParseParameters("test", new[] { $"{item.Key}()" }, localizedItems, "test", null); 23 | Assert.NotNull(res); 24 | Assert.True(res.Parameters.Count == 1); 25 | _ = Assert.IsType(res.Parameters[0]); 26 | var stringRefParam = (StringRefFormatTagParameter)res.Parameters[0]; 27 | Assert.Equal(item.Key, stringRefParam.Id); 28 | Assert.Null(res.PluralizationParameter); 29 | Assert.Null(res.VariantParameter); 30 | } 31 | } 32 | 33 | [Fact] 34 | public void TestParseParameters_WrongStringRef() 35 | { 36 | var localizedItems = new List() 37 | { 38 | new("TestString", "Test"), 39 | new("Hello", "World"), 40 | new("1223", "Number"), 41 | new("Test_String", "TEST"), 42 | }; 43 | 44 | var wrongRefItems = new List() 45 | { 46 | "AA", 47 | "Test", 48 | "Number" 49 | }; 50 | 51 | foreach (var item in wrongRefItems) 52 | { 53 | var res = FormatTag.ParseParameters("test", new[] { $"{item}()" }, localizedItems, "test", null); 54 | Assert.Null(res); 55 | } 56 | } 57 | 58 | [Fact] 59 | public void TestParseParameters_Multi() 60 | { 61 | var localizedItems = new List() 62 | { 63 | new("TestString", "Test"), 64 | new("Hello", "World"), 65 | new("1223", "Number"), 66 | new("Test_String", "TEST"), 67 | }; 68 | 69 | foreach (var stringRef1 in localizedItems) 70 | { 71 | foreach (var stringRef2 in localizedItems) 72 | { 73 | var res = FormatTag.ParseParameters("test", new[] { 74 | $"{stringRef1.Key}()", 75 | $"{stringRef2.Key}()", 76 | }, localizedItems, "test", null); 77 | Assert.NotNull(res); 78 | Assert.True(res.Parameters.Count == 2); 79 | for (var i = 0; i < 2; ++i) 80 | { 81 | _ = Assert.IsType(res.Parameters[i]); 82 | var macroParam = (StringRefFormatTagParameter)res.Parameters[i]; 83 | Assert.Equal(i == 0 ? stringRef1.Key : stringRef2.Key, macroParam.Id); 84 | Assert.Null(res.PluralizationParameter); 85 | Assert.Null(res.VariantParameter); 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /tests/ReswPlusUnitTests/FormatTagTyped.cs: -------------------------------------------------------------------------------- 1 | using ReswPlus.Core.ResourceParser; 2 | using Xunit; 3 | 4 | namespace ReswPlusUnitTests; 5 | 6 | public class FormatTagTyped 7 | { 8 | [Fact] 9 | public void TestGetParameterTypeExistingTypes() 10 | { 11 | foreach (var type in FormatTag.AcceptedTypes) 12 | { 13 | var typeRes = FormatTag.GetParameterType(type.Key, false); 14 | Assert.Equal(typeRes.type, type.Value.Type); 15 | Assert.Null(typeRes.typeToCast); 16 | Assert.False(typeRes.isVariantId); 17 | 18 | typeRes = FormatTag.GetParameterType(type.Key, true); 19 | Assert.Equal(typeRes.type, type.Value.Type); 20 | Assert.Equal(typeRes.typeToCast.HasValue, type.Value.CanBeQuantifier && type.Value.Type != ParameterType.Double); 21 | if (typeRes.typeToCast.HasValue) 22 | { 23 | Assert.Equal(ParameterType.Double, typeRes.typeToCast.Value); 24 | } 25 | } 26 | 27 | var res = FormatTag.GetParameterType("", true); 28 | Assert.Equal(ParameterType.Double, res.type); 29 | Assert.Null(res.typeToCast); 30 | } 31 | 32 | [Fact] 33 | public void TestGetParameterTypeIncorrectTypes() 34 | { 35 | var res = FormatTag.GetParameterType("", false); 36 | Assert.Null(res.type); 37 | Assert.Null(res.typeToCast); 38 | 39 | foreach (var type in new string[]{ 40 | "ant", 41 | "doble", 42 | "Int, Double", 43 | "UnsignedInt" 44 | }) 45 | { 46 | res = FormatTag.GetParameterType(type, false); 47 | Assert.Null(res.type); 48 | Assert.Null(res.typeToCast); 49 | 50 | res = FormatTag.GetParameterType(type, true); 51 | Assert.Null(res.type); 52 | Assert.Null(res.typeToCast); 53 | } 54 | } 55 | 56 | [Fact] 57 | public void TestParseParameters_OneValidParameter() 58 | { 59 | foreach (var type in FormatTag.AcceptedTypes) 60 | { 61 | var basicLocalizedItems = new ReswItem[0]; 62 | var res = FormatTag.ParseParameters("test", new[] { type.Key }, basicLocalizedItems, "test", null); 63 | Assert.NotNull(res); 64 | Assert.True(res.Parameters.Count == 1); 65 | _ = Assert.IsType(res.Parameters[0]); 66 | Assert.Equal(((FunctionFormatTagParameter)res.Parameters[0]).Type, type.Value.Type); 67 | Assert.Null(res.PluralizationParameter); 68 | Assert.Null(res.VariantParameter); 69 | } 70 | } 71 | 72 | [Fact] 73 | public void TestParseParameters_OneValidNamedParameter() 74 | { 75 | foreach (var type in FormatTag.AcceptedTypes) 76 | { 77 | var basicLocalizedItems = new ReswItem[0]; 78 | var res = FormatTag.ParseParameters("test", new[] { type.Key + " param" }, basicLocalizedItems, "test", null); 79 | Assert.NotNull(res); 80 | Assert.True(res.Parameters.Count == 1); 81 | _ = Assert.IsType(res.Parameters[0]); 82 | Assert.Equal("param", ((FunctionFormatTagParameter)res.Parameters[0]).Name); 83 | Assert.Equal("param", ((FunctionFormatTagParameter)res.Parameters[0]).Name); 84 | Assert.False(((FunctionFormatTagParameter)res.Parameters[0]).IsVariantId); 85 | Assert.Null(res.PluralizationParameter); 86 | Assert.Null(res.VariantParameter); 87 | } 88 | } 89 | 90 | [Fact] 91 | public void TestParseParameters_MultiValidParameter() 92 | { 93 | foreach (var type1 in FormatTag.AcceptedTypes) 94 | { 95 | foreach (var type2 in FormatTag.AcceptedTypes) 96 | { 97 | var basicLocalizedItems = new ReswItem[0]; 98 | var res = FormatTag.ParseParameters("test", new[] { type1.Key, type2.Key + " paramName" }, basicLocalizedItems, "test", null); 99 | Assert.NotNull(res); 100 | Assert.True(res.Parameters.Count == 2); 101 | _ = Assert.IsType(res.Parameters[0]); 102 | Assert.Equal(((FunctionFormatTagParameter)res.Parameters[0]).Type, type1.Value.Type); 103 | Assert.False(((FunctionFormatTagParameter)res.Parameters[0]).IsVariantId); 104 | Assert.Null(res.PluralizationParameter); 105 | Assert.Null(res.VariantParameter); 106 | _ = Assert.IsType(res.Parameters[1]); 107 | Assert.Equal(((FunctionFormatTagParameter)res.Parameters[1]).Type, type2.Value.Type); 108 | Assert.False(((FunctionFormatTagParameter)res.Parameters[1]).IsVariantId); 109 | Assert.Equal("paramName", ((FunctionFormatTagParameter)res.Parameters[1]).Name); 110 | Assert.Null(res.PluralizationParameter); 111 | Assert.Null(res.VariantParameter); 112 | } 113 | } 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /tests/ReswPlusUnitTests/FormatTagVariants.cs: -------------------------------------------------------------------------------- 1 | using ReswPlus.Core.ResourceParser; 2 | using Xunit; 3 | 4 | namespace ReswPlusUnitTests; 5 | 6 | public class FormatTagVariants 7 | { 8 | [Fact] 9 | public void TestParseParameters_OneValidNamelessVariantParameter() 10 | { 11 | var basicLocalizedItems = new ReswItem[0]; 12 | var res = FormatTag.ParseParameters("test", new[] { "Variant" }, basicLocalizedItems, "test", null); 13 | Assert.NotNull(res); 14 | Assert.True(res.Parameters.Count == 1); 15 | _ = Assert.IsType(res.Parameters[0]); 16 | var functionParam = (FunctionFormatTagParameter)res.Parameters[0]; 17 | Assert.Equal(ParameterType.Long, functionParam.Type); 18 | Assert.Null(res.PluralizationParameter); 19 | Assert.True(functionParam.IsVariantId); 20 | Assert.Equal(res.VariantParameter, functionParam); 21 | } 22 | 23 | [Fact] 24 | public void TestParseParameters_ValidNamedVariantParameter() 25 | { 26 | var basicLocalizedItems = new ReswItem[0]; 27 | var res = FormatTag.ParseParameters("test", new[] { "Variant var" }, basicLocalizedItems, "test", null); 28 | Assert.NotNull(res); 29 | Assert.True(res.Parameters.Count == 1); 30 | _ = Assert.IsType(res.Parameters[0]); 31 | var functionParam = (FunctionFormatTagParameter)res.Parameters[0]; 32 | Assert.Equal(ParameterType.Long, functionParam.Type); 33 | Assert.Null(res.PluralizationParameter); 34 | Assert.True(functionParam.IsVariantId); 35 | Assert.Equal("var", functionParam.Name); 36 | Assert.Equal(res.VariantParameter, functionParam); 37 | } 38 | 39 | [Fact] 40 | public void TestParseParameters_OnlyOneVariantAccepted() 41 | { 42 | var basicLocalizedItems = new ReswItem[0]; 43 | var res = FormatTag.ParseParameters("test", new[] { "Variant var1", "Variant var2" }, basicLocalizedItems, "test", null); 44 | Assert.Null(res); 45 | } 46 | 47 | [Fact] 48 | public void TestParseParameters_TypedVariantNotAccepted() 49 | { 50 | var basicLocalizedItems = new ReswItem[0]; 51 | var res = FormatTag.ParseParameters("test", new[] { "Variant Int var1", "Variant var2" }, basicLocalizedItems, "test", null); 52 | Assert.Null(res); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/ReswPlusUnitTests/ReswPlusUnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0-windows10.0.19041.0 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | 15 | 16 | 17 | 18 | 19 | {44d125b3-6c8a-4f2f-a76f-bffb2ad7e70d} 20 | ReswPlus.SourceGenerator 21 | 22 | 23 | 24 | 25 | --------------------------------------------------------------------------------