angular-t9n
Version:
A translation tool for Angular i18n
101 lines (91 loc) • 2.99 kB
text/typescript
import { Injectable } from '@angular/core';
import { switchMap } from 'rxjs/operators';
import { TranslationTargetUnitResponse } from '../../../models';
import { ImportResult } from './import-result';
import { TranslationTargetService } from './translation-target.service';
()
export class ImportService {
constructor(private _translationTargetService: TranslationTargetService) {}
async import(files: FileList, state: 'translated' | 'reviewed' | 'final') {
const { read, utils } = await import('xlsx');
const result = new ImportResult();
const unitRows = await Promise.all(
Array.from(files).map(async (f) => {
try {
const binary = await this._readFileAsBinary(f);
const workbook = read(binary, { type: 'binary' });
const sheet = workbook.Sheets[workbook.SheetNames[0]];
const rows = utils
.sheet_to_json<string[]>(sheet, { header: 1 })
.slice(1)
.map((row) => this._toPartialTargetUnit(row))
.filter((u) => u.id && u.target);
if (!rows.length) {
throw new Error(`${f.name} contains no valid units`);
}
return rows;
} catch (e) {
console.log(e);
result.failedFiles.push(f.name);
return [] as Partial<TranslationTargetUnitResponse>[];
}
}),
);
await Promise.all(
unitRows
.reduce((current, next) => current.concat(next), [])
.map(async (u) => {
try {
const response = (await this._importUnit(u, state).toPromise())!;
result.importedUnits.push(response);
} catch {
result.failedUnits.push(u);
}
}),
);
return result.sort();
}
private _readFileAsBinary(file: File) {
return new Promise<any>((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event: ProgressEvent<FileReader>) => {
const bytes = new Uint8Array(event.target!.result as ArrayBuffer);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
resolve(binary);
};
reader.onerror = (event: ProgressEvent<FileReader>) => reject(event.target!.error);
reader.onabort = () => reject();
reader.readAsArrayBuffer(file);
});
}
private _toPartialTargetUnit([
id,
description,
meaning,
source,
target,
]: string[]): Partial<TranslationTargetUnitResponse> {
return {
id,
description,
meaning,
source,
target,
};
}
private _importUnit(
unit: Partial<TranslationTargetUnitResponse>,
state: 'translated' | 'reviewed' | 'final',
) {
return this._translationTargetService
.unit(unit.id!)
.pipe(
switchMap((u) =>
this._translationTargetService.updateUnit({ ...u, target: unit.target!, state }),
),
);
}
}