Skip to content

Commit 52aaa75

Browse files
committed
feat(I18n): Support I18N
1 parent 8f3fbaa commit 52aaa75

File tree

45 files changed

+428
-101
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+428
-101
lines changed

src/BuildingBlocks/Data/Masa.BuildingBlocks.Data/Constants/ErrorCode.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ static ErrorCode()
236236
{
237237
var errorMessage = AttributeUtils.GetDescriptionByField(field);
238238

239-
_errorCodeMessageDictionary.Add(field.GetRawConstantValue()!.ToString(), errorMessage);
239+
_errorCodeMessageDictionary.Add(field.GetRawConstantValue()!.ToString()!, errorMessage);
240240
}
241241
}
242242

src/BuildingBlocks/Globalization/Masa.BuildingBlocks.Globalization.I18N/CultureModel.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ public class CultureModel
77
{
88
public string Culture { get; set; }
99

10-
public string DisplayName { get; set; }
10+
public string? DisplayName { get; set; }
1111

1212
public string Icon { get; set; }
1313

14-
public CultureModel(string culture, string displayName, string? icon = null)
14+
public CultureModel(string culture, string? displayName = null, string? icon = null)
1515
{
1616
Culture = culture;
1717
DisplayName = displayName;

src/BuildingBlocks/Globalization/Masa.BuildingBlocks.Globalization.I18N/DefaultLanguageProvider.cs

+15-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ public class DefaultLanguageProvider : ILanguageProvider
88
private readonly II18N<MasaLanguageResource> _i18N;
99
private readonly IOptions<CultureSettings> _options;
1010

11+
private static Dictionary<string, string> _languages = new()
12+
{
13+
{ "en-US", "English (United States)" },
14+
{ "zh-CN", "中文 (简体)" }
15+
};
16+
1117
public DefaultLanguageProvider(II18N<MasaLanguageResource> i18N, IOptions<CultureSettings> options)
1218
{
1319
_i18N = i18N;
@@ -24,7 +30,7 @@ public IReadOnlyList<LanguageInfo> GetLanguages()
2430
nameof(LanguageInfo.UIDisplayName) :
2531
$"{culture.Culture}\\.{nameof(LanguageInfo.UIDisplayName)}";
2632
var uiDisplayName = _i18N.T(key);
27-
var languageInfo = new LanguageInfo(culture.Culture, culture.DisplayName, culture.Icon)
33+
var languageInfo = new LanguageInfo(culture.Culture, culture.DisplayName ?? GetDisplayName(cultureName), culture.Icon)
2834
{
2935
UIDisplayName = uiDisplayName
3036
};
@@ -33,4 +39,12 @@ public IReadOnlyList<LanguageInfo> GetLanguages()
3339
});
3440
return list;
3541
}
42+
43+
private static string GetDisplayName(string cultureName)
44+
{
45+
if (_languages.TryGetValue(cultureName, out string? displayName))
46+
return displayName;
47+
48+
return string.Empty;
49+
}
3650
}

src/BuildingBlocks/Globalization/Masa.BuildingBlocks.Globalization.I18N/I18N.cs

+5
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ public static class I18N
77
{
88
private static readonly IServiceProvider _serviceProvider = MasaApp.RootServiceProvider;
99
private static readonly II18N _i18N = InitI18N();
10+
private static readonly ILanguageProvider _languageProvider = InitLanguage();
1011

1112
static II18N InitI18N() => _serviceProvider.GetRequiredService<II18N>();
1213

14+
static ILanguageProvider InitLanguage() => _serviceProvider.GetRequiredService<ILanguageProvider>();
15+
1316
/// <summary>
1417
/// Gets the string resource with the given name.
1518
/// </summary>
@@ -77,4 +80,6 @@ public static class I18N
7780
/// </summary>
7881
/// <param name="culture"></param>
7982
public static void SetUiCulture(CultureInfo culture) => _i18N.SetUiCulture(culture);
83+
84+
public static IReadOnlyList<LanguageInfo> GetLanguages() => _languageProvider.GetLanguages();
8085
}

