Skip to content

Commit cd29af7

Browse files
committed
add basic serverside localisation
1 parent 76e7026 commit cd29af7

9 files changed

Lines changed: 773 additions & 321 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Microsoft.AspNetCore.Builder;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Microsoft.Extensions.Logging;
8+
using NetEvent.Server.Data;
9+
using NetEvent.Server.Models;
10+
using NetEvent.Shared;
11+
using NetEvent.Shared.Config;
12+
13+
namespace NetEvent.Server.Extensions;
14+
15+
public static class DefaultCultureExtension
16+
{
17+
public static Task SetDefaultCulture(this WebApplication app)
18+
{
19+
var logger = app.Services.GetRequiredService<ILogger<WebApplication>>();
20+
21+
try
22+
{
23+
using (var scope = app.Services.GetRequiredService<IServiceScopeFactory>().CreateScope())
24+
{
25+
using (var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>())
26+
{
27+
var organizationCulture = context.Set<SystemSettingValue>().Select(x => DtoMapper.Mapper.SystemSettingValueToSystemSettingValueDto(x)).ToList().Find(x => x.Key.Equals(SystemSettings.DataCultureInfo));
28+
29+
if (organizationCulture == null)
30+
{
31+
return Task.CompletedTask;
32+
}
33+
34+
var culture = organizationCulture.Value;
35+
36+
var cultureInfo = new CultureInfo(culture);
37+
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
38+
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
39+
}
40+
}
41+
}
42+
catch (Exception ex)
43+
{
44+
logger.LogError(ex, "Unable to get Culture");
45+
}
46+
47+
return Task.CompletedTask;
48+
}
49+
}

