Skip to content

Commit 987dabb

Browse files
committed
Ability to perform localized validation on data attributes
1 parent d6d3695 commit 987dabb

9 files changed

Lines changed: 987 additions & 163 deletions

File tree

README.md

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Why MultiLanguages is better:
2323
| Memory Heavy, Hard to Maintain RESX Resource Files | :heavy_check_mark: | |
2424
| Less Memory, Easy to Maintain YAML Resource Files | | :heavy_check_mark: |
2525
| Generate English Resource YAML File from Localizable Strings from your UI Code | | :heavy_check_mark: |
26-
| Replace Localizable Strings with Variables | | :heavy_check_mark: |
26+
| Automatically Replace Localizable Strings with Variables | | :heavy_check_mark: |
2727
| Data Attribute Localization | :heavy_check_mark: | :heavy_check_mark: |
2828
| Hierarchal Language Key Support | | :heavy_check_mark: |
2929
| Translate Resource Files into 69 Different Languages | | :heavy_check_mark: |
@@ -72,24 +72,24 @@ https://youtu.be/Xz68c8GBYz4
7272

7373

7474
# Why YAML
75-
Most common solution for multilanguage in .NET is the .resx resource files. .resx files are XML based so they are not too friendly to deal with and most likely a GUI tool is needed for keys management. XML is also huge and slower to parse. On the other hand, YAML is new, very fast to parse, and file structure is very simple and doesn't contain any single not-needed character which make the file size too small comparing to the XML one.
75+
Most common solution for multilanguage in .NET are .resx resource files. .resx files are XML based so they are not too friendly to deal with and most likely a GUI tool is needed for keys management. XML is also huge and slower to parse. On the other hand, YAML is new, very fast to parse, and the file structure is very simple and doesn't contain any unneeded characters which make the file size smaller compared to XML.
7676
For modern SPA apps with Blazor WebAssembly for example, large language files with .resx might slow down the load time for the download.
7777
YAML file structure allows for nested objects which a lovely feature you can take advantage of to build an organized language key-values files without long concatenated names.
7878
Finally, due to the simplicity of YAML, it's makes it very easy to build automation on top of it like source generator and static classes creation.
7979

8080
# Features
8181
AKSoftware.Localization.Multilanguage prvoides all the feature set needed for any multilanguage support like:
8282
- Easy to get started.
83-
- Online traslator tool to translate your files in one click for more 65 languages https://akmultilanguages.azurewebsites.net
84-
- Light and high-performant
83+
- Online translator tool to translate your files in one click for more 65 languages https://akmultilanguages.azurewebsites.net
84+
- Light and high-performance
8585
- Blazor Server & WebAssembly support
8686
- Out of the box state management for **Blazor** components
8787
- Multiple language file sources (Files in folder or embedded files)
8888
- String interpolation support
8989
- Dynamically list all language keys
9090
- Dynamically list all available langauges
9191
- Dependency injection support
92-
- Hierarcy language keys in YAML
92+
- Hierarchical language keys in YAML
9393
- Code generators to generate full keys accessor service, static class with const strings, enums, and more..
9494
- v6.1 will bring the localization assistant to localize existing apps with minimal effort.
9595
- Full UWP support
@@ -187,7 +187,7 @@ Welcome: Welcome
187187

188188

189189

190-
Select the file in the Solution Explorer window and from the properties window set the build action property to "Embeded Resources"
190+
Select the file in the Solution Explorer window and from the properties window set the build action property to "Embedded Resource"
191191

