├── .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 | 
5 | 
6 | 
7 | 
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