diff --git a/app/Http/Controllers/LanguageController.php b/app/Http/Controllers/LanguageController.php
new file mode 100644
index 0000000000000000000000000000000000000000..f80638567162a458676b79b6ec6051bb1c070512
--- /dev/null
+++ b/app/Http/Controllers/LanguageController.php
@@ -0,0 +1,232 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
+
+class LanguageController extends Controller
+{
+    public function createOverview(Request $request)
+    {
+        $languageFilePath = resource_path() . "/lang/";
+        $files            = scandir($languageFilePath);
+        $dirs             = [];
+        foreach ($files as $file) {
+            if (is_dir($languageFilePath . $file) && $file !== "." && $file !== "..") {
+                $dirs[] = $file;
+            }
+
+        }
+        # Im Array "$dirs" haben wir nun alle Verzeichnisse mit dem entsprechenden Sprachkürzel
+        # Alle von uns bislang unterstützen Sprachen sind hier eingetragen.
+        $langTexts = [];
+        $sum       = [];
+        foreach ($dirs as $dir) {
+            # Wir überprüfen nun für jede Datei die Anzahl der vorhandenen Übersetzungen
+            $di                           = new RecursiveDirectoryIterator($languageFilePath . $dir);
+            $langTexts[$dir]["textCount"] = 0;
+            $langTexts[$dir]["fileCount"] = 0;
+            foreach (new RecursiveIteratorIterator($di) as $filename => $file) {
+                if (!$this->endsWith($filename, ".")) {
+                    $langTexts[$dir]["fileCount"] += 1;
+                    $tmp = include $filename;
+                    foreach ($tmp as $key => $value) {
+                        $sum = array_merge($sum, $this->getValues([$key => $value], basename($filename)));
+                    }
+                    $langTexts[$dir]["textCount"] += count($tmp);
+                }
+
+            }
+        }
+        $deComplete = $langTexts["de"]["textCount"] === count($sum) ? true : false;
+        return view('languages.overview')
+            ->with('title', trans('titles.languages'))
+            ->with('langTexts', $langTexts)
+            ->with('sum', $sum)
+            ->with('deComplete', $deComplete);
+    }
+
+    public function createEditPage($from, $to, $exclude = "")
+    {
+        $languageFilePath = resource_path() . "/lang/";
+        $files            = scandir($languageFilePath);
+        $dirs             = [];
+        foreach ($files as $file) {
+            if (is_dir($languageFilePath . $file) && $file !== "." && $file !== "..") {
+                $dirs[$file] = $file;
+            }
+
+        }
+        # Abbruchbedingungen:
+        if ($from === "" || $to === "" || ($from !== "de" && $from !== "all") || ($from === "all" && $to !== "de") && !array_has($dirs, $to)) {
+            return redirect(url('languages'));
+        }
+
+        $texts = [];
+
+        $langTexts = [];
+        $sum       = [];
+        $filePath  = [];
+        foreach ($dirs as $dir) {
+            if ($from !== "all" && $dir !== $to && $dir !== $from) {
+                continue;
+            }
+
+            # Wir überprüfen nun für jede Datei die Anzahl der vorhandenen Übersetzungen
+            $di              = new RecursiveDirectoryIterator($languageFilePath . $dir);
+            $langTexts[$dir] = 0;
+            foreach (new RecursiveIteratorIterator($di) as $filename => $file) {
+                if (!$this->endsWith($filename, ".")) {
+                    $tmp = include $filename;
+                    foreach ($tmp as $key => $value) {
+                        $sum                                    = array_merge($sum, $this->getValues([$key => $value], basename($filename)));
+                        $texts[basename($filename)][$key][$dir] = $value;
+                    }
+                    $filePath[basename($filename)] = preg_replace("/lang\/.*?\//si", "lang/$to/", substr($filename, strpos($filename, "lang")));
+                    $langTexts[$dir] += count($tmp);
+                }
+
+            }
+        }
+        $langs = [];
+        $fn    = "";
+        $t     = [];
+        $ex    = ['files' => [], 'new' => 0];
+        if ($exclude !== "") {
+            try {
+                $ex = unserialize(base64_decode($exclude));
+            } catch (\ErrorException $e) {
+                $ex = ['files' => [], 'new' => 0];
+            }
+        }
+        foreach ($texts as $filename => $text) {
+            $has = false;
+            foreach ($ex['files'] as $file) {
+                if ($file === $filename) {
+                    $has = true;
+                }
+            }
+            if ($has) {
+                continue;
+            }
+
+            # Hier können wir später die bereits bearbeiteten Dateien ausschließen.
+            foreach ($text as $textname => $languages) {
+
+                foreach ($languages as $lang => $value) {
+                    if ($lang !== $to) {
+                        $langs = array_add($langs, $lang, $lang);
+                    }
+
+                }
+                if (!isset($languages[$to])) {
+                    $fn = $filePath[$filename];
+                    $t  = $text;
+                    break;
+                }
+            }
+
+        }
+
+        while ($this->hasToMuchDimensions($t)) {
+            $t = $this->deMultidimensionalizeArray($t);
+        }
+
+        #die(var_dump($t));
+
+        return view('languages.edit')
+            ->with('texts', $t)
+            ->with('filename', $fn)
+            ->with('title', trans('titles.languages.edit'))
+            ->with('langs', $langs)
+            ->with('to', $to)
+            ->with('langTexts', $langTexts)
+            ->with('sum', $sum)
+            ->with('css', 'editLanguage.css')
+            ->with('new', $ex["new"]);
+    }
+
+    private function getValues($values, $prefix = "")
+    {
+        $return = [];
+        if (!is_array($values)) {
+            return $return;
+        } else {
+            foreach ($values as $key => $value) {
+                if (is_array($value)) {
+                    $return = array_merge($return, $this->getValues($value, $prefix . $key));
+                } elseif (is_string($value)) {
+                    $return[$prefix . $key] = $value;
+                }
+            }
+        }
+
+        return $return;
+    }
+
+    private function hasToMuchDimensions($t)
+    {
+        foreach ($t as $key => $value) {
+            if (is_array($value)) {
+                foreach ($value as $lang => $val) {
+                    if (is_array($val)) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private function deMultidimensionalizeArray($t)
+    {
+        # Es gibt noch Besonderheiten in den Texten
+        # Es kann sein, dass statt einem String ein Array aus Strings als Werte existieren.
+        # Diese müssen aufgelöst werden:
+        $tmp = [];
+        foreach ($t as $key => $value) {
+            $isArray = false;
+            if (is_array($value)) {
+                foreach ($value as $lang => $val) {
+                    if (is_array($val)) {
+                        $isArray = true;
+                    }
+
+                }
+            } else {
+                $tmp[$key] = $value;
+                continue;
+            }
+            if (!$isArray) {
+                $tmp[$key] = $value;
+            } else {
+                $tmp[$key] = "";
+                foreach ($value as $lang => $val) {
+                    if (is_array($val)) {
+                        foreach ($val as $key2 => $val) {
+                            $tmp["\t" . $key . "#" . $key2][$lang] = $val;
+                        }
+
+                    }
+                }
+            }
+
+        }
+        return $tmp;
+    }
+
+    private function startsWith($haystack, $needle)
+    {
+        // search backwards starting from haystack length characters from the end
+        return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false;
+    }
+
+    private function endsWith($haystack, $needle)
+    {
+        // search forward starting from end minus needle length characters
+        return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== false);
+    }
+}
diff --git a/app/Http/Controllers/MailController.php b/app/Http/Controllers/MailController.php
index a536f3b8c35ca147e46ac99c0231536e3bf64083..37c7dc48f48a50ac1af8ca277dbf8800c23cf3aa 100644
--- a/app/Http/Controllers/MailController.php
+++ b/app/Http/Controllers/MailController.php
@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
 
 use App\Http\Controllers\Controller;
 use Illuminate\Http\Request;
+use Illuminate\Http\Response;
 use LaravelLocalization;
 use Mail;
 
@@ -119,4 +120,73 @@ class MailController extends Controller
         }
 
     }
+
+    public function sendLanguageFile(Request $request, $from, $to, $exclude = "")
+    {
+
+        $filename = $request->input('filename');
+
+        # Wir erstellen nun zunächst den Inhalt der Datei:
+        $data = [];
+        $new  = 0;
+        foreach ($request->all() as $key => $value) {
+            if ($key === "filename" || $value === "") {
+                continue;
+            }
+            if (strpos($key, "_new_") === 0 && $value !== "") {
+                $new++;
+                $key = substr($key, strpos($key, "_new_") + 5);
+            }
+            $key = trim($key);
+            if (!strpos($key, "#")) {
+                $data[$key] = $value;
+            } else {
+                $ref = &$data;
+                do {
+                    $ref = &$ref[substr($key, 0, strpos($key, "#"))];
+                    $key = substr($key, strpos($key, "#") + 1);
+                } while (strpos($key, "#"));
+                $ref = &$ref[$key];
+                $ref = $value;
+            }
+
+        }
+        $output = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
+        $output = preg_replace("/\{/si", "[", $output);
+        $output = preg_replace("/\}/si", "]", $output);
+        $output = preg_replace("/\": ([\"\[])/si", "\"\t=>\t$1", $output);
+
+        $output = "<?php\n\nreturn $output;\n";
+
+        $message = "Moin moin,\n\nein Benutzer hat eine Sprachdatei aktualisiert.\nSollten die Texte so in Ordnung sein, ersetzt, oder erstellt die Datei aus dem Anhang in folgendem Pfad:\n$filename\n\nFolgend zusätzlich der Inhalt der Datei:\n\n$output";
+
+        #Mail::send(['text' => 'kontakt.mail'], ['messageText' => $message], function ($message) use ($output, $filename) {
+        #    $message->subject('MetaGer - Sprachdatei');
+        #    $message->from('noreply@metager.de');
+        #    $message->to('dominik@suma-ev.de');
+        #    $message->attachData($output, basename($filename));
+        #});
+
+        # Wir haben nun eine Mail an uns geschickt, welche die entsprechende Datei beinhaltet.
+        # Nun müssen wir den Nutzer eigentlich nur noch zurück leiten und die Letzte bearbeitete Datei ausschließen:
+        $ex = [];
+        if ($exclude !== "") {
+            try {
+                $ex = unserialize(base64_decode($exclude));
+            } catch (\ErrorException $e) {
+                $ex = [];
+            }
+
+            if (!isset($ex["files"])) {
+                $ex["files"] = [];
+            }
+        }
+        if (!isset($ex["new"])) {
+            $ex["new"] = 0;
+        }
+        $ex['files'][] = basename($filename);
+        $ex["new"] += $new;
+        $ex = base64_encode(serialize($ex));
+        return redirect(url('languages/edit', ['from' => $from, 'to' => $to, 'exclude' => $ex]));
+    }
 }
