Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"hi": "Hallo",
"welcome": "Willkommen {0}, wie geht es dir?"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"hi": "Hello",
"welcome": "Welcome {0}, How are you?"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using uBeac.Localization;
using uBeac.Web;

namespace Identity.MongoDB.API.Controllers;

public class LocalizationController : BaseController
{
private readonly IStringLocalizer _localizer;
private readonly ILocalizationService _localizationService;

public LocalizationController(IStringLocalizer localizer, ILocalizationService localizationService)
{
_localizer = localizer;
_localizationService = localizationService;
}

[HttpGet]
public IResult<string> Test(string name = "Hesam")
{
return $"{_localizer["hi"]} {_localizer["welcome", name]}"
.ToResult();
}

[HttpPost]
public async Task Upsert(LocalizationValue value)
{
await _localizationService.Upsert(value);
}

[HttpPost]
public async Task Delete(string key, string cultureName)
{
await _localizationService.Delete(key, cultureName);
}
}
2 changes: 2 additions & 0 deletions src/Examples/Identity.MongoDB.API/Identity.MongoDB.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
<ItemGroup>
<ProjectReference Include="..\..\Common\uBeac.Core.Common\uBeac.Core.Common.csproj" />
<ProjectReference Include="..\..\Common\uBeac.Core.Configuration\uBeac.Core.Configuration.csproj" />
<ProjectReference Include="..\..\Localization\uBeac.Core.Localization.Repositories.Json\uBeac.Core.Localization.Repositories.Json.csproj" />
<ProjectReference Include="..\..\Localization\uBeac.Core.Localization\uBeac.Core.Localization.csproj" />
<ProjectReference Include="..\..\Logging\uBeac.Core.Web.Logging.MongoDB\uBeac.Core.Web.Logging.MongoDB.csproj" />
<ProjectReference Include="..\..\Repository\uBeac.Core.Repositories.History.Extensions\uBeac.Core.Repositories.History.Extensions.csproj" />
<ProjectReference Include="..\..\Repository\uBeac.Core.Repositories.History.MongoDB\uBeac.Core.Repositories.History.MongoDB.csproj" />
Expand Down
9 changes: 9 additions & 0 deletions src/Examples/Identity.MongoDB.API/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using uBeac.Localization;
using uBeac.Repositories.History.MongoDB;
using uBeac.Repositories.MongoDB;
using uBeac.Web;
Expand All @@ -17,6 +18,7 @@
// Adding http logging
builder.Services.AddMongoDbHttpLogging<HttpLogMongoDBContext>("HttpLoggingConnection", builder.Configuration.GetInstance<MongoDbHttpLogOptions>("HttpLogging"));

builder.Services.AddMemoryCache();
builder.Services.AddHttpContextAccessor();
builder.Services.AddControllers();
builder.Services.AddAutoMapper(Assembly.GetExecutingAssembly());
Expand All @@ -43,6 +45,13 @@
builder.Services.AddMongo<HistoryMongoDBContext>("HistoryConnection");
builder.Services.AddHistory<MongoDBHistoryRepository>().For<User>();

// Adding localization
builder.Services.AddCustomLocalization(localization =>
{
localization.UseJsonFiles();
localization.UseInMemoryCaching();
});

// Adding CORS
var corsPolicyOptions = builder.Configuration.GetSection("CorsPolicy");
builder.Services.AddCorsPolicy(corsPolicyOptions);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace uBeac.Localization;

