@ui18n/angular
Version:
🅰️ Modern Angular internationalization with standalone components, signals, and dependency injection support for Angular 15+
1,722 lines (1,605 loc) • 81.3 kB
JavaScript
import { Injectable, Directive, Input, Output, EventEmitter, Pipe, Component, ChangeDetectionStrategy, NgModule } from '@angular/core';
import { Subject, BehaviorSubject, combineLatest, interval } from 'rxjs';
import { map, distinctUntilChanged, debounceTime, takeUntil, startWith } from 'rxjs/operators';
import { createUI18n } from '@ui18n/core';
export { AIProvider, AIProviderConfig, AITranslator, BuiltinDictionary, CacheConfig, CacheManager, DEFAULT_CONFIG, DictionaryEntry, EnterpriseUI18nConfig, LanguageDetectionResult, LanguageDetector, ServiceMode, ServiceModeManager, SupportedLanguage, SystemStatus, TranslationPipeline, TranslationRequest, TranslationResult, TranslationSearchResult, TranslationStats, UI18n, UI18nConfig, VERSION, VersionControlManager, checkBrowserSupport, createDevelopmentUI18n, createEnterpriseUI18n, createLanguageSwitcher, createProductionUI18n, createTranslationMonitor, createUI18n, getRecommendedLanguages, quickSetup } from '@ui18n/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
function _checkInRHS(e) {
if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null"));
return e;
}
function _setFunctionName(e, t, n) {
"symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : "");
try {
Object.defineProperty(e, "name", {
configurable: !0,
value: n ? n + " " + t : t
});
} catch (e) {}
return e;
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (String )(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _applyDecs2305(e, t, r, n, o, a) {
function i(e, t, r) {
return function (n, o) {
return r && r(n), e[t].call(n, o);
};
}
function c(e, t) {
for (var r = 0; r < e.length; r++) e[r].call(t);
return t;
}
function s(e, t, r, n) {
if ("function" != typeof e && (n || void 0 !== e)) throw new TypeError(t + " must " + (r || "be") + " a function" + (n ? "" : " or undefined"));
return e;
}
function applyDec(e, t, r, n, o, a, c, u, l, f, p, d, h) {
function m(e) {
if (!h(e)) throw new TypeError("Attempted to access private element on non-instance");
}
var y,
v = t[0],
g = t[3],
b = !u;
if (!b) {
r || Array.isArray(v) || (v = [v]);
var w = {},
S = [],
A = 3 === o ? "get" : 4 === o || d ? "set" : "value";
f ? (p || d ? w = {
get: _setFunctionName(function () {
return g(this);
}, n, "get"),
set: function (e) {
t[4](this, e);
}
} : w[A] = g, p || _setFunctionName(w[A], n, 2 === o ? "" : A)) : p || (w = Object.getOwnPropertyDescriptor(e, n));
}
for (var P = e, j = v.length - 1; j >= 0; j -= r ? 2 : 1) {
var D = v[j],
E = r ? v[j - 1] : void 0,
I = {},
O = {
kind: ["field", "accessor", "method", "getter", "setter", "class"][o],
name: n,
metadata: a,
addInitializer: function (e, t) {
if (e.v) throw Error("attempted to call addInitializer after decoration was finished");
s(t, "An initializer", "be", true), c.push(t);
}.bind(null, I)
};
try {
if (b) (y = s(D.call(E, P, O), "class decorators", "return")) && (P = y);else {
var k, F;
O.static = l, O.private = f, f ? 2 === o ? k = function (e) {
return m(e), w.value;
} : (o < 4 && (k = i(w, "get", m)), 3 !== o && (F = i(w, "set", m))) : (k = function (e) {
return e[n];
}, (o < 2 || 4 === o) && (F = function (e, t) {
e[n] = t;
}));
var N = O.access = {
has: f ? h.bind() : function (e) {
return n in e;
}
};
if (k && (N.get = k), F && (N.set = F), P = D.call(E, d ? {
get: w.get,
set: w.set
} : w[A], O), d) {
if ("object" == typeof P && P) (y = s(P.get, "accessor.get")) && (w.get = y), (y = s(P.set, "accessor.set")) && (w.set = y), (y = s(P.init, "accessor.init")) && S.push(y);else if (void 0 !== P) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
} else s(P, (p ? "field" : "method") + " decorators", "return") && (p ? S.push(P) : w[A] = P);
}
} finally {
I.v = true;
}
}
return (p || d) && u.push(function (e, t) {
for (var r = S.length - 1; r >= 0; r--) t = S[r].call(e, t);
return t;
}), p || b || (f ? d ? u.push(i(w, "get"), i(w, "set")) : u.push(2 === o ? w[A] : i.call.bind(w[A])) : Object.defineProperty(e, n, w)), P;
}
function u(e, t) {
return Object.defineProperty(e, Symbol.metadata || Symbol.for("Symbol.metadata"), {
configurable: true,
enumerable: true,
value: t
});
}
if (arguments.length >= 6) var l = a[Symbol.metadata || Symbol.for("Symbol.metadata")];
var f = Object.create(null == l ? null : l),
p = function (e, t, r, n) {
var o,
a,
i = [],
s = function (t) {
return _checkInRHS(t) === e;
},
u = new Map();
function l(e) {
e && i.push(c.bind(null, e));
}
for (var f = 0; f < t.length; f++) {
var p = t[f];
if (Array.isArray(p)) {
var d = p[1],
h = p[2],
m = p.length > 3,
y = 16 & d,
v = !!(8 & d),
g = 0 == (d &= 7),
b = h + "/" + v;
if (!g && !m) {
var w = u.get(b);
if (true === w || 3 === w && 4 !== d || 4 === w && 3 !== d) throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h);
u.set(b, !(d > 2) || d);
}
applyDec(v ? e : e.prototype, p, y, m ? "#" + h : _toPropertyKey(h), d, n, v ? a = a || [] : o = o || [], i, v, m, g, 1 === d, v && m ? s : r);
}
}
return l(o), l(a), i;
}(e, t, o, f);
return r.length || u(e, f), {
e: p,
get c() {
var t = [];
return r.length && [u(applyDec(e, [r], n, e.name, 5, f, t), f), c.bind(null, t, e)];
}
};
}
var _UI18nService2;
let _initClass$9, _classDecs$9;
/**
* 批量翻译选项
*/
/**
* 实时同步选项
*/
/**
* 缓存优化选项
*/
/**
* 实时同步状态
*/
/**
* 缓存统计信息
*/
_classDecs$9 = [Injectable({
providedIn: 'root'
})];
let _UI18nService;
/**
* Angular UI18n服务
* 提供响应式的翻译功能和状态管理
*/
class UI18nService {
constructor() {
this.ui18nInstance = null;
this.destroy$ = new Subject();
// 响应式状态
this.currentLanguageSubject = new BehaviorSubject('zh-CN');
this.isInitializedSubject = new BehaviorSubject(false);
this.isLoadingSubject = new BehaviorSubject(false);
this.statsSubject = new BehaviorSubject(null);
this.statusSubject = new BehaviorSubject(null);
// 高级功能状态
this.batchProgressSubject = new BehaviorSubject(0);
this.realTimeSyncStatusSubject = new BehaviorSubject({
enabled: false,
connected: false,
method: 'polling',
syncErrors: 0
});
this.cacheStatsSubject = new BehaviorSubject(null);
this.syncErrorsSubject = new BehaviorSubject(0);
// 公共Observable
this.currentLanguage$ = this.currentLanguageSubject.asObservable();
this.isInitialized$ = this.isInitializedSubject.asObservable();
this.isLoading$ = this.isLoadingSubject.asObservable();
this.stats$ = this.statsSubject.asObservable();
this.status$ = this.statusSubject.asObservable();
// 高级功能Observable
this.batchProgress$ = this.batchProgressSubject.asObservable();
this.realTimeSyncStatus$ = this.realTimeSyncStatusSubject.asObservable();
this.cacheStats$ = this.cacheStatsSubject.asObservable();
this.syncErrors$ = this.syncErrorsSubject.asObservable();
// 组合Observable
this.isConnected$ = this.realTimeSyncStatus$.pipe(map(status => status.connected), distinctUntilChanged());
this.cacheHealthy$ = this.cacheStats$.pipe(map(stats => stats ? stats.memoryUtilization < 0.8 : true), distinctUntilChanged());
}
/**
* 初始化UI18n实例(基础版本)
*/
async initialize(config) {
try {
this.isLoadingSubject.next(true);
this.ui18nInstance = createUI18n(config);
// 设置当前语言
if (config.defaultLanguage) {
this.currentLanguageSubject.next(config.defaultLanguage);
}
this.isInitializedSubject.next(true);
this.startStatsPolling();
} catch (error) {
console.error('UI18n初始化失败:', error);
throw error;
} finally {
this.isLoadingSubject.next(false);
}
}
/**
* 初始化UI18n实例(企业版本)
*/
async initializeEnterprise(config) {
try {
this.isLoadingSubject.next(true);
// 企业版配置直接使用createUI18n,因为EnterpriseUI18nConfig扩展了UI18nConfig
this.ui18nInstance = createUI18n(config);
// 设置当前语言
if (config.defaultLanguage) {
this.currentLanguageSubject.next(config.defaultLanguage);
}
this.isInitializedSubject.next(true);
this.startStatsPolling();
} catch (error) {
console.error('UI18n企业版初始化失败:', error);
throw error;
} finally {
this.isLoadingSubject.next(false);
}
}
/**
* 翻译单个文本
*/
async translate(text, targetLanguage) {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
const target = targetLanguage || this.currentLanguageSubject.value;
return await this.ui18nInstance.translate(text, target);
}
/**
* 翻译单个文本(简化版本)
*/
async t(text, targetLanguage) {
const result = await this.translate(text, targetLanguage);
return result.text;
}
/**
* 批量翻译(基础版本)
*/
async translateBatch(texts, targetLanguage) {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
const target = targetLanguage || this.currentLanguageSubject.value;
return await this.ui18nInstance.translateBatch(texts, target);
}
/**
* 智能批量翻译(增强版本)
*/
async translateBatchOptimized(texts, options = {}) {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
const {
language,
context,
maxConcurrency,
priority = 'normal',
useOptimizer = true,
enableProgressTracking = true
} = options;
const targetLanguage = language || this.currentLanguageSubject.value;
try {
if (enableProgressTracking) {
this.batchProgressSubject.next(0);
}
let results;
if (useOptimizer) {
// 使用智能批量优化器
results = await this.ui18nInstance.translateBatch(texts, targetLanguage, {
context,
maxConcurrency,
useOptimizer: true,
priority: priority
});
} else {
// 传统批量翻译
results = await this.ui18nInstance.translateBatch(texts, targetLanguage, {
context,
maxConcurrency
});
}
if (enableProgressTracking) {
this.batchProgressSubject.next(1);
}
return results;
} catch (error) {
if (enableProgressTracking) {
this.batchProgressSubject.next(0);
}
throw error;
}
}
/**
* 切换语言
*/
async switchLanguage(language) {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
this.ui18nInstance.setLanguage(language);
this.currentLanguageSubject.next(language);
}
/**
* 检测语言
*/
async detectLanguage(text) {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
// 语言检测功能需要通过LanguageDetector实现
const {
LanguageDetector
} = await import('@ui18n/core');
const result = LanguageDetector.detectTextLanguage(text);
return result.language;
}
/**
* 获取翻译统计
*/
getStats() {
if (!this.ui18nInstance) {
return null;
}
// 使用核心包的实际API获取统计信息
return this.ui18nInstance.getSystemStatus();
}
/**
* 获取系统状态
*/
getStatus() {
if (!this.ui18nInstance) {
return null;
}
// 使用核心包的实际API获取系统状态
return this.ui18nInstance.getSystemStatus();
}
/**
* 清理缓存
*/
async clearCache(pattern) {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
await this.ui18nInstance.clearCache(pattern);
this.updateCacheStats();
}
/**
* 优化缓存
*/
async optimizeCache() {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
try {
// 获取优化的缓存管理器
const optimizedCacheManager = this.ui18nInstance.optimizedCache;
if (optimizedCacheManager && optimizedCacheManager.cleanup) {
await optimizedCacheManager.cleanup();
}
this.updateCacheStats();
} catch (error) {
console.error('缓存优化失败:', error);
}
}
/**
* 预加载语言
*/
async preloadLanguage(language) {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
const commonPhrases = ['Hello', 'Thank you', 'Please', 'Yes', 'No', 'Save', 'Cancel', 'Delete', 'Edit', 'View', 'Login', 'Logout', 'Settings', 'Help', 'About'];
for (const phrase of commonPhrases) {
try {
await this.ui18nInstance.translate(phrase, language);
} catch (error) {
console.warn(`预加载短语失败: ${phrase}`, error);
}
}
this.updateCacheStats();
}
/**
* 连接实时同步
*/
async connectRealTimeSync(options = {}) {
if (!this.ui18nInstance) {
throw new Error('UI18n未初始化,请先调用initialize()方法');
}
try {
const versionControlManager = this.ui18nInstance.versionControlManager;
if (versionControlManager && versionControlManager.reconnectRealTimeSync) {
const success = await versionControlManager.reconnectRealTimeSync();
this.updateRealTimeSyncStatus();
return success;
}
return false;
} catch (error) {
console.error('连接实时同步失败:', error);
this.syncErrorsSubject.next(this.syncErrorsSubject.value + 1);
return false;
}
}
/**
* 断开实时同步
*/
disconnectRealTimeSync() {
if (!this.ui18nInstance) {
return;
}
try {
const versionControlManager = this.ui18nInstance.versionControlManager;
if (versionControlManager) {
console.log('断开实时同步连接');
this.updateRealTimeSyncStatus();
}
} catch (error) {
console.error('断开实时同步失败:', error);
}
}
/**
* 手动同步
*/
async manualSync(language) {
if (!this.ui18nInstance) {
return false;
}
try {
const versionControlManager = this.ui18nInstance.versionControlManager;
if (versionControlManager) {
if (language) {
if (versionControlManager.syncLanguagePack) {
await versionControlManager.syncLanguagePack(language);
}
} else {
if (versionControlManager.syncAllLanguagePacks) {
await versionControlManager.syncAllLanguagePacks();
}
}
this.updateRealTimeSyncStatus();
return true;
}
return false;
} catch (error) {
console.error('手动同步失败:', error);
this.syncErrorsSubject.next(this.syncErrorsSubject.value + 1);
return false;
}
}
/**
* 获取缓存统计
*/
getCacheStats() {
if (!this.ui18nInstance || !this.ui18nInstance.getCacheStats) {
return null;
}
try {
const stats = this.ui18nInstance.getCacheStats();
return {
totalItems: stats.totalItems || 0,
memoryUsageMB: stats.memoryUsageMB || 0,
memoryLimitMB: stats.memoryLimitMB || 50,
memoryUtilization: stats.memoryUtilization || 0,
hits: stats.hits || 0,
misses: stats.misses || 0,
hitRate: stats.hitRate || 0,
type: stats.type || 'memory',
hotItems: stats.hotItems,
coldItems: stats.coldItems,
averageAccessCount: stats.averageAccessCount
};
} catch (error) {
console.warn('获取缓存统计失败:', error);
return null;
}
}
/**
* 获取实时同步状态
*/
getRealTimeSyncStatus() {
if (!this.ui18nInstance) {
return {
enabled: false,
connected: false,
method: 'polling',
syncErrors: this.syncErrorsSubject.value
};
}
try {
const versionControlManager = this.ui18nInstance.versionControlManager;
if (versionControlManager && versionControlManager.getRealTimeSyncStatus) {
const status = versionControlManager.getRealTimeSyncStatus();
return {
enabled: status.enabled,
connected: status.connected,
method: status.method,
lastEvent: status.lastEvent,
syncErrors: this.syncErrorsSubject.value
};
}
} catch (error) {
console.warn('获取实时同步状态失败:', error);
}
return {
enabled: false,
connected: false,
method: 'polling',
syncErrors: this.syncErrorsSubject.value
};
}
/**
* 获取当前语言
*/
getCurrentLanguage() {
return this.currentLanguageSubject.value;
}
/**
* 检查是否已初始化
*/
isInitialized() {
return this.isInitializedSubject.value;
}
/**
* 开始统计轮询
*/
startStatsPolling() {
// 每5秒更新一次统计信息
const interval = setInterval(() => {
if (this.ui18nInstance) {
const stats = this.getStats();
const status = this.getStatus();
this.statsSubject.next(stats);
this.statusSubject.next(status);
// 更新高级功能状态
this.updateCacheStats();
this.updateRealTimeSyncStatus();
}
}, 5000);
// 在组件销毁时清理定时器
this.destroy$.subscribe(() => {
clearInterval(interval);
});
}
/**
* 更新缓存统计
*/
updateCacheStats() {
const cacheStats = this.getCacheStats();
this.cacheStatsSubject.next(cacheStats);
}
/**
* 更新实时同步状态
*/
updateRealTimeSyncStatus() {
const syncStatus = this.getRealTimeSyncStatus();
this.realTimeSyncStatusSubject.next(syncStatus);
}
/**
* 销毁服务
*/
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
if (this.ui18nInstance) {
this.ui18nInstance.destroy();
}
}
}
_UI18nService2 = UI18nService;
[_UI18nService, _initClass$9] = _applyDecs2305(_UI18nService2, [], _classDecs$9).c;
_initClass$9();
var _UI18nAdvancedService2;
let _initClass$8, _classDecs$8;
/**
* 批量翻译状态
*/
/**
* 语言检测状态
*/
_classDecs$8 = [Injectable({
providedIn: 'root'
})];
let _UI18nAdvancedService;
/**
* UI18n高级功能服务
* 提供类似React Hooks的响应式功能
*/
class UI18nAdvancedService {
constructor(ui18nService) {
this.ui18nService = ui18nService;
this.destroy$ = new Subject();
// 批量翻译状态
this.batchTranslationState$ = new BehaviorSubject({
translations: {},
translationArray: [],
loading: false,
error: null,
progress: 0,
completedCount: 0,
totalCount: 0,
failedTexts: []
});
// 语言检测状态
this.languageDetectionState$ = new BehaviorSubject({
detectedLanguage: null,
confidence: 0,
loading: false
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
/**
* 使用批量翻译功能
* 返回响应式的批量翻译状态和操作方法
*/
useBatchTranslation(texts, options = {}) {
const state$ = this.batchTranslationState$.asObservable();
const translateBatch = async (textsToTranslate = texts, skipCache = false) => {
if (textsToTranslate.length === 0) {
return;
}
// 更新状态:开始翻译
this.updateBatchState({
loading: true,
error: null,
progress: 0,
completedCount: 0,
totalCount: textsToTranslate.length,
failedTexts: []
});
try {
const results = await this.ui18nService.translateBatchOptimized(textsToTranslate, {
...options,
enableProgressTracking: true
});
// 构建翻译映射和数组
const translations = {};
const translationArray = [];
results.forEach((result, index) => {
const originalText = textsToTranslate[index];
const translatedText = result.text;
translations[originalText] = translatedText;
translationArray.push(translatedText);
});
// 更新状态:翻译完成
this.updateBatchState({
translations,
translationArray,
loading: false,
progress: 1,
completedCount: results.length,
error: null
});
} catch (error) {
// 更新状态:翻译失败
this.updateBatchState({
loading: false,
error: error,
progress: 0
});
console.error('批量翻译失败:', error);
}
};
const refresh = () => translateBatch(texts, true);
const retryFailed = () => {
const currentState = this.batchTranslationState$.value;
if (currentState.failedTexts.length > 0) {
translateBatch(currentState.failedTexts, true);
}
};
// 自动执行初始翻译
if (texts.length > 0) {
translateBatch();
}
return {
state$,
translateBatch,
refresh,
retryFailed
};
}
/**
* 使用语言检测功能
* 返回响应式的语言检测状态和操作方法
*/
useLanguageDetection() {
const state$ = this.languageDetectionState$.asObservable();
const detectLanguage = async text => {
if (!text.trim()) {
return;
}
// 更新状态:开始检测
this.updateLanguageDetectionState({
loading: true,
detectedLanguage: null,
confidence: 0
});
try {
const language = await this.ui18nService.detectLanguage(text);
// 更新状态:检测完成
this.updateLanguageDetectionState({
detectedLanguage: language,
confidence: 0.8,
// 默认置信度
loading: false
});
} catch (error) {
// 更新状态:检测失败
this.updateLanguageDetectionState({
loading: false,
detectedLanguage: 'en',
confidence: 0.5
});
console.error('语言检测失败:', error);
}
};
return {
state$,
detectLanguage
};
}
/**
* 使用实时同步功能
* 返回实时同步状态和控制方法
*/
useRealTimeSync(options = {}) {
const status$ = this.ui18nService.realTimeSyncStatus$;
const isConnected$ = this.ui18nService.isConnected$;
const syncErrors$ = this.ui18nService.syncErrors$;
const connect = () => this.ui18nService.connectRealTimeSync(options);
const disconnect = () => this.ui18nService.disconnectRealTimeSync();
const manualSync = language => this.ui18nService.manualSync(language);
return {
status$,
isConnected$,
syncErrors$,
connect,
disconnect,
manualSync
};
}
/**
* 使用缓存优化功能
* 返回缓存状态和管理方法
*/
useCacheOptimization(options = {}) {
const stats$ = this.ui18nService.cacheStats$;
const isHealthy$ = this.ui18nService.cacheHealthy$;
const clearCache = pattern => this.ui18nService.clearCache(pattern);
const optimizeCache = () => this.ui18nService.optimizeCache();
const preloadLanguage = language => this.ui18nService.preloadLanguage(language);
return {
stats$,
isHealthy$,
clearCache,
optimizeCache,
preloadLanguage
};
}
/**
* 使用翻译功能(增强版本)
* 提供响应式的单个文本翻译
*/
useTranslation(text, options) {
const translatedText$ = new BehaviorSubject(text);
const loading$ = new BehaviorSubject(false);
const error$ = new BehaviorSubject(null);
const translate = async () => {
if (!text || !this.ui18nService.isInitialized()) {
return;
}
loading$.next(true);
error$.next(null);
try {
const result = await this.ui18nService.translate(text, options === null || options === void 0 ? void 0 : options.language);
translatedText$.next(result.text);
} catch (err) {
error$.next(err);
translatedText$.next(text); // 失败时返回原文
} finally {
loading$.next(false);
}
};
// 监听语言变化,自动重新翻译
this.ui18nService.currentLanguage$.pipe(distinctUntilChanged(), debounceTime(100), takeUntil(this.destroy$)).subscribe(() => {
translate();
});
// 自动执行初始翻译
translate();
return {
translatedText$: translatedText$.asObservable(),
loading$: loading$.asObservable(),
error$: error$.asObservable(),
translate
};
}
/**
* 使用组合状态
* 将多个状态组合成一个统一的状态流
*/
useCombinedState() {
return combineLatest([this.ui18nService.currentLanguage$, this.ui18nService.isInitialized$, this.ui18nService.isLoading$, this.ui18nService.stats$, this.ui18nService.realTimeSyncStatus$, this.ui18nService.cacheStats$]).pipe(map(([currentLanguage, isInitialized, isLoading, stats, syncStatus, cacheStats]) => ({
currentLanguage,
isInitialized,
isLoading,
stats,
syncStatus,
cacheStats,
isReady: isInitialized && !isLoading,
isSyncConnected: (syncStatus === null || syncStatus === void 0 ? void 0 : syncStatus.connected) || false,
cacheHealthy: cacheStats ? cacheStats.memoryUtilization < 0.8 : true
})));
}
/**
* 更新批量翻译状态
*/
updateBatchState(update) {
const currentState = this.batchTranslationState$.value;
this.batchTranslationState$.next({
...currentState,
...update
});
}
/**
* 更新语言检测状态
*/
updateLanguageDetectionState(update) {
const currentState = this.languageDetectionState$.value;
this.languageDetectionState$.next({
...currentState,
...update
});
}
}
_UI18nAdvancedService2 = UI18nAdvancedService;
[_UI18nAdvancedService, _initClass$8] = _applyDecs2305(_UI18nAdvancedService2, [], _classDecs$8).c;
_initClass$8();
var _UI18nTranslateDirective;
let _initClass$7, _classDecs$7, _textDecs, _init_text, _targetLanguageDecs, _init_targetLanguage, _fallbackTextDecs, _init_fallbackText, _loadingTextDecs$1, _init_loadingText$1, _ref$4;
_classDecs$7 = [Directive({
selector: '[ui18nTranslate]'
})];
let _UI18nTranslateDirect;
_ref$4 = (_textDecs = Input('ui18nTranslate'), _targetLanguageDecs = Input('ui18nLang'), _fallbackTextDecs = Input('ui18nFallback'), _loadingTextDecs$1 = Input('ui18nLoading'), "text");
/**
* UI18n翻译指令
* 用法: <div ui18nTranslate="Hello World"></div>
* 或: <div ui18nTranslate="Hello World" [ui18nLang]="'en'"></div>
*/
class UI18nTranslateDirective {
constructor(elementRef, renderer, ui18nService) {
this.elementRef = elementRef;
this.renderer = renderer;
this.ui18nService = ui18nService;
this[_ref$4] = _init_text(this, '');
this.targetLanguage = _init_targetLanguage(this);
this.fallbackText = _init_fallbackText(this);
this.loadingText = _init_loadingText$1(this, '翻译中...');
this.destroy$ = new Subject();
this.isTranslating = false;
}
ngOnInit() {
// 监听语言变化
this.ui18nService.currentLanguage$.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.translateText();
});
// 监听初始化状态
this.ui18nService.isInitialized$.pipe(takeUntil(this.destroy$)).subscribe(initialized => {
if (initialized) {
this.translateText();
}
});
}
ngOnChanges(changes) {
// 当输入属性变化时重新翻译
if (changes['text'] || changes['targetLanguage']) {
this.translateText();
}
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
/**
* 执行翻译
*/
async translateText() {
if (!this.text || this.isTranslating || !this.ui18nService.isInitialized()) {
return;
}
try {
this.isTranslating = true;
// 显示加载状态
if (this.loadingText) {
this.updateElementText(this.loadingText);
}
// 执行翻译
const translatedText = await this.ui18nService.t(this.text, this.targetLanguage);
this.updateElementText(translatedText);
} catch (error) {
console.error('翻译失败:', error);
// 使用fallback文本或原文本
const fallback = this.fallbackText || this.text;
this.updateElementText(fallback);
} finally {
this.isTranslating = false;
}
}
/**
* 更新元素文本内容
*/
updateElementText(text) {
const element = this.elementRef.nativeElement;
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
// 对于输入元素,更新placeholder
this.renderer.setAttribute(element, 'placeholder', text);
} else {
// 对于其他元素,更新文本内容
this.renderer.setProperty(element, 'textContent', text);
}
}
}
_UI18nTranslateDirective = UI18nTranslateDirective;
({
e: [_init_text, _init_targetLanguage, _init_fallbackText, _init_loadingText$1],
c: [_UI18nTranslateDirect, _initClass$7]
} = _applyDecs2305(_UI18nTranslateDirective, [[_textDecs, 0, "text"], [_targetLanguageDecs, 0, "targetLanguage"], [_fallbackTextDecs, 0, "fallbackText"], [_loadingTextDecs$1, 0, "loadingText"]], _classDecs$7));
_initClass$7();
var _UI18nBatchTranslateDirective;
let _initClass$6, _classDecs$6, _textsDecs, _init_texts, _optionsDecs, _init_options, _autoTranslateDecs, _init_autoTranslate, _displayModeDecs, _init_displayMode, _separatorDecs, _init_separator, _loadingTextDecs, _init_loadingText, _errorTextDecs, _init_errorText, _translationsReadyDecs, _init_translationsReady, _progressUpdateDecs, _init_progressUpdate, _translationErrorDecs, _init_translationError, _ref$3;
_classDecs$6 = [Directive({
selector: '[ui18nBatchTranslate]'
})];
let _UI18nBatchTranslateD;
_ref$3 = (_textsDecs = Input('ui18nBatchTranslate'), _optionsDecs = Input(), _autoTranslateDecs = Input(), _displayModeDecs = Input(), _separatorDecs = Input(), _loadingTextDecs = Input(), _errorTextDecs = Input(), _translationsReadyDecs = Output(), _progressUpdateDecs = Output(), _translationErrorDecs = Output(), "texts");
/**
* 批量翻译指令
* 用法: <div ui18nBatchTranslate [texts]="textArray" [options]="batchOptions" (translationsReady)="onReady($event)"></div>
*/
class UI18nBatchTranslateDirective {
constructor(element, ui18nService, cdr) {
this.element = element;
this.ui18nService = ui18nService;
this.cdr = cdr;
this[_ref$3] = _init_texts(this, []);
this.options = _init_options(this, {});
this.autoTranslate = _init_autoTranslate(this, true);
this.displayMode = _init_displayMode(this, 'join');
this.separator = _init_separator(this, ', ');
this.loadingText = _init_loadingText(this, '正在翻译...');
this.errorText = _init_errorText(this, '翻译失败');
this.translationsReady = _init_translationsReady(this, new EventEmitter());
this.progressUpdate = _init_progressUpdate(this, new EventEmitter());
this.translationError = _init_translationError(this, new EventEmitter());
this.destroy$ = new Subject();
this.originalContent = '';
this.isTranslating = false;
this.lastTexts = [];
this.lastLanguage = '';
this.originalContent = this.element.nativeElement.textContent || '';
}
ngOnInit() {
// 监听语言变化
this.ui18nService.currentLanguage$.pipe(takeUntil(this.destroy$)).subscribe(() => {
if (this.autoTranslate && this.texts.length > 0) {
this.translateTexts();
}
});
// 监听批量进度
this.ui18nService.batchProgress$.pipe(takeUntil(this.destroy$)).subscribe(progress => {
this.progressUpdate.emit(progress);
});
// 初始翻译
if (this.autoTranslate && this.texts.length > 0) {
this.translateTexts();
}
}
ngOnChanges(changes) {
if (changes['texts'] && !changes['texts'].firstChange) {
if (this.autoTranslate) {
this.translateTexts();
}
}
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
/**
* 手动触发翻译
*/
async translate() {
await this.translateTexts();
}
/**
* 翻译文本数组
*/
async translateTexts() {
if (!this.texts || this.texts.length === 0 || this.isTranslating) {
return;
}
if (!this.ui18nService.isInitialized()) {
this.updateElementContent(this.texts);
return;
}
const currentLanguage = this.ui18nService.getCurrentLanguage();
const textsKey = this.texts.join('|');
// 检查是否需要重新翻译
if (this.lastTexts.join('|') === textsKey && this.lastLanguage === currentLanguage) {
return;
}
try {
this.isTranslating = true;
this.updateElementContent([this.loadingText]);
// 使用增强的批量翻译
const results = await this.ui18nService.translateBatchOptimized(this.texts, {
...this.options,
enableProgressTracking: true
});
// 更新显示内容
const translatedTexts = results.map(result => result.text);
this.updateElementContent(translatedTexts);
// 缓存结果
this.lastTexts = [...this.texts];
this.lastLanguage = currentLanguage;
// 发出事件
this.translationsReady.emit(results);
this.cdr.markForCheck();
} catch (error) {
console.error('批量翻译失败:', error);
this.updateElementContent([this.errorText]);
this.translationError.emit(error);
} finally {
this.isTranslating = false;
}
}
/**
* 更新元素内容
*/
updateElementContent(texts) {
let content = '';
switch (this.displayMode) {
case 'join':
content = texts.join(this.separator);
break;
case 'list':
content = texts.map(text => `• ${text}`).join('\n');
break;
case 'custom':
// 自定义模式不更新内容,由用户通过事件处理
return;
default:
content = texts.join(this.separator);
}
if (this.element.nativeElement) {
this.element.nativeElement.textContent = content;
}
}
}
_UI18nBatchTranslateDirective = UI18nBatchTranslateDirective;
({
e: [_init_texts, _init_options, _init_autoTranslate, _init_displayMode, _init_separator, _init_loadingText, _init_errorText, _init_translationsReady, _init_progressUpdate, _init_translationError],
c: [_UI18nBatchTranslateD, _initClass$6]
} = _applyDecs2305(_UI18nBatchTranslateDirective, [[_textsDecs, 0, "texts"], [_optionsDecs, 0, "options"], [_autoTranslateDecs, 0, "autoTranslate"], [_displayModeDecs, 0, "displayMode"], [_separatorDecs, 0, "separator"], [_loadingTextDecs, 0, "loadingText"], [_errorTextDecs, 0, "errorText"], [_translationsReadyDecs, 0, "translationsReady"], [_progressUpdateDecs, 0, "progressUpdate"], [_translationErrorDecs, 0, "translationError"]], _classDecs$6));
_initClass$6();
var _UI18nTranslatePipe2;
let _initClass$5, _classDecs$5;
_classDecs$5 = [Pipe({
name: 'ui18nTranslate',
pure: false // 设置为非纯管道以响应语言变化
})];
let _UI18nTranslatePipe;
/**
* UI18n翻译管道
* 用法: {{ 'Hello World' | ui18nTranslate }}
* 或: {{ 'Hello World' | ui18nTranslate:'en' }}
*/
class UI18nTranslatePipe {
constructor(ui18nService, cdr) {
this.ui18nService = ui18nService;
this.cdr = cdr;
this.destroy$ = new Subject();
this.lastText = '';
this.lastLang = '';
this.lastResult = '';
this.isTranslating = false;
// 监听语言变化,触发重新翻译
this.ui18nService.currentLanguage$.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.lastLang = ''; // 重置缓存,强制重新翻译
this.cdr.markForCheck();
});
}
async transform(text, targetLanguage) {
if (!text) {
return '';
}
if (!this.ui18nService.isInitialized()) {
return text; // 未初始化时返回原文
}
const currentLang = targetLanguage || this.ui18nService.getCurrentLanguage();
// 检查缓存
if (this.lastText === text && this.lastLang === currentLang && this.lastResult) {
return this.lastResult;
}
// 避免重复翻译
if (this.isTranslating) {
return this.lastResult || text;
}
try {
this.isTranslating = true;
const translatedText = await this.ui18nService.t(text, targetLanguage);
// 更新缓存
this.lastText = text;
this.lastLang = currentLang;
this.lastResult = translatedText;
// 触发变更检测
this.cdr.markForCheck();
return translatedText;
} catch (error) {
console.error('管道翻译失败:', error);
return text; // 翻译失败时返回原文
} finally {
this.isTranslating = false;
}
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
_UI18nTranslatePipe2 = UI18nTranslatePipe;
[_UI18nTranslatePipe, _initClass$5] = _applyDecs2305(_UI18nTranslatePipe2, [], _classDecs$5).c;
_initClass$5();
var _LanguageSelectorComponent;
let _initClass$4, _classDecs$4, _languagesDecs, _init_languages, _showSearchDecs, _init_showSearch, _showNativeNameDecs, _init_showNativeName, _showBothNamesDecs, _init_showBothNames, _disabledDecs, _init_disabled, _searchPlaceholderDecs, _init_searchPlaceholder, _noResultsTextDecs, _init_noResultsText, _languageChangeDecs, _init_languageChange, _ref$2;
_classDecs$4 = [Component({
selector: 'ui18n-language-selector',
template: `
<div class="ui18n-language-selector" [class.disabled]="disabled">
<!-- 当前语言显示 -->
<button
class="ui18n-current-language"
[class.open]="isOpen"
(click)="toggleDropdown()"
[disabled]="disabled"
type="button"
>
<span class="ui18n-flag" *ngIf="currentLanguageOption?.flag">
{{ currentLanguageOption.flag }}
</span>
<span class="ui18n-name">
{{ showNativeName ? currentLanguageOption?.nativeName : currentLanguageOption?.name }}
</span>
<span class="ui18n-arrow" [class.rotated]="isOpen">▼</span>
</button>
<!-- 语言下拉列表 -->
<div class="ui18n-dropdown" *ngIf="isOpen" (click)="$event.stopPropagation()">
<!-- 搜索框 -->
<div class="ui18n-search" *ngIf="showSearch">
<input
type="text"
[(ngModel)]="searchQuery"
[placeholder]="searchPlaceholder"
class="ui18n-search-input"
(input)="onSearchChange()"
/>
</div>
<!-- 语言列表 -->
<div class="ui18n-language-list">
<button
*ngFor="let lang of filteredLanguages"
class="ui18n-language-option"
[class.selected]="lang.code === currentLanguage"
(click)="selectLanguage(lang.code)"
type="button"
>
<span class="ui18n-flag" *ngIf="lang.flag">{{ lang.flag }}</span>
<span class="ui18n-names">
<span class="ui18n-name">{{ lang.name }}</span>
<span class="ui18n-native-name" *ngIf="showBothNames">{{ lang.nativeName }}</span>
</span>
<span class="ui18n-check" *ngIf="lang.code === currentLanguage">✓</span>
</button>
</div>
<!-- 无结果提示 -->
<div class="ui18n-no-results" *ngIf="filteredLanguages.length === 0">
{{ noResultsText }}
</div>
</div>
</div>
<!-- 遮罩层 -->
<div class="ui18n-overlay" *ngIf="isOpen" (click)="closeDropdown()"></div>
`,
styleUrls: ['./language-selector.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})];
let _LanguageSelectorComp;
_ref$2 = (_languagesDecs = Input(), _showSearchDecs = Input(), _showNativeNameDecs = Input(), _showBothNamesDecs = Input(), _disabledDecs = Input(), _searchPlaceholderDecs = Input(), _noResultsTextDecs = Input(), _languageChangeDecs = Output(), "languages");
/**
* 语言选择器组件
* 提供用户友好的语言切换界面
*/
class LanguageSelectorComponent {
constructor(ui18nService, cdr) {
this.ui18nService = ui18nService;
this.cdr = cdr;
this[_ref$2] = _init_languages(this, [{
code: 'zh-CN',
name: '简体中文',
nativeName: '简体中文',
flag: '🇨🇳'
}, {
code: 'zh-TW',
name: '繁體中文',
nativeName: '繁體中文',
flag: '🇹🇼'
}, {
code: 'en-US',
name: 'English (US)',
nativeName: 'English (US)',
flag: '🇺🇸'
}, {
code: 'en-GB',
name: 'English (UK)',
nativeName: 'English (UK)',
flag: '🇬🇧'
}, {
code: 'ja-JP',
name: '日本語',
nativeName: '日本語',
flag: '🇯🇵'
}, {
code: 'ko-KR',
name: '한국어',
nativeName: '한국어',
flag: '🇰🇷'
}, {
code: 'fr-FR',
name: 'Français',
nativeName: 'Français',
flag: '🇫🇷'
}, {
code: 'de-DE',
name: 'Deutsch',
nativeName: 'Deutsch',
flag: '🇩🇪'
}, {
code: 'es-ES',
name: 'Español',
nativeName: 'Español',
flag: '🇪🇸'
}, {
code: 'pt-BR',
name: 'Português (Brasil)',
nativeName: 'Português (Brasil)',
flag: '🇧🇷'
}, {
code: 'ru-RU',
name: 'Русский',
nativeName: 'Русский',
flag: '🇷🇺'
}, {
code: 'ar-SA',
name: 'العربية',
nativeName: 'العربية',
flag: '🇸🇦'
}]);
this.showSearch = _init_showSearch(this, true);
this.showNativeName = _init_showNativeName(this, true);
this.showBothNames = _init_showBothNames(this, false);
this.disabled = _init_disabled(this, false);
this.searchPlaceholder = _init_searchPlaceholder(this, '搜索语言...');
this.noResultsText = _init_noResultsText(this, '未找到匹配的语言');
this.languageChange = _init_languageChange(this, new EventEmitter());
this.isOpen = false;
this.searchQuery = '';
this.filteredLanguages = [];
this.currentLanguage = 'zh-CN';
this.currentLanguageOption = void 0;
this.destroy$ = new Subject();
}
ngOnInit() {
// 监听当前语言变化
this.ui18nService.currentLanguage$.pipe(takeUntil(this.destroy$)).subscribe(language => {
this.currentLanguage = language;
this.updateCurrentLanguageOption();
this.cdr.markForCheck();
});
// 初始化过滤列表
this.filteredLanguages = [...this.languages];
this.updateCurrentLanguageOption();
// 点击外部关闭下拉框
document.addEventListener('click', this.onDocumentClick.bind(this));
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
document.removeEventListener('click', this.onDocumentClick.bind(this));
}
/**
* 切换下拉框显示状态
*/
toggleDropdown() {
if (this.disabled) return;
this.isOpen = !this.isOpen;
if (this.isOpen) {
this.searchQuery = '';
this.filteredLanguages = [...this.languages];
}
this.cdr.markForCheck();
}
/**
* 关闭下拉框
*/
closeDropdown() {
this.isOpen = false;
this.cdr.markForCheck();
}
/**
* 选择语言
*/
async selectLanguage(language) {
try {
await this.ui18nService.switchLanguage(language);
this.languageChange.emit(language);
this.closeDropdown();
} catch (error) {
console.error('切换语言失败:', error);
}
}
/**
* 搜索变化处理
*/
onSearchChange() {
const query = this.searchQuery.toLowerCase().trim();
if (!query) {
this.filteredLanguages = [...this.languages];
} else {
this.filteredLanguages = this.languages.filter(lang => lang.name.toLowerCase().includes(query) || lang.nativeName.toLowerCase().includes(query) || lang.code.toLowerCase().includes(query));
}
this.cdr.markForCheck();
}
/**
* 文档点击处理
*/
onDocumentClick(event) {
const target = event.target;
const selector = target.closest('.ui18n-language-selector');
if (!selector && this.isOpen) {
this.closeDropdown();
}
}
/**
* 更新当前语言选项
*/
updateCurrentLanguageOption() {
this.currentLanguageOption = this.languages.find(lang => lang.code === this.currentLanguage);
}
}
_LanguageSelectorComponent = LanguageSelectorComponent;
({
e: [_init_languages, _init_showSearch, _init_showNativeName, _init_showBothNames, _init_disabled, _init_searchPlaceholder, _init_noResultsText, _init_languageChange],
c: [_LanguageSelectorComp, _initClass$4]
} = _applyDecs2305(_LanguageSelectorComponent, [[_languagesDecs, 0, "languages"], [_showSearchDecs, 0, "showSearch"], [_showNativeNameDecs, 0, "showNativeName"], [_showBothNamesDecs, 0, "showBothNames"], [_disabledDecs, 0, "disabled"], [_searchPlaceholderDecs, 0, "searchPlaceholder"], [_noResultsTextDecs, 0, "noResultsText"], [_languageChangeDecs, 0, "languageChange"]], _classDecs$4));
_initClass$4();
var _RealTimeSyncComponent;
let _initClass$3, _classDecs$3, _showDetailsDecs, _init_showDetails, _showControlsDecs$1, _init_showControls$1, _syncOptionsDecs, _init_syncOptions, _autoConnectDecs, _init_autoConnect, _connectedDecs, _init_connected, _syncCompletedDecs, _init_syncCompleted, _syncErrorDecs, _init_syncError, _ref$1;
_classDecs$3 = [Component({
selector: 'ui18n-realtime-sync',
template: `
<div class="ui18n-realtime-sync" [class.connected]="syncStatus?.connected">
<!-- 状态指示器 -->
<div class="ui18n-sync-indicator">
<div
class="ui18n-status-dot"
[class.connected]="syncStatus?.connected"
[class.disconnected]="!syncStatus?.connected"
[class.error]="syncErrors > 0"
></div>
<span class="ui18n-status-text">
{{ getStatusText() }}
</span>
</div>
<!-- 同步信息 -->
<div class="ui18n-sync-info" *ngIf="showDetails">
<div class="ui18n-sync-method">
<label>同步方式:</label>
<span>{{ syncStatus?.method || 'polling' }}</span>
</div>
<div class="ui18n-last-sync" *ngIf="lastSyncTime">
<label>上次同步:</label>
<span>{{ formatTime(lastSyncTime) }}</span>
</div>
<div class="ui18n-sync-errors" *ngIf="syncErrors > 0">
<label>错误次数:</label>
<span class="error">{{ syncErrors }}</span>
</div>
</div>
<!-- 控制按钮 -->
<div class="ui18n-sync-controls" *ngIf="showControls">
<button
*ngIf="!syncStatus?.connected"
(click)="connect()"
[disabled]="isConnecting"
class="ui18n-btn ui18n-btn-connect"
>
{{ isConnecting ? '连接中...' : '连接' }}
</button>
<button
*ngIf="syncStatus?.connected"
(click)="disconnect()"
class="ui18n-btn ui18n-btn-disconnect"
>
断开
</button>
<button
(click)="manualSync()"
[disabled]="isSyncing"
class="ui18n-btn ui18n-btn-sync"
>
{{ isSyncing ? '同步中...' : '手动同步' }}
</button>
<button
(click)="clearErrors()"
*ngIf="syncErrors > 0"
class="ui18n-btn ui18n-btn-clear"
>
清除错误
</button>
</div>
</div>
`,
styles: [`
.ui18n-realtime-sync {
padding: 12px;
border: 1px solid #e0e0e0;
border-radius: 6px;
background: #f9f9f9;
font-size: 14px;
}
.ui18n-realtime-sync.connected {
border-color: #4caf50;
background: #f1f8e9;
}
.ui18n-sync-indicator {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}
.ui18n-status-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: #bdbdbd;
animation: pulse 2s infinite;
}
.ui18n-status-dot.connected {
background: #4caf50;
}
.ui18n-status-dot.disconnected {
background: #f44336;
}
.ui18n-status-dot.error {
background: #ff9800;
}
.ui18n-status-text {
font-weight: 500;
}
.ui18n-sync-info {
margin-bottom: 12px;
font-size: 13px;
}
.ui18n-sync-info > div {
display: flex;
justify-content: space-between;
margin-bottom: 4px;
}
.ui18n-sync-info label {
color: #666;
}
.ui18n-sync-info .error {
color: #f44336;
font-weight: 500;
}
.ui18n-sync-controls {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.ui18n-btn {
padding: 6px 12px;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
cursor: pointer;
font-size: 12px;
transition: all 0.2s;
}
.ui18n-btn:hover:not(:disabled) {
background: #f5f5f5;
}
.ui18n-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.ui18n-btn-connect {
border-color: #4caf50;
color: #4caf50;
}
.ui18n-btn-disconnect {
border-color: #f44336;
color: #f44336;
}
.ui18n-btn-sync {
border-color: #2196f3;
color: #2196f3;
}
.ui18n-btn-clear {
border-color: #ff9800;
color: #ff9800;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
`],
changeDetection: ChangeDetectionStrategy.OnPush
})];
let _RealTimeSyncComponen;
_ref$1 = (_showDetailsDecs = Input(), _showControlsDecs$1 = Input(), _syncOptionsDecs = Input(), _autoConnectDecs = Input(), _connectedDecs = Output(), _syncCompletedDecs = Output(), _syncErrorDecs = Output(), "showDetails");
/**
* 实时同步状态组件
* 显示和控制实时同步功能
*/
class RealTimeSyncComponent {
constructor(ui18nService, cdr) {
this.ui18nService = ui18nService;
this.cdr = cdr;
this[_ref$1] = _init_showDetails(this, true);
this.showControls = _init_showControls$1(this, true);
this.syncOptions = _init_syncOptions(this, {});
this.autoConnect = _init_autoConnect(this, false);
this.connected = _init_connected(this, new EventEmitter());
this.syncCompleted = _init_syncCompleted(this, new EventEmitter());
this.syncError = _init_syncError(this, new EventEmitter());
this.syncStatus = null;
this.syncErrors = 0;
this.lastSyncTime = null;
this.isConnecting = false;
this.isSyncing = false;
this.destroy$ = new Subject();
}
ngOnInit() {
// 订阅实时同步状态
this.ui18nService.realTimeSyncStatus$.pipe(takeUntil(this.destroy$)).subscribe(status => {
this.syncStatus = status;
this.syncErrors = status.syn