Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/frontend/src/preferences.ts
blob: 59b8d0da61c93d1ca0a28f78f6d070146316854f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
// SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1

import { computed, ref, watch } from "vue";
import {
  forwardArrow,
  initialLocale,
  isVisitorChoice,
  textDirection,
  type Locale,
} from "./locales";

export { supportedLocales, type Locale } from "./locales";
export type Theme = "dark" | "light";

// Holds a language only after the visitor picked one in the menu. The earlier
// `vxs-locale` key was written on every visit, so it cannot tell a choice
// from the former English default and is no longer read.
const localeChoiceKey = "tala-locale-choice";
const themeKey = "tala-theme";

// The keys carried the former name of the language. A value stored under the
// former key moves to the current one once, so no visitor loses a choice.
function migrate(key: string, former: string): void {
  const value = localStorage.getItem(former);
  if (value !== null && localStorage.getItem(key) === null) {
    localStorage.setItem(key, value);
  }
  localStorage.removeItem(former);
}
migrate(localeChoiceKey, "vxs-locale-choice");
migrate(themeKey, "vxs-theme");

function storedTheme(): Theme {
  return localStorage.getItem(themeKey) === "light" ? "light" : "dark";
}

export const locale = ref<Locale>(
  initialLocale(localStorage.getItem(localeChoiceKey), navigator.languages ?? []),
);
export const theme = ref<Theme>(storedTheme());

/** The arrow that points onward in the current language. */
export const arrow = computed(() => forwardArrow(locale.value));

function showLocale(value: Locale): void {
  document.documentElement.lang = value;
  document.documentElement.dataset.textDirection = textDirection(value);
}

showLocale(locale.value);
// The language changes through the menu. It is remembered only when a
// visitor has acted on the page, so nothing but a person makes a choice.
watch(locale, (value) => {
  showLocale(value);
  if (isVisitorChoice(navigator.userActivation)) {
    localStorage.setItem(localeChoiceKey, value);
  }
});

watch(
  theme,
  (value) => {
    document.documentElement.dataset.theme = value;
    localStorage.setItem(themeKey, value);
  },
  { immediate: true },
);