@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
183 lines (179 loc) • 7.71 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable } from '@angular/core';
import * as i1 from '@c8y/client';
import { ApplicationType, ApplicationAvailability } from '@c8y/client';
import * as i2 from '@c8y/ngx-components';
import { uniq } from 'lodash-es';
class TranslationStoreService {
constructor(appService, appState, zip) {
this.appService = appService;
this.appState = appState;
this.zip = zip;
this.translationAppName = 'User defined translations';
this.translationAppContextPath = 'user-defined-translations';
}
/**
* Retrieves a list of available translations for the given locales from all the hosted apps available on the tenant.
*/
async getAvailableTranslations(locales) {
const { data: hostedApps } = await this.appService.list({
tenant: this.appState.currentTenant.value.name,
type: 'HOSTED',
pageSize: 2000
});
const uniqueContextPaths = uniq(hostedApps
.filter(app => app.contextPath && app.manifest?.webSdkVersion)
.map(app => app.contextPath));
const translations = {};
for (const contextPath of uniqueContextPaths) {
for (const locale of locales) {
try {
const translationsForLanguageAndApp = await this.getFileFromPath(`/apps/${contextPath}/${locale}.json`);
for (const key of Object.keys(translationsForLanguageAndApp)) {
if (!translations[key]) {
translations[key] = {};
}
translations[key][locale] = translationsForLanguageAndApp[key];
}
}
catch (e) {
continue;
}
}
}
return translations;
}
/**
* Retrieves the translations for the given locale from the translation app.
*/
async getTranslationsForLocale(locale) {
try {
const translations = await this.getFileFromTranslationApp(`${locale}.json`);
if (translations[locale]) {
return translations[locale];
}
}
catch (e) {
// do nothing.
}
return {};
}
/**
* Retrieves the translations for the given locales from the translation app.
*/
async loadTranslationsForLocales(locales) {
const translations = {};
const loadAndAddLocale = async (locale) => {
translations[locale] = await this.getTranslationsForLocale(locale);
};
await Promise.all(locales.map(loadAndAddLocale));
return translations;
}
/**
* Retrieves a combined list of translations for all the provided locales.
* The locales are combined into a single object per key and an array of these objects is returned.
*/
async getCombinedListOfTranslationsForPerKey(locales) {
const translations = await this.loadTranslationsForLocales(locales);
const translationMap = {};
for (const locale of Object.keys(translations)) {
for (const key of Object.keys(translations[locale])) {
let translationsForKey = translationMap[key];
if (!translationsForKey) {
translationsForKey = {};
translationMap[key] = translationsForKey;
}
translationsForKey[locale] = translations[locale][key];
}
}
const keys = Object.keys(translationMap).sort((a, b) => a.localeCompare(b));
return keys.map(key => Object.assign({ key }, translationMap[key]));
}
/**
* Updates the files of the translation application with the provided translations.
*/
async updateTranslations(translations) {
const filesToUpload = new Array();
const translationsPerLocale = {};
for (const entry of translations) {
const key = entry.key;
for (const locale of Object.keys(entry)) {
if (locale === 'key') {
continue;
}
if (!translationsPerLocale[locale]) {
translationsPerLocale[locale] = {};
}
if (entry[locale]) {
translationsPerLocale[locale][key] = entry[locale];
}
}
}
const langs = this.appState.state.langs;
for (const locale of langs) {
const fileName = `${locale}.json`;
filesToUpload.push({
path: fileName,
contents: new File([JSON.stringify({ [locale]: translationsPerLocale[locale] || {} })], fileName)
});
}
const app = await this.getOrCreateTranslationApp();
await this.appService.binary(app).updateFiles(filesToUpload);
}
/**
* @returns The translation app for the current tenant. If it does not exist, it will be created.
*/
async getOrCreateTranslationApp() {
const { data: apps } = await this.appService.listByName(this.translationAppName);
const ownApp = apps.find(app => app.contextPath === this.translationAppContextPath &&
app.owner.tenant.id === this.appState.currentTenant.value.name);
if (ownApp) {
return ownApp;
}
const { data: app } = await this.appService.create({
name: this.translationAppName,
contextPath: this.translationAppContextPath,
key: `${this.translationAppContextPath}-app-key`,
type: ApplicationType.HOSTED,
availability: ApplicationAvailability.MARKET,
config: {
icon: {
class: 'language1'
}
},
noAppSwitcher: true,
description: 'Providing user defined translations'
});
const zip = await this.zip.createZip([]);
const { data: binary } = await this.appService.binary(app).upload(zip, 'translations.zip');
const { data: updatedApp } = await this.appService.update({
id: app.id,
activeVersionId: binary.id
});
return updatedApp;
}
async getFileFromTranslationApp(file) {
return this.getFileFromPath(`/apps/public/${this.translationAppContextPath}/${file}`);
}
async getFileFromPath(path) {
const finalPath = `${path}?nocache=${Date.now()}`;
const response = await fetch(finalPath);
if (response.status !== 200) {
throw new Error(`Failed to fetch file from ${path}`);
}
return response.json();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationStoreService, deps: [{ token: i1.ApplicationService }, { token: i2.AppStateService }, { token: i2.ZipService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵ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: () => [{ type: i1.ApplicationService }, { type: i2.AppStateService }, { type: i2.ZipService }] });
/**
* Generated bundle index. Do not edit.
*/
export { TranslationStoreService };
//# sourceMappingURL=c8y-ngx-components-translation-editor-data.mjs.map