diff --git a/app/Http/routes.php b/app/Http/routes.php
index 47c40dc10af28c4a5cb7f8d4a2fcf3b2a625802a..9c3cc316c264d4e0a03a5e8466039d0d136dc88e 100644
--- a/app/Http/routes.php
+++ b/app/Http/routes.php
@@ -165,4 +165,7 @@ Route::group(
         Route::get('databund', function () {
             return redirect('https://metager.de/klassik/databund');
         });
+        Route::get('languages', 'LanguageController@createOverview');
+        Route::get('languages/edit/{from}/{to}/{exclude?}', 'LanguageController@createEditPage');
+        Route::post('languages/edit/{from}/{to}/{exclude?}', 'MailController@sendLanguageFile');
     });
diff --git a/public/css/editLanguage.css b/public/css/editLanguage.css
new file mode 100644
index 0000000000000000000000000000000000000000..77644c66ef62c94e1b0518df1e593a666db3673d
--- /dev/null
+++ b/public/css/editLanguage.css
@@ -0,0 +1,3 @@
+td.name {
+    white-space: pre;
+}
\ No newline at end of file
diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php
index a292aad22c2a92a46b15cc7bfd75ce8c8fe9386f..14bc895284a6ce59401bf86d75181bb552c3c6c1 100644
--- a/resources/views/index.blade.php
+++ b/resources/views/index.blade.php
@@ -2,10 +2,6 @@
 
 @section('title', $title )
 
