diff --git a/aleksis/apps/alsijil/assets/components/coursebook/CourseBook.vue b/aleksis/apps/alsijil/assets/components/coursebook/CourseBook.vue
index 857406ffba4b456e5cb1ab1477a95cbff73f893c..6c29cc64e5635cf89b825a0e2809c9bf018eb047 100644
--- a/aleksis/apps/alsijil/assets/components/coursebook/CourseBook.vue
+++ b/aleksis/apps/alsijil/assets/components/coursebook/CourseBook.vue
@@ -5,14 +5,14 @@
   >
     <template v-slot="{ result: { loading, error, data } }">
         <!-- Error -->
-        <message-box v-if="error" type="error">An error occurred</message-box>
+        <message-box v-if="error" type="error">{{ $t("alsijil.error_occurred") }}</message-box>
     
         <!-- Result -->
         <div v-else-if="data" class="result apollo">
           <div class="d-flex justify-space-between">
             <v-btn text color="primary" :href="$root.urls.select_coursebook()">
               <v-icon left>mdi-chevron-left</v-icon>
-              {{ $root.django.gettext("Back") }}
+              {{ $t("alsijil.back") }}
             </v-btn>
             <update-indicator @manual-update="updateManually()" ref="indicator" :status="status"></update-indicator>
           </div>
diff --git a/aleksis/apps/alsijil/assets/components/coursebook/LessonDocumentation.vue b/aleksis/apps/alsijil/assets/components/coursebook/LessonDocumentation.vue
index 9b1182dba4dbcbc8ae2fd3f8c646b109deae4c12..e2679b4ade3b67b44b24ef60f96f2d024d29aeab 100644
--- a/aleksis/apps/alsijil/assets/components/coursebook/LessonDocumentation.vue
+++ b/aleksis/apps/alsijil/assets/components/coursebook/LessonDocumentation.vue
@@ -25,11 +25,9 @@
                 >
                   <template v-slot:activator="{ on, attrs }">
                     <span>
-                      <span
-                          v-text="new Date(lessonDocumentationEdit.date).toLocaleDateString($root.languageCode)"
-                          class="ma-1 text-h5"></span>
-                      <v-btn right v-bind="attrs" v-on="on" icon
-                             v-if="hover && dateAndPeriodEditable">
+                      <span v-text="$d(new Date(lessonDocumentationEdit.date), 'short')"
+                            class="ma-1 text-h5"></span>
+                      <v-btn right v-bind="attrs" v-on="on" icon v-if="hover && dateAndPeriodEditable">
                         <v-icon>mdi-pencil-outline</v-icon>
                       </v-btn>
                     </span>
@@ -49,7 +47,7 @@
                   <template v-slot:activator="{ on, attrs }">
                     <span>
                       <span
-                          v-text="$root.django.gettext('Period') + ' ' + lessonDocumentationEdit.period"
+                          v-text="$t('alsijil.period_number', {number: lessonDocumentationEdit.period})"
                           class="ma-1 text-h5"></span>
                       <v-btn
                           right
@@ -78,10 +76,10 @@
           <v-card-text>
             <v-row>
               <v-col cols="12" md="12" lg="12">
-                <message-box type="error" v-if="error">Error updating data</message-box>
+                <message-box type="error" v-if="error">{{ $t("alsijil.error_updating") }}</message-box>
                 <v-textarea
                     name="input-7-1"
-                    :label="$root.django.gettext('Topic')"
+                    :label="$t('alsijil.lesson_documentation.topic')"
                     rows="1"
                     auto-grow
                     required
@@ -90,7 +88,7 @@
                 ></v-textarea>
                 <v-textarea
                     name="input-7-1"
-                    :label="$root.django.gettext('Homework')"
+                    :label="$t('alsijil.lesson_documentation.homework')"
                     rows="1"
                     auto-grow
 
@@ -98,7 +96,7 @@
                 ></v-textarea>
                 <v-textarea
                     name="input-7-1"
-                    :label="$root.django.gettext('Group note')"
+                    :label="$t('alsijil.lesson_documentation.group_note')"
                     rows="1"
                     auto-grow
 
@@ -126,13 +124,13 @@
                 outlined
                 @click="$emit('cancel-lesson-documentation-dialog', $event)"
             >
-              {{ $root.django.gettext('Cancel') }}
+              {{ $t('alsijil.cancel') }}
             </v-btn>
             <v-btn
                 color="success"
                 @click="mutate()"
             >
