Merge branch 'newgen' of https://github.com/ceee/zero into newgen
This commit is contained in:
@@ -57,7 +57,7 @@ public interface IFileSystem
|
||||
/// <summary>
|
||||
/// Get all items within a directory
|
||||
/// </summary>
|
||||
IAsyncEnumerable<IFileMeta> GetDirectoryContent(string path = null, bool recursive = false, CancellationToken cancellationToken = default);
|
||||
IEnumerable<IFileMeta> GetDirectoryContent(string path = null, bool recursive = false, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Tries to create a directory at the given path. This method returns if the directory already exists.
|
||||
|
||||
@@ -196,17 +196,17 @@ public class PhysicalFileSystem : IFileSystem
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IAsyncEnumerable<IFileMeta> GetDirectoryContent(string path = null, bool recursive = false, CancellationToken cancellationToken = default)
|
||||
public virtual IEnumerable<IFileMeta> GetDirectoryContent(string path = null, bool recursive = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
string resolvedPath = ResolvePath(path);
|
||||
List<IFileMeta> results = new();
|
||||
List<IFileMeta> results = [];
|
||||
SearchOption searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
|
||||
if (!Directory.Exists(resolvedPath))
|
||||
{
|
||||
return results.ToAsyncEnumerable();
|
||||
return results;
|
||||
}
|
||||
|
||||
results.AddRange(Directory.GetDirectories(resolvedPath, "*", searchOption).Select(f =>
|
||||
@@ -221,7 +221,7 @@ public class PhysicalFileSystem : IFileSystem
|
||||
return new PhysicalFileMeta(fileSystemInfo, ResolvePath(f.Substring(_root.Length)));
|
||||
}));
|
||||
|
||||
return results.ToAsyncEnumerable();
|
||||
return results;
|
||||
}
|
||||
catch (Exception ex) when (ex is not FileSystemException)
|
||||
{
|
||||
|
||||
@@ -1,32 +1,35 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace zero.Localization;
|
||||
|
||||
public class ConfigurationLocalizer : Localizer
|
||||
{
|
||||
private IConfiguration _configuration;
|
||||
protected ConcurrentDictionary<string, Translation> FileCache { get; set; } = [];
|
||||
|
||||
|
||||
public ConfigurationLocalizer(IConfiguration configuration, ICultureResolver cultureResolver, IOptionsMonitor<LocalizationOptions> options) : base(cultureResolver)
|
||||
{
|
||||
_configuration = configuration;
|
||||
IConfigurationSection section = configuration.GetSection($"Zero:Localization:{LanguageCode}");
|
||||
|
||||
if (section != null)
|
||||
{
|
||||
foreach (IConfigurationSection child in section.GetChildren())
|
||||
{
|
||||
FileCache.TryAdd(child.Key, new Translation() { Value = child.Value });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override Translation LoadTranslation(string key)
|
||||
{
|
||||
IConfigurationSection section = _configuration.GetSection($"Zero:Localization:{LanguageCode}:{key}");
|
||||
|
||||
if (section == null)
|
||||
if (!FileCache.TryGetValue(key, out Translation translation))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new()
|
||||
{
|
||||
Key = key,
|
||||
Value = section.Value
|
||||
};
|
||||
return translation;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace zero.Localization;
|
||||
|
||||
public class Translation
|
||||
public record Translation
|
||||
{
|
||||
/// <summary>
|
||||
/// Key of the translation
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Mvc.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc.Localization;
|
||||
using Microsoft.AspNetCore.Mvc.Localization;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace zero.Localization;
|
||||
|
||||
|
||||
@@ -2,9 +2,20 @@
|
||||
|
||||
public class MailOptions
|
||||
{
|
||||
//public string Host { get; set; }
|
||||
|
||||
//public int Port { get; set; }
|
||||
|
||||
//public string Username { get; set; }
|
||||
|
||||
//public string Password { get; set; }
|
||||
|
||||
//public string To { get; set; }
|
||||
|
||||
public string SenderEmail { get; set; }
|
||||
|
||||
public string SenderName { get; set; }
|
||||
|
||||
|
||||
public Func<Mail, string> BuildViewPath { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
namespace zero.Validation;
|
||||
|
||||
public class FluentValidationGermanLanguage
|
||||
{
|
||||
public static Dictionary<string, string> Translations = new()
|
||||
{
|
||||
{ "EmailValidator", "Keine gültige E-Mail-Adresse" },
|
||||
{ "UrlValidator", "Keine gültige URL" },
|
||||
{ "HexValidator", "Keine gültige HEX Farbangabe" },
|
||||
{ "GreaterThanOrEqualValidator", "Der Wert muss grösser oder gleich '{ComparisonValue}' sein." },
|
||||
{ "GreaterThanValidator", "Der Wert muss grösser sein als '{ComparisonValue}'." },
|
||||
{ "LengthValidator", "Die Länge muss zwischen {MinLength} und {MaxLength} Zeichen liegen. Es wurden {TotalLength} Zeichen eingetragen." },
|
||||
{ "MinimumLengthValidator", "Die Länge muss größer oder gleich {MinLength} sein. Sie haben {TotalLength} Zeichen eingegeben." },
|
||||
{ "MaximumLengthValidator", "Die Länge muss kleiner oder gleich {MaxLength} sein. Sie haben {TotalLength} Zeichen eingegeben." },
|
||||
{ "LessThanOrEqualValidator", "Der Wert muss kleiner oder gleich '{ComparisonValue}' sein." },
|
||||
{ "LessThanValidator", "Der Wert muss kleiner sein als '{ComparisonValue}'." },
|
||||
{ "NotEmptyValidator", "Dieses Feld darf nicht leer sein." },
|
||||
{ "NotEqualValidator", "Dieser Wert darf nicht '{ComparisonValue}' sein." },
|
||||
{ "NotNullValidator", "Dieses Feld darf nicht leer sein." },
|
||||
{ "PredicateValidator", "Der Wert entspricht nicht der festgelegten Bedingung." },
|
||||
{ "AsyncPredicateValidator", "Der Wert entspricht nicht der festgelegten Bedingung." },
|
||||
{ "RegularExpressionValidator", "Dieses Feld weist ein ungültiges Format auf." },
|
||||
{ "EqualValidator", "Der Wert muss gleich '{ComparisonValue}' sein." },
|
||||
{ "ExactLengthValidator", "Dieses Feld muss genau {MaxLength} lang sein. Es wurden {TotalLength} eingegeben." },
|
||||
{ "ExclusiveBetweenValidator", "Der Wert muss zwischen {From} und {To} sein (exklusiv). Es wurde {PropertyValue} eingegeben." },
|
||||
{ "InclusiveBetweenValidator", "Der Wert muss zwischen {From} and {To} sein. Es wurde {PropertyValue} eingegeben." },
|
||||
{ "CreditCardValidator", "Keine gültige Kreditkartennummer." },
|
||||
{ "ScalePrecisionValidator", "Das Feld darf insgesamt nicht mehr als {ExpectedPrecision} Ziffern enthalten, mit Berücksichtigung von {ExpectedScale} Dezimalstellen. Es wurden {Digits} Ziffern und {ActualScale} Dezimalstellen gefunden." },
|
||||
{ "EmptyValidator", "Dieses Feld sollte leer sein." },
|
||||
{ "NullValidator", "Dieses Feld sollte leer sein." },
|
||||
{ "EnumValidator", "Dieses Feld hat einen Wertebereich, der '{PropertyValue}' nicht enthält." },
|
||||
// Additional fallback messages used by clientside validation integration.
|
||||
{ "Length_Simple", "Die Länge muss zwischen {MinLength} und {MaxLength} Zeichen liegen." },
|
||||
{ "MinimumLength_Simple", "Die Länge muss größer oder gleich {MinLength} sein." },
|
||||
{ "MaximumLength_Simple", "Die Länge muss kleiner oder gleich {MaxLength} sein." },
|
||||
{ "ExactLength_Simple", "Dieses Feld muss genau {MaxLength} lang sein." },
|
||||
{ "InclusiveBetween_Simple", "Der Wert muss zwischen {From} and {To} sein." }
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace zero.Validation;
|
||||
|
||||
public class GermanIdentityErrorDescriber : IdentityErrorDescriber
|
||||
{
|
||||
public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"Ein unbekannter Fehler ist aufgetreten" }; }
|
||||
public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Ein unbekannter Fehler ist aufgetreten" }; }
|
||||
public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Die Passwörter stimmen nicht überein" }; }
|
||||
public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Der Token ist ungültig" }; }
|
||||
public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "Ein Benutzer mit diesem Login existiert bereits" }; }
|
||||
public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"Der Username '{userName}' ist ungültig (nur Buchstaben und Zahlen gültig)" }; }
|
||||
public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"Die Email-Adresse '{email}' ist ungültig" }; }
|
||||
public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"Der Username '{userName}' ist bereits vergeben" }; }
|
||||
public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"Die Email-Adresse '{email}' ist bereits vergeben" }; }
|
||||
//public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"Role name '{role}' is invalid." }; }
|
||||
//public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"Role name '{role}' is already taken." }; }
|
||||
//public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "User already has a password set." }; }
|
||||
//public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Lockout is not enabled for this user." }; }
|
||||
//public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"User already in role '{role}'." }; }
|
||||
//public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"User is not in role '{role}'." }; }
|
||||
public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"Das Passwort muss mindestens {length} Zeichen lang sein" }; }
|
||||
public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Passwörter müssen zumindest ein alphanumerisches Zeichen (a-z, 0-9) enthalten" }; }
|
||||
public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Passwörter müssen zumindest eine Zahl enthalten ('0'-'9')" }; }
|
||||
public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Passwörter müssen zumindest einen Kleinbuchstaben enthalten ('a'-'z')" }; }
|
||||
public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Passwörter müssen zumindest einen Großbuchstaben enthalten ('A'-'Z')" }; }
|
||||
public override IdentityError PasswordRequiresUniqueChars(int uniqueChars) { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = $"Passwörter müssen zumindest {uniqueChars} verschiedene Zeichen enthalten" }; }
|
||||
//public override IdentityError RecoveryCodeRedemptionFailed() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Passwords must have at least one uppercase ('A'-'Z')." }; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation.Resources;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace zero.Validation;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static void AddGermanValidation(this IServiceCollection services)
|
||||
{
|
||||
ValidatorOptions.Global.LanguageManager.AddGermanOverrides();
|
||||
services.Replace<IdentityErrorDescriber, GermanIdentityErrorDescriber>(ServiceLifetime.Scoped);
|
||||
}
|
||||
|
||||
|
||||
static ILanguageManager AddGermanOverrides(this ILanguageManager manager)
|
||||
{
|
||||
if (manager is LanguageManager)
|
||||
{
|
||||
var lmanager = manager as LanguageManager;
|
||||
|
||||
foreach (var kvp in FluentValidationGermanLanguage.Translations)
|
||||
{
|
||||
lmanager.AddTranslation("de", kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="8.0.1" />
|
||||
<PackageReference Include="FluentValidation" Version="11.9.2" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.3" />
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user