UNPKG

@ogs-gmbh/ngx-translate

Version:

A lightweight, REST-based Angular i18n library designed for seamless internationalization with minimal setup. It supports dynamic language switching & flexible translation management via RESTful APIs.

830 lines (804 loc) 41.9 kB
import * as i0 from '@angular/core'; import { InjectionToken, inject, Injectable, SkipSelf, ChangeDetectorRef, Pipe, APP_INITIALIZER, NgModule } from '@angular/core'; import { BehaviorSubject, distinctUntilChanged, timeout, retry, filter, EMPTY, tap, map, switchMap, of, Subject, catchError, combineLatestWith } from 'rxjs'; import { mergeHttpHeaders, HttpRequestStatus, buildHttpConnectionString } from '@ogs-gmbh/ngx-http'; import { HttpHeaders, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http'; import { CommonModule } from '@angular/common'; var CollectingStrategies; (function (CollectingStrategies) { CollectingStrategies["ALL"] = "all"; CollectingStrategies["CURRENT"] = "current"; })(CollectingStrategies || (CollectingStrategies = {})); var PreloadingStrategies; (function (PreloadingStrategies) { PreloadingStrategies["INITIALIZATION"] = "initialization"; PreloadingStrategies["RUNTIME"] = "runtime"; })(PreloadingStrategies || (PreloadingStrategies = {})); class LocaleNotDefinedError extends Error { name; constructor(locale) { super(`Locale "${locale.value}" does not exists. Please check if the locale is provided in the translation config.`); this.name = "LocaleNotDefinedError"; } } class SourceLocaleNotDefinedError extends Error { name; constructor() { super(`A source locale does not exists. Please check if a source locale is provided in the translation config.`); this.name = "SourceLocaleNotDefinedError"; } } const TRANSLATION_CONFIG_TOKEN = new InjectionToken("translation-config-token"); class TranslationStoreService { _loadedScopes; _notifierScopes = null; _translationConfig = inject(TRANSLATION_CONFIG_TOKEN); _locale; _locale$; _storageAttributes = { collectingStrategy: this._translationConfig.storageConfig?.collectingStrategy ?? CollectingStrategies.CURRENT, locale: { type: this._translationConfig.storageConfig?.locale?.type ?? window.localStorage, key: this._translationConfig.storageConfig?.locale?.key ?? "locale" }, translations: { type: this._translationConfig.storageConfig?.translations?.type ?? window.sessionStorage, key: this._translationConfig.storageConfig?.translations?.key ?? "translations" } }; constructor() { const sourceLocale = this.getSourceLocale(); if (sourceLocale === undefined) throw new SourceLocaleNotDefinedError(); if (this._translationConfig.storageConfig?.locale?.store) { const localeStorageValue = this._getStorageValue("locale"); const localeExists = localeStorageValue ? this._checkIfLocaleExists(localeStorageValue) : false; const isSourceLocale = localeStorageValue ? this._checkIfLocaleIsSourceLocale(localeStorageValue) : false; if (!localeExists || isSourceLocale) this._setStorageValue("locale", null); this._locale = new BehaviorSubject(localeStorageValue ?? sourceLocale); } else this._locale = new BehaviorSubject(sourceLocale); if (this._translationConfig.storageConfig?.translations?.store) { const translationsStorageValue = this._getStorageValue("translations"); this._loadedScopes = translationsStorageValue ?? null; } else this._loadedScopes = null; this._locale$ = this._locale.asObservable(); } getCurrentLocale() { return this._locale.value; } getLocale$() { return this._locale$.pipe(distinctUntilChanged()); } setLocale(locale) { if (!this._checkIfLocaleExists(locale)) throw new LocaleNotDefinedError(locale); if (this._translationConfig.storageConfig?.locale?.store) { this._checkIfLocaleIsSourceLocale(locale) ? this._setStorageValue("locale", null) : this._setStorageValue("locale", locale); } if (this._translationConfig.storageConfig?.translations?.store && this._translationConfig.storageConfig.collectingStrategy === CollectingStrategies.CURRENT) this._setStorageValue("translations", null); this._locale.next(locale); } getLocales() { return this._translationConfig.locales; } setScopedFile(scopeName, file) { const existingScope = scopeName ? this._getScopeByScopeName(scopeName) : undefined; if (existingScope === undefined) this._appendScope(scopeName, file); else existingScope.file = file; if (this._translationConfig.storageConfig?.translations?.store) this._setStorageValue("translations", this._loadedScopes); } getScopedFile(scopeName) { const existingScope = this._getScopeByScopeName(scopeName); return existingScope ? existingScope.file : undefined; } hasScopedFile(scopeName) { const existingScope = this._getScopeByScopeName(scopeName); return Boolean(existingScope); } hasScopedFiles(scopeNames) { const existingScopes = this._getScopeByScopeNames(scopeNames); return Boolean(existingScopes); } isScopeExisting(scopeName) { const existingScope = this._getScopeByScopeName(scopeName); return existingScope !== undefined; } getExistingScopes(scopeNames) { return scopeNames.filter((scopeName) => this.isScopeExisting(scopeName)); } isScopeNameInNotifierScopes(scopeName) { return Boolean(this._notifierScopes?.find((notifierScope) => notifierScope.scope === scopeName)); } areScopeNamesInNotifierScopes(scopeNames) { return scopeNames.map((scopeName) => this.isScopeNameInNotifierScopes(scopeName)) .reduce((previous, current) => previous && current); } getExistingNotifierScopes(scopeNames) { return scopeNames.filter((scopeName) => this.isScopeNameInNotifierScopes(scopeName)); } getNotiferScope(scopeName) { return this._notifierScopes?.find((notiferScope) => notiferScope.scope === scopeName); } getNotifierScopes(scopeNames) { const filteredScopes = scopeNames.map((scopeName) => this.getNotiferScope(scopeName)) .filter((notifierScope) => notifierScope !== undefined); return filteredScopes.length === 0 ? filteredScopes : undefined; } addNotifierScope(notifierScope) { this._notifierScopes === null ? this._notifierScopes = [notifierScope] : this._notifierScopes.push(notifierScope); } addNotifierScopes(notifierScopes) { this._notifierScopes === null ? this._notifierScopes = notifierScopes : this._notifierScopes.push(...notifierScopes); } addNotifierToNotifierScope(scopeName, notifier) { this._notifierScopes = this._notifierScopes?.map((notifierScope) => { if (notifierScope.scope !== scopeName) return notifierScope; notifierScope.notifiers === null ? notifierScope.notifiers = [notifier] : notifierScope.notifiers.push(notifier); return notifierScope; }) ?? null; } removeNotifierScope(scopeName) { if (this._notifierScopes === null) return; this._notifierScopes = this._notifierScopes.filter((notifierScope) => notifierScope.scope !== scopeName); } getSourceLocale() { return this._translationConfig.locales.find((localeConfig) => localeConfig.isSource); } _checkIfLocaleExists(locale) { return this._translationConfig.locales.some((configLocale) => configLocale.value === locale.value); } _checkIfLocaleIsSourceLocale(locale) { return this._translationConfig.locales.some((localeConfig) => localeConfig.value === locale.value && localeConfig.isSource); } _setStorageValue(dataType, storageValue) { storageValue === null ? this._storageAttributes[dataType].type.removeItem(this._storageAttributes[dataType].key) : this._storageAttributes[dataType].type.setItem(this._storageAttributes[dataType].key, JSON.stringify(storageValue)); } _getStorageValue(dataType) { const serializedStorageValue = this._storageAttributes[dataType].type.getItem(this._storageAttributes[dataType].key); return serializedStorageValue ? JSON.parse(serializedStorageValue) : null; } _getScopeByScopeName(scopeName) { if (this._storageAttributes.collectingStrategy === CollectingStrategies.ALL) { const localeLoadedScopes = this._loadedScopes; if (this._loadedScopes === null) return undefined; const _loadedScopes = localeLoadedScopes[this._locale.value.value]; return _loadedScopes?.find((loadedScope) => loadedScope.scope === scopeName); } const loadedScopes = this._loadedScopes; return loadedScopes?.find((loadedScope) => loadedScope.scope === scopeName); } _getScopeByScopeNames(scopeNames) { if (this._storageAttributes.collectingStrategy === CollectingStrategies.ALL) { const localeLoadedScopes = this._loadedScopes; if (this._loadedScopes === null) return undefined; const _loadedScopes = localeLoadedScopes[this._locale.value.value]; return _loadedScopes?.filter((loadedScope) => scopeNames.includes(loadedScope.scope)); } const loadedScopes = this._loadedScopes; return loadedScopes.filter((loadedScope) => scopeNames.includes(loadedScope.scope)); } _appendScope(scopeName, file) { if (this._storageAttributes.collectingStrategy === CollectingStrategies.ALL) { const localeLoadedScopes = this._loadedScopes; if (localeLoadedScopes === null) { this._loadedScopes = { [this._locale.value.value]: [{ scope: scopeName, file }] }; return; } const loadedScope = localeLoadedScopes[this._locale.value.value]; if (loadedScope === undefined) { localeLoadedScopes[this._locale.value.value] = [{ scope: scopeName, file }]; return; } loadedScope.push({ scope: scopeName, file }); return; } this._loadedScopes === null ? this._loadedScopes = [{ scope: scopeName, file }] : this._loadedScopes.push({ scope: scopeName, file }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationStoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationStoreService, providedIn: "root" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationStoreService, decorators: [{ type: Injectable, args: [{ providedIn: "root" }] }], ctorParameters: () => [] }); class TranslationInterceptor { _translationStoreService = inject(TranslationStoreService); intercept(httpRequest, httpHandler) { const currentLocale = this._translationStoreService.getCurrentLocale(); const clonedHttpRequest = httpRequest.clone({ setHeaders: { language: currentLocale.value } }); return httpHandler.handle(clonedHttpRequest); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationInterceptor, providedIn: "root" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationInterceptor, decorators: [{ type: Injectable, args: [{ providedIn: "root" }] }] }); const TRANSLATION_SCOPE_TOKEN = new InjectionToken("translation-scope-token"); class ScopeNotDefinedError extends Error { name; constructor(isDefaultScope, scopeName) { super(isDefaultScope ? `The default scope does not exists. Please check if the given scope is provided.` : `Scope "${scopeName}" does not exists. Please check if the given scope is provided.`); this.name = "ScopeNotDefinedError"; } } class TranslationNotDefinedError extends Error { name; constructor(token, value) { super(`Translation for token "${token}" ${value && `and its default value "${value}"`} does not exists. Please check if the translation for the given token is provided in the translations.`); this.name = "TranslationNotDefinedError"; } } const parseMultiScopedFile = (multiScopedFile) => { const splittedMultiScopedFile = []; const globalScopedFile = {}; Object.keys(multiScopedFile).forEach((key) => { const currentItem = multiScopedFile[key]; if (!(currentItem !== undefined && !Array.isArray(currentItem))) return; if (typeof currentItem === "object") { return void splittedMultiScopedFile.push({ scopeName: key, file: currentItem }); } globalScopedFile[key] = currentItem; }); splittedMultiScopedFile.push({ scopeName: null, file: globalScopedFile }); return splittedMultiScopedFile; }; const splitMultiScopedFile = (multiScopedFile) => { const scopedFile = []; const globalScopedFile = {}; Object.keys(multiScopedFile).forEach((key) => { const currentItem = multiScopedFile[key]; if (!(currentItem !== undefined && !Array.isArray(currentItem))) return; if (typeof currentItem === "object") return void scopedFile.push(currentItem); globalScopedFile[key] = currentItem; }); scopedFile.push(globalScopedFile); return scopedFile; }; const findScopeInMultiScopedFile = (multiScopedFile, scopeName) => { if (scopeName === null) { const newScopedFile = {}; Object.keys(multiScopedFile).forEach((key) => { const currentItem = multiScopedFile[key]; if (!(currentItem !== undefined && typeof currentItem !== "object" && !Array.isArray(currentItem))) return; newScopedFile[key] = currentItem; }); return newScopedFile; } const scopedFile = multiScopedFile[scopeName]; if (scopedFile === undefined) throw new ScopeNotDefinedError(false, scopeName); return scopedFile; }; const parseMultiScopedFileByScope = (multiScopedFile, scopeName) => { if (Array.isArray(scopeName)) return scopeName.map((_scopeName) => findScopeInMultiScopedFile(multiScopedFile, _scopeName)); return [findScopeInMultiScopedFile(multiScopedFile, scopeName)]; }; const findTokenInScopedFiles = (scopedFiles, token) => { const foundScopedFile = scopedFiles.find((scopedFile) => Object.keys(scopedFile).includes(token)); if (foundScopedFile === undefined) throw new TranslationNotDefinedError(token); return foundScopedFile; }; const translateTokenByScopedFile = (scopedFile, token) => { const isTokenValid = Object.keys(scopedFile).includes(token); if (!isTokenValid) return; return scopedFile[token]; }; const translateTokenByScopedFiles = (scopedFiles, token) => { let translation; scopedFiles.some((scopedFile) => { const isTokenValid = Object.keys(scopedFile).includes(token); if (!isTokenValid) return false; translation = scopedFile[token]; return true; }); return translation; }; const translateTokenByMultiScopedFile = (multiScopedFile, scopeName, token) => { const scopedFile = findScopeInMultiScopedFile(multiScopedFile, scopeName); return translateTokenByScopedFile(scopedFile, token); }; function resolveScope(translationConfig, scopeName) { return (scopeName ?? translationConfig?.defaultScope ?? null); } const TRANSLATION_HTTP_CONFIG = new InjectionToken("translation-http-config"); const TRANSLATION_HTTP_OPTIONS = new InjectionToken("translation-http-options"); class TranslationHttpSerivce { _translationHttpConfig = inject(TRANSLATION_HTTP_CONFIG); _translationConfig = inject(TRANSLATION_CONFIG_TOKEN, { optional: true }); _translationHttpOptions = inject(TRANSLATION_HTTP_OPTIONS, { optional: true }); getWithRef$(httpClientRef, scopeName, httpOptions) { let path = this._translationHttpConfig; if (typeof scopeName === "string" || scopeName === null) { if (scopeName !== null) path += `?scope=${encodeURIComponent(scopeName)}`; } else { const urlSearchParams = new URLSearchParams(); scopeName.forEach((scopeNameItem) => { if (scopeNameItem === null) return; urlSearchParams.append("scope", encodeURIComponent(scopeNameItem)); }); path += `?${urlSearchParams.toString()}`; } let headers = new HttpHeaders(); if (this._translationHttpOptions?.headers !== undefined) headers = mergeHttpHeaders(headers, this._translationHttpOptions.headers); if (httpOptions?.headers !== undefined) headers = mergeHttpHeaders(headers, httpOptions.headers); return httpClientRef.get(path, { responseType: "json", observe: "body", headers }).pipe(timeout(this._translationConfig?.timeout ?? 3000), retry(0)); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationHttpSerivce, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationHttpSerivce, providedIn: "root" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationHttpSerivce, decorators: [{ type: Injectable, args: [{ providedIn: "root" }] }] }); class TranslationService { _httpClient = inject(HttpClient); _translationConfig = inject(TRANSLATION_CONFIG_TOKEN); _translationStoreService = inject(TranslationStoreService); _translationHttpService = inject(TranslationHttpSerivce); _isHttpLoading = new BehaviorSubject(null); _isHttpLoading$ = this._isHttpLoading.asObservable(); isHttpLoading$() { return this._isHttpLoading$.pipe(distinctUntilChanged(), filter((isHttpLoading) => isHttpLoading !== null)); } _preloadWithRef$(httpClient, translationStoreService, translationHttpService, _locale, scopeName, httpOptions) { if ((typeof scopeName === "string" || scopeName === null) && translationStoreService.hasScopedFile(scopeName)) return EMPTY; if (Array.isArray(scopeName) && translationStoreService.hasScopedFiles(scopeName)) return EMPTY; if ((typeof scopeName === "string" || scopeName === null) && translationStoreService.isScopeNameInNotifierScopes(scopeName)) return EMPTY; if (Array.isArray(scopeName) && translationStoreService.areScopeNamesInNotifierScopes(scopeName)) return EMPTY; if (typeof scopeName === "string" || scopeName === null) { return translationHttpService.getWithRef$(httpClient, scopeName, httpOptions).pipe(tap((scopedFile) => { translationStoreService.setScopedFile(scopeName, scopedFile); }), map(() => void 0)); } else { const existingScopes = translationStoreService.getExistingScopes(scopeName); if (existingScopes.length === scopeName.length) return EMPTY; const extinctScopes = scopeName.filter((_scopeName) => !existingScopes.includes(_scopeName)); if (extinctScopes.length === 0) return EMPTY; return translationHttpService.getWithRef$(httpClient, extinctScopes, httpOptions).pipe(tap((multiScopedFile) => { const parsedMultiScopedFiles = parseMultiScopedFile(multiScopedFile); parsedMultiScopedFiles.forEach((parsedScopedFile) => { translationStoreService.setScopedFile(parsedScopedFile.scopeName, parsedScopedFile.file); }); }), map(() => void 0)); } } translateTokenByLocale$(token, value, scopeName, httpOptions) { return this._translationStoreService.getLocale$().pipe(switchMap((locale) => this._translateWithRef$(this._httpClient, this._translationStoreService, this._translationHttpService, locale, token, value, this._resolveScope(scopeName), httpOptions))); } translateTokenByCurrentLocale$(token, value, scopeName, httpOptions) { const currentLocale = this._translationStoreService.getCurrentLocale(); return this._translateWithRef$(this._httpClient, this._translationStoreService, this._translationHttpService, currentLocale, token, value, scopeName, httpOptions); } preloadByLocale(httpClient, translationStoreService, translationHttpService, scopeName, httpOptions) { return translationStoreService.getLocale$().pipe(switchMap((locale) => this._preloadWithRef$(httpClient, translationStoreService, translationHttpService, locale, scopeName, httpOptions))); } preloadByCurrentLocale(httpClient, translationStoreService, translationHttpService, scopeName, httpOptions) { const currentLocale = translationStoreService.getCurrentLocale(); return this._preloadWithRef$(httpClient, translationStoreService, translationHttpService, currentLocale, scopeName, httpOptions); } _resolveScope(scopeName) { return resolveScope(this._translationConfig, scopeName); } _translateBySourceLocale(token, value) { if (!value) throw new TranslationNotDefinedError(token); return of(value); } _translateByStore(scope, token) { if (typeof scope === "string" || scope === null) { const scopedFile = this._translationStoreService.getScopedFile(scope); const _translatedToken = translateTokenByScopedFile(scopedFile, token); if (_translatedToken === undefined) throw new TranslationNotDefinedError(token); return of(_translatedToken); } let translatedToken; scope.map((_scope) => this._translationStoreService.getScopedFile(_scope)) .some((scopedFile) => { if (scopedFile === undefined) return false; const _translatedToken = translateTokenByScopedFile(scopedFile, token); if (_translatedToken === undefined) return false; translatedToken = _translatedToken; return true; }); if (translatedToken === undefined) throw new TranslationNotDefinedError(token); return of(translatedToken); } _getScopedFileByNotifier(scope) { const currentNotifier = new Subject(); this._translationStoreService.addNotifierToNotifierScope(scope, currentNotifier); return currentNotifier.asObservable(); } _getScopedFileByAddingNotifier(scope) { const currentNotifier = new Subject(); this._translationStoreService.addNotifierScope({ scope, notifiers: [currentNotifier] }); return currentNotifier; } _getScopedFileByHttpWithRef$(httpClient, translationStoreService, translationHttpService, scope, httpOptions) { if (typeof scope === "string" || scope === null) translationStoreService.addNotifierScope({ scope, notifiers: null }); else translationStoreService.addNotifierScopes(scope.map((_scope) => ({ scope: _scope, notifiers: null }))); this._isHttpLoading.next(HttpRequestStatus.PENDING); return translationHttpService.getWithRef$(httpClient, scope, httpOptions).pipe(catchError(() => { this._isHttpLoading.next(HttpRequestStatus.ERROR); this._isHttpLoading.next(null); if (typeof scope === "string" || scope === null) translationStoreService.isScopeNameInNotifierScopes(scope) && translationStoreService.removeNotifierScope(scope); else { scope.forEach((_scope) => { if (!translationStoreService.isScopeNameInNotifierScopes(_scope)) return; translationStoreService.removeNotifierScope(_scope); }); } return of(); }), tap((genericScopedFile) => { this._isHttpLoading.next(HttpRequestStatus.SUCCESS); this._isHttpLoading.next(null); if (typeof scope === "string" || scope === null) { translationStoreService.setScopedFile(scope, genericScopedFile); const notifierScope = translationStoreService.getNotiferScope(scope); if (notifierScope === undefined) return; notifierScope.notifiers?.forEach((notifier) => { notifier.next(genericScopedFile); }); translationStoreService.removeNotifierScope(scope); return; } scope.forEach((_scope) => { const parsedScopedFile = findScopeInMultiScopedFile(genericScopedFile, _scope); const notifierScope = translationStoreService.getNotiferScope(_scope); if (notifierScope === undefined) return; notifierScope.notifiers?.forEach((notifier) => { notifier.next(parsedScopedFile); }); translationStoreService.removeNotifierScope(_scope); }); })); } _translateWithRef$(httpClient, translationStoreService, translationHttpService, locale, token, value, scopeName, httpOptions) { let resolvedScopes; const sourceLocale = this._translationStoreService.getSourceLocale(); if (sourceLocale !== undefined && sourceLocale === this._translationStoreService.getCurrentLocale()) return this._translateBySourceLocale(token, value); if (typeof scopeName === "string" || scopeName === null) { resolvedScopes = this._resolveScope(scopeName); if (translationStoreService.hasScopedFile(resolvedScopes)) return this._translateByStore(resolvedScopes, token); } else { resolvedScopes = this._resolveScope(scopeName); if (translationStoreService.hasScopedFiles(resolvedScopes)) return this._translateByStore(resolvedScopes, token); } if (typeof resolvedScopes === "string" || resolvedScopes === null) { if (translationStoreService.isScopeNameInNotifierScopes(resolvedScopes)) { return this._getScopedFileByNotifier(resolvedScopes) .pipe(map((scopedFile) => { const translatedToken = translateTokenByScopedFile(scopedFile, token); if (translatedToken === undefined) throw new TranslationNotDefinedError(token, value); return translatedToken; })); } } else { const existingScopes = translationStoreService.getExistingNotifierScopes(resolvedScopes); const extinctScopes = resolvedScopes.filter((resolvedScope) => !existingScopes.includes(resolvedScope)); const existingNotifiers = existingScopes.map((existingScope) => this._getScopedFileByNotifier(existingScope)); const extinctScopesHttp = this._getScopedFileByHttpWithRef$(httpClient, translationStoreService, translationHttpService, extinctScopes, httpOptions) .pipe(tap((multiScopedFile) => { const castedMultiScopedFile = multiScopedFile; const parsedMultiScopedFile = parseMultiScopedFile(castedMultiScopedFile); parsedMultiScopedFile.forEach((_parsedMultiScopedFile) => { translationStoreService.setScopedFile(_parsedMultiScopedFile.scopeName, _parsedMultiScopedFile.file); }); }), map((multiScopedFile) => { const castedMultiScopedFile = multiScopedFile; const splittedMultiScopedFiles = splitMultiScopedFile(castedMultiScopedFile); return findTokenInScopedFiles(splittedMultiScopedFiles, token); })); return extinctScopesHttp.pipe(combineLatestWith(...existingNotifiers), map((scopedFiles) => { const translatedToken = translateTokenByScopedFiles(scopedFiles, token); if (translatedToken === undefined) throw new TranslationNotDefinedError(token, value); return translatedToken; })); } return of(locale).pipe(switchMap(() => (typeof resolvedScopes === "string" || resolvedScopes === null ? this._getScopedFileByHttpWithRef$(httpClient, translationStoreService, translationHttpService, resolvedScopes, httpOptions).pipe(map((scopedFile) => { translationStoreService.setScopedFile(resolvedScopes, scopedFile); const translatedToken = translateTokenByScopedFile(scopedFile, token); if (translatedToken === undefined) throw new TranslationNotDefinedError(token, value); return translatedToken; })) : this._getScopedFileByHttpWithRef$(httpClient, translationStoreService, translationHttpService, resolvedScopes, httpOptions).pipe(tap((multiScopedFile) => { const parsedMultiScopedFile = parseMultiScopedFile(multiScopedFile); parsedMultiScopedFile.forEach((_parsedMultiScopedFile) => { translationStoreService.setScopedFile(_parsedMultiScopedFile.scopeName, _parsedMultiScopedFile.file); }); }), map((multiScopedFile) => { const splittedMultiScopedFiles = splitMultiScopedFile(multiScopedFile); const foundScopedFile = findTokenInScopedFiles(splittedMultiScopedFiles, token); const translatedToken = translateTokenByScopedFile(foundScopedFile, token); if (translatedToken === undefined) throw new TranslationNotDefinedError(token, value); return translatedToken; }))))); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationService, providedIn: "root" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationService, decorators: [{ type: Injectable, args: [{ providedIn: "root" }] }], propDecorators: { _httpClient: [{ type: SkipSelf }] } }); class TranslationPipe { _translationServiceSubscription = null; _lastValue = null; _hasTranslationChanged = false; _translationService = inject(TranslationService); _changeDetectorRef = inject(ChangeDetectorRef); _translationScopeToken = inject(TRANSLATION_SCOPE_TOKEN, { optional: true }); _translationConfig = inject(TRANSLATION_CONFIG_TOKEN, { optional: true }); transform(value, token, scope, fallback) { if (this._translationServiceSubscription !== null) return this._lastValue ?? value; this._translationServiceSubscription = this._translationService.translateTokenByLocale$(token, value, this._resolveScope(scope)) .pipe(catchError((_httpErrorResponse, _) => { const fallbackToSourceLocale = fallback ?? this._translationConfig?.fallbackToSourceLocale; if (fallbackToSourceLocale) this._updateLastValue(value); return EMPTY; }), filter((translation) => translation !== this._lastValue)) .subscribe({ next: (translation) => { this._hasTranslationChanged = translation !== this._lastValue; this._updateLastValue(translation); } }); return this._lastValue ?? value; } ngOnDestroy() { this._translationServiceSubscription?.unsubscribe(); } _resolveScope(scope) { return resolveScope(this._translationConfig, scope ?? this._translationScopeToken); } _updateLastValue(newValue) { this._lastValue = newValue; this._hasTranslationChanged && this._changeDetectorRef.markForCheck(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: TranslationPipe, name: "translate", pure: false }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationPipe, decorators: [{ type: Pipe, args: [{ name: "translate", pure: false }] }] }); const TRANSLATION_PRELOAD_TOKEN = new InjectionToken("translation-preload-token"); const provideTranslationScope = (scope) => ({ provide: TRANSLATION_SCOPE_TOKEN, useValue: scope, multi: false }); const handleInitializationStrategy = (httpClient, translationHttpService, translationStoreService, translationSerivce, scopes) => () => void translationSerivce.preloadByCurrentLocale(httpClient, translationStoreService, translationHttpService, scopes).subscribe(); const handleRuntimeStrategy = (httpClient, translationHttpService, translationStoreService, translationSerivce, scopes) => () => { translationSerivce.preloadByCurrentLocale(httpClient, translationStoreService, translationHttpService, scopes).subscribe(); return translationSerivce; }; const provideTranslationPreload = (preloadProvider) => { switch (preloadProvider.preloadingStrategy) { case PreloadingStrategies.INITIALIZATION: { return { provide: APP_INITIALIZER, useFactory: (httpClient, translationHttpService, translationStoreService, translationSerivce) => handleInitializationStrategy(httpClient, translationHttpService, translationStoreService, translationSerivce, preloadProvider.scopes), deps: [HttpClient, TranslationHttpSerivce, TranslationStoreService, TranslationService], multi: true }; } case PreloadingStrategies.RUNTIME: { return { provide: TRANSLATION_PRELOAD_TOKEN, useFactory: (httpClient, translationHttpService, translationStoreService, translationSerivce) => handleRuntimeStrategy(httpClient, translationHttpService, translationStoreService, translationSerivce, preloadProvider.scopes), deps: [HttpClient, TranslationHttpSerivce, TranslationStoreService, TranslationService], multi: false }; } } }; const handleReactiveInitializationStrategy = (httpClient, translationHttpService, translationStoreService, translationSerivce, scopes) => () => void translationSerivce.preloadByLocale(httpClient, translationStoreService, translationHttpService, scopes).subscribe(); const handleReactiveRuntimeStrategy = (httpClient, translationHttpService, translationStoreService, translationSerivce, scopes) => () => { translationSerivce.preloadByLocale(httpClient, translationStoreService, translationHttpService, scopes).subscribe(); return translationSerivce; }; const provideTranslationPreloadReactive = (preloadProvider) => { switch (preloadProvider.preloadingStrategy) { case PreloadingStrategies.INITIALIZATION: { return { provide: APP_INITIALIZER, useFactory: (httpClient, translationHttpService, translationStoreService, translationSerivce) => handleReactiveInitializationStrategy(httpClient, translationHttpService, translationStoreService, translationSerivce, preloadProvider.scopes), deps: [HttpClient, TranslationHttpSerivce, TranslationStoreService, TranslationService], multi: true }; } case PreloadingStrategies.RUNTIME: { return { provide: TRANSLATION_PRELOAD_TOKEN, useFactory: (httpClient, translationHttpService, translationStoreService, translationSerivce) => handleReactiveRuntimeStrategy(httpClient, translationHttpService, translationStoreService, translationSerivce, preloadProvider.scopes), deps: [HttpClient, TranslationHttpSerivce, TranslationStoreService, TranslationService], multi: false }; } } }; const provideTranslationConfig = (translationConfig) => ({ provide: TRANSLATION_CONFIG_TOKEN, useValue: translationConfig, multi: false }); const provideTranslationInterceptor = () => ({ provide: HTTP_INTERCEPTORS, useClass: TranslationInterceptor, multi: true }); class TranslationPipeModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationPipeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: TranslationPipeModule, declarations: [TranslationPipe], imports: [CommonModule], exports: [TranslationPipe] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationPipeModule, imports: [CommonModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationPipeModule, decorators: [{ type: NgModule, args: [{ imports: [ CommonModule ], declarations: [ TranslationPipe ], exports: [ TranslationPipe ] }] }] }); const provideTranslationHttpConfig = (httpConfig) => ({ provide: TRANSLATION_HTTP_CONFIG, useValue: buildHttpConnectionString(httpConfig), multi: false }); const provideTranslationHttpOptions = (httpOptions) => ({ provide: TRANSLATION_HTTP_OPTIONS, useValue: httpOptions, multi: false }); class TranslationModule { static forRoot(translateConfig) { const providers = [ provideTranslationConfig(translateConfig.translate), provideTranslationHttpConfig(translateConfig.http.config) ]; if (translateConfig.http.options !== undefined) { providers.push(provideTranslationHttpOptions(translateConfig.http.options)); } return { ngModule: TranslationModule, providers }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: TranslationModule, imports: [CommonModule, TranslationPipeModule], exports: [TranslationPipeModule] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationModule, providers: [ TranslationHttpSerivce, TranslationStoreService, TranslationService, provideTranslationInterceptor() ], imports: [CommonModule, TranslationPipeModule, TranslationPipeModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationModule, decorators: [{ type: NgModule, args: [{ imports: [ CommonModule, TranslationPipeModule ], providers: [ TranslationHttpSerivce, TranslationStoreService, TranslationService, provideTranslationInterceptor() ], exports: [ TranslationPipeModule ] }] }] }); export { CollectingStrategies, PreloadingStrategies, TRANSLATION_CONFIG_TOKEN, TRANSLATION_PRELOAD_TOKEN, TRANSLATION_SCOPE_TOKEN, TranslationHttpSerivce, TranslationInterceptor, TranslationModule, TranslationPipe, TranslationPipeModule, TranslationService, TranslationStoreService, provideTranslationConfig, provideTranslationInterceptor, provideTranslationPreload, provideTranslationPreloadReactive, provideTranslationScope }; //# sourceMappingURL=ogs-gmbh-ngx-translate.mjs.map