diff --git a/.eslintrc.js b/.eslintrc.js
index 3bdc1f231b3a75f10ae3ba0687e8c649d7218082..23bf7ef438799b5e5d186c19b4fe838229b74015 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -3,12 +3,38 @@ module.exports = {
     "eslint:recommended",
     "plugin:vue/strongly-recommended",
     "prettier",
+    "plugin:@intlify/vue-i18n/recommended",
   ],
   rules: {
+    "no-unused-vars": "warn",
     "vue/no-unused-vars": "off",
     "vue/multi-word-component-names": "off",
+    "@intlify/vue-i18n/key-format-style": [
+      "error",
+      "snake_case",
+      {
+        splitByDots: false,
+      },
+    ],
+    // "@intlify/vue-i18n/no-unused-keys": ["warn", {}],
+    "@intlify/vue-i18n/no-raw-text": [
+      "error",
+      {
+        ignoreNodes: ["v-icon"],
+        ignorePattern: "^[-–—·#:()\\[\\]&\\.\\s]+$",
+      },
+    ],
+  },
+  settings: {
+    "vue-i18n": {
+      localeDir: "./aleksis/core/assets/messages/*.{json}",
+      messageSyntaxVersion: "^8.0.0",
+    },
   },
   env: {
     es2021: true,
   },
+  parserOptions: {
+    ecmaVersion: "latest",
+  },
 };
diff --git a/aleksis/core/assets/App.vue b/aleksis/core/assets/App.vue
index c12f15d27ba9811a81459ba09f2056e69e577c1f..4ee81730c0772d05f83e62e78e114611e16c50a5 100644
--- a/aleksis/core/assets/App.vue
+++ b/aleksis/core/assets/App.vue
@@ -278,6 +278,7 @@
                       class="white--text text-decoration-none"
                       >{{ $t("base.about_aleksis") }}
                     </router-link>
+                    <!-- eslint-disable-next-line -->
                     <span>© The AlekSIS Team</span>
                   </div>
                 </v-col>
diff --git a/aleksis/core/assets/components/MessageBox.vue b/aleksis/core/assets/components/MessageBox.vue
index 4c79f4d51a36123f4e91f4e187e594d83387e1d3..62e00f314a4dccbf2f0de98286944a15f4b3e6f3 100644
--- a/aleksis/core/assets/components/MessageBox.vue
+++ b/aleksis/core/assets/components/MessageBox.vue
@@ -7,9 +7,6 @@ export default {
 
 <template>
   <v-alert border="left" text v-bind="$attrs">
-    <slot>
-      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
-      tempor incididunt ut labore et dolore magna aliqua.
-    </slot>
+    <slot></slot>
   </v-alert>
 </template>
diff --git a/aleksis/core/assets/components/about/InstalledAppCard.vue b/aleksis/core/assets/components/about/InstalledAppCard.vue
index 99f63dfd0af39e33a8da7f4e3289883baa16a580..3076c52225bd9da785b7f862154dd8f9e8b68e67 100644
--- a/aleksis/core/assets/components/about/InstalledAppCard.vue
+++ b/aleksis/core/assets/components/about/InstalledAppCard.vue
@@ -97,7 +97,7 @@
             <v-row>
               <v-col cols="12" v-if="app.copyrights.length !== 0">
                 <span v-for="(copyright, index) in app.copyrights" :key="index">
-                  Copyright © {{ copyright.years }}
+                  {{ "Copyright ©" + copyright.years }}
                   <a :href="'mailto:' + copyright.email">
                     {{ copyright.name }}
                   </a>
diff --git a/aleksis/core/assets/plugins/aleksis.js b/aleksis/core/assets/plugins/aleksis.js
index 87ebfcb680576db41acad426c6c1b3055e213fc8..b4cb6338c7c33add911c360d57e4ba77818bda64 100644
--- a/aleksis/core/assets/plugins/aleksis.js
+++ b/aleksis/core/assets/plugins/aleksis.js
@@ -6,13 +6,12 @@ AleksisVue.install = function (Vue, options) {
   Vue.prototype.$setPageTitle = function (title, route) {
     let titleParts = [];
 
-
     if (title) {
       titleParts.push(title);
     } else {
       if (!route) {
         route = this.$route;
-      };
+      }
       if (route.meta.titleKey) {
         titleParts.push(this.$t(route.meta.titleKey));
       }
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 7c1f0c0bd0837508329cd9fd4da2d35c47eda0eb..a19a8611cdb9d3782190d77cd40b5367fadca93a 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -581,12 +581,13 @@ YARN_INSTALLED_APPS = [
     "@rollup/plugin-graphql@^2.0.2",
     "@rollup/plugin-virtual@^3.0.1",
     "rollup-plugin-license@^3.0.1",
-    "vue-i18n@8",
+    "vue-i18n@^8.0.0",
     "@sentry/vue@^7.28.0",
     "prettier@^2.8.1",
     "eslint@^8.26.0",
     "eslint-plugin-vue@^9.7.0",
     "eslint-config-prettier@^8.5.0",
+    "@intlify/eslint-plugin-vue-i18n@^2.0.0",
     "stylelint@^14.14.0",
     "stylelint-config-standard@^29.0.0",
     "stylelint-config-prettier@^9.0.3",
diff --git a/aleksis/core/vite.config.js b/aleksis/core/vite.config.js
index fa51a4854937f3896e50ea308037009a8f391e77..c8d28e932807ad72fb0ab156fdb560fbf5723e99 100644
--- a/aleksis/core/vite.config.js
+++ b/aleksis/core/vite.config.js
@@ -98,7 +98,13 @@ export default defineConfig({
     strictPort: true,
     origin: "http://localhost:5173",
     watch: {
-      ignored: ["**/*.py", "**/__pycache__/**", "**/*.mo", "**/.venv/**", "**/.tox/**"],
+      ignored: [
+        "**/*.py",
+        "**/__pycache__/**",
+        "**/*.mo",
+        "**/.venv/**",
+        "**/.tox/**",
+      ],
     },
     fs: {
       allow: [