viewlogic 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/viewlogic-router.js +24 -10
- package/dist/viewlogic-router.js.map +2 -2
- package/dist/viewlogic-router.min.js +3 -3
- package/dist/viewlogic-router.min.js.map +3 -3
- package/dist/viewlogic-router.umd.js +1 -1
- package/package.json +1 -2
- package/src/core/ComponentLoader.js +0 -182
- package/src/core/ErrorHandler.js +0 -331
- package/src/core/RouteLoader.js +0 -368
- package/src/plugins/AuthManager.js +0 -505
- package/src/plugins/CacheManager.js +0 -352
- package/src/plugins/I18nManager.js +0 -507
- package/src/plugins/QueryManager.js +0 -402
- package/src/viewlogic-router.js +0 -469
|
@@ -1,507 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ViewLogic Internationalization System
|
|
3
|
-
* 다국어 지원 시스템
|
|
4
|
-
*/
|
|
5
|
-
export class I18nManager {
|
|
6
|
-
constructor(router, options = {}) {
|
|
7
|
-
this.config = {
|
|
8
|
-
enabled: options.useI18n !== undefined ? options.useI18n : true,
|
|
9
|
-
defaultLanguage: options.defaultLanguage || 'ko',
|
|
10
|
-
fallbackLanguage: options.defaultLanguage || 'ko',
|
|
11
|
-
cacheKey: options.cacheKey || 'viewlogic_lang',
|
|
12
|
-
dataCacheKey: options.dataCacheKey || 'viewlogic_i18n_data',
|
|
13
|
-
cacheVersion: options.cacheVersion || '1.0.0',
|
|
14
|
-
enableDataCache: options.enableDataCache !== false,
|
|
15
|
-
debug: options.debug || false
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
// 라우터 인스턴스 참조 (필요시 언어 변경 시 라우터 상태 업데이트)
|
|
19
|
-
this.router = router;
|
|
20
|
-
|
|
21
|
-
this.messages = new Map();
|
|
22
|
-
this.currentLanguage = this.config.defaultLanguage;
|
|
23
|
-
this.isLoading = false;
|
|
24
|
-
this.loadPromises = new Map();
|
|
25
|
-
|
|
26
|
-
// 이벤트 리스너들
|
|
27
|
-
this.listeners = {
|
|
28
|
-
languageChanged: []
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// 비동기 초기화 시작 (constructor 내에서는 await 불가)
|
|
32
|
-
this.initPromise = this.init();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async init() {
|
|
36
|
-
// i18n이 비활성화된 경우 초기화하지 않음
|
|
37
|
-
if (!this.config.enabled) {
|
|
38
|
-
this.log('info', 'I18n system disabled');
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// 캐시에서 언어 설정 로드
|
|
43
|
-
this.loadLanguageFromCache();
|
|
44
|
-
|
|
45
|
-
// 개발 모드에서는 캐시 비활성화
|
|
46
|
-
if (this.config.debug) {
|
|
47
|
-
this.config.enableDataCache = false;
|
|
48
|
-
this.log('debug', 'Data cache disabled in debug mode');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 초기 언어 파일 자동 로드 (아직 로드되지 않은 경우에만)
|
|
52
|
-
if (!this.messages.has(this.currentLanguage)) {
|
|
53
|
-
try {
|
|
54
|
-
await this.loadMessages(this.currentLanguage);
|
|
55
|
-
} catch (error) {
|
|
56
|
-
this.log('error', 'Failed to load initial language file:', error);
|
|
57
|
-
}
|
|
58
|
-
} else {
|
|
59
|
-
this.log('debug', 'Language messages already loaded:', this.currentLanguage);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 캐시에서 언어 설정 로드
|
|
65
|
-
*/
|
|
66
|
-
loadLanguageFromCache() {
|
|
67
|
-
try {
|
|
68
|
-
const cachedLang = localStorage.getItem(this.config.cacheKey);
|
|
69
|
-
if (cachedLang && this.isValidLanguage(cachedLang)) {
|
|
70
|
-
this.currentLanguage = cachedLang;
|
|
71
|
-
this.log('debug', 'Language loaded from cache:', cachedLang);
|
|
72
|
-
}
|
|
73
|
-
} catch (error) {
|
|
74
|
-
this.log('warn', 'Failed to load language from cache:', error);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* 언어 유효성 검사
|
|
81
|
-
*/
|
|
82
|
-
isValidLanguage(lang) {
|
|
83
|
-
return typeof lang === 'string' && /^[a-z]{2}$/.test(lang);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* 현재 언어 반환
|
|
88
|
-
*/
|
|
89
|
-
getCurrentLanguage() {
|
|
90
|
-
return this.currentLanguage;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* 언어 변경
|
|
95
|
-
*/
|
|
96
|
-
async setLanguage(language) {
|
|
97
|
-
if (!this.isValidLanguage(language)) {
|
|
98
|
-
this.log('warn', 'Invalid language code:', language);
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (this.currentLanguage === language) {
|
|
103
|
-
this.log('debug', 'Language already set to:', language);
|
|
104
|
-
return true;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const oldLanguage = this.currentLanguage;
|
|
108
|
-
this.currentLanguage = language;
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
// 언어 파일 로드
|
|
112
|
-
await this.loadMessages(language);
|
|
113
|
-
|
|
114
|
-
// 캐시에 저장
|
|
115
|
-
this.saveLanguageToCache(language);
|
|
116
|
-
|
|
117
|
-
// 이벤트 발생
|
|
118
|
-
this.emit('languageChanged', {
|
|
119
|
-
from: oldLanguage,
|
|
120
|
-
to: language,
|
|
121
|
-
messages: this.messages.get(language)
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
this.log('info', 'Language changed successfully', { from: oldLanguage, to: language });
|
|
125
|
-
return true;
|
|
126
|
-
} catch (error) {
|
|
127
|
-
// 실패 시 이전 언어로 복원
|
|
128
|
-
this.currentLanguage = oldLanguage;
|
|
129
|
-
this.log('error', 'Failed to change language:', error);
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* 언어를 캐시에 저장
|
|
136
|
-
*/
|
|
137
|
-
saveLanguageToCache(language) {
|
|
138
|
-
try {
|
|
139
|
-
localStorage.setItem(this.config.cacheKey, language);
|
|
140
|
-
this.log('debug', 'Language saved to cache:', language);
|
|
141
|
-
} catch (error) {
|
|
142
|
-
this.log('warn', 'Failed to save language to cache:', error);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* 언어 메시지 파일 로드
|
|
148
|
-
*/
|
|
149
|
-
async loadMessages(language) {
|
|
150
|
-
// 이미 로드된 경우
|
|
151
|
-
if (this.messages.has(language)) {
|
|
152
|
-
this.log('debug', 'Messages already loaded for:', language);
|
|
153
|
-
return this.messages.get(language);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// 이미 로딩 중인 경우
|
|
157
|
-
if (this.loadPromises.has(language)) {
|
|
158
|
-
this.log('debug', 'Messages loading in progress for:', language);
|
|
159
|
-
return await this.loadPromises.get(language);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const loadPromise = this._loadMessagesFromFile(language);
|
|
163
|
-
this.loadPromises.set(language, loadPromise);
|
|
164
|
-
|
|
165
|
-
try {
|
|
166
|
-
const messages = await loadPromise;
|
|
167
|
-
this.messages.set(language, messages);
|
|
168
|
-
this.loadPromises.delete(language);
|
|
169
|
-
this.log('debug', 'Messages loaded successfully for:', language);
|
|
170
|
-
return messages;
|
|
171
|
-
} catch (error) {
|
|
172
|
-
this.loadPromises.delete(language);
|
|
173
|
-
throw error;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* 파일에서 메시지 로드 (캐싱 지원)
|
|
179
|
-
*/
|
|
180
|
-
async _loadMessagesFromFile(language) {
|
|
181
|
-
// 캐시에서 먼저 시도
|
|
182
|
-
if (this.config.enableDataCache) {
|
|
183
|
-
const cachedData = this.getDataFromCache(language);
|
|
184
|
-
if (cachedData) {
|
|
185
|
-
this.log('debug', 'Messages loaded from cache:', language);
|
|
186
|
-
return cachedData;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
// JSON 파일로 변경
|
|
192
|
-
const response = await fetch(`../i18n/${language}.json`);
|
|
193
|
-
if (!response.ok) {
|
|
194
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
195
|
-
}
|
|
196
|
-
const messages = await response.json();
|
|
197
|
-
|
|
198
|
-
// 캐시에 저장
|
|
199
|
-
if (this.config.enableDataCache) {
|
|
200
|
-
this.saveDataToCache(language, messages);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return messages;
|
|
204
|
-
} catch (error) {
|
|
205
|
-
this.log('error', 'Failed to load messages file for:', language, error);
|
|
206
|
-
|
|
207
|
-
// 폴백 언어 시도
|
|
208
|
-
if (language !== this.config.fallbackLanguage) {
|
|
209
|
-
this.log('info', 'Trying fallback language:', this.config.fallbackLanguage);
|
|
210
|
-
return await this._loadMessagesFromFile(this.config.fallbackLanguage);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
throw new Error(`Failed to load messages for language: ${language}`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* 언어 데이터를 캐시에서 가져오기
|
|
219
|
-
*/
|
|
220
|
-
getDataFromCache(language) {
|
|
221
|
-
try {
|
|
222
|
-
const cacheKey = `${this.config.dataCacheKey}_${language}_${this.config.cacheVersion}`;
|
|
223
|
-
const cachedItem = localStorage.getItem(cacheKey);
|
|
224
|
-
|
|
225
|
-
if (cachedItem) {
|
|
226
|
-
const { data, timestamp, version } = JSON.parse(cachedItem);
|
|
227
|
-
|
|
228
|
-
// 버전 확인
|
|
229
|
-
if (version !== this.config.cacheVersion) {
|
|
230
|
-
this.log('debug', 'Cache version mismatch, clearing:', language);
|
|
231
|
-
localStorage.removeItem(cacheKey);
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// TTL 확인 (24시간)
|
|
236
|
-
const now = Date.now();
|
|
237
|
-
const maxAge = 24 * 60 * 60 * 1000; // 24시간
|
|
238
|
-
|
|
239
|
-
if (now - timestamp > maxAge) {
|
|
240
|
-
this.log('debug', 'Cache expired, removing:', language);
|
|
241
|
-
localStorage.removeItem(cacheKey);
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return data;
|
|
246
|
-
}
|
|
247
|
-
} catch (error) {
|
|
248
|
-
this.log('warn', 'Failed to read from cache:', error);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return null;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* 언어 데이터를 캐시에 저장
|
|
256
|
-
*/
|
|
257
|
-
saveDataToCache(language, data) {
|
|
258
|
-
try {
|
|
259
|
-
const cacheKey = `${this.config.dataCacheKey}_${language}_${this.config.cacheVersion}`;
|
|
260
|
-
const cacheItem = {
|
|
261
|
-
data,
|
|
262
|
-
timestamp: Date.now(),
|
|
263
|
-
version: this.config.cacheVersion
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
localStorage.setItem(cacheKey, JSON.stringify(cacheItem));
|
|
267
|
-
this.log('debug', 'Data saved to cache:', language);
|
|
268
|
-
} catch (error) {
|
|
269
|
-
this.log('warn', 'Failed to save to cache:', error);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* 메시지 번역
|
|
275
|
-
*/
|
|
276
|
-
t(key, params = {}) {
|
|
277
|
-
// i18n이 비활성화된 경우 키 자체를 반환
|
|
278
|
-
if (!this.config.enabled) {
|
|
279
|
-
return key;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const messages = this.messages.get(this.currentLanguage);
|
|
283
|
-
if (!messages) {
|
|
284
|
-
this.log('warn', 'No messages loaded for current language:', this.currentLanguage);
|
|
285
|
-
return key;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const message = this.getNestedValue(messages, key);
|
|
289
|
-
if (message === undefined) {
|
|
290
|
-
this.log('warn', 'Translation not found for key:', key);
|
|
291
|
-
|
|
292
|
-
// 폴백 언어에서 찾기
|
|
293
|
-
const fallbackMessages = this.messages.get(this.config.fallbackLanguage);
|
|
294
|
-
if (fallbackMessages && this.currentLanguage !== this.config.fallbackLanguage) {
|
|
295
|
-
const fallbackMessage = this.getNestedValue(fallbackMessages, key);
|
|
296
|
-
if (fallbackMessage !== undefined) {
|
|
297
|
-
return this.interpolate(fallbackMessage, params);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return key;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return this.interpolate(message, params);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* 중첩된 객체에서 값 가져오기
|
|
309
|
-
*/
|
|
310
|
-
getNestedValue(obj, path) {
|
|
311
|
-
return path.split('.').reduce((current, key) => {
|
|
312
|
-
return current && current[key] !== undefined ? current[key] : undefined;
|
|
313
|
-
}, obj);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* 문자열 보간 처리
|
|
318
|
-
*/
|
|
319
|
-
interpolate(message, params) {
|
|
320
|
-
if (typeof message !== 'string') {
|
|
321
|
-
return message;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
return message.replace(/\{(\w+)\}/g, (match, key) => {
|
|
325
|
-
return params.hasOwnProperty(key) ? params[key] : match;
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* 복수형 처리
|
|
331
|
-
*/
|
|
332
|
-
plural(key, count, params = {}) {
|
|
333
|
-
const pluralKey = count === 1 ? `${key}.singular` : `${key}.plural`;
|
|
334
|
-
return this.t(pluralKey, { ...params, count });
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* 사용 가능한 언어 목록
|
|
339
|
-
*/
|
|
340
|
-
getAvailableLanguages() {
|
|
341
|
-
return ['ko', 'en']; // 추후 동적으로 로드하도록 변경 가능
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* 언어 변경 이벤트 리스너 등록
|
|
346
|
-
*/
|
|
347
|
-
on(event, callback) {
|
|
348
|
-
if (this.listeners[event]) {
|
|
349
|
-
this.listeners[event].push(callback);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* 언어 변경 이벤트 리스너 제거
|
|
355
|
-
*/
|
|
356
|
-
off(event, callback) {
|
|
357
|
-
if (this.listeners[event]) {
|
|
358
|
-
const index = this.listeners[event].indexOf(callback);
|
|
359
|
-
if (index > -1) {
|
|
360
|
-
this.listeners[event].splice(index, 1);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* 이벤트 발생
|
|
367
|
-
*/
|
|
368
|
-
emit(event, data) {
|
|
369
|
-
if (this.listeners[event]) {
|
|
370
|
-
this.listeners[event].forEach(callback => {
|
|
371
|
-
try {
|
|
372
|
-
callback(data);
|
|
373
|
-
} catch (error) {
|
|
374
|
-
this.log('error', 'Error in event listener:', error);
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* 현재 언어의 모든 메시지 반환
|
|
382
|
-
*/
|
|
383
|
-
getMessages() {
|
|
384
|
-
return this.messages.get(this.currentLanguage) || {};
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
* 언어별 날짜 포맷팅
|
|
389
|
-
*/
|
|
390
|
-
formatDate(date, options = {}) {
|
|
391
|
-
const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';
|
|
392
|
-
return new Intl.DateTimeFormat(locale, options).format(new Date(date));
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* 언어별 숫자 포맷팅
|
|
397
|
-
*/
|
|
398
|
-
formatNumber(number, options = {}) {
|
|
399
|
-
const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';
|
|
400
|
-
return new Intl.NumberFormat(locale, options).format(number);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* 로깅 래퍼 메서드
|
|
405
|
-
*/
|
|
406
|
-
log(level, ...args) {
|
|
407
|
-
if (this.router?.errorHandler) {
|
|
408
|
-
this.router.errorHandler.log(level, 'I18nManager', ...args);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* i18n 활성화 여부 확인
|
|
414
|
-
*/
|
|
415
|
-
isEnabled() {
|
|
416
|
-
return this.config.enabled;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* 초기 로딩이 완료되었는지 확인
|
|
421
|
-
*/
|
|
422
|
-
async isReady() {
|
|
423
|
-
if (!this.config.enabled) {
|
|
424
|
-
return true;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
try {
|
|
428
|
-
await this.initPromise;
|
|
429
|
-
return true;
|
|
430
|
-
} catch (error) {
|
|
431
|
-
this.log('error', 'I18n initialization failed:', error);
|
|
432
|
-
return false;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* 캐시 초기화 (버전 변경 시 사용)
|
|
438
|
-
*/
|
|
439
|
-
clearCache() {
|
|
440
|
-
try {
|
|
441
|
-
const keys = Object.keys(localStorage);
|
|
442
|
-
const cacheKeys = keys.filter(key => key.startsWith(this.config.dataCacheKey));
|
|
443
|
-
|
|
444
|
-
cacheKeys.forEach(key => {
|
|
445
|
-
localStorage.removeItem(key);
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
this.log('debug', 'Cache cleared, removed', cacheKeys.length, 'items');
|
|
449
|
-
} catch (error) {
|
|
450
|
-
this.log('warn', 'Failed to clear cache:', error);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
* 캐시 상태 확인
|
|
456
|
-
*/
|
|
457
|
-
getCacheInfo() {
|
|
458
|
-
const info = {
|
|
459
|
-
enabled: this.config.enableDataCache,
|
|
460
|
-
version: this.config.cacheVersion,
|
|
461
|
-
languages: {}
|
|
462
|
-
};
|
|
463
|
-
|
|
464
|
-
try {
|
|
465
|
-
const keys = Object.keys(localStorage);
|
|
466
|
-
const cacheKeys = keys.filter(key => key.startsWith(this.config.dataCacheKey));
|
|
467
|
-
|
|
468
|
-
cacheKeys.forEach(key => {
|
|
469
|
-
const match = key.match(new RegExp(`${this.config.dataCacheKey}_(\w+)_(.+)`));
|
|
470
|
-
if (match) {
|
|
471
|
-
const [, language, version] = match;
|
|
472
|
-
const cachedItem = JSON.parse(localStorage.getItem(key));
|
|
473
|
-
|
|
474
|
-
info.languages[language] = {
|
|
475
|
-
version,
|
|
476
|
-
timestamp: cachedItem.timestamp,
|
|
477
|
-
age: Date.now() - cachedItem.timestamp
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
});
|
|
481
|
-
} catch (error) {
|
|
482
|
-
this.log('warn', 'Failed to get cache info:', error);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
return info;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* 시스템 초기화 (현재 언어의 메시지 로드)
|
|
490
|
-
*/
|
|
491
|
-
async initialize() {
|
|
492
|
-
if (!this.config.enabled) {
|
|
493
|
-
this.log('info', 'I18n system is disabled, skipping initialization');
|
|
494
|
-
return true;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
try {
|
|
498
|
-
// 초기 설정이 완료될 때까지 대기
|
|
499
|
-
await this.initPromise;
|
|
500
|
-
this.log('info', 'I18n system fully initialized');
|
|
501
|
-
return true;
|
|
502
|
-
} catch (error) {
|
|
503
|
-
this.log('error', 'Failed to initialize I18n system:', error);
|
|
504
|
-
return false;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|