public class LocalizationValue : Entity
{
public string Key { get; set; } // "welcome-message"
public string Value { get; set; } // "Welcome to uBeac!"
public string CultureName { get; set; } // "en-US"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace uBeac.Localization;

public interface ILocalizationBuilder
{
ILocalizationBuilder SetRepository(Type repositoryType);
ILocalizationBuilder SetService(Type serviceType);
ILocalizationBuilder SetCachingService(Type cachingServiceType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using uBeac.Services;

namespace uBeac.Localization;

public interface ILocalizationCachingService : IService
{
void AddRange(IEnumerable<LocalizationValue> values);

IEnumerable<LocalizationValue> GetAll();

void Clear();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using uBeac.Repositories;

namespace uBeac.Localization;

public interface ILocalizationRepository : IRepository
{
Task<IEnumerable<LocalizationValue>> GetAll(CancellationToken cancellationToken = default);

Task Upsert(LocalizationValue entity, CancellationToken cancellationToken = default);

Task Delete(string key, string cultureName, CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using uBeac.Services;

namespace uBeac.Localization;

public interface ILocalizationService : IService
{
Task<IEnumerable<LocalizationValue>> GetAllByCultureName(string cultureName, CancellationToken cancellationToken = default);

Task<bool> ExistsValue(string key, string cultureName, CancellationToken cancellationToken = default);

Task<LocalizationValue> GetValue(string key, string cultureName, CancellationToken cancellationToken = default);

Task Upsert(LocalizationValue entity, CancellationToken cancellationToken = default);

Task Delete(string key, string cultureName, CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Common\uBeac.Core.Common\uBeac.Core.Common.csproj" />
<ProjectReference Include="..\..\Repository\uBeac.Core.Repositories.Abstractions\uBeac.Core.Repositories.Abstractions.csproj" />
<ProjectReference Include="..\..\Service\uBeac.Core.Services.Abstractions\uBeac.Core.Services.Abstractions.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using uBeac.Localization.Repositories.Json;

namespace uBeac.Localization;

public static class BuilderExtensions
{
public static ILocalizationBuilder UseJsonFiles(this ILocalizationBuilder builder)
{
builder.SetRepository(typeof(JsonLocalizationRepository));

return builder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace uBeac.Localization.Repositories.Json;

public class JsonLocalizationOptions
{
public string FolderName { get; set; } = "Config\\Localization";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System.Text;
using Newtonsoft.Json;

namespace uBeac.Localization.Repositories.Json;

public interface IJsonLocalizationRepository : ILocalizationRepository
{
}

public class JsonLocalizationRepository : IJsonLocalizationRepository
{
protected readonly string ContentRootPath;
protected readonly JsonLocalizationOptions Options;

protected readonly JsonSerializerSettings SerializerSettings = new();

protected readonly string DirectoryPath;

public JsonLocalizationRepository(string contentRootPath = null, JsonLocalizationOptions options = null)
{
ContentRootPath = contentRootPath ?? Environment.CurrentDirectory;
Options = options ?? new JsonLocalizationOptions();

DirectoryPath = Path.Combine(ContentRootPath, Options.FolderName);
}

public async Task<IEnumerable<LocalizationValue>> GetAll(CancellationToken cancellationToken = default)
{
var result = new List<LocalizationValue>();

foreach (var file in Directory.GetFiles(DirectoryPath))
{
if (Path.GetExtension(file) != ".json") continue;

var cultureName = Path.GetFileNameWithoutExtension(file);
var dictionary = ReadDictionaryFromCultureFile(cultureName);
var values = MapDictionaryToLocalizationValues(cultureName, dictionary);

result.AddRange(values);
}

return await Task.FromResult(result);
}

public Task Upsert(LocalizationValue entity, CancellationToken cancellationToken = default)
{
var values = ReadDictionaryFromCultureFile(entity.CultureName);

TryRemove(values, entity.Key);

values.Add(entity.Key, entity.Value);

WriteValuesToCultureFile(entity.CultureName, values);

return Task.CompletedTask;
}

public Task Delete(string key, string cultureName, CancellationToken cancellationToken = default)
{
var values = ReadDictionaryFromCultureFile(cultureName);

TryRemove(values, key);

WriteValuesToCultureFile(cultureName, values);

return Task.CompletedTask;
}

public string GetCultureFilePath(string cultureName) => Path.Combine(DirectoryPath, $"{cultureName}.json");

public IDictionary<string, string> ReadDictionaryFromCultureFile(string cultureName)
{
var file = GetCultureFilePath(cultureName);
var fileContent = File.ReadAllText(file, Encoding.UTF8);
return JsonConvert.DeserializeObject<Dictionary<string, string>>(fileContent, SerializerSettings);
}

public void WriteValuesToCultureFile(string cultureName, IDictionary<string, string> values)
{
var file = GetCultureFilePath(cultureName);
var fileContent = JsonConvert.SerializeObject(values, SerializerSettings);
File.WriteAllText(file, fileContent, Encoding.UTF8);
}

public void TryRemove(IDictionary<string, string> values, string key)
{
if (values.ContainsKey(key)) values.Remove(key);
}

public IEnumerable<LocalizationValue> MapDictionaryToLocalizationValues(string cultureName, IDictionary<string, string> dictionary)
{
return dictionary.Select(x => new LocalizationValue
{
Key = x.Key,
Value = x.Value,
CultureName = cultureName
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\uBeac.Core.Localization.Abstractions\uBeac.Core.Localization.Abstractions.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using uBeac.Localization.Repositories.MongoDB;
using uBeac.Repositories.MongoDB;

namespace uBeac.Localization;

public static class BuilderExtensions
{
public static ILocalizationBuilder UseMongoDB<TContext>(this ILocalizationBuilder builder) where TContext : IMongoDBContext
{
builder.SetRepository(typeof(MongoDBLocalizationRepository<TContext>));

return builder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using uBeac.Repositories.History;
using uBeac.Repositories.MongoDB;

namespace uBeac.Localization.Repositories.MongoDB;

public interface IMongoDBLocalizationRepository : ILocalizationRepository
{
}

public class MongoDBLocalizationRepository<TContext> : MongoEntityRepository<LocalizationValue, TContext>, IMongoDBLocalizationRepository
where TContext : IMongoDBContext
{
public MongoDBLocalizationRepository(TContext mongoDbContext, IApplicationContext applicationContext, IHistoryManager history) : base(mongoDbContext, applicationContext, history)
{
}

public async Task Upsert(LocalizationValue entity, CancellationToken cancellationToken = default)
{
var dbEntity = await GetByKey(entity.Key, entity.CultureName, cancellationToken);

if (dbEntity == null)
{
await Create(entity, cancellationToken);
return;
}

dbEntity.Value = entity.Value;
await Update(entity, cancellationToken);
}

public async Task Delete(string key, string cultureName, CancellationToken cancellationToken = default)
{
var entity = await GetByKey(key, cultureName, cancellationToken);
await Delete(entity.Id, cancellationToken);
}

public async Task<LocalizationValue> GetByKey(string key, string cultureName, CancellationToken cancellationToken = default)
{
return await Collection.AsQueryable()
.FirstOrDefaultAsync(x => x.Key == key && x.CultureName == cultureName, cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Repository\uBeac.Core.Repositories.MongoDB\uBeac.Core.Repositories.MongoDB.csproj" />
<ProjectReference Include="..\uBeac.Core.Localization.Abstractions\uBeac.Core.Localization.Abstractions.csproj" />
</ItemGroup>

</Project>
Loading