192192
>**Note**
193193
>In case of using the Source Generator package, that will be taken care of automatically.
@@ -412,6 +412,7 @@ We are currently working on version 6. Here are the upcoming features.
412412
Verify All Keys Can Be Found](#verify-all-keys-can-be-found)
413413
* [Verify No Unused Keys](#verify-no-unused-keys)
414414
* [Verify No Duplicate Keys](#verify-no-duplicate-keys)
415+
* [Data Attribute Localization Validation](#data-attribute-localization-validation)
415416

416417
## Specify the assembly by name
417418
If you have multiple projects in your Visual Studio Solution that depend upon language translation, as of version 6.0 and higher you can specify the assembly by name. Place your resources in a project that can be used by the other projects in your Solution.
@@ -817,6 +818,53 @@ public void ReplaceLocalizableStringsWithVariablesExample()
817818
}
818819
```
819820

821+
## Data Attribute Localization Validation
822+
In order to localize validation messages, use the Create or Update [Resource File from Localizable Strings](#create-or-update-resource-file-from-localizable-strings) feature. Below is a full Blazor example using a Contact Us Page.
823+
824+
```C#
825+
public partial class ContactUsPage : ComponentBase
826+
{
827+
[Inject] private ILanguageContainerService Language { get; set; }
828+
private ContactUs _contactUs;
829+
private ValidationMessageStore _validationMessageStore;
830+
private EditContext? EC { get; set; }
831+
832+
protected override void OnInitialized()
833+
{
834+
Language.InitLocalizedComponent(this);
835+
_contactUs = new Common.Models.ContactUs();
836+
EC = new EditContext(_contactUs);
837+
_validationMessageStore = new ValidationMessageStore(EC);
838+
}
839+
840+
private ClearValidationMessages()
841+
{
842+
_validationMessageStore.Clear();
843+
}
844+
845+
private bool IsValid()
846+
{
847+
ClearValidationMessages();
848+
bool isValid = ValidationLocalization.ValidateModel(_contactUs, _validationMessageStore, Language);
849+
if (!isValid)
850+
{
851+
EC.NotifyValidationStateChanged();
852+
return false;
853+
}
854+
855+
return true;
856+
}
857+
858+
private void HandleSubmitClick()
859+
{
860+
if (!IsValid())
861+
return;
862+
863+
//Handle Form Submission
864+
}
865+
}
866+
```
867+
820868
# Thanks for the awesome contributors
821869

822870
<a href="https://github.com/aksoftware98/multilanguages/graphs/contributors">
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace AKSoftware.Localization.MultiLanguages.Tests.TestClasses
4+
{
5+
public class Customer
6+
{
7+
[Required]
8+
public string Name { get; set; }
9+
}
10+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using AKSoftware.Localization.MultiLanguages.Providers;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Globalization;
5+
using System.Linq;
6+
using System.Reflection;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using Microsoft.AspNetCore.Components.Forms;
10+
using Xunit;
11+
using Xunit.Abstractions;
12+
13+
namespace AKSoftware.Localization.MultiLanguages.Tests
14+
{
15+
public class ValidationLocalizationTests
16+
{
17+
private readonly ITestOutputHelper _output;
18+
19+
public ValidationLocalizationTests(ITestOutputHelper output)
20+
{
21+
_output = output;
22+
}
23+
24+
[Fact]
25+
public void ValidateModelTest()
26+
{
27+
//Arrange
28+
var customer = new TestClasses.Customer();
29+
var keysProvider = new EmbeddedResourceKeysProvider(Assembly.GetExecutingAssembly());
30+
ILanguageContainerService language = new LanguageContainer(CultureInfo.GetCultureInfo("en-US"), keysProvider);
31+
EditContext editContext = new EditContext(customer);
32+
var validationMessageStore = new ValidationMessageStore(editContext);
33+
34+
//Act
35+
ValidationLocalization.ValidateModel(customer, validationMessageStore, language);
36+
37+
//Assert
38+
List<string> messages = validationMessageStore[editContext.Field("Name")].ToList();
39+
Assert.NotEmpty(messages);
40+
Assert.Equal("Name is required", messages[0]);
41+
42+
}
43+
}
44+
}

src/AKSoftware.Localization.MultiLanguages.Tests/VerifyLocalization.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public void VerifyAllSourceCodeFilesAreLocalized()
2828
parms.ResourceFilePath = Path.Combine(solutionPath, "BlazorServerLocalizationSample",
2929
"Resources", "en-US.yml");
3030
parms.KeyReference = "Language";
31+
parms.RemoveLocalizedKeys = true;
3132

3233
//Act
3334
ParseCodeLogic logic = new ParseCodeLogic();

src/AKSoftware.Localization.MultiLanguages/AKSoftware.Localization.MultiLanguages.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
</PropertyGroup>
2323

2424
<ItemGroup>
25+
<PackageReference Include="Microsoft.AspNetCore.Components.Forms" Version="3.1.32" />
2526
<PackageReference Include="Microsoft.csharp" Version="4.7.0" />
2627
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
2728
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />

0 commit comments

Comments
 (0)