NetEvent/Server/Localize.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace NetEvent.Server
2+
{
3+
public class Localize
4+
{
5+
}
6+
}
Lines changed: 82 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,82 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Reflection;
4-
using System.Threading;
5-
using System.Threading.Tasks;
6-
using MediatR;
7-
using NetEvent.Shared.Dto;
8-
9-
namespace NetEvent.Server.Modules.System.Endpoints
10-
{
11-
public static class GetSystemInfo
12-
{
13-
public sealed class Handler : IRequestHandler<Request, Response>
14-
{
15-
public Handler()
16-
{
17-
}
18-
19-
public Task<Response> Handle(Request request, CancellationToken cancellationToken)
20-
{
21-
var systeminfocomponents = new List<SystemInfoComponentEntryDto>();
22-
var systeminfohealth = new List<SystemInfoHealthEntryDto>();
23-
var systeminfoversions = new List<SystemInfoVersionEntryDto>();
24-
25-
AppDomain currentDomain = AppDomain.CurrentDomain;
26-
Assembly[] assems = currentDomain.GetAssemblies();
27-
foreach (Assembly assem in assems)
28-
{
29-
systeminfocomponents.Add(new SystemInfoComponentEntryDto(assem.ManifestModule.Name, assem.ToString()));
30-
}
31-
32-
systeminfoversions.Add(new SystemInfoVersionEntryDto("NETEVENT", Assembly.GetEntryAssembly()?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion));
33-
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDNODE"));
34-
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDID"));
35-
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDNUMBER"));
36-
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("SOURCE_COMMIT"));
37-
38-
// TODO: think about healthchecks and healthcheck modularity (to perform checks on various services like game servers, the mail server, payment apis ...) and remove dummy services
39-
systeminfohealth.Add(new SystemInfoHealthEntryDto("NETEVENT Server", string.Empty, true));
40-
systeminfohealth.Add(new SystemInfoHealthEntryDto("Email Service", "servername", false));
41-
42-
var systeminfo = new SystemInfoDto(systeminfocomponents, systeminfohealth, systeminfoversions);
43-
44-
return Task.FromResult(new Response(systeminfo));
45-
}
46-
47-
private static SystemInfoVersionEntryDto CreateSystemInfoVersionEntryFromEnv(string envName)
48-
{
49-
return new SystemInfoVersionEntryDto(envName, string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName)) ? "dev" : Environment.GetEnvironmentVariable(envName));
50-
}
51-
}
52-
53-
public sealed class Request : IRequest<Response>
54-
{
55-
public Request()
56-
{
57-
}
58-
}
59-
60-
public sealed class Response : ResponseBase<SystemInfoDto>
61-
{
62-
public Response(SystemInfoDto value) : base(value)
63-
{
64-
}
65-
66-
public Response(ReturnType returnType, string error) : base(returnType, error)
67-
{
68-
}
69-
}
70-
}
71-
}
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using MediatR;
7+
using NetEvent.Shared.Dto;
8+
using Microsoft.AspNetCore.Components;
9+
using Microsoft.Extensions.Localization;
10+
using NetEvent.Server;
11+
12+
namespace NetEvent.Server.Modules.System.Endpoints
13+
{
14+
public static class GetSystemInfo
15+
{
16+
public sealed class Handler : IRequestHandler<Request, Response>
17+
{
18+
// TODO: remove localizer as soon as it is implemented somewhere where it makes sense
19+
private IStringLocalizer<Localize> _Localizer { get; set; }
20+
21+
// TODO: remove localizer as soon as it is implemented somewhere where it makes sense
22+
public Handler(IStringLocalizer<Localize> localizer)
23+
{
24+
_Localizer = localizer;
25+
}
26+
27+
public Task<Response> Handle(Request request, CancellationToken cancellationToken)
28+
{
29+
var systeminfocomponents = new List<SystemInfoComponentEntryDto>();
30+
var systeminfohealth = new List<SystemInfoHealthEntryDto>();
31+
var systeminfoversions = new List<SystemInfoVersionEntryDto>();
32+
33+
AppDomain currentDomain = AppDomain.CurrentDomain;
34+
Assembly[] assems = currentDomain.GetAssemblies();
35+
foreach (Assembly assem in assems)
36+
{
37+
systeminfocomponents.Add(new SystemInfoComponentEntryDto(assem.ManifestModule.Name, assem.ToString()));
38+
}
39+
40+
systeminfoversions.Add(new SystemInfoVersionEntryDto("NETEVENT", Assembly.GetEntryAssembly()?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion));
41+
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDNODE"));
42+
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDID"));
43+
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("BUILDNUMBER"));
44+
systeminfoversions.Add(CreateSystemInfoVersionEntryFromEnv("SOURCE_COMMIT"));
45+
46+
// TODO: think about healthchecks and healthcheck modularity (to perform checks on various services like game servers, the mail server, payment apis ...) and remove dummy services
47+
systeminfohealth.Add(new SystemInfoHealthEntryDto("NETEVENT Server", string.Empty, true));
48+
systeminfohealth.Add(new SystemInfoHealthEntryDto("Email Service", "servername", false));
49+
50+
var systeminfo = new SystemInfoDto(systeminfocomponents, systeminfohealth, systeminfoversions);
51+
52+
// TODO: remove localizer as soon as it is implemented somewhere where it makes sense
53+
Console.WriteLine(_Localizer["test.test"]);
54+
55+
return Task.FromResult(new Response(systeminfo));
56+
}
57+
58+
private static SystemInfoVersionEntryDto CreateSystemInfoVersionEntryFromEnv(string envName)
59+
{
60+
return new SystemInfoVersionEntryDto(envName, string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName)) ? "dev" : Environment.GetEnvironmentVariable(envName));
61+
}
62+
}
63+
64+
public sealed class Request : IRequest<Response>
65+
{
66+
public Request()
67+
{
68+
}
69+
}
70+
71+
public sealed class Response : ResponseBase<SystemInfoDto>
72+
{
73+
public Response(SystemInfoDto value) : base(value)
74+
{
75+
}
76+
77+
public Response(ReturnType returnType, string error) : base(returnType, error)
78+
{
79+
}
80+
}
81+
}
82+
}
Lines changed: 80 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,80 @@
1-
using System.Threading;
2-
using System.Threading.Tasks;
3-
using MediatR;
4-
using NetEvent.Server.Data;
5-
using NetEvent.Server.Models;
6-
using NetEvent.Shared;
7-
using NetEvent.Shared.Config;
8-
using NetEvent.Shared.Dto;
9-
10-
namespace NetEvent.Server.Modules.System.Endpoints
11-
{
12-
public static class PostSystemSetting
13-
{
14-
public sealed class Handler : IRequestHandler<Request, Response>
15-
{
16-
private readonly ApplicationDbContext _ApplicationDbContext;
17-
18-
public Handler(ApplicationDbContext applicationDbContext)
19-
{
20-
_ApplicationDbContext = applicationDbContext;
21-
}
22-
23-
public async Task<Response> Handle(Request request, CancellationToken cancellationToken)
24-
{
25-
if (request.SystemSettingValue?.Key == null)
26-
{
27-
return new Response(ReturnType.Error, "Empty key is not allowed");
28-
}
29-
30-
var data = await _ApplicationDbContext.FindAsync<SystemSettingValue>(new object[] { request.SystemSettingValue.Key }, cancellationToken);
31-
if (data != null)
32-
{
33-
data.SerializedValue = request.SystemSettingValue.Value;
34-
}
35-
else
36-
{
37-
var serverData = request.SystemSettingValue.ToSystemSettingValue();
38-
await _ApplicationDbContext.AddAsync(serverData, cancellationToken);
39-
}
40-
41-
await _ApplicationDbContext.SaveChangesAsync(cancellationToken);
42-
43-
return new Response();
44-
}
45-
}
46-
47-
public sealed class Request : IRequest<Response>
48-
{
49-
public Request(SystemSettingGroup systemSettingGroup, SystemSettingValueDto systemSettingValue)
50-
{
51-
SystemSettingGroup = systemSettingGroup;
52-
SystemSettingValue = systemSettingValue;
53-
}
54-
55-
public SystemSettingGroup SystemSettingGroup { get; }
56-
57-
public SystemSettingValueDto SystemSettingValue { get; }
58-
}
59-
60-
public sealed class Response : ResponseBase
61-
{
62-
public Response()
63-
{
64-
}
65-
66-
public Response(ReturnType returnType, string error) : base(returnType, error)
67-
{
68-
}
69-
}
70-
}
71-
}
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using MediatR;
4+
using NetEvent.Server.Data;
5+
using NetEvent.Server.Models;
6+
using NetEvent.Shared;
7+
using NetEvent.Shared.Config;
8+
using NetEvent.Shared.Dto;
9+
using System.Globalization;
10+
11+
namespace NetEvent.Server.Modules.System.Endpoints
12+
{
13+
public static class PostSystemSetting
14+
{
15+
public sealed class Handler : IRequestHandler<Request, Response>
16+
{
17+
private readonly ApplicationDbContext _ApplicationDbContext;
18+
19+
public Handler(ApplicationDbContext applicationDbContext)
20+
{
21+
_ApplicationDbContext = applicationDbContext;
22+
}
23+
24+
public async Task<Response> Handle(Request request, CancellationToken cancellationToken)
25+
{
26+
if (request.SystemSettingValue?.Key == null)
27+
{
28+
return new Response(ReturnType.Error, "Empty key is not allowed");
29+
}
30+
31+
var data = await _ApplicationDbContext.FindAsync<SystemSettingValue>(new object[] { request.SystemSettingValue.Key }, cancellationToken);
32+
if (data != null)
33+
{
34+
data.SerializedValue = request.SystemSettingValue.Value;
35+
}
36+
else
37+
{
38+
var serverData = request.SystemSettingValue.ToSystemSettingValue();
39+
await _ApplicationDbContext.AddAsync(serverData, cancellationToken);
40+
}
41+
42+
await _ApplicationDbContext.SaveChangesAsync(cancellationToken);
43+
44+
// TODO: move special serverside handling to service
45+
if (request.SystemSettingValue?.Key == SystemSettings.OrganizationData.DataCultureInfo)
46+
{
47+
var cultureInfo = new CultureInfo(request.SystemSettingValue.Value);
48+
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
49+
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
50+
}
51+
52+
return new Response();
53+
}
54+
}
55+
56+
public sealed class Request : IRequest<Response>
57+
{
58+
public Request(SystemSettingGroup systemSettingGroup, SystemSettingValueDto systemSettingValue)
59+
{
60+
SystemSettingGroup = systemSettingGroup;
61+
SystemSettingValue = systemSettingValue;
62+
}
63+
64+
public SystemSettingGroup SystemSettingGroup { get; }
65+
66+
public SystemSettingValueDto SystemSettingValue { get; }
67+
}
68+
69+
public sealed class Response : ResponseBase
70+
{
71+
public Response()
72+
{
73+
}
74+
75+
public Response(ReturnType returnType, string error) : base(returnType, error)
76+
{
77+
}
78+
}
79+
}
80+
}

NetEvent/Server/NetEvent.Server.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,10 @@
5252
<Folder Include="Migrations\" />
5353
</ItemGroup>
5454

55+
<ItemGroup>
56+
<EmbeddedResource Update="Resources\Localize.resx">
57+
<SubType>Designer</SubType>
58+
</EmbeddedResource>
59+
</ItemGroup>
60+
5561
</Project>

0 commit comments

Comments
 (0)