diff --git a/app/MindWork AI Studio/Tools/PluginSystem/ILanguagePlugin.cs b/app/MindWork AI Studio/Tools/PluginSystem/ILanguagePlugin.cs
new file mode 100644
index 00000000..a33bf3f5
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/PluginSystem/ILanguagePlugin.cs
@@ -0,0 +1,21 @@
+namespace AIStudio.Tools.PluginSystem;
+
+///
+/// Represents a contract for a language plugin.
+///
+public interface ILanguagePlugin
+{
+ ///
+ /// Tries to get a text from the language plugin.
+ ///
+ ///
+ /// When the key does not exist, the value will be an empty string.
+ /// Please note that the key is case-sensitive. Furthermore, the keys
+ /// are in the format "root::key". That means that the keys are
+ /// hierarchical and separated by "::".
+ ///
+ /// The key to use to get the text.
+ /// The desired text.
+ /// True if the key exists, false otherwise.
+ public bool TryGetText(string key, out string value);
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PluginLanguage.cs b/app/MindWork AI Studio/Tools/PluginSystem/PluginLanguage.cs
new file mode 100644
index 00000000..e1676e49
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/PluginSystem/PluginLanguage.cs
@@ -0,0 +1,48 @@
+using Lua;
+
+namespace AIStudio.Tools.PluginSystem;
+
+public sealed class PluginLanguage : PluginBase, ILanguagePlugin
+{
+ private readonly Dictionary content = [];
+
+ private ILanguagePlugin? baseLanguage;
+
+ public PluginLanguage(string path, LuaState state, PluginType type) : base(path, state, type)
+ {
+ if (this.TryInitUITextContent(out var issue, out var readContent))
+ this.content = readContent;
+ else
+ this.pluginIssues.Add(issue);
+ }
+
+ ///
+ /// Sets the base language plugin. This plugin will be used to fill in missing keys.
+ ///
+ /// The base language plugin to use.
+ public void SetBaseLanguage(ILanguagePlugin baseLanguagePlugin) => this.baseLanguage = baseLanguagePlugin;
+
+ ///
+ /// Tries to get a text from the language plugin.
+ ///
+ ///
+ /// When the key neither in the base language nor in this language exist,
+ /// the value will be an empty string. Please note that the key is case-sensitive.
+ /// Furthermore, the keys are in the format "root::key". That means that
+ /// the keys are hierarchical and separated by "::".
+ ///
+ /// The key to use to get the text.
+ /// The desired text.
+ /// True if the key exists, false otherwise.
+ public bool TryGetText(string key, out string value)
+ {
+ if (this.content.TryGetValue(key, out value!))
+ return true;
+
+ if(this.baseLanguage is not null && this.baseLanguage.TryGetText(key, out value))
+ return true;
+
+ value = string.Empty;
+ return false;
+ }
+}
\ No newline at end of file