-              {{ $root.django.gettext('Save') }}
+              {{ $t('alsijil.save') }}
             </v-btn>
           </v-card-actions>
         </v-form>
diff --git a/aleksis/apps/alsijil/assets/components/coursebook/LessonDocumentations.vue b/aleksis/apps/alsijil/assets/components/coursebook/LessonDocumentations.vue
index 3d5e5f1f91771b373dbc2cccc63121e6c3f00bf8..555d9da6df9f1af97280ec79fcb720726e0cae2a 100644
--- a/aleksis/apps/alsijil/assets/components/coursebook/LessonDocumentations.vue
+++ b/aleksis/apps/alsijil/assets/components/coursebook/LessonDocumentations.vue
@@ -9,7 +9,7 @@
           <v-select
             v-if="saveLessonDocumentationsPerWeek === 'True'"
             :items="emptyLessonPeriods"
-            label="Choose week"
+            :label="$t('alsijil.coursebook.choose_week')"
             :item-text="getWeekText"
             v-model="selectedLessonPeriodDatetime"
             return-object
@@ -17,7 +17,7 @@
           <v-select
             v-else
             :items="emptyLessonPeriods"
-            label="Choose Lesson date"
+            :label="$t('alsijil.coursebook.choose_lesson_date')"
             :item-text="getLessonText"
             v-model="selectedLessonPeriodDatetime"
             return-object
@@ -31,7 +31,7 @@
             v-on="on"
             @click="createLessonDocumentation()"
           >
-            {{ $root.django.gettext("Create documentation") }}
+            {{ $t("alsijil.coursebook.create_documentation") }}
           </v-btn>
         </v-col>
       </v-row>
@@ -104,11 +104,11 @@
         dialog: false,
         expanded: [],
         headers: [
-          { text: "Period", value: "period" },
-          { text: "Topic", value: "topic" },
-          { text: "Homework", value: "homework" },
-          { text: "Group note", value: "groupNote" },
-          { text: "Personal notes", value: "data-table-expand" }
+          { text: this.$t("alsijil.period"), value: "period" },
+          { text: this.$t("alsijil.lesson_documentation.topic"), value: "topic" },
+          { text: this.$t("alsijil.lesson_documentation.homework"), value: "homework" },
+          { text: this.$t("alsijil.lesson_documentation.group_note"), value: "groupNote" },
+          { text: this.$t("alsijil.personal_note.title_plural"), value: "data-table-expand" }
         ],
         lessonDocumentationEdit: {},
         selectedLessonPeriodDatetime: {},
