UNPKG

14.8 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 => r.json()).then(data => {
81 for (const key in data) {
82 this.translations[key] = data[key];
83 this.requestedKeys.delete(key);
84 }
85 }).catch(err => {
86 // An error occurred, so remove the chunks we were trying to load
87 // from loadedChunks. This allows us to try to load those chunk
88 // translations again
89 unloaded.forEach(key => {
90 this.requestedKeys.delete(key);
91 });
92 throw err;
93 });
94 }
95 }
96
97 translate(key, interpolations = {}) {
98 const template = this.translations[key];
99
100 if (typeof template !== 'string') {
101 events && events.emit('i18n-translate-miss', {
102 key
103 });
104 return key;
105 }
106
107 return template.replace(/\${(.*?)}/g, (_, k) => interpolations[k] === void 0 ? '${' + k + '}' : String(interpolations[k]));
108 }
109
110 }
111
112 const i18n = new I18n();
113 return {
114 from: () => i18n
115 };
116 }
117});
118
119export default true && pluginFactory();
120//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImJyb3dzZXIuanMiXSwibmFtZXMiOlsiRmV0Y2hUb2tlbiIsImNyZWF0ZVBsdWdpbiIsInVuZXNjYXBlIiwiY3JlYXRlVG9rZW4iLCJVbml2ZXJzYWxFdmVudHNUb2tlbiIsImxvYWRUcmFuc2xhdGlvbnMiLCJlbGVtZW50IiwiZG9jdW1lbnQiLCJnZXRFbGVtZW50QnlJZCIsIkVycm9yIiwiSlNPTiIsInBhcnNlIiwidGV4dENvbnRlbnQiLCJlIiwiSHlkcmF0aW9uU3RhdGVUb2tlbiIsInBsdWdpbkZhY3RvcnkiLCJkZXBzIiwiZmV0Y2giLCJvcHRpb25hbCIsImh5ZHJhdGlvblN0YXRlIiwiZXZlbnRzIiwicHJvdmlkZXMiLCJ3aW5kb3ciLCJJMThuIiwiY29uc3RydWN0b3IiLCJsb2NhbGVDb2RlIiwidHJhbnNsYXRpb25zIiwicmVxdWVzdGVkS2V5cyIsIlNldCIsImxvY2FsZSIsImxvYWQiLCJ0cmFuc2xhdGlvbktleXMiLCJsb2FkZWRLZXlzIiwiT2JqZWN0Iiwia2V5cyIsInVubG9hZGVkIiwiZmlsdGVyIiwia2V5IiwiaW5kZXhPZiIsImhhcyIsImxlbmd0aCIsImZvckVhY2giLCJhZGQiLCJmZXRjaE9wdHMiLCJtZXRob2QiLCJoZWFkZXJzIiwiQWNjZXB0IiwiYm9keSIsInN0cmluZ2lmeSIsInRoZW4iLCJyIiwianNvbiIsImRhdGEiLCJkZWxldGUiLCJjYXRjaCIsImVyciIsInRyYW5zbGF0ZSIsImludGVycG9sYXRpb25zIiwidGVtcGxhdGUiLCJlbWl0IiwicmVwbGFjZSIsIl8iLCJrIiwiU3RyaW5nIiwiaTE4biIsImZyb20iXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztBQVFBO0FBQ0EsU0FBUUEsVUFBUixRQUF5QixlQUF6QjtBQUNBLFNBQVFDLFlBQVIsRUFBc0JDLFFBQXRCLEVBQWdDQyxXQUFoQyxRQUFrRCxhQUFsRDtBQUVBLFNBQVFDLG9CQUFSLFFBQW1DLGdDQUFuQzs7QUFZQSxTQUFTQyxnQkFBVCxHQUFvRDtBQUNsRCxR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S0FBUDtBQUNEO0FBcEZVLENBQUQsQ0FEZDs7QUF3RkEsZUFBaUIsUUFBZWpELGFBQWEsRUFBN0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKiogQ29weXJpZ2h0IChjKSAyMDE4IFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG4vKiBlc2xpbnQtZW52IGJyb3dzZXIgKi9cbmltcG9ydCB7RmV0Y2hUb2tlbn0gZnJvbSAnZnVzaW9uLXRva2Vucyc7XG5pbXBvcnQge2NyZWF0ZVBsdWdpbiwgdW5lc2NhcGUsIGNyZWF0ZVRva2VufSBmcm9tICdmdXNpb24tY29yZSc7XG5pbXBvcnQgdHlwZSB7RnVzaW9uUGx1Z2luLCBUb2tlbn0gZnJvbSAnZnVzaW9uLWNvcmUnO1xuaW1wb3J0IHtVbml2ZXJzYWxFdmVudHNUb2tlbn0gZnJvbSAnZnVzaW9uLXBsdWdpbi11bml2ZXJzYWwtZXZlbnRzJztcblxuaW1wb3J0IHR5cGUge1xuICBJMThuRGVwc1R5cGUsXG4gIEkxOG5TZXJ2aWNlVHlwZSxcbiAgVHJhbnNsYXRpb25zT2JqZWN0VHlwZSxcbn0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbnR5cGUgTG9hZGVkVHJhbnNsYXRpb25zVHlwZSA9IHtcbiAgbG9jYWxlQ29kZT86IHN0cmluZyxcbiAgdHJhbnNsYXRpb25zPzogVHJhbnNsYXRpb25zT2JqZWN0VHlwZSxcbn07XG5mdW5jdGlvbiBsb2FkVHJhbnNsYXRpb25zKCk6IExvYWRlZFRyYW5zbGF0aW9uc1R5cGUge1xuICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ19fVFJBTlNMQVRJT05TX18nKTtcbiAgaWYgKCFlbGVtZW50KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ1tmdXNpb24tcGx1Z2luLWkxOG5dIC0gQ291bGQgbm90IGZpbmQgYSBfX1RSQU5TTEFUSU9OU19fIGVsZW1lbnQnXG4gICAgKTtcbiAgfVxuICB0cnkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKHVuZXNjYXBlKGVsZW1lbnQudGV4dENvbnRlbnQpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICdbZnVzaW9uLXBsdWdpbi1pMThuXSAtIEVycm9yIHBhcnNpbmcgX19UUkFOU0xBVElPTlNfXyBlbGVtZW50IGNvbnRlbnQnXG4gICAgKTtcbiAgfVxufVxuXG50eXBlIEh5ZHJhdGlvblN0YXRlVHlwZSA9IHtcbiAgbG9jYWxlQ29kZT86IHN0cmluZyxcbiAgdHJhbnNsYXRpb25zOiBUcmFuc2xhdGlvbnNPYmplY3RUeXBlLFxufTtcbmV4cG9ydCBjb25zdCBIeWRyYXRpb25TdGF0ZVRva2VuOiBUb2tlbjxIeWRyYXRpb25TdGF0ZVR5cGU+ID0gY3JlYXRlVG9rZW4oXG4gICdIeWRyYXRpb25TdGF0ZVRva2VuJ1xuKTtcblxudHlwZSBQbHVnaW5UeXBlID0gRnVzaW9uUGx1Z2luPEkxOG5EZXBzVHlwZSwgSTE4blNlcnZpY2VUeXBlPjtcbmNvbnN0IHBsdWdpbkZhY3Rvcnk6ICgpID0+IFBsdWdpblR5cGUgPSAoKSA9PlxuICBjcmVhdGVQbHVnaW4oe1xuICAgIGRlcHM6IHtcbiAgICAgIGZldGNoOiBGZXRjaFRva2VuLm9wdGlvbmFsLFxuICAgICAgaHlkcmF0aW9uU3RhdGU6IEh5ZHJhdGlvblN0YXRlVG9rZW4ub3B0aW9uYWwsXG4gICAgICBldmVudHM6IFVuaXZlcnNhbEV2ZW50c1Rva2VuLm9wdGlvbmFsLFxuICAgIH0sXG4gICAgcHJvdmlkZXM6ICh7ZmV0Y2ggPSB3aW5kb3cuZmV0Y2gsIGh5ZHJhdGlvblN0YXRlLCBldmVudHN9ID0ge30pID0+IHtcbiAgICAgIGNsYXNzIEkxOG4ge1xuICAgICAgICBsb2NhbGU6IHN0cmluZztcbiAgICAgICAgdHJhbnNsYXRpb25zOiBUcmFuc2xhdGlvbnNPYmplY3RUeXBlO1xuICAgICAgICByZXF1ZXN0ZWRLZXlzOiBTZXQ8c3RyaW5nPjtcblxuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICBjb25zdCB7bG9jYWxlQ29kZSwgdHJhbnNsYXRpb25zfSA9XG4gICAgICAgICAgICBoeWRyYXRpb25TdGF0ZSB8fCBsb2FkVHJhbnNsYXRpb25zKCk7XG4gICAgICAgICAgdGhpcy5yZXF1ZXN0ZWRLZXlzID0gbmV3IFNldCgpO1xuICAgICAgICAgIHRoaXMudHJhbnNsYXRpb25zID0gdHJhbnNsYXRpb25zIHx8IHt9O1xuICAgICAgICAgIGlmIChsb2NhbGVDb2RlKSB7XG4gICAgICAgICAgICB0aGlzLmxvY2FsZSA9IGxvY2FsZUNvZGU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFzeW5jIGxvYWQodHJhbnNsYXRpb25LZXlzKSB7XG4gICAgICAgICAgY29uc3QgbG9hZGVkS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMudHJhbnNsYXRpb25zKTtcbiAgICAgICAgICBjb25zdCB1bmxvYWRlZCA9IHRyYW5zbGF0aW9uS2V5cy5maWx0ZXIoa2V5ID0+IHtcbiAgICAgICAgICAgIHJldHVybiBsb2FkZWRLZXlzLmluZGV4T2Yoa2V5KSA8IDAgJiYgIXRoaXMucmVxdWVzdGVkS2V5cy5oYXMoa2V5KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAodW5sb2FkZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgLy8gRG9uJ3QgdHJ5IHRvIGxvYWQgdHJhbnNsYXRpb25zIGFnYWluIGlmIGEgcmVxdWVzdCBpcyBhbHJlYWR5IGluXG4gICAgICAgICAgICAvLyBmbGlnaHQuIFRoaXMgbWVhbnMgdGhhdCB3ZSBuZWVkIHRvIGFkZCB1bmxvYWRlZCBjaHVua3MgdG9cbiAgICAgICAgICAgIC8vIGxvYWRlZENodW5rcyBvcHRpbWlzdGljYWxseSBhbmQgcmVtb3ZlIHRoZW0gaWYgc29tZSBlcnJvciBoYXBwZW5zXG4gICAgICAgICAgICB1bmxvYWRlZC5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMucmVxdWVzdGVkS2V5cy5hZGQoa2V5KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgZmV0Y2hPcHRzID0ge1xuICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgIEFjY2VwdDogJyovKicsXG4gICAgICAgICAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgICAgICAuLi4odGhpcy5sb2NhbGUgPyB7J1gtRnVzaW9uLUxvY2FsZS1Db2RlJzogdGhpcy5sb2NhbGV9IDoge30pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh1bmxvYWRlZCksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy8gVE9ETygjMykgZG9uJ3QgYXBwZW5kIHByZWZpeCBpZiBpbmplY3RlZCBmZXRjaCBhbHNvIGluamVjdHMgcHJlZml4XG4gICAgICAgICAgICByZXR1cm4gZmV0Y2goXG4gICAgICAgICAgICAgIGAvX3RyYW5zbGF0aW9ucyR7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhbGUgPyBgP2xvY2FsZUNvZGU9JHt0aGlzLmxvY2FsZX1gIDogJydcbiAgICAgICAgICAgICAgfWAsXG4gICAgICAgICAgICAgIGZldGNoT3B0c1xuICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAudGhlbihyID0+IHIuanNvbigpKVxuICAgICAgICAgICAgICAudGhlbigoZGF0YToge1tzdHJpbmddOiBzdHJpbmd9KSA9PiB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2xhdGlvbnNba2V5XSA9IGRhdGFba2V5XTtcbiAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdGVkS2V5cy5kZWxldGUoa2V5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5jYXRjaCgoZXJyOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIEFuIGVycm9yIG9jY3VycmVkLCBzbyByZW1vdmUgdGhlIGNodW5rcyB3ZSB3ZXJlIHRyeWluZyB0byBsb2FkXG4gICAgICAgICAgICAgICAgLy8gZnJvbSBsb2FkZWRDaHVua3MuIFRoaXMgYWxsb3dzIHVzIHRvIHRyeSB0byBsb2FkIHRob3NlIGNodW5rXG4gICAgICAgICAgICAgICAgLy8gdHJhbnNsYXRpb25zIGFnYWluXG4gICAgICAgICAgICAgICAgdW5sb2FkZWQuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0ZWRLZXlzLmRlbGV0ZShrZXkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRyYW5zbGF0ZShrZXksIGludGVycG9sYXRpb25zID0ge30pIHtcbiAgICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IHRoaXMudHJhbnNsYXRpb25zW2tleV07XG5cbiAgICAgICAgICBpZiAodHlwZW9mIHRlbXBsYXRlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgZXZlbnRzICYmIGV2ZW50cy5lbWl0KCdpMThuLXRyYW5zbGF0ZS1taXNzJywge2tleX0pO1xuICAgICAgICAgICAgcmV0dXJuIGtleTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdGVtcGxhdGUucmVwbGFjZSgvXFwkeyguKj8pfS9nLCAoXywgaykgPT5cbiAgICAgICAgICAgIGludGVycG9sYXRpb25zW2tdID09PSB2b2lkIDBcbiAgICAgICAgICAgICAgPyAnJHsnICsgayArICd9J1xuICAgICAgICAgICAgICA6IFN0cmluZyhpbnRlcnBvbGF0aW9uc1trXSlcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBpMThuID0gbmV3IEkxOG4oKTtcbiAgICAgIHJldHVybiB7ZnJvbTogKCkgPT4gaTE4bn07XG4gICAgfSxcbiAgfSk7XG5cbmV4cG9ydCBkZWZhdWx0ICgoX19CUk9XU0VSX18gJiYgcGx1Z2luRmFjdG9yeSgpOiBhbnkpOiBQbHVnaW5UeXBlKTtcbiJdfQ==
\No newline at end of file