UNPKG

4.49 kBJavaScriptView Raw
1/**
2 * Default configuration object.
3 */
4export const defaultTranslateConfig = {
5 loader: () => Promise.resolve({}),
6 emptyPlaceholder: key => `[${key}]`,
7 getTranslation: getTranslation,
8 interpolate: interpolate,
9 translationCache: {},
10 languageCache: {},
11 lang: null,
12 translations: null
13};
14// The current configuration for the translation.
15let currentConfig = defaultTranslateConfig;
16/**
17 * Registers a translation config.
18 * @param config
19 */
20export function registerTranslateConfig(config) {
21 return (currentConfig = Object.assign({}, currentConfig, config));
22}
23/**
24 * Loads translations using either the values from the cache or the provided translations loader.
25 * @param lang
26 * @param config
27 */
28export async function loadTranslations(lang, config = currentConfig) {
29 return config.languageCache[lang] != null ? config.languageCache[lang] : await currentConfig.loader(lang, config);
30}
31/**
32 * Dispatches a language changed event.
33 * @param detail
34 */
35export function dispatchLangChanged(detail) {
36 window.dispatchEvent(new CustomEvent("langChanged" /* LANG_CHANGED */, { detail }));
37}
38/**
39 * Updates the configuration object with a new language and translations and then dispatches than the language has changed.
40 * @param config
41 * @param newLang
42 * @param newTranslations
43 */
44export function updateConfig(config, newLang, newTranslations) {
45 dispatchLangChanged({
46 previousTranslations: config.translations,
47 previousLang: config.lang,
48 lang: (config.lang = newLang),
49 translations: (config.translations = newTranslations)
50 });
51}
52/**
53 * Listens for changes in the language.
54 * Returns a method for unsubscribing from the event.
55 * @param callback
56 * @param options
57 */
58export function listenForLangChanged(callback, options) {
59 const handler = (e) => callback(e.detail);
60 window.addEventListener("langChanged" /* LANG_CHANGED */, handler, options);
61 return () => window.removeEventListener("langChanged" /* LANG_CHANGED */, handler);
62}
63/**
64 * Sets a new current language and dispatches a global language changed event.
65 * @param lang
66 * @param config
67 */
68export async function use(lang, config = currentConfig) {
69 // Load the translations and set the cache
70 const translations = await loadTranslations(lang);
71 config.languageCache[lang] = translations;
72 config.translationCache = {};
73 // Dispatch global language changed event while setting the new values
74 updateConfig(config, lang, translations);
75}
76/**
77 * Interpolates the values into the string.
78 * @param text
79 * @param values
80 */
81export function interpolate(text, values) {
82 return Object.entries(extract(values)).reduce((text, [key, value]) => text.replace(new RegExp(`{{[  ]*${key}[  ]*}}`), String(extract(value))), text);
83}
84/**
85 * Returns a translation based on a chain of keys using the dot notation.
86 * @param key
87 * @param config
88 */
89export function getTranslation(key, config = currentConfig) {
90 // Split the key in parts (example: hello.world)
91 const parts = key.split(".");
92 // Find the translation by traversing through the strings matching the chain of keys
93 let translation = config.translations || {};
94 while (parts.length > 0) {
95 translation = translation[parts.shift()];
96 // Do not continue if the translation is not defined
97 if (translation == null)
98 return config.emptyPlaceholder(key, config);
99 }
100 // Make sure the translation is a string!
101 return translation.toString();
102}
103/**
104 * Translates a key and interpolates if values are defined.
105 * Uses the current strings and string cache to fetch the string.
106 * @param key (eg. "common.get_started")
107 * @param values (eg. { count: 42 })
108 * @param config
109 */
110export function get(key, values, config = currentConfig) {
111 // Either use the translation from the cache or get it and add it to the cache
112 let translation = config.translationCache[key]
113 || (config.translationCache[key] = config.getTranslation(key, config));
114 // Extract the values
115 values = values != null ? extract(values) : null;
116 // Replace the placeholders and return the translation
117 return values != null ? currentConfig.interpolate(translation, values, config) : translation;
118}
119/**
120 * Extracts either the value from the function or return the value that was passed in.
121 * @param obj
122 */
123export function extract(obj) {
124 return (typeof obj === "function") ? obj() : obj;
125}
126//# sourceMappingURL=translate.js.map
\No newline at end of file