diff --git a/src/i18n/de.js b/src/i18n/de.js
index f5f37601e8ed1fec3db11a73c5c068e858e6ae24..a89106dd8161a77f4f50be39778cf0a60c8f94c1 100644
--- a/src/i18n/de.js
+++ b/src/i18n/de.js
@@ -462,16 +462,6 @@ export default {
   rrule: {
     rrule: 'Wiederholungsregel',
 
-    day: {
-      sunday: 'Sonntag',
-      monday: 'Montag',
-      tuesday: 'Dienstag',
-      wednesday: 'Mittwoch',
-      thursday: 'Donnerstag',
-      friday: 'Freitag',
-      saturday: 'Samstag',
-    },
-
     rule: {
       1: 'einmalig',
       2: 'täglich',
diff --git a/src/i18n/en.js b/src/i18n/en.js
index 2a831d18f23c53063b39eca34b6b379a100eb858..ee04c5ebcddb483df797792e769e0008faebff37 100644
--- a/src/i18n/en.js
+++ b/src/i18n/en.js
@@ -461,16 +461,6 @@ export default {
   rrule: {
     rrule: 'Repetition rule',
 
-    day: {
-      sunday: 'Sunday',
-      monday: 'Monday',
-      tuesday: 'Tuesday',
-      wednesday: 'Wednesday',
-      thursday: 'Thursday',
-      friday: 'Friday',
-      saturday: 'Saturday',
-    },
-
     rule: {
       1: 'once',
       2: 'daily',
diff --git a/src/mixins/prettyDate.js b/src/mixins/prettyDate.js
index b78ce9b3b012d536c19b74953d2785e8be598118..1ae29d168a2e63eabfc111203abb3b4e3c43dfc8 100644
--- a/src/mixins/prettyDate.js
+++ b/src/mixins/prettyDate.js
@@ -1,115 +1,169 @@
+import { useI18n } from '@/i18n'
+
 const day = [
-  'rrule.day.sunday',
-  'rrule.day.monday',
-  'rrule.day.tuesday',
-  'rrule.day.wednesday',
-  'rrule.day.thursday',
-  'rrule.day.friday',
-  'rrule.day.saturday',
+  // static days from sunday to saturday
+  // (note: month is zero-indexed)
+  new Date(2023, 3, 2),
+  new Date(2023, 3, 3),
+  new Date(2023, 3, 4),
+  new Date(2023, 3, 5),
+  new Date(2023, 3, 6),
+  new Date(2023, 3, 7),
+  new Date(2023, 3, 8),
 ]
 
-export default {
-  methods: {
-    leadingZero(num) {
-      if (num < 10) {
-        return '0' + num
-      } else {
-        return num.toString()
-      }
-    },
+function prettyWeekday(locale, weekday, format = 'long') {
+  return day[(weekday + 1) % 7].toLocaleString(locale, { weekday: format })
+}
 
-    apiDate: function (date) {
-      const dateObj = new Date(date)
-      return `${dateObj.getFullYear()}-${this.leadingZero(
-        dateObj.getMonth() + 1,
-      )}-${this.leadingZero(dateObj.getDate())}`
-    },
-    getWeekdayFromApiDate: function (date) {
-      const dateObj = new Date(date)
-      const weekday = dateObj.getDay()
-      // Date.getDay() returns 0 for Sundays, but for our APIs we need 0 for Mondays
-      if (weekday === 0) {
-        return 6
-      } else {
-        return weekday - 1
-      }
-    },
-    prettyDate: function (date) {
-      return new Date(date).toLocaleString(this.$activeLocale(), {
-        weekday: 'long',
-        day: 'numeric',
-        month: 'long',
-        year: 'numeric',
-      })
-    },
+function leadingZero(num) {
+  return String(num).padStart(2, '0')
+}
 
-    prettyTime: function (date) {
-      return new Date(date).toLocaleString(this.$activeLocale(), {
-        hour: '2-digit',
-        minute: '2-digit',
-      })
-    },
+export function apiDate(date) {
+  const dateObj = new Date(date)
+  return `${dateObj.getFullYear()}-${leadingZero(dateObj.getMonth() + 1)}-${leadingZero(
+    dateObj.getDate(),
+  )}`
+}
 
-    prettyDateTime: function (date) {
-      return new Date(date).toLocaleString(this.$activeLocale(), {
-        weekday: 'long',
-        day: 'numeric',
-        month: 'long',
-        year: 'numeric',
-        hour: '2-digit',
-        minute: '2-digit',
-      })
-    },
-    prettyHours(hours) {
-      return hours.replace(/:00$/, '')
-    },
-    prettyDuration: function (start, end) {
-      const seconds = (new Date(end).getTime() - new Date(start).getTime()) / 1000
-      const minutes = Math.floor(seconds / 60)
-      let duration = minutes + 'min'
-      if (minutes < seconds / 60) {
-        duration += ' '
-        duration += seconds - 60 * minutes
-        duration += 'sec'
-      }
-      return { duration, minutes }
-    },
-    durationInSeconds: function (ns) {
-      const durationInMilliseconds = Math.floor(ns / 1000 / 1000)
+export function getWeekdayFromApiDate(date) {
+  const dateObj = new Date(date)
+  const weekday = dateObj.getDay()
+  // Date.getDay() returns 0 for Sundays, but for our APIs we need 0 for Mondays
+  if (weekday === 0) {
+    return 6
+  } else {
+    return weekday - 1
+  }
+}
 
-      return Math.floor(durationInMilliseconds / 1000)
-    },
-    prettyNanoseconds: function (ns) {
-      const durationInMilliseconds = Math.floor(ns / 1000 / 1000)
+function prettyDate(locale, date) {
+  return new Date(date).toLocaleString(locale, {
+    weekday: 'long',
+    day: 'numeric',
+    month: 'long',
+    year: 'numeric',
+  })
+}
+
+function prettyTime(locale, date) {
+  return new Date(date).toLocaleString(locale, {
+    hour: '2-digit',
+    minute: '2-digit',
+  })
+}
+
+function prettyDateTime(locale, date) {
+  return new Date(date).toLocaleString(locale, {
+    weekday: 'long',
+    day: 'numeric',
+    month: 'long',
+    year: 'numeric',
+    hour: '2-digit',
+    minute: '2-digit',
+  })
+}
 
-      const seconds = Math.floor((durationInMilliseconds / 1000) % 60)
-      const minutes = Math.floor((durationInMilliseconds / (1000 * 60)) % 60)
-      const hours = Math.floor((durationInMilliseconds / (1000 * 60 * 60)) % 24)
+export function prettyHours(hours) {
+  return hours.replace(/:00$/, '')
+}
+
+export function prettyDuration(start, end) {
+  const seconds = (new Date(end).getTime() - new Date(start).getTime()) / 1000
+  const minutes = Math.floor(seconds / 60)
+  let duration = minutes + 'min'
+  if (minutes < seconds / 60) {
+    duration += ' '
+    duration += seconds - 60 * minutes
+    duration += 'sec'
+  }
+  return { duration, minutes }
+}
 
-      return (
-        this.leadingZero(hours) + ':' + this.leadingZero(minutes) + ':' + this.leadingZero(seconds)
-      )
+export function durationInSeconds(ns) {
+  const durationInMilliseconds = Math.floor(ns / 1000 / 1000)
+  return Math.floor(durationInMilliseconds / 1000)
+}
+
+export function prettyNanoseconds(ns) {
+  const durationInMilliseconds = Math.floor(ns / 1000 / 1000)
+  const seconds = Math.floor((durationInMilliseconds / 1000) % 60)
+  const minutes = Math.floor((durationInMilliseconds / (1000 * 60)) % 60)
+  const hours = Math.floor((durationInMilliseconds / (1000 * 60 * 60)) % 24)
+
+  return `${leadingZero(hours)}:${leadingZero(minutes)}:${leadingZero(seconds)}`
+}
+
+export function nanosecondsToMinutes(ns) {
+  return ns / 1000 / 1000 / 1000 / 60
+}
+
+export function minutesToNanoseconds(m) {
+  return m * 60 * 1000 * 1000 * 1000
+}
+
+export function hmsToNanoseconds(hms) {
+  const parts = hms.split(':')
+  const seconds = +parts[0] * 60 * 60 + +parts[1] * 60 + +parts[2]
+
+  return seconds * 1000 * 1000 * 1000
+}
+
+export function minutesToHm(minutes) {
+  const numMinutes = minutes % 60
+  const numHours = (minutes - numMinutes) / 60
+
+  return `${leadingZero(numHours)}:${leadingZero(numMinutes)}`
+}
+
+const methods = {
+  leadingZero,
+  apiDate,
+  getWeekdayFromApiDate,
+  prettyHours,
+  prettyDuration,
+  durationInSeconds,
+  prettyNanoseconds,
+  nanosecondsToMinutes,
+  minutesToNanoseconds,
+  hmsToNanoseconds,
+  minutesToHm,
+}
+
+export function usePretty() {
+  const { locale } = useI18n()
+  return {
+    ...methods,
+    prettyDate(date) {
+      return prettyDate(locale.value, date)
     },
-    nanosecondsToMinutes: function (ns) {
-      return ns / 1000 / 1000 / 1000 / 60
+    prettyTime(date) {
+      return prettyTime(locale.value, date)
     },
-    minutesToNanoseconds: function (m) {
-      return m * 60 * 1000 * 1000 * 1000
+    prettyDateTime(date) {
+      return prettyDateTime(locale.value, date)
     },
-    hmsToNanoseconds: function (hms) {
-      const parts = hms.split(':')
-      const seconds = +parts[0] * 60 * 60 + +parts[1] * 60 + +parts[2]
-
-      return seconds * 1000 * 1000 * 1000
+    prettyWeekday(weekday) {
+      return prettyWeekday(locale.value, weekday)
     },
-    minutesToHm: function (minutes) {
-      const numMinutes = minutes % 60
-      const numHours = (minutes - numMinutes) / 60
+  }
+}
 
-      return `${this.leadingZero(numHours)}:${this.leadingZero(numMinutes)}`
+export default {
+  methods: {
+    ...methods,
+    prettyDate(date) {
+      return prettyDate(this.$activeLocale(), date)
+    },
+    prettyTime(date) {
+      return prettyTime(this.$activeLocale(), date)
+    },
+    prettyDateTime(date) {
+      return prettyDateTime(this.$activeLocale(), date)
     },
-    prettyWeekday: function (weekday) {
-      return this.$t(day[(weekday + 1) % 7])
+    prettyWeekday(weekday) {
+      return prettyWeekday(this.$activeLocale(), weekday)
     },
   },
 }
diff --git a/src/mixins/rrules.js b/src/mixins/rrules.js
index 93d833dfa9ac694a0006dcb83616a85ffe5e94b8..59f9b73d90bf4a5ec6afce7a79e819f4c7c46747 100644
--- a/src/mixins/rrules.js
+++ b/src/mixins/rrules.js
@@ -1,27 +1,46 @@
+import { computed } from 'vue'
+import { useI18n } from '@/i18n'
+
+function rruleRender(t, rruleId) {
+  return t(`rrule.rule.${rruleId}`)
+}
+
+function rruleOptions(t) {
+  return [
+    { value: 1, text: t('rrule.rule.1') },
+    { value: 2, text: t('rrule.rule.2') },
+    { value: 3, text: t('rrule.rule.3') },
+    { value: 4, text: t('rrule.rule.4') },
+    { value: 5, text: t('rrule.rule.5') },
+    { value: 6, text: t('rrule.rule.6') },
+    { value: 7, text: t('rrule.rule.7') },
+    { value: 8, text: t('rrule.rule.8') },
+    { value: 9, text: t('rrule.rule.9') },
+    { value: 10, text: t('rrule.rule.10') },
+    { value: 11, text: t('rrule.rule.11') },
+    { value: 12, text: t('rrule.rule.12') },
+    { value: 13, text: t('rrule.rule.13') },
+  ]
+}
+
+export function useRRule() {
+  const { t } = useI18n()
+  const rruleOptions = computed(() => rruleOptions(t))
+  return {
+    rruleOptions,
+    rruleRender: (rruleID) => rruleRender(t, rruleID),
+  }
+}
+
 export default {
   computed: {
     rruleOptions() {
-      return [
-        { value: 1, text: this.$t('rrule.rule.1') },
-        { value: 2, text: this.$t('rrule.rule.2') },
-        { value: 3, text: this.$t('rrule.rule.3') },
-        { value: 4, text: this.$t('rrule.rule.4') },
-        { value: 5, text: this.$t('rrule.rule.5') },
-        { value: 6, text: this.$t('rrule.rule.6') },
-        { value: 7, text: this.$t('rrule.rule.7') },
-        { value: 8, text: this.$t('rrule.rule.8') },
-        { value: 9, text: this.$t('rrule.rule.9') },
-        { value: 10, text: this.$t('rrule.rule.10') },
-        { value: 11, text: this.$t('rrule.rule.11') },
-        { value: 12, text: this.$t('rrule.rule.12') },
-        { value: 13, text: this.$t('rrule.rule.13') },
-      ]
+      return rruleOptions(this.$t)
     },
   },
-
   methods: {
     rruleRender(rrule) {
-      return this.$t(`rrule.rule.${rrule}`)
+      return rruleRender(this.$t, rrule)
     },
   },
 }