Browse Source

Merge branch 'rel-7.0' into upradge-bookstore-blazor-ef-abp-7-0

pull/15303/head
malik masis 4 years ago
parent
commit
5f8fc45a39
  1. 4
      docs/en/Module-Entity-Extensions.md
  2. 2
      docs/en/Tutorials/Part-10.md
  3. 6
      docs/en/Tutorials/Part-2.md
  4. 8
      docs/en/Tutorials/Part-3.md
  5. 11
      docs/en/UI/Angular/OAuth-Module.md
  6. 21
      docs/en/UI/AspNetCore/Forms-Validation.md
  7. 23
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  8. 3
      framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
  9. 3
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/EnumHelper.cs
  10. 4
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs
  11. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/SelectExtensionProperty.razor.cs
  12. 66
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpEnumLocalizer.cs
  13. 19
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpEnumLocalizerExtensions.cs
  14. 4
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpInternalLocalizationHelper.cs
  15. 11
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/IAbpEnumLocalizer.cs
  16. 47
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpEnumLocalizer_Tests.cs
  17. 6
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalizationTestModule.cs
  18. 9
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/en.json
  19. 9
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json

4
docs/en/Module-Entity-Extensions.md

@ -312,12 +312,14 @@ An enum properties is shown as combobox (select) in the create/edit forms:
Enum member name is shown on the table and forms by default. If you want to localize it, just create a new entry on your [localization](https://docs.abp.io/en/abp/latest/Localization) file: Enum member name is shown on the table and forms by default. If you want to localize it, just create a new entry on your [localization](https://docs.abp.io/en/abp/latest/Localization) file:
````json ````json
"UserType.SuperUser": "Super user" "Enum:UserType.0": "Super user"
```` ````
One of the following names can be used as the localization key: One of the following names can be used as the localization key:
* `Enum:UserType.0`
* `Enum:UserType.SuperUser` * `Enum:UserType.SuperUser`
* `UserType.0`
* `UserType.SuperUser` * `UserType.SuperUser`
* `SuperUser` * `SuperUser`

2
docs/en/Tutorials/Part-10.md

@ -725,7 +725,7 @@ Book list page change is trivial. Open the `Pages/Books/Index.js` in the `Acme.B
title: l('Type'), title: l('Type'),
data: "type", data: "type",
render: function (data) { render: function (data) {
return l('Enum:BookType:' + data); return l('Enum:BookType.' + data);
} }
}, },
... ...

6
docs/en/Tutorials/Part-2.md

@ -147,7 +147,7 @@ Open the `en.json` (*the English translations*) file and change the content as s
* Localization key names are arbitrary. You can set any name. We prefer some conventions for specific text types; * Localization key names are arbitrary. You can set any name. We prefer some conventions for specific text types;
* Add `Menu:` prefix for menu items. * Add `Menu:` prefix for menu items.
* Use `Enum:<enum-type>.<enum-name>` or `<enum-type>.<enum-name>` or `<enum-name>` naming convention to localize the enum members. When you do it like that, ABP can automatically localize the enums in some proper cases. * Use `Enum:<enum-type>.<enum-value>` or `<enum-type>.<enum-value>` naming convention to localize the enum members. When you do it like that, ABP can automatically localize the enums in some proper cases.
If a text is not defined in the localization file, it **falls back** to the localization key (as ASP.NET Core's standard behavior). If a text is not defined in the localization file, it **falls back** to the localization key (as ASP.NET Core's standard behavior).
@ -279,7 +279,7 @@ $(function () {
title: l('Type'), title: l('Type'),
data: "type", data: "type",
render: function (data) { render: function (data) {
return l('Enum:BookType:' + data); return l('Enum:BookType.' + data);
} }
}, },
{ {
@ -517,7 +517,7 @@ Open the `/src/app/book/book.component.html` and replace the content as shown be
<ngx-datatable-column [name]="'::Name' | abpLocalization" prop="name"></ngx-datatable-column> <ngx-datatable-column [name]="'::Name' | abpLocalization" prop="name"></ngx-datatable-column>
<ngx-datatable-column [name]="'::Type' | abpLocalization" prop="type"> <ngx-datatable-column [name]="'::Type' | abpLocalization" prop="type">
<ng-template let-row="row" ngx-datatable-cell-template> <ng-template let-row="row" ngx-datatable-cell-template>
{%{{{ '::Enum:BookType:' + row.type | abpLocalization }}}%} {%{{{ '::Enum:BookType.' + row.type | abpLocalization }}}%}
</ng-template> </ng-template>
</ngx-datatable-column> </ngx-datatable-column>
<ngx-datatable-column [name]="'::PublishDate' | abpLocalization" prop="publishDate"> <ngx-datatable-column [name]="'::PublishDate' | abpLocalization" prop="publishDate">

8
docs/en/Tutorials/Part-3.md

@ -232,7 +232,7 @@ $(function () {
title: l('Type'), title: l('Type'),
data: "type", data: "type",
render: function (data) { render: function (data) {
return l('Enum:BookType:' + data); return l('Enum:BookType.' + data);
} }
}, },
{ {
@ -418,7 +418,7 @@ $(function () {
title: l('Type'), title: l('Type'),
data: "type", data: "type",
render: function (data) { render: function (data) {
return l('Enum:BookType:' + data); return l('Enum:BookType.' + data);
} }
}, },
{ {
@ -556,7 +556,7 @@ $(function () {
title: l('Type'), title: l('Type'),
data: "type", data: "type",
render: function (data) { render: function (data) {
return l('Enum:BookType:' + data); return l('Enum:BookType.' + data);
} }
}, },
{ {
@ -789,7 +789,7 @@ Open `/src/app/book/book.component.html` and replace `<ng-template #abpBody> </n
<label for="book-type">Type</label><span> * </span> <label for="book-type">Type</label><span> * </span>
<select class="form-control" id="book-type" formControlName="type"> <select class="form-control" id="book-type" formControlName="type">
<option [ngValue]="null">Select a book type</option> <option [ngValue]="null">Select a book type</option>
<option [ngValue]="type.value" *ngFor="let type of bookTypes"> {%{{{ type.key }}}%}</option> <option [ngValue]="type.value" *ngFor="let type of bookTypes"> {%{{{ '::Enum:BookType.' + type.value | abpLocalization }}}%}</option>
</select> </select>
</div> </div>

11
docs/en/UI/Angular/OAuth-Module.md

@ -7,8 +7,15 @@ Those abstractions can be found in the @abp/ng-core packages.
- `AuthService` (the class that implements the IAuthService interface). - `AuthService` (the class that implements the IAuthService interface).
- `NAVIGATE_TO_MANAGE_PROFILE` Inject token. - `NAVIGATE_TO_MANAGE_PROFILE` Inject token.
- `AuthGuard` (the class that implements the IAuthGuard interface). - `AuthGuard` (the class that implements the IAuthGuard interface).
- `ApiInterceptor` (the class that implements the IApiInterceptor interface).
Those base classes are overridden by the "AbpOAuthModule" for oAuth. There are also three functions provided with AbpOAuthModule.
- `PIPE_TO_LOGIN_FN_KEY` a provide that calls a function when the user is not authenticated. The function should be PipeToLoginFn type.
- `SET_TOKEN_RESPONSE_TO_STORAGE_FN_KEY` a provide that calls a function when the user is authenticated. The function should be SetTokenResponseToStorageFn type.
- `CHECK_AUTHENTICATION_STATE_FN_KEY` a provide that calls a function when the user is authenticated and stores the auth state. The function should be CheckAuthenticationStateFn type.
The tokens and interfaces are in the `@abp/ng.core` package but the implementation of these interfaces is in the `@abp/ng.oauth` package.
Those base classes are overridden by the "AbpOAuthModule" for oAuth.
If you want to make your own authentication system, you must also change these 'abstract' classes. If you want to make your own authentication system, you must also change these 'abstract' classes.
ApiInterceptor is provided by @abp/ng.oauth. The ApiInterceptor adds the token, accepted-language, and tenant id to the header of the HTTP request. ApiInterceptor is provided by `@abp/ng.core` but overridden with `@abp/ng.oauth`. The ApiInterceptor adds the token, accepted-language, and tenant id to the header of the HTTP request. It also calls the http-wait service.

21
docs/en/UI/AspNetCore/Forms-Validation.md

@ -201,6 +201,27 @@ In this case, you can add an entry to the localization file using the key `MyNam
> If you use the `[DisplayName]` but not add a corresponding entity to the localization file, then ABP Framework shows the given key as the field name, `MyNameKey` for this case. So, it provides a way to specify a hard coded display name even if you don't need to use the localization system. > If you use the `[DisplayName]` but not add a corresponding entity to the localization file, then ABP Framework shows the given key as the field name, `MyNameKey` for this case. So, it provides a way to specify a hard coded display name even if you don't need to use the localization system.
### Enum Localization
Enum members are also automatically localized wherever possible. For example, when we added `<abp-select asp-for="Movie.Genre"/>` to the form (like we did in the *ABP Form Tag Helpers* section), ABP can automatically fill the localized names of Enum members. To enabled it, you should define the localized values in your localization JSON file. Example entries for the `Genre` Enum defined in the *ABP Form Tag Helpers* section:
````json
"Enum:Genre.0": "Classic movie",
"Enum:Genre.1": "Action movie",
"Enum:Genre.2": "Fiction",
"Enum:Genre.3": "Fantasy",
"Enum:Genre.4": "Animation/Cartoon"
````
You can use one of the following syntaxes for the localization keys:
* `Enum:<enum-type-name>.<enum-value>`
* `<enum-type-name>.<enum-value>`
> Remember that if you don't specify values for your Enum, the values will be ordered, starting from `0`.
> MVC tag helpers also support using Enum member names instead of values (so, you can define `"Enum:Genre.Action"` instead of `"Enum:Genre.1"`, for example), but it is not suggested. Because, when you serialize Enum properties to JSON and send to clients, default serializer uses Enum values instead of Enum names. So, the Enum name won't be available to clients, and it will be a problem if you want to use the same localization values on the client side.
## See Also ## See Also
* [Server Side Validation](../../Validation.md) * [Server Side Validation](../../Validation.md)

23
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs

@ -22,17 +22,20 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
private readonly HtmlEncoder _encoder; private readonly HtmlEncoder _encoder;
private readonly IAbpTagHelperLocalizer _tagHelperLocalizer; private readonly IAbpTagHelperLocalizer _tagHelperLocalizer;
private readonly IStringLocalizerFactory _stringLocalizerFactory; private readonly IStringLocalizerFactory _stringLocalizerFactory;
private readonly IAbpEnumLocalizer _abpEnumLocalizer;
public AbpSelectTagHelperService( public AbpSelectTagHelperService(
IHtmlGenerator generator, IHtmlGenerator generator,
HtmlEncoder encoder, HtmlEncoder encoder,
IAbpTagHelperLocalizer tagHelperLocalizer, IAbpTagHelperLocalizer tagHelperLocalizer,
IStringLocalizerFactory stringLocalizerFactory) IStringLocalizerFactory stringLocalizerFactory,
IAbpEnumLocalizer abpEnumLocalizer)
{ {
_generator = generator; _generator = generator;
_encoder = encoder; _encoder = encoder;
_tagHelperLocalizer = tagHelperLocalizer; _tagHelperLocalizer = tagHelperLocalizer;
_stringLocalizerFactory = stringLocalizerFactory; _stringLocalizerFactory = stringLocalizerFactory;
_abpEnumLocalizer = abpEnumLocalizer;
} }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
@ -264,22 +267,12 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
foreach (var enumValue in enumType.GetEnumValues()) foreach (var enumValue in enumType.GetEnumValues())
{ {
var memberName = enumType.GetEnumName(enumValue); var localizedMemberName = _abpEnumLocalizer.GetString(enumType, enumValue,
var localizedMemberName = AbpInternalLocalizationHelper.LocalizeWithFallback(
new[] new[]
{ {
containerLocalizer, containerLocalizer,
_stringLocalizerFactory.CreateDefaultOrNull() _stringLocalizerFactory.CreateDefaultOrNull()
}, });
new[]
{
$"Enum:{enumType.Name}.{memberName}",
$"{enumType.Name}.{memberName}",
memberName
},
memberName
);
selectItems.Add(new SelectListItem selectItems.Add(new SelectListItem
{ {
Value = enumValue.ToString(), Value = enumValue.ToString(),

3
framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs

@ -176,6 +176,7 @@ public abstract class AbpCrudPageBase<
{ {
[Inject] protected TAppService AppService { get; set; } [Inject] protected TAppService AppService { get; set; }
[Inject] protected IStringLocalizer<AbpUiResource> UiLocalizer { get; set; } [Inject] protected IStringLocalizer<AbpUiResource> UiLocalizer { get; set; }
[Inject] public IAbpEnumLocalizer AbpEnumLocalizer { get; set; }
protected virtual int PageSize { get; } = LimitedResultRequestDto.DefaultMaxResultCount; protected virtual int PageSize { get; } = LimitedResultRequestDto.DefaultMaxResultCount;
@ -626,7 +627,7 @@ public abstract class AbpCrudPageBase<
if (propertyInfo.Type.IsEnum) if (propertyInfo.Type.IsEnum)
{ {
column.ValueConverter = (val) => column.ValueConverter = (val) =>
EnumHelper.GetLocalizedMemberName(propertyInfo.Type, val.As<ExtensibleObject>().ExtraProperties[propertyInfo.Name], StringLocalizerFactory); AbpEnumLocalizer.GetString(propertyInfo.Type, val.As<ExtensibleObject>().ExtraProperties[propertyInfo.Name], new IStringLocalizer[]{ StringLocalizerFactory.CreateDefaultOrNull() });
} }
yield return column; yield return column;

3
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/EnumHelper.cs

@ -10,6 +10,7 @@ namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending;
public static class EnumHelper public static class EnumHelper
{ {
[Obsolete("Use IAbpEnumLocalizer instead.")]
public static string GetLocalizedMemberName(Type enumType, object value, IStringLocalizerFactory stringLocalizerFactory) public static string GetLocalizedMemberName(Type enumType, object value, IStringLocalizerFactory stringLocalizerFactory)
{ {
var memberName = enumType.GetEnumName(value); var memberName = enumType.GetEnumName(value);
@ -20,7 +21,9 @@ public static class EnumHelper
}, },
new[] new[]
{ {
$"Enum:{enumType.Name}.{value}",
$"Enum:{enumType.Name}.{memberName}", $"Enum:{enumType.Name}.{memberName}",
$"{enumType.Name}.{value}",
$"{enumType.Name}.{memberName}", $"{enumType.Name}.{memberName}",
memberName memberName
}, },

4
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Components.Web; using Volo.Abp.AspNetCore.Components.Web;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.Localization;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending; namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending;
@ -17,6 +18,9 @@ public abstract class ExtensionPropertyComponentBase<TEntity, TResourceType> : O
[Inject] [Inject]
public IStringLocalizerFactory StringLocalizerFactory { get; set; } public IStringLocalizerFactory StringLocalizerFactory { get; set; }
[Inject]
public IAbpEnumLocalizer AbpEnumLocalizer { get; set; }
[Inject] [Inject]
public IValidationMessageLocalizerAttributeFinder ValidationMessageLocalizerAttributeFinder { get; set; } public IValidationMessageLocalizerAttributeFinder ValidationMessageLocalizerAttributeFinder { get; set; }

2
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/SelectExtensionProperty.razor.cs

@ -30,7 +30,7 @@ public partial class SelectExtensionProperty<TEntity, TResourceType>
selectItems.Add(new SelectItem<int> selectItems.Add(new SelectItem<int>
{ {
Value = (int)enumValue, Value = (int)enumValue,
Text = EnumHelper.GetLocalizedMemberName(PropertyInfo.Type, enumValue, StringLocalizerFactory) Text = AbpEnumLocalizer.GetString(PropertyInfo.Type, enumValue, new []{ StringLocalizerFactory.CreateDefaultOrNull() })
}); });
} }

66
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpEnumLocalizer.cs

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Localization;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Localization;
public class AbpEnumLocalizer : IAbpEnumLocalizer, ITransientDependency
{
protected readonly IStringLocalizerFactory StringLocalizerFactory;
public AbpEnumLocalizer(IStringLocalizerFactory stringLocalizerFactory)
{
StringLocalizerFactory = stringLocalizerFactory;
}
public virtual string GetString(Type enumType, object enumValue)
{
return GetStringInternal(enumType, enumValue, StringLocalizerFactory.CreateDefaultOrNull());
}
public virtual string GetString(Type enumType, object enumValue, params IStringLocalizer[] specifyLocalizers)
{
return GetStringInternal(enumType, enumValue, specifyLocalizers);
}
protected virtual string GetStringInternal(Type enumType, object enumValue, params IStringLocalizer[] specifyLocalizers)
{
var memberName = enumType.GetEnumName(enumValue);
var localizedString = GetStringOrNull(
specifyLocalizers,
new[]
{
$"Enum:{enumType.Name}.{enumValue}",
$"Enum:{enumType.Name}.{memberName}",
$"{enumType.Name}.{enumValue}",
$"{enumType.Name}.{memberName}",
memberName
}
);
return localizedString ?? memberName;
}
protected virtual string GetStringOrNull(IStringLocalizer[] localizers, IEnumerable<string> keys)
{
foreach (var key in keys)
{
foreach (var l in localizers)
{
if (l == null)
{
continue;
}
var localizedString = l[key];
if (!localizedString.ResourceNotFound)
{
return localizedString.Value;
}
}
}
return null;
}
}

19
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpEnumLocalizerExtensions.cs

@ -0,0 +1,19 @@
using System;
using Microsoft.Extensions.Localization;
namespace Volo.Abp.Localization;
public static class AbpEnumLocalizerExtensions
{
public static string GetString<TEnum>(this IAbpEnumLocalizer abpEnumLocalizer, object enumValue)
where TEnum : Enum
{
return abpEnumLocalizer.GetString(typeof(TEnum), enumValue);
}
public static string GetString<TEnum>(this IAbpEnumLocalizer abpEnumLocalizer, object enumValue, IStringLocalizer[] specifyLocalizers)
where TEnum : Enum
{
return abpEnumLocalizer.GetString(typeof(TEnum), enumValue, specifyLocalizers);
}
}

4
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpInternalLocalizationHelper.cs

@ -1,4 +1,5 @@
using Microsoft.Extensions.Localization; using System;
using Microsoft.Extensions.Localization;
namespace Volo.Abp.Localization; namespace Volo.Abp.Localization;
@ -22,6 +23,7 @@ public static class AbpInternalLocalizationHelper
/// Return value if none of the localizers has none of the keys. /// Return value if none of the localizers has none of the keys.
/// </param> /// </param>
/// <returns></returns> /// <returns></returns>
[Obsolete("Use IAbpEnumLocalizer instead.")]
public static string LocalizeWithFallback( public static string LocalizeWithFallback(
IStringLocalizer[] localizers, IStringLocalizer[] localizers,
string[] keys, string[] keys,

11
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/IAbpEnumLocalizer.cs

@ -0,0 +1,11 @@
using System;
using Microsoft.Extensions.Localization;
namespace Volo.Abp.Localization;
public interface IAbpEnumLocalizer
{
string GetString(Type enumType, object enumValue);
string GetString(Type enumType, object enumValue, IStringLocalizer[] specifyLocalizers);
}

47
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpEnumLocalizer_Tests.cs

@ -0,0 +1,47 @@
using Microsoft.Extensions.Localization;
using Shouldly;
using Volo.Abp.Localization.TestResources.Base.Validation;
using Volo.Abp.Testing;
using Xunit;
namespace Volo.Abp.Localization;
public class AbpEnumLocalizer_Tests : AbpIntegratedTest<AbpLocalizationTestModule>
{
private readonly IAbpEnumLocalizer _enumLocalizer;
public AbpEnumLocalizer_Tests()
{
_enumLocalizer = GetRequiredService<IAbpEnumLocalizer>();
}
[Fact]
public void GetString_Test()
{
using (CultureHelper.Use("en"))
{
_enumLocalizer.GetString<BookType>(BookType.Undefined).ShouldBe("Undefined");
_enumLocalizer.GetString<BookType>(BookType.Adventure).ShouldBe("Adventure");
_enumLocalizer.GetString<BookType>(0).ShouldBe("Undefined with value 0");
_enumLocalizer.GetString<BookType>(1).ShouldBe("Adventure with value 1");
_enumLocalizer.GetString<BookType>(BookType.Biography).ShouldBe("Biography");
var specifyLocalizer = new[]
{
GetRequiredService<IStringLocalizerFactory>().Create<LocalizationTestValidationResource>()
};
_enumLocalizer.GetString<BookType>(BookType.Undefined, specifyLocalizer).ShouldBe("Undefined from ValidationResource");
_enumLocalizer.GetString<BookType>(BookType.Adventure, specifyLocalizer).ShouldBe("Adventure from ValidationResource");
_enumLocalizer.GetString<BookType>(0, specifyLocalizer).ShouldBe("Undefined with value 0 from ValidationResource");
_enumLocalizer.GetString<BookType>(1, specifyLocalizer).ShouldBe("Adventure with value 1 from ValidationResource");
_enumLocalizer.GetString<BookType>(BookType.Biography, specifyLocalizer).ShouldBe("Biography from ValidationResource");
}
}
}
enum BookType
{
Undefined,
Adventure,
Biography,
}

6
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalizationTestModule.cs

@ -19,6 +19,8 @@ public class AbpLocalizationTestModule : AbpModule
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.DefaultResourceType = typeof(LocalizationTestResource);
options.Resources options.Resources
.Add<LocalizationTestValidationResource>("en") .Add<LocalizationTestValidationResource>("en")
.AddVirtualJson("/Volo/Abp/Localization/TestResources/Base/Validation"); .AddVirtualJson("/Volo/Abp/Localization/TestResources/Base/Validation");
@ -35,8 +37,8 @@ public class AbpLocalizationTestModule : AbpModule
options.Resources options.Resources
.Get<LocalizationTestResource>() .Get<LocalizationTestResource>()
.AddVirtualJson("/Volo/Abp/Localization/TestResources/SourceExt"); .AddVirtualJson("/Volo/Abp/Localization/TestResources/SourceExt");
options.GlobalContributors.Add<TestExternalLocalizationContributor>(); options.GlobalContributors.Add<TestExternalLocalizationContributor>();
}); });
} }
} }

9
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/en.json

@ -2,6 +2,11 @@
"culture": "en", "culture": "en",
"texts": { "texts": {
"ThisFieldIsRequired": "This field is required", "ThisFieldIsRequired": "This field is required",
"MaxLenghtErrorMessage": "This field can be maximum of '{0}' chars" "MaxLenghtErrorMessage": "This field can be maximum of '{0}' chars",
"Enum:BookType.Undefined": "Undefined from ValidationResource",
"Enum:BookType.0": "Undefined with value 0 from ValidationResource",
"BookType.Adventure": "Adventure from ValidationResource",
"BookType.1": "Adventure with value 1 from ValidationResource",
"Biography": "Biography from ValidationResource"
} }
} }

9
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json

@ -6,6 +6,11 @@
"CarPlural": "Cars", "CarPlural": "Cars",
"MaxLenghtErrorMessage": "This field's length can be maximum of '{0}' chars", "MaxLenghtErrorMessage": "This field's length can be maximum of '{0}' chars",
"Universe": "Universe", "Universe": "Universe",
"FortyTwo": "Forty Two" "FortyTwo": "Forty Two",
"Enum:BookType.Undefined": "Undefined",
"Enum:BookType.0": "Undefined with value 0",
"BookType.Adventure": "Adventure",
"BookType.1": "Adventure with value 1",
"Biography": "Biography"
} }
} }

Loading…
Cancel
Save