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 },
);
|