@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
JavaScript
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