@@ -237,8 +237,8 @@
 
       getLessonText(item) {
         let date_obj = new Date(item.hasOwnProperty("datetimeStart") ? item.datetimeStart : item.date)
-        let period = item.lessonPeriod ? ", " + this.$root.django.gettext('period') + " " + item.lessonPeriod.period.period : "" // FIXME: Cases without lessonPeriod
-        return date_obj.toLocaleDateString(this.$root.languageCode) + period
+        let period = item.lessonPeriod ? ", " + this.$t('alsijil.period_number', {number: item.lessonPeriod.period.period}) : "" // FIXME: Cases without lessonPeriod
+        return this.$d(date_obj, "short") + period
       },
       getWeekText(item) {
         if (item.hasOwnProperty("startDate")) {
@@ -249,18 +249,18 @@
         }
         let end_date = new Date(start_date)
         end_date.setDate(end_date.getDate() + 7)
-        return start_date.toLocaleDateString(this.$root.languageCode) + " - " + end_date.toLocaleDateString(this.$root.languageCode) + ", " + this.$root.django.gettext('CW') + " " + item.week
+        return $d(start_date, "short") + " - " + $d(end_date, "short") + ", " + this.$root.django.gettext('CW') + " " + item.week
       },
       personalNoteString(personalNote) {
           let personalNoteString = "";
           if (personalNote.late > 0) {
-              personalNoteString += personalNote.late + " min. ";
+              personalNoteString += personalNote.late + "', ";
           }
           if (personalNote.absent) {
-              personalNoteString += this.$root.django.gettext("abwesend") + " ";
+              personalNoteString += this.$t("absent") + ", ";
           }
           if (personalNote.excused) {
-              personalNoteString += this.$root.django.gettext("entschuldigt") + " ";
+              personalNoteString += this.$t("excused") + ", ";
           }
           if (personalNote.excuseType) {
               personalNoteString += personalNote.excuseType.name;
diff --git a/aleksis/apps/alsijil/assets/components/coursebook/PersonalNotes.vue b/aleksis/apps/alsijil/assets/components/coursebook/PersonalNotes.vue
index b2c8da1731d247a3219f42ab4b862c47e442d4a6..c237a2ad0230eada28d721f24e03edf46e29dee3 100644
--- a/aleksis/apps/alsijil/assets/components/coursebook/PersonalNotes.vue
+++ b/aleksis/apps/alsijil/assets/components/coursebook/PersonalNotes.vue
@@ -29,7 +29,7 @@
               </v-icon>
             </v-btn>
           </template>
-          <span v-text="$root.django.gettext('Add personal note')"></span>
+          <span v-text="$t('alsijil.coursebook.add_personal_note')"></span>
         </v-tooltip>
       </template>
       <v-card>
@@ -42,31 +42,31 @@
               item-text="fullName"
               item-value="id"
               :items="persons"
-              label="Student"
+              :label="$t('alsijil.personal_note.person')"
               v-model="editedPersonID"
               @input="updatePersonalNote"
             ></v-select>
             <v-text-field
-              label="Tardiness"
+              :label="$t('alsijil.personal_note.tardiness')"
               suffix="min" type="number"
               min="0"
               :disabled="editedPersonID === ID_NO_PERSON"
               v-model="editedTardiness"
             ></v-text-field>
             <v-checkbox
-              label="Absent"
+              :label="$t('alsijil.personal_note.absent')"
               v-model="editedAbsent"
               :disabled="editedPersonID === ID_NO_PERSON"
               @change="editedExcused = false; editedExcuseType = null"
             ></v-checkbox>
             <v-checkbox
-              label="Excused"
+              :label="$t('alsijil.personal_note.excused')"
               v-model="editedExcused"
               :disabled="editedPersonID === ID_NO_PERSON || !editedAbsent"
               @change="editedExcuseType = null"
             ></v-checkbox>
             <v-select
-              label="Excuse Type"
+              :label="$t('alsijil.personal_note.excuse_type')"
               v-model="editedExcuseType"
               :items="excuseTypes"
               item-text="name"
@@ -74,7 +74,7 @@
               :disabled="editedPersonID === ID_NO_PERSON || !editedAbsent || !editedExcused"
             ></v-select>
             <v-select
-              label="Extra Marks"
+              :label="$t('alsijil.personal_note.extra_marks')"
               v-model="editedExtraMarks"
               :items="extraMarks"
               item-text="name"
@@ -84,7 +84,7 @@
               chips
             ></v-select>
             <v-text-field
-              label="Remarks"
+              :label="$t('alsijil.personal_note.remarks')"
               v-model="editedRemarks"
               :disabled="editedPersonID === ID_NO_PERSON"
             ></v-text-field>
@@ -97,14 +97,14 @@
             outlined
             @click="cancelDialog"
           >
-            Cancel
+            {{ $t("alsijil.cancel") }}
           </v-btn>
           <v-btn
             color="success"
             @click="saveDialog"
             :disabled="editedPersonID === ID_NO_PERSON"
           >
-            Save
+            {{ $t("alsijil.save") }}
           </v-btn>
         </v-card-actions>
       </v-card>
@@ -291,13 +291,13 @@ export default {
         personalNoteString(personalNote) {
             let personalNoteString = "";
             if (personalNote.late > 0) {
-                personalNoteString += personalNote.late + " min. ";
+                personalNoteString += personalNote.late + "', ";
             }
             if (personalNote.absent) {
-                personalNoteString += "abwesend ";
+                personalNoteString += $t("alsijil.absent") + " ";
             }
             if (personalNote.excused) {
-                personalNoteString += "entschuldigt ";
+                personalNoteString += $t("alsijil.excused") + " ";
             }
             if (personalNote.excuseType) {
                 personalNoteString += personalNote.excuseType.name;
diff --git a/aleksis/apps/alsijil/assets/components/coursebook/UpdateIndicator.vue b/aleksis/apps/alsijil/assets/components/coursebook/UpdateIndicator.vue
index d3a061e5fc7697063020f8bab120828cbad9e703..4ae2d9518d0be459cf71b80df738cbb97a5fc617 100644
--- a/aleksis/apps/alsijil/assets/components/coursebook/UpdateIndicator.vue
+++ b/aleksis/apps/alsijil/assets/components/coursebook/UpdateIndicator.vue
@@ -40,13 +40,13 @@ export default {
         text() {
             switch (this.status) {
                 case SAVED:
-                    return this.$root.django.gettext("All changes are processed.");
+                    return this.$t("alsijil.coursebook.sync.saved");
                 case UPDATING:
-                    return this.$root.django.gettext("Changes are being synced.");
+                    return this.$t("alsijil.coursebook.sync.updating");
                 case CHANGES:
-                    return this.$root.django.gettext("You have unsaved changes. Click to save immediately.");
+                    return this.$t("alsijil.coursebook.sync.changes");
                 default:
-                    return this.$root.django.gettext("There has been an error processing the latest changes.");
+                    return this.$t("alsijil.coursebook.sync.error");
             }
         },
         color() {
diff --git a/aleksis/apps/alsijil/assets/index.js b/aleksis/apps/alsijil/assets/index.js
index 2030ee27683c60b07a77058b1b93e8c4ae716d69..85c460ff1e1953d83cff9d0c27764ebc2d41e7ce 100644
--- a/aleksis/apps/alsijil/assets/index.js
+++ b/aleksis/apps/alsijil/assets/index.js
@@ -1,3 +1,6 @@
 import CourseBook from './components/coursebook/CourseBook.vue'
+import messages from "./messages.json";
 
 window.router.addRoute({ path: "/app/alsijil/coursebook/:lessonId", component: CourseBook, props: true });
+
+window.i18n.registerLocale(messages);
diff --git a/aleksis/apps/alsijil/assets/messages.json b/aleksis/apps/alsijil/assets/messages.json
new file mode 100644
index 0000000000000000000000000000000000000000..ecf5f79e4ece66dbe7b7a35f21af2a773f944a44
--- /dev/null
+++ b/aleksis/apps/alsijil/assets/messages.json
@@ -0,0 +1,53 @@
+{
+  "en": {
+    "alsijil": {
+      "coursebook": {
+        "title": "Coursebook",
+        "create_documentation": "Create documentation",
+        "choose_week": "Choose week",
+        "choose_lesson_date": "Choose lesson date",
+        "sync": {
+          "saved": "All changes are saved.",
+          "updating": "Changes are being synced.",
+          "changes": "You have unsaved changes. Click to save them immediately.",
+          "error": "There has been an error while saving the latest changes."
+        }
+      },
+      "period": "Period",
+      "period_number": "{number}. period",
+      "lesson_documentation": {
+        "topic": "Topic",
+        "homework": "Homework",
+        "group_note": "Group note"
+      },
+      "calendar_week": "Calendar week",
+      "calendar_week_short": "Week",
+      "personal_note": {
+        "title": "Personal Note",
+        "title_plural": "Personal Notes",
+        "absent_title": "Absent",
+        "excused_title": "Excused",
+        "absent": "absent",
+        "excused": "excused",
+        "person": "Person",
+        "tardiness": "Tardiness",
+        "excuse_type": "Excuse type",
+        "extra_marks": "Extra marks",
+        "remarks": "Remarks",
+        "actions": {
+          "add": "Add personal note"
+        }
+      },
+      "error_occurred": "An error occurred",
+      "error_updating": "Error updating data",
+      "cancel": "Cancel",
+      "save": "Save",
+      "back": "Back"
+    }
+  },
+  "de": {
+    "coursebook": {
+      "title": "Kursbuch"
+    }
+  }
+}
diff --git a/aleksis/apps/alsijil/templates/alsijil/class_register/select_coursebook.html b/aleksis/apps/alsijil/templates/alsijil/class_register/select_coursebook.html
index bce61aee1f08c4de4f0da6250b228eb681ccd786..57114df23ebd2e1631f56596fd89c220740fdad8 100644
--- a/aleksis/apps/alsijil/templates/alsijil/class_register/select_coursebook.html
+++ b/aleksis/apps/alsijil/templates/alsijil/class_register/select_coursebook.html
@@ -1,5 +1,6 @@
 {% extends "core/vue_base.html" %}
 {% load static i18n %}
+{% load render_bundle from webpack_loader %}
 
 {% block page_title %}{% trans "Select Coursebook" %}{% endblock %}
 {% block browser_title %}{% trans "Select Coursebook" %}{% endblock %}
@@ -48,5 +49,5 @@
 {% endblock %}
 
 {% block extra_body %}
-  {#  <script type="module" src="{% static "js/vue/alsijil/LoadComponents.js" %}"></script>#}
+  {% render_bundle "aleksis.apps.alsijil" %}
 {% endblock %}