UNPKG

15.6 kBJavaScriptView Raw
1/** Copyright (c) 2018 Uber Technologies, Inc.
2 *
3 * This source code is licensed under the MIT license found in the
4 * LICENSE file in the root directory of this source tree.
5 *
6 *
7 */
8
9/* eslint-env browser */
10import { FetchToken } from 'fusion-tokens';
11import { createPlugin, unescape, createToken } from 'fusion-core';
12import { UniversalEventsToken } from 'fusion-plugin-universal-events';
13
14function loadTranslations() {
15 const element = document.getElementById('__TRANSLATIONS__');
16
17 if (!element) {
18 throw new Error('[fusion-plugin-i18n] - Could not find a __TRANSLATIONS__ element');
19 }
20
21 try {
22 return JSON.parse(unescape(element.textContent));
23 } catch (e) {
24 throw new Error('[fusion-plugin-i18n] - Error parsing __TRANSLATIONS__ element content');
25 }
26}
27
28export const HydrationStateToken = createToken('HydrationStateToken');
29
30const pluginFactory = () => createPlugin({
31 deps: {
32 fetch: FetchToken.optional,
33 hydrationState: HydrationStateToken.optional,
34 events: UniversalEventsToken.optional
35 },
36 provides: ({
37 fetch = window.fetch,
38 hydrationState,
39 events
40 } = {}) => {
41 class I18n {
42 constructor() {
43 const {
44 localeCode,
45 translations
46 } = hydrationState || loadTranslations();
47 this.requestedKeys = new Set();
48 this.translations = translations || {};
49
50 if (localeCode) {
51 this.locale = localeCode;
52 }
53 }
54
55 async load(translationKeys) {
56 const loadedKeys = Object.keys(this.translations);
57 const unloaded = translationKeys.filter(key => {
58 return loadedKeys.indexOf(key) < 0 && !this.requestedKeys.has(key);
59 });
60
61 if (unloaded.length > 0) {
62 // Don't try to load translations again if a request is already in
63 // flight. This means that we need to add unloaded chunks to
64 // loadedChunks optimistically and remove them if some error happens
65 unloaded.forEach(key => {
66 this.requestedKeys.add(key);
67 });
68 const fetchOpts = {
69 method: 'POST',
70 headers: {
71 Accept: '*/*',
72 'Content-Type': 'application/json',
73 ...(this.locale ? {
74 'X-Fusion-Locale-Code': this.locale
75 } : {})
76 },
77 body: JSON.stringify(unloaded)
78 }; // TODO(#3) don't append prefix if injected fetch also injects prefix
79
80 return fetch(`/_translations${this.locale ? `?localeCode=${this.locale}` : ''}`, fetchOpts).then(r => {
81 try {
82 return r.json();
83 } catch (err) {
84 events && events.emit('i18n-load-error', {
85 text: r.text()
86 });
87 throw err;
88 }
89 }).then(data => {
90 for (const key in data) {
91 this.translations[key] = data[key];
92 this.requestedKeys.delete(key);
93 }
94 }).catch(err => {
95 // An error occurred, so remove the chunks we were trying to load
96 // from loadedChunks. This allows us to try to load those chunk
97 // translations again
98 unloaded.forEach(key => {
99 this.requestedKeys.delete(key);
100 });
101 });
102 }
103 }
104
105 translate(key, interpolations = {}) {
106 const template = this.translations[key];
107
108 if (typeof template !== 'string') {
109 events && events.emit('i18n-translate-miss', {
110 key
111 });
112 return key;
113 }
114
115 return template.replace(/\${(.*?)}/g, (_, k) => interpolations[k] === void 0 ? '${' + k + '}' : String(interpolations[k]));
116 }
117
118 }
119
120 const i18n = new I18n();
121 return {
122 from: () => i18n
123 };
124 }
125});
126
127export default false && pluginFactory();
128//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImJyb3dzZXIuanMiXSwibmFtZXMiOlsiRmV0Y2hUb2tlbiIsImNyZWF0ZVBsdWdpbiIsInVuZXNjYXBlIiwiY3JlYXRlVG9rZW4iLCJVbml2ZXJzYWxFdmVudHNUb2tlbiIsImxvYWRUcmFuc2xhdGlvbnMiLCJlbGVtZW50IiwiZG9jdW1lbnQiLCJnZXRFbGVtZW50QnlJZCIsIkVycm9yIiwiSlNPTiIsInBhcnNlIiwidGV4dENvbnRlbnQiLCJlIiwiSHlkcmF0aW9uU3RhdGVUb2tlbiIsInBsdWdpbkZhY3RvcnkiLCJkZXBzIiwiZmV0Y2giLCJvcHRpb25hbCIsImh5ZHJhdGlvblN0YXRlIiwiZXZlbnRzIiwicHJvdmlkZXMiLCJ3aW5kb3ciLCJJMThuIiwiY29uc3RydWN0b3IiLCJsb2NhbGVDb2RlIiwidHJhbnNsYXRpb25zIiwicmVxdWVzdGVkS2V5cyIsIlNldCIsImxvY2FsZSIsImxvYWQiLCJ0cmFuc2xhdGlvbktleXMiLCJsb2FkZWRLZXlzIiwiT2JqZWN0Iiwia2V5cyIsInVubG9hZGVkIiwiZmlsdGVyIiwia2V5IiwiaW5kZXhPZiIsImhhcyIsImxlbmd0aCIsImZvckVhY2giLCJhZGQiLCJmZXRjaE9wdHMiLCJtZXRob2QiLCJoZWFkZXJzIiwiQWNjZXB0IiwiYm9keSIsInN0cmluZ2lmeSIsInRoZW4iLCJyIiwianNvbiIsImVyciIsImVtaXQiLCJ0ZXh0IiwiZGF0YSIsImRlbGV0ZSIsImNhdGNoIiwidHJhbnNsYXRlIiwiaW50ZXJwb2xhdGlvbnMiLCJ0ZW1wbGF0ZSIsInJlcGxhY2UiLCJfIiwiayIsIlN0cmluZyIsImkxOG4iLCJmcm9tIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7QUFRQTtBQUNBLFNBQVFBLFVBQVIsUUFBeUIsZUFBekI7QUFDQSxTQUFRQyxZQUFSLEVBQXNCQyxRQUF0QixFQUFnQ0MsV0FBaEMsUUFBa0QsYUFBbEQ7QUFFQSxTQUFRQyxvQkFBUixRQUFtQyxnQ0FBbkM7O0FBWUEsU0FBU0MsZ0JBQVQsR0FBb0Q7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Q0FBRCxDQUFkLEtBQXNCLEtBQUssQ0FBM0IsR0FDSSxPQUFPQSxDQUFQLEdBQVcsR0FEZixHQUVJQyxNQUFNLENBQUNMLGNBQWMsQ0FBQ0ksQ0FBRCxDQUFmLENBSEwsQ0FBUDtBQUtEOztBQS9FUTs7QUFpRlgsVUFBTUUsSUFBSSxHQUFHLElBQUkxQyxJQUFKLEVBQWI7QUFDQSxXQUFPO0FBQUMyQyxNQUFBQSxJQUFJLEVBQUUsTUFBTUQ7QUFBYixLQUFQO0FBQ0Q7QUExRlUsQ0FBRCxDQURkOztBQThGQSxlQUFpQixTQUFlbEQsYUFBYSxFQUE3QyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBDb3B5cmlnaHQgKGMpIDIwMTggVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbi8qIGVzbGludC1lbnYgYnJvd3NlciAqL1xuaW1wb3J0IHtGZXRjaFRva2VufSBmcm9tICdmdXNpb24tdG9rZW5zJztcbmltcG9ydCB7Y3JlYXRlUGx1Z2luLCB1bmVzY2FwZSwgY3JlYXRlVG9rZW59IGZyb20gJ2Z1c2lvbi1jb3JlJztcbmltcG9ydCB0eXBlIHtGdXNpb25QbHVnaW4sIFRva2VufSBmcm9tICdmdXNpb24tY29yZSc7XG5pbXBvcnQge1VuaXZlcnNhbEV2ZW50c1Rva2VufSBmcm9tICdmdXNpb24tcGx1Z2luLXVuaXZlcnNhbC1ldmVudHMnO1xuXG5pbXBvcnQgdHlwZSB7XG4gIEkxOG5EZXBzVHlwZSxcbiAgSTE4blNlcnZpY2VUeXBlLFxuICBUcmFuc2xhdGlvbnNPYmplY3RUeXBlLFxufSBmcm9tICcuL3R5cGVzLmpzJztcblxudHlwZSBMb2FkZWRUcmFuc2xhdGlvbnNUeXBlID0ge1xuICBsb2NhbGVDb2RlPzogc3RyaW5nLFxuICB0cmFuc2xhdGlvbnM/OiBUcmFuc2xhdGlvbnNPYmplY3RUeXBlLFxufTtcbmZ1bmN0aW9uIGxvYWRUcmFuc2xhdGlvbnMoKTogTG9hZGVkVHJhbnNsYXRpb25zVHlwZSB7XG4gIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnX19UUkFOU0xBVElPTlNfXycpO1xuICBpZiAoIWVsZW1lbnQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnW2Z1c2lvbi1wbHVnaW4taTE4bl0gLSBDb3VsZCBub3QgZmluZCBhIF9fVFJBTlNMQVRJT05TX18gZWxlbWVudCdcbiAgICApO1xuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UodW5lc2NhcGUoZWxlbWVudC50ZXh0Q29udGVudCkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ1tmdXNpb24tcGx1Z2luLWkxOG5dIC0gRXJyb3IgcGFyc2luZyBfX1RSQU5TTEFUSU9OU19fIGVsZW1lbnQgY29udGVudCdcbiAgICApO1xuICB9XG59XG5cbnR5cGUgSHlkcmF0aW9uU3RhdGVUeXBlID0ge1xuICBsb2NhbGVDb2RlPzogc3RyaW5nLFxuICB0cmFuc2xhdGlvbnM6IFRyYW5zbGF0aW9uc09iamVjdFR5cGUsXG59O1xuZXhwb3J0IGNvbnN0IEh5ZHJhdGlvblN0YXRlVG9rZW46IFRva2VuPEh5ZHJhdGlvblN0YXRlVHlwZT4gPSBjcmVhdGVUb2tlbihcbiAgJ0h5ZHJhdGlvblN0YXRlVG9rZW4nXG4pO1xuXG50eXBlIFBsdWdpblR5cGUgPSBGdXNpb25QbHVnaW48STE4bkRlcHNUeXBlLCBJMThuU2VydmljZVR5cGU+O1xuY29uc3QgcGx1Z2luRmFjdG9yeTogKCkgPT4gUGx1Z2luVHlwZSA9ICgpID0+XG4gIGNyZWF0ZVBsdWdpbih7XG4gICAgZGVwczoge1xuICAgICAgZmV0Y2g6IEZldGNoVG9rZW4ub3B0aW9uYWwsXG4gICAgICBoeWRyYXRpb25TdGF0ZTogSHlkcmF0aW9uU3RhdGVUb2tlbi5vcHRpb25hbCxcbiAgICAgIGV2ZW50czogVW5pdmVyc2FsRXZlbnRzVG9rZW4ub3B0aW9uYWwsXG4gICAgfSxcbiAgICBwcm92aWRlczogKHtmZXRjaCA9IHdpbmRvdy5mZXRjaCwgaHlkcmF0aW9uU3RhdGUsIGV2ZW50c30gPSB7fSkgPT4ge1xuICAgICAgY2xhc3MgSTE4biB7XG4gICAgICAgIGxvY2FsZTogc3RyaW5nO1xuICAgICAgICB0cmFuc2xhdGlvbnM6IFRyYW5zbGF0aW9uc09iamVjdFR5cGU7XG4gICAgICAgIHJlcXVlc3RlZEtleXM6IFNldDxzdHJpbmc+O1xuXG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgIGNvbnN0IHtsb2NhbGVDb2RlLCB0cmFuc2xhdGlvbnN9ID1cbiAgICAgICAgICAgIGh5ZHJhdGlvblN0YXRlIHx8IGxvYWRUcmFuc2xhdGlvbnMoKTtcbiAgICAgICAgICB0aGlzLnJlcXVlc3RlZEtleXMgPSBuZXcgU2V0KCk7XG4gICAgICAgICAgdGhpcy50cmFuc2xhdGlvbnMgPSB0cmFuc2xhdGlvbnMgfHwge307XG4gICAgICAgICAgaWYgKGxvY2FsZUNvZGUpIHtcbiAgICAgICAgICAgIHRoaXMubG9jYWxlID0gbG9jYWxlQ29kZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXN5bmMgbG9hZCh0cmFuc2xhdGlvbktleXMpIHtcbiAgICAgICAgICBjb25zdCBsb2FkZWRLZXlzID0gT2JqZWN0LmtleXModGhpcy50cmFuc2xhdGlvbnMpO1xuICAgICAgICAgIGNvbnN0IHVubG9hZGVkID0gdHJhbnNsYXRpb25LZXlzLmZpbHRlcihrZXkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGxvYWRlZEtleXMuaW5kZXhPZihrZXkpIDwgMCAmJiAhdGhpcy5yZXF1ZXN0ZWRLZXlzLmhhcyhrZXkpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmICh1bmxvYWRlZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAvLyBEb24ndCB0cnkgdG8gbG9hZCB0cmFuc2xhdGlvbnMgYWdhaW4gaWYgYSByZXF1ZXN0IGlzIGFscmVhZHkgaW5cbiAgICAgICAgICAgIC8vIGZsaWdodC4gVGhpcyBtZWFucyB0aGF0IHdlIG5lZWQgdG8gYWRkIHVubG9hZGVkIGNodW5rcyB0b1xuICAgICAgICAgICAgLy8gbG9hZGVkQ2h1bmtzIG9wdGltaXN0aWNhbGx5IGFuZCByZW1vdmUgdGhlbSBpZiBzb21lIGVycm9yIGhhcHBlbnNcbiAgICAgICAgICAgIHVubG9hZGVkLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0ZWRLZXlzLmFkZChrZXkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBmZXRjaE9wdHMgPSB7XG4gICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgQWNjZXB0OiAnKi8qJyxcbiAgICAgICAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgICAgIC4uLih0aGlzLmxvY2FsZSA/IHsnWC1GdXNpb24tTG9jYWxlLUNvZGUnOiB0aGlzLmxvY2FsZX0gOiB7fSksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHVubG9hZGVkKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBUT0RPKCMzKSBkb24ndCBhcHBlbmQgcHJlZml4IGlmIGluamVjdGVkIGZldGNoIGFsc28gaW5qZWN0cyBwcmVmaXhcbiAgICAgICAgICAgIHJldHVybiBmZXRjaChcbiAgICAgICAgICAgICAgYC9fdHJhbnNsYXRpb25zJHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsZSA/IGA/bG9jYWxlQ29kZT0ke3RoaXMubG9jYWxlfWAgOiAnJ1xuICAgICAgICAgICAgICB9YCxcbiAgICAgICAgICAgICAgZmV0Y2hPcHRzXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAgIC50aGVuKHIgPT4ge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gci5qc29uKCk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICBldmVudHMgJiYgZXZlbnRzLmVtaXQoJ2kxOG4tbG9hZC1lcnJvcicsIHt0ZXh0OiByLnRleHQoKX0pO1xuICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLnRoZW4oKGRhdGE6IHtbc3RyaW5nXTogc3RyaW5nfSkgPT4ge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNsYXRpb25zW2tleV0gPSBkYXRhW2tleV07XG4gICAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RlZEtleXMuZGVsZXRlKGtleSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuY2F0Y2goKGVycjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBBbiBlcnJvciBvY2N1cnJlZCwgc28gcmVtb3ZlIHRoZSBjaHVua3Mgd2Ugd2VyZSB0cnlpbmcgdG8gbG9hZFxuICAgICAgICAgICAgICAgIC8vIGZyb20gbG9hZGVkQ2h1bmtzLiBUaGlzIGFsbG93cyB1cyB0byB0cnkgdG8gbG9hZCB0aG9zZSBjaHVua1xuICAgICAgICAgICAgICAgIC8vIHRyYW5zbGF0aW9ucyBhZ2FpblxuICAgICAgICAgICAgICAgIHVubG9hZGVkLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdGVkS2V5cy5kZWxldGUoa2V5KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRyYW5zbGF0ZShrZXksIGludGVycG9sYXRpb25zID0ge30pIHtcbiAgICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IHRoaXMudHJhbnNsYXRpb25zW2tleV07XG5cbiAgICAgICAgICBpZiAodHlwZW9mIHRlbXBsYXRlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgZXZlbnRzICYmIGV2ZW50cy5lbWl0KCdpMThuLXRyYW5zbGF0ZS1taXNzJywge2tleX0pO1xuICAgICAgICAgICAgcmV0dXJuIGtleTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdGVtcGxhdGUucmVwbGFjZSgvXFwkeyguKj8pfS9nLCAoXywgaykgPT5cbiAgICAgICAgICAgIGludGVycG9sYXRpb25zW2tdID09PSB2b2lkIDBcbiAgICAgICAgICAgICAgPyAnJHsnICsgayArICd9J1xuICAgICAgICAgICAgICA6IFN0cmluZyhpbnRlcnBvbGF0aW9uc1trXSlcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBpMThuID0gbmV3IEkxOG4oKTtcbiAgICAgIHJldHVybiB7ZnJvbTogKCkgPT4gaTE4bn07XG4gICAgfSxcbiAgfSk7XG5cbmV4cG9ydCBkZWZhdWx0ICgoX19CUk9XU0VSX18gJiYgcGx1Z2luRmFjdG9yeSgpOiBhbnkpOiBQbHVnaW5UeXBlKTtcbiJdfQ==
\No newline at end of file