File size: 1,712 Bytes
494c9e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import * as d3 from 'd3';
import { getCurrentLanguage, setLanguage, type Language } from '../lang/i18n-lite';
import { tr } from '../lang/i18n-lite';
import { createSettingsDropdown } from './settingsDropdown';

export type LanguageManagerOptions = {
    onLanguageChange?: () => void;
};

export type LanguageManager = {
    dispose: () => void;
};

const languageOptions: Array<{ lang: Language; label: string }> = [
    { lang: 'en', label: 'English' },
    { lang: 'zh', label: 'Chinese' },
];

export function initLanguageManager(options: LanguageManagerOptions = {}, containerSelector: string = '#language_toggle'): LanguageManager {
    const { onLanguageChange } = options;
    const container = d3.select(containerSelector);

    const selectLang = (lang: Language) => {
        setLanguage(lang);
        dropdown.updateCurrent(lang);
        onLanguageChange?.();
        location.reload();
    };

    const dropdown = createSettingsDropdown<Language>({
        container,
        classPrefix: 'language',
        options: languageOptions.map(({ lang, label }) => ({ value: lang, html: `<span>${tr(label)}</span>` })),
        dataAttr: 'data-lang',
        bodyClickNamespace: 'language-dropdown',
        onSelect: selectLang,
    });

    const storageListener = (event: StorageEvent) => {
        if (event.key !== 'app_language') return;
        if (event.newValue === 'en' || event.newValue === 'zh') location.reload();
    };

    dropdown.updateCurrent(getCurrentLanguage());
    window.addEventListener('storage', storageListener);

    return {
        dispose: () => {
            window.removeEventListener('storage', storageListener);
            dropdown.dispose();
        },
    };
}