src/BuildingBlocks/Globalization/Masa.BuildingBlocks.Globalization.I18N/I18NResource.cs

+14-2
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ public class I18NResource
99

1010
public Type ResourceType { get; }
1111

12-
public IEnumerable<Type> BaseResourceTypes { get; }
12+
public List<Type> BaseResourceTypes { get; private set; }
1313

1414
public IEnumerable<Assembly> Assemblies { get; set; } = new List<Assembly>();
1515

1616
public I18NResource(Type resourceType, IEnumerable<Type> baseResourceTypes)
1717
{
1818
_dictionary = new(StringComparer.OrdinalIgnoreCase);
1919
ResourceType = resourceType;
20-
BaseResourceTypes = baseResourceTypes;
20+
BaseResourceTypes = baseResourceTypes.ToList();
2121
}
2222

2323
public void AddContributor(string cultureName, II18NResourceContributor localizationResourceContributor)
@@ -37,4 +37,16 @@ public void AddContributor(string cultureName, II18NResourceContributor localiza
3737

3838
return null;
3939
}
40+
41+
public void TryAddBaseResourceTypes<TBaseResourceType>() where TBaseResourceType : class
42+
=> TryAddBaseResourceTypes(typeof(TBaseResourceType));
43+
44+
public void TryAddBaseResourceTypes(params Type[] resourceTypes)
45+
{
46+
foreach (var type in resourceTypes)
47+
{
48+
if (!BaseResourceTypes.Contains(type))
49+
BaseResourceTypes.Add(type);
50+
}
51+
}
4052
}

