UNPKG

5.3 kBJavaScriptView Raw
1/**
2 * @copyright Copyright (c) 2019 Maxim Khorin <maksimovichu@gmail.com>
3 */
4'use strict';
5
6const Base = require('../base/Component');
7
8module.exports = class I18n extends Base {
9
10 static getConstants () {
11 return {
12 CORE_SOURCE: 'areto',
13 APP_SOURCE: 'app'
14 };
15 }
16
17 constructor (config) {
18 const parent = config.parent;
19 super({
20 language: parent ? parent.language : 'en',
21 sourceLanguage: parent ? parent.sourceLanguage : 'en',
22 sources: {},
23 MessageFormatter,
24 ...config
25 });
26 this.createSources();
27 }
28
29 async init () {
30 this.messageFormatter = this.spawn(this.MessageFormatter);
31 this.resolveSourceParents();
32 await this.loadSources();
33 }
34
35 getSource (name) {
36 return Object.prototype.hasOwnProperty.call(this.sources, name) ? this.sources[name] : null;
37 }
38
39 async loadSources () {
40 for (const source of Object.values(this.sources)) {
41 await source.load();
42 }
43 }
44
45 createSources () {
46 for (const name of Object.keys(this.sources)) {
47 this.sources[name] = this.createSource(name, this.sources[name]);
48 }
49 if (!this.getSource(this.CORE_SOURCE)) {
50 this.sources[this.CORE_SOURCE] = this.createCoreSource();
51 }
52 if (!this.getSource(this.APP_SOURCE)) {
53 this.sources[this.APP_SOURCE] = this.createAppSource();
54 }
55 if (this.parent instanceof I18n) {
56 AssignHelper.assignUndefined(this.sources, this.parent.sources);
57 }
58 }
59
60 createCoreSource () {
61 if (this.parent) {
62 return this.parent.sources[this.CORE_SOURCE];
63 }
64 return this.createSource(this.CORE_SOURCE, {
65 basePath: path.join(__dirname, 'message', this.CORE_SOURCE)
66 });
67 }
68
69 createAppSource () {
70 const source = this.createSource(this.APP_SOURCE);
71 if (source.parent === undefined && !this.parent) {
72 source.setParent(this.sources[this.CORE_SOURCE]);
73 }
74 return source;
75 }
76
77 createSource (name, config) {
78 if (config instanceof MessageSource) {
79 return config;
80 }
81 return this.spawn({
82 Class: FileMessageSource,
83 i18n: this,
84 basePath: `message/${name}`,
85 ...config
86 });
87 }
88
89 resolveSourceParents () {
90 for (const name of Object.keys(this.sources)) {
91 this.sources[name].setParent(this.resolveSourceParent(name));
92 if (ObjectHelper.hasCircularLinks(this.sources[name], 'parent')) {
93 throw new Error(`Circular source parents: ${name}`);
94 }
95 }
96 }
97
98 resolveSourceParent (name) {
99 const parent = this.sources[name].parent;
100 if (parent instanceof MessageSource) {
101 return parent;
102 }
103 return parent === undefined
104 ? this.getSourceParent(name)
105 : this.getSource(parent);
106 }
107
108 getSourceParent (name) {
109 const parent = this.parent;
110 return parent ? (parent.getSource(name) || parent.getSourceParent(name)) : null;
111 }
112
113 format () {
114 return this.messageFormatter.format(...arguments);
115 }
116
117 translate (message, params, name, language = this.language) {
118 const source = this.getSource(name);
119 if (!source) {
120 this.log('error', `Message source not found: ${name}`);
121 return message;
122 }
123 let result;
124 if (source.sourceLanguage !== language) {
125 result = source.translate(message, language);
126 if (result === null) {
127 language = source.sourceLanguage;
128 if (source.forceTranslation) {
129 result = source.translate(message, language);
130 }
131 }
132 } else if (source.forceTranslation) {
133 result = source.translate(message, language);
134 } else if (source.forceTranslationParent) {
135 result = source.forceTranslationParent.translate(message, language);
136 }
137 message = result || message;
138 return params ? this.format(message, params, language) : message;
139 }
140
141 translateMessage (message) {
142 if (Array.isArray(message)) {
143 return this.translate(...message);
144 }
145 if (message instanceof Message) {
146 return message.translate(this);
147 }
148 return this.translate(...arguments);
149 }
150
151 translateMessageMap (data, ...args) {
152 data = {...data};
153 for (const key of Object.keys(data)) {
154 data[key] = this.translateMessage(data[key], ...args);
155 }
156 return data;
157 }
158};
159module.exports.init();
160
161const path = require('path');
162const AssignHelper = require('../helper/AssignHelper');
163const ObjectHelper = require('../helper/ObjectHelper');
164const MessageSource = require('./MessageSource');
165const FileMessageSource = require('./FileMessageSource');
166const MessageFormatter = require('./MessageFormatter');
167const Message = require('./Message');
\No newline at end of file