diff --git a/PG.Commons/PG.Commons/Repository/IRepository.cs b/PG.Commons/PG.Commons/Repository/IRepository.cs
new file mode 100644
index 00000000..1a2d01d3
--- /dev/null
+++ b/PG.Commons/PG.Commons/Repository/IRepository.cs
@@ -0,0 +1,45 @@
+// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+
+using PG.Commons.Validation;
+
+namespace PG.Commons.Repository;
+
+///
+/// Base contract for a object storage repository.
+///
+/// The key to access values.
+/// The value.
+public interface IRepository : IValidatable where TValue : IValidatable
+{
+ ///
+ /// Tries to insert an object into the repository.
+ ///
+ /// The object's key.
+ /// the object
+ /// True if the insert succeeded, false else.
+ bool TryCreate(TKey key, TValue value);
+
+ ///
+ /// Tries to load the value for a given key.
+ ///
+ /// The key.
+ /// The object to load.
+ /// True if the read succeeded, false else.
+ bool TryRead(TKey key, out TValue? value);
+
+ ///
+ /// Tries to update the value for a given key.
+ ///
+ /// The key.
+ /// The object to load.
+ /// True if the update succeeded, false else.
+ bool TryUpdate(TKey key, TValue value);
+
+ ///
+ /// Tries to delete a given object from the repository.
+ ///
+ /// The key.
+ /// True if the delete succeeded, false else.
+ bool TryDelete(TKey key);
+}
\ No newline at end of file
diff --git a/PG.Commons/PG.Commons/Repository/RepositoryBase.cs b/PG.Commons/PG.Commons/Repository/RepositoryBase.cs
new file mode 100644
index 00000000..1706dd54
--- /dev/null
+++ b/PG.Commons/PG.Commons/Repository/RepositoryBase.cs
@@ -0,0 +1,127 @@
+// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using FluentValidation.Results;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using PG.Commons.Validation;
+
+namespace PG.Commons.Repository;
+
+///
+public abstract class RepositoryBase : IRepository
+ where TKey : notnull
+ where TValue :
+ IValidatable
+{
+ ///
+ /// .ctor
+ ///
+ ///
+ protected RepositoryBase(IServiceProvider services)
+ {
+ Logger = services.GetService()?.CreateLogger(GetType()) ?? NullLogger.Instance;
+ }
+
+ ///
+ /// The internal Dictionary.
+ ///
+ protected readonly Dictionary InternalRepository = new();
+
+ ///
+ protected readonly ILogger Logger;
+
+ ///
+ public ValidationResult Validate()
+ {
+ var errors = new List();
+ foreach (var validationFailures in InternalRepository.Values.Select(v => v.Validate().Errors))
+ {
+ errors.AddRange(validationFailures);
+ }
+
+ return new ValidationResult(errors);
+ }
+
+ ///
+ public void ValidateAndThrow()
+ {
+ foreach (var v in InternalRepository.Values)
+ {
+ v.ValidateAndThrow();
+ }
+ }
+
+ ///
+ public bool TryCreate(TKey key, TValue value)
+ {
+ if (InternalRepository.ContainsKey(key))
+ {
+ Logger.LogInformation(
+ "The repository already has a value set for the key={key}. The value could not be inserted.", key);
+ return false;
+ }
+
+ var validationResult = value.Validate();
+ if (!validationResult.IsValid)
+ {
+ Logger.LogWarning("The provided value {value} is invalid. Validation result: {validationResult}", value,
+ validationResult);
+ return false;
+ }
+
+ InternalRepository.Add(key, value);
+ return true;
+ }
+
+ ///
+ public bool TryRead(TKey key, out TValue? value)
+ {
+ if (!InternalRepository.ContainsKey(key))
+ {
+ Logger.LogInformation("There is no object with key={key} in repository.", key);
+ value = default;
+ return false;
+ }
+
+ value = InternalRepository[key];
+ return true;
+ }
+
+ ///
+ public bool TryUpdate(TKey key, TValue value)
+ {
+ if (!InternalRepository.ContainsKey(key))
+ {
+ Logger.LogInformation("There is no object with key={key} in repository.", key);
+ return false;
+ }
+
+ var validationResult = value.Validate();
+ if (!validationResult.IsValid)
+ {
+ Logger.LogWarning("The provided value {value} is invalid. Validation result: {validationResult}", value,
+ validationResult);
+ return false;
+ }
+
+ InternalRepository[key] = value;
+ return true;
+ }
+
+ ///
+ public bool TryDelete(TKey key)
+ {
+ if (!InternalRepository.ContainsKey(key))
+ {
+ Logger.LogInformation("There is no object with key={key} in repository.", key);
+ return false;
+ }
+
+ return InternalRepository.Remove(key);
+ }
+}
\ No newline at end of file
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Attributes/DefaultLanguageAttribute.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Attributes/DefaultLanguageAttribute.cs
index 0f7b6bd5..8c609657 100644
--- a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Attributes/DefaultLanguageAttribute.cs
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Attributes/DefaultLanguageAttribute.cs
@@ -10,7 +10,7 @@ namespace PG.StarWarsGame.Localisation.Attributes;
/// that can be used to mark a as the default
/// language.
///
-public class DefaultLanguageAttribute : Attribute
+public sealed class DefaultLanguageAttribute : Attribute
{
///
/// Is set to true, if the language is a default.
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/LocalisationDomain.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/LocalisationDomain.cs
index e8276d93..d7ea4f8b 100644
--- a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/LocalisationDomain.cs
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/LocalisationDomain.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for details.
using Microsoft.Extensions.DependencyInjection;
-using PG.StarWarsGame.Files.DAT;
using PG.StarWarsGame.Localisation.Commons.Helper;
namespace PG.StarWarsGame.Localisation;
@@ -18,7 +17,7 @@ public static class LocalisationDomain
/// The service collection to populate.
public static void RegisterServices(IServiceCollection serviceCollection)
{
- DatDomain.RegisterServices(serviceCollection);
+ PG.StarWarsGame.Files.DAT.DatDomain.RegisterServices(serviceCollection);
serviceCollection
.AddSingleton(sp => new AlamoLanguageDefinitionHelper(sp))
;
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation.csproj b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation.csproj
index 611edd87..93f4c1c9 100644
--- a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation.csproj
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation.csproj
@@ -12,6 +12,10 @@
true
true
+
+ $(BaseIntermediateOutputPath)Generated
+ true
+
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItem.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItem.cs
new file mode 100644
index 00000000..18a7a24c
--- /dev/null
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItem.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+
+using PG.Commons.Validation;
+
+namespace PG.StarWarsGame.Localisation.Repository;
+
+///
+/// A simple translation item.
+///
+public interface ITranslationItem : IValidatable
+{
+ ///
+ /// The item's key.
+ ///
+ string Key { get; }
+
+ ///
+ /// The item's value.
+ ///
+ string Value { get; }
+}
\ No newline at end of file
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItemRepository.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItemRepository.cs
new file mode 100644
index 00000000..6d5c1af3
--- /dev/null
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItemRepository.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+
+using PG.Commons.Repository;
+using PG.StarWarsGame.Localisation.Languages;
+
+namespace PG.StarWarsGame.Localisation.Repository;
+
+///
+/// A repository to hold s.
+///
+public interface ITranslationItemRepository : IRepository
+{
+}
\ No newline at end of file
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationRepository.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationRepository.cs
new file mode 100644
index 00000000..5b340e96
--- /dev/null
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationRepository.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+
+using PG.Commons.Repository;
+
+namespace PG.StarWarsGame.Localisation.Repository;
+
+///
+/// Repository for sorted localisations.
+///
+public interface ITranslationRepository : IRepository
+{
+}
\ No newline at end of file
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItem.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItem.cs
new file mode 100644
index 00000000..4b4b8030
--- /dev/null
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItem.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+
+using System;
+using FluentValidation;
+using FluentValidation.Results;
+
+namespace PG.StarWarsGame.Localisation.Repository;
+
+///
+public sealed class TranslationItem : ITranslationItem
+{
+ internal TranslationItem()
+ {
+ }
+
+ ///
+ /// .ctor
+ ///
+ /// The string key.
+ /// The translated text.
+ ///
+ internal TranslationItem(string key, string value)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ Key = key ?? throw new ArgumentNullException(nameof(key));
+ Value = value ?? throw new ArgumentNullException(nameof(value));
+ }
+
+
+ ///
+ public string Key { get; private set; } = null!;
+
+ ///
+ public string Value { get; private set; } = null!;
+
+ ///
+ public ValidationResult Validate()
+ {
+ return new TranslationItemValidator().Validate(this);
+ }
+
+ ///
+ public void ValidateAndThrow()
+ {
+ new TranslationItemValidator().ValidateAndThrow(this);
+ }
+
+ ///
+ private class TranslationItemValidator : AbstractValidator
+ {
+ internal TranslationItemValidator()
+ {
+ RuleFor(i => i.Key).NotNull().NotEmpty();
+ RuleFor(i => i.Value).NotNull().NotEmpty();
+ }
+ }
+}
\ No newline at end of file
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItemRepository.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItemRepository.cs
new file mode 100644
index 00000000..b01ed9db
--- /dev/null
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItemRepository.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+
+using System;
+using PG.Commons.Repository;
+using PG.StarWarsGame.Localisation.Languages;
+
+namespace PG.StarWarsGame.Localisation.Repository;
+
+///
+internal sealed class TranslationItemRepository : RepositoryBase,
+ ITranslationItemRepository
+{
+ ///
+ public TranslationItemRepository(IServiceProvider services) : base(services)
+ {
+ }
+}
\ No newline at end of file
diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationRepository.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationRepository.cs
new file mode 100644
index 00000000..0a1ca95e
--- /dev/null
+++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationRepository.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+
+using System;
+using PG.Commons.Repository;
+
+namespace PG.StarWarsGame.Localisation.Repository;
+
+internal sealed class TranslationRepository : RepositoryBase, ITranslationRepository
+{
+ ///
+ public TranslationRepository(IServiceProvider services) : base(services)
+ {
+ }
+}
\ No newline at end of file