-@section('navbarFocus.search', 'class="active"')
-
-@section('navbarFocus.donate', 'class="dropdown"')
-
 @section('content')
   <div class="modal fade" id="plugin-modal" tab-index="-1" role="dialog">
       <div class="modal-dialog ">
diff --git a/resources/views/languages/edit.blade.php b/resources/views/languages/edit.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a0e0e9192e3192916cab5c4c7743aa9580f2121
--- /dev/null
+++ b/resources/views/languages/edit.blade.php
@@ -0,0 +1,53 @@
+@extends('layouts.subPages')
+
+@section('title', $title )
+
+@section('content')
+<h1>MetaGer - Ãœbersetzungen</h1>
+<p>Vielen Dank, dass du erwägst MetaGer bei der Übersetzung seiner Texte zu unterstützen. Dir wird im unteren Bereich eine Datei und tabellarisch die dazugehörigen Texte angezeigt. Das Feld "#ID" dient dabei nur der Orientierung und ist für die Übersetzung unwichtig.
+In der nächsten Spalte findest du entweder Texte der Sprache für die uns einige Übersetzungen fehlen, oder aber ein Textfeld. Wird hier für eine Reihe ein Textfeld angezeigt, so fehlen uns die Texte in der angegebenen Sprache.</p>
+<p>Du kannst uns unterstützen, indem du dir die Referenztexte in den folgenden Spalten (rechts daneben) ansiehst und nach Möglichkeit eine Übersetzung in der gesuchten Sprache in das Textfeld einträgst.</p>
+<div class="progress">
+  <div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" aria-valuenow="{{ round(100 * (($langTexts[$to]+$new) / count($sum))) }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ round(100 * (($langTexts[$to]+$new) / count($sum))) }}%">
+  {{ ($langTexts[$to]+$new) . "/" . count($sum) . " Texten übersetzt (" . round(100 * (($langTexts[$to]+$new) / count($sum))) . "%)"}}
+  </div>
+</div>
+<h1>{{$filename}}</h1>
+<form id="submit" method="POST">
+<input type="hidden" name="filename" value="{{$filename}}" />
+</form>
+<table class="table">
+	<thead>
+	<tr>
+		<th>#ID</th>
+		<th>{{$to}}
+		@foreach($langs as $lang => $value)
+		<th>{{$lang}}</th>
+		@endforeach
+	</tr>
+	</thead>
+	<tbody>
+		@foreach($texts as $name => $langValues)
+		@if($langValues === "")
+		<tr>
+		<td class="name">{{preg_replace("/(\s*).*#(.*)$/si", "$1$2", $name)}}</td>
+		<td></td>
+		<td></td>
+		</tr>
+		@else
+		<tr>
+			<td class="name">{{preg_replace("/(\s*).*#(.*)$/si", "$1$2", $name)}}</td>
+			<td>@if(isset($langValues[$to])) <input type="text" size="50" form="submit" name="_new_{{$name}}" value="{{$langValues[$to]}}" readonly /> @else <input type="text" size="50" form="submit" name="_new_{{$name}}" /> @endif</td>
+			@foreach($langs as $lang => $value)
+			<td>{{ $langValues[$lang] or "" }}</td>
+			@endforeach
+		</tr>
+		@endif
+
+		@endforeach
+	</tbody>
+</table>
+<p>Sobald du mit deinen Texten zufrieden bist, kannst du uns diese mit einem Klick auf folgenden Knopf automatisch zusenden. Wenn es mehr fehlende Texte in der angegebenen Sprache gibt, wird dein Browser dich danach direkt zu diesen leiten.</p>
+<p><b>Hinweis</b>: Die übermittelten Texte werden von diesem Tool erst erkannt, sobald diese von uns gesichtet und eingefügt wurden. Wenn du deine Arbeit sichern möchtest um diese zu einem späteren Zeitpunkt fortzusetzen (auch wenn wir deine bisherige Arbeit noch nicht übernehmen konnten), so reicht es vollkommen, den aktuellen Link aus deiner Browserleiste zu kopieren und zu einem späteren Zeitpunkt wieder aufzurufen.</p>
+<button class="btn btn-success" type="submit" form="submit">Daten übermitteln</button>
+@endsection
diff --git a/resources/views/languages/overview.blade.php b/resources/views/languages/overview.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..89ab3ffbab2827d9dccbe20af87888bc29753b02
--- /dev/null
+++ b/resources/views/languages/overview.blade.php
@@ -0,0 +1,28 @@
+@extends('layouts.subPages')
+
+@section('title', $title )
+
+@section('content')
+@if(!$deComplete)
+<p>Hinweis: Es sind nicht alle Texte für die Referenzsprache(deutsch) vorhanden. Das Bearbeiten der Sprachdateien ist auf die deutsche begrenzt, bis diese komplett ist.</p>
+@endif
+<table class="table">
+	<thead>
+	<tr>
+		<th>Sprachkürzel</th>
+		<th>Status</th>
+		<th>Aktion</th>
+	</tr>
+	</thead>
+	<tbody>
+		@foreach($langTexts as $lang => $values)
+			<tr @if(floor(($values['textCount'] / count($sum)) * 100) < 100) class="danger" @else class="success" @endif>
+				<td>{{$lang}}</td>
+				<td>{{ $values['textCount'] . "/" . count($sum)}} Texten übersetzt. ({{ floor(($values['textCount'] / count($sum)) * 100) }} %)</td>
+				<td><a href="{{ LaravelLocalization::getLocalizedURL(LaravelLocalization::getCurrentLocale(), url("/languages/edit", ['from'=>'all', 'to'=>'de'])) }}" class="btn btn-default @if(!$deComplete && $lang !== "de" || floor(($values['textCount'] / count($sum)) * 100) === 100) disabled @endif">Texte für "{{ $lang }}" ergänzen</a></td>
+			</tr>
+		@endforeach
+	</tbody>
+</table>
+
+@endsection