src/Contrib/Dispatcher/Masa.Contrib.Dispatcher.Events.FluentValidation/Middleware/ValidatorMiddleware.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ namespace Masa.Contrib.Dispatcher.Events;
88
public class ValidatorMiddleware<TEvent> : Middleware<TEvent>
99
where TEvent : IEvent
1010
{
11-
private readonly ILogger<ValidatorMiddleware<TEvent>> _logger;
11+
private readonly ILogger<ValidatorMiddleware<TEvent>>? _logger;
1212
private readonly IEnumerable<IValidator<TEvent>> _validators;
1313

14-
public ValidatorMiddleware(IEnumerable<IValidator<TEvent>> validators, ILogger<ValidatorMiddleware<TEvent>> logger)
14+
public ValidatorMiddleware(IEnumerable<IValidator<TEvent>> validators, ILogger<ValidatorMiddleware<TEvent>>? logger = null)
1515
{
1616
_validators = validators;
1717
_logger = logger;
@@ -21,7 +21,7 @@ public override async Task HandleAsync(TEvent @event, EventHandlerDelegate next)
2121
{
2222
var typeName = @event.GetType().FullName;
2323

24-
_logger.LogDebug("----- Validating command {CommandType}", typeName);
24+
_logger?.LogDebug("----- Validating command {CommandType}", typeName);
2525

2626
var failures = _validators
2727
.Select(v => v.Validate(@event))
@@ -31,7 +31,7 @@ public override async Task HandleAsync(TEvent @event, EventHandlerDelegate next)
3131

3232
if (failures.Any())
3333
{
34-
_logger.LogError("Validation errors - {CommandType} - Event: {@Command} - Errors: {@ValidationErrors}",
34+
_logger?.LogError("Validation errors - {CommandType} - Event: {@Command} - Errors: {@ValidationErrors}",
3535
typeName,
3636
@event,
3737
failures);

src/Contrib/Exception/Masa.Contrib.Exceptions/Extensions/ApplicationBuilderExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace Microsoft.AspNetCore.Builder;
77

8+
[ExcludeFromCodeCoverage]
89
public static class ApplicationBuilderExtensions
910
{
1011
/// <summary>

src/Contrib/Exception/Masa.Contrib.Exceptions/Extensions/MvcBuilderExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace Microsoft.Extensions.DependencyInjection;
77

8+
[ExcludeFromCodeCoverage]
89
public static class MvcBuilderExtensions
910
{
1011
public static IMvcBuilder AddMasaExceptionHandler(this IMvcBuilder builder)

src/Contrib/Exception/Masa.Contrib.Exceptions/Handlers/ExceptionHandlerMiddleware.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace Microsoft.AspNetCore.Builder;
77

8+
[ExcludeFromCodeCoverage]
89
public class ExceptionHandlerMiddleware
910
{
1011
private readonly RequestDelegate _next;

src/Contrib/Exception/Masa.Contrib.Exceptions/Handlers/MvcGlobalExceptionFilter.cs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters;
88
/// <summary>
99
/// Mvc pipeline exception filter to catch global exception
1010
/// </summary>
11+
[ExcludeFromCodeCoverage]
1112
public class MvcGlobalExceptionFilter : IExceptionFilter
1213
{
1314
private readonly IServiceProvider _serviceProvider;

src/Contrib/Exception/Masa.Contrib.Exceptions/Internal/Constant.cs

-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,4 @@ namespace Masa.Contrib.Exceptions.Internal;
66
internal static class Constant
77
{
88
public const string DEFAULT_HTTP_CONTENT_TYPE = "text/plain; charset=utf-8";
9-
10-
// public const string DEFAULT_EXCEPTION_MESSAGE = "An error occur in masa framework.";
119
}

src/Contrib/Exception/Masa.Contrib.Exceptions/Internal/ExceptionExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace Masa.Contrib.Exceptions.Internal;
55

6+
[ExcludeFromCodeCoverage]
67
internal static class ExceptionExtensions
78
{
89
public static int GetHttpStatusCode(this Exception exception)

src/Contrib/Exception/Masa.Contrib.Exceptions/Internal/HttpResponseExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace Masa.Contrib.Exceptions.Internal;
55

6+
[ExcludeFromCodeCoverage]
67
internal static class HttpResponseExtensions
78
{
89
/// <summary>

src/Contrib/Exception/Masa.Contrib.Exceptions/Internal/LoggerExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace System;
77

8+
[ExcludeFromCodeCoverage]
89
internal static class LoggerExtensions
910
{
1011
public static void WriteLog(

src/Contrib/Exception/Masa.Contrib.Exceptions/Internal/ServiceProviderExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace Masa.Contrib.Exceptions.Internal;
55

6+
[ExcludeFromCodeCoverage]
67
internal static class ServiceProviderExtensions
78
{
89
public static IMasaExceptionHandler? GetMasaExceptionHandler(this IServiceProvider serviceProvider, Type? masaExceptionHandlerType)

src/Contrib/Exception/Masa.Contrib.Exceptions/MasaExceptionContext.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace System;
77

8+
[ExcludeFromCodeCoverage]
89
public class MasaExceptionContext
910
{
1011
public IServiceProvider ServiceProvider { get; set; }

src/Contrib/Exception/Masa.Contrib.Exceptions/Options/MasaExceptionHandlerOptions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace System;
77

8+
[ExcludeFromCodeCoverage]
89
public class MasaExceptionHandlerOptions
910
{
1011
public bool CatchAllException { get; set; } = true;

src/Contrib/Exception/Masa.Contrib.Exceptions/Options/MasaExceptionLogRelationOptions.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55

66
namespace System;
77

8+
[ExcludeFromCodeCoverage]
89
public class MasaExceptionLogRelationOptions
910
{
10-
internal Dictionary<Type, LogLevel> Mappings { get; } = new();
11+
private Dictionary<Type, LogLevel> Mappings { get; } = new();
1112

1213
public MasaExceptionLogRelationOptions MapLogLevel<TException>(LogLevel logLevel) where TException : Exception
1314
{

src/Contrib/Exception/Masa.Contrib.Exceptions/Results/DefaultExceptionResult.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace Microsoft.AspNetCore.Mvc;
77

8+
[ExcludeFromCodeCoverage]
89
public class DefaultExceptionResult : IActionResult
910
{
1011
public string Message { get; set; }

src/Contrib/Exception/Masa.Contrib.Exceptions/Results/InternalServerErrorObjectResult.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace Microsoft.AspNetCore.Mvc;
77

8+
[ExcludeFromCodeCoverage]
89
public class InternalServerErrorObjectResult : ObjectResult
910
{
1011
public InternalServerErrorObjectResult(object obj)

src/Contrib/Exception/Masa.Contrib.Exceptions/Results/UserFriendlyExceptionResult.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace Microsoft.AspNetCore.Mvc;
77

8+
[ExcludeFromCodeCoverage]
89
public class UserFriendlyExceptionResult : IActionResult
910
{
1011
public string Message { get; set; }

src/Contrib/Exception/Masa.Contrib.Exceptions/_Imports.cs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
global using Microsoft.Extensions.DependencyInjection;
1111
global using Microsoft.Extensions.Logging;
1212
global using Microsoft.Extensions.Options;
13+
global using System.Diagnostics.CodeAnalysis;
1314
global using System.Net;
1415
global using System.Reflection;
1516
global using System.Text;

src/Contrib/Globalization/Masa.Contrib.Globalization.I18N.AspNetCore/Extensions/ApplicationBuilderExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace Microsoft.AspNetCore.Builder;
77

8+
[ExcludeFromCodeCoverage]
89
public static class ApplicationBuilderExtensions
910
{
1011
private static bool _isInitialize;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
[](README.zh-CN.md) | EN
2+
3+
Provides the ability to parse and obtain Culture, and use it with [I18N](../Masa.Contrib.Globalization.I18N/README.md). Currently, there are three ways to switch languages:
4+
5+
* URL parameter method: ?culture=en-US, this method has the highest priority, the format is: culture=region code
6+
* Cookies method: call L.SetCulture (region code) method to switch
7+
* Client browser language automatic matching: If neither of the previous two methods are set, it supports automatic matching according to the client browser language.
8+
9+
## Masa.Contrib.Globalization.I18N.AspNetCore
10+
11+
Example:
12+
13+
``` powershell
14+
Install-Package Masa.Contrib.Globalization.I18N.AspNetCore
15+
```
16+
17+
### getting Started
18+
19+
1. Default resource folder structure
20+
21+
``` structure
22+
- Resources
23+
- I18n
24+
- en-US.json
25+
- zh-CN.json
26+
- supportedCultures.json
27+
```
28+
29+
* en-US.json
30+
31+
``` en-US.json
32+
{
33+
"Home":"Home",
34+
"Docs":"Docs",
35+
"Blog":"Blog",
36+
"Team":"Team",
37+
"Search":"Search"
38+
"User":{
39+
"Name":"Name"
40+
}
41+
}
42+
```
43+
44+
* zh-CN.json
45+
46+
``` zh-CN.json
47+
{
48+
"Home":"Home",
49+
"Docs":"Documents",
50+
"Blog":"Blog",
51+
"Team":"Team",
52+
"Search":"Search",
53+
"User":{
54+
"Name":"Name"
55+
}
56+
}
57+
```
58+
59+
* supportedCultures.json
60+
61+
``` supportedCultures.json
62+
[
63+
{
64+
"Culture":"zh-CN",
65+
"DisplayName":"Simplified Chinese",
66+
"Icon": "{Replace-Your-Icon}"
67+
},
68+
{
69+
"Culture":"en-US",
70+
"DisplayName":"English (United States)",
71+
"Icon": "{Replace-Your-Icon}"
72+
}
73+
]
74+
```
75+
76+
2. Register to use I18N, modify `Program.cs`
77+
78+
``` C#
79+
services.AddI18N();
80+
```
81+
82+
3. Use `Masa.Contrib.Globalization.I18N.AspNetCore` to provide the ability to parse Culture
83+
84+
``` C#
85+
app.UseI18N();
86+
```
87+
88+
4. How to use I18N
89+
90+
* Get `II18N` from DI (**II18N** is the interface, supports getting from DI)
91+
* Use `I18N` (**I18N** is a static class)
92+
93+
Take `I18N` as an example:
94+
95+
```` C#
96+
var home = I18N.T("Home"); //Get the value of the language corresponding to the key value Home, this method call will return "Home";
97+
var name = I18N.T("User.Name");//Output: name (support nesting)
98+
````

0 commit comments

Comments
 (0)