forked from samuelmeuli/mini-diary
-
Notifications
You must be signed in to change notification settings - Fork 0
/
i18n.ts
125 lines (113 loc) · 3.99 KB
/
i18n.ts
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { app } from "electron";
import logger from "electron-log";
import { Translations } from "../../shared/types";
import translationsDe from "./translations/de";
import translationsEl from "./translations/el";
import translationsEn from "./translations/en";
import translationsEs from "./translations/es";
import translationsFr from "./translations/fr";
import translationsIs from "./translations/is";
import translationsIt from "./translations/it";
import translationsNo from "./translations/no";
import translationsPt from "./translations/pt";
import translationsTr from "./translations/tr";
import translationsUk from "./translations/uk";
import translationsZh from "./translations/zh";
import translationsZhTw from "./translations/zhTw";
const ALL_TRANSLATIONS: Record<string, Partial<Translations>> = {
de: translationsDe,
el: translationsEl,
en: translationsEn,
es: translationsEs,
fr: translationsFr,
is: translationsIs,
it: translationsIt,
nb: translationsNo,
no: translationsNo,
pt: translationsPt,
tr: translationsTr,
uk: translationsUk,
zh: translationsZh,
"zh-TW": translationsZhTw,
};
let translations: Partial<Translations>; // String translations for langNoRegion
const FALLBACK_LANG = "en";
let systemLang;
let lang: string; // Language used by app (e.g. 'en-US'), used for dates/calendar
let langNoRegion: string; // Language used by app without region string (e.g. 'en'), used for translations
/**
* Return language to use for the app
*/
export function getUsedLang(): string {
return lang;
}
/**
* Determine language to use for the app (use system language if translations are available,
* otherwise fall back to default language
*/
export function initI18n(): void {
systemLang = app.getLocale();
const systemLangNoRegion = systemLang.split("-")[0];
const defaultTranslations = ALL_TRANSLATIONS[FALLBACK_LANG];
logger.log(`System language is "${systemLang}" ("${systemLangNoRegion}" without region)`);
if (systemLang in ALL_TRANSLATIONS) {
// This if-else statement can ensure that if there is any region-specified localizations found,
// the system will detect and choose the regional localization, instead of the more general one
lang = systemLang;
translations = {
...defaultTranslations,
...ALL_TRANSLATIONS[lang],
};
logger.log(`Using "${lang}" locale and translations`);
} else if (systemLangNoRegion in ALL_TRANSLATIONS) {
// Use system language if translations are available
lang = systemLang;
langNoRegion = systemLangNoRegion;
translations = {
...defaultTranslations,
...ALL_TRANSLATIONS[langNoRegion],
};
logger.log(`Using "${lang}" locale and "${langNoRegion}" translations`);
} else {
// Otherwise, fall back to default language
lang = FALLBACK_LANG;
langNoRegion = FALLBACK_LANG;
translations = defaultTranslations;
logger.log(`Using default locale and translations ("${FALLBACK_LANG}")`);
}
}
/**
* Return translation for string with the provided translation key. Perform string substitutions if
* required
*/
export function translate(
i18nKey: keyof Translations,
substitutions?: Record<string, string>,
): string {
let translation = translations[i18nKey];
// Log error and return `i18nKey` if translation string is missing both in current and fallback
// language
if (!translation) {
logger.error(`Missing translation of i18nKey "${i18nKey}"`);
return i18nKey;
}
// Return translation if no `substitutions` object is provided
if (!substitutions) {
return translation;
}
// Perform string substitutions if `substitutions` object is provided
// Example:
// Translation definition: { test: 'Hello {var}' }
// Function call: translate('test', { var: 'World' })
// Result: 'Hello World'
Object.entries(substitutions).forEach(([toReplace, replacement]): void => {
translation = (translation as string).replace(new RegExp(`{${toReplace}}`, "g"), replacement);
});
return translation;
}
/**
* Return all translations for the detected language
*/
export function getTranslations(): Partial<Translations> {
return translations;
}