/
_app-translations.js
116 lines (91 loc) · 3.42 KB
/
_app-translations.js
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
// @flow
import { loadMessageTranslationList } from '../../../shared/get-translations';
import { getDefault } from '../../../shared/util/ModuleUtil';
import { triggerHotReload } from './_hot-reload';
import { getFileName, getLocaleBestFit, runBundleLoader } from './_locale-utils';
import { getActiveLocale } from './index';
let messageTranslationsLoaders = loadMessageTranslationList();
let localeToFileMapping: Map<string, string> = buildMessagesLocaleList(messageTranslationsLoaders);
function buildMessagesLocaleList(loaders) {
const mapping = new Map();
loaders.keys().map(filePath => {
const locale = getFileName(filePath);
// if there is a fr.js and fr.json file, throw.
if (mapping.has(locale)) {
throw new Error(`Duplicate translation file for locale ${JSON.stringify(locale)}`);
}
mapping.set(locale, filePath);
return locale;
});
return mapping;
}
function formatTranslationMessages(messages) {
if (!Array.isArray(messages)) {
return messages;
}
const formattedMessages = {};
for (const message of messages) {
formattedMessages[message.id] = message.message || message.defaultMessage;
}
return formattedMessages;
}
let messageTranslations = {};
function getReactIntlMessages() {
return messageTranslations;
}
function installReactIntlMessagesForLocale(locale: string): Promise<void> {
return downloadMessagesTranslationFile(locale)
.then(translations => {
if (translations == null || typeof translations !== 'object') {
throw new TypeError(`Invalid translation file for locale ${JSON.stringify(locale)}, expected it to export an Object or an Array.`);
}
messageTranslations = formatTranslationMessages(translations);
Object.freeze(messageTranslations);
});
}
function downloadMessagesTranslationFile(localeName: string): Promise<any> {
return Promise.resolve().then(() => {
// if we're trying to load en-US but we only have en, using en is fine.
const actualLocale = getMessageLocaleBestFit(localeName);
if (actualLocale == null) {
throw new Error(`Unknown locale ${JSON.stringify(localeName)}. Did you forget to add the translation file ?`);
}
const file = localeToFileMapping.get(actualLocale);
if (file == null) {
throw new Error('ReworkJs: Internal Error while loading locale');
}
const loader = messageTranslationsLoaders(file);
return runBundleLoader(loader)
.then(module => getDefault(module));
});
}
function getMessageLocaleBestFit(localeName: string) {
return getLocaleBestFit(localeName, [...localeToFileMapping.keys()]);
}
/**
* Checks if a given locale has matching translations in this app.
* (eg. Is this app available in dutch?)
*
* @param localeName The locale for which we wish to know if the translation exists.
* @returns Whether the translation is available.
*/
function isTranslationSupported(localeName: string): boolean {
return getMessageLocaleBestFit(localeName) !== null;
}
export {
installReactIntlMessagesForLocale,
getReactIntlMessages,
isTranslationSupported,
};
// HOT RELOAD INDIVIDUAL TRANSLATION FILES
// $FlowIgnore
if (module.hot) {
module.hot.accept(messageTranslationsLoaders.id, () => {
messageTranslationsLoaders = loadMessageTranslationList();
localeToFileMapping = buildMessagesLocaleList(messageTranslationsLoaders);
installReactIntlMessagesForLocale(getActiveLocale())
.then(() => {
triggerHotReload();
});
});
}