UNPKG

angular-t9n

Version:
215 lines (202 loc) 9.3 kB
'use strict'; var common = require('@nestjs/common'); var core = require('@nestjs/core'); var platformWs = require('@nestjs/platform-ws'); var fs = require('fs'); var path = require('path'); var index = require('../server/index.cjs'); class AsyncWorkspaceHost { readFile(path) { return fs.promises.readFile(path, 'utf8'); } writeFile(path, data) { return fs.promises.writeFile(path, data, 'utf8'); } isDirectory(path) { return fs.promises .stat(path) .then((p) => p.isDirectory()) .catch(() => false); } isFile(path) { return fs.promises .stat(path) .then((p) => p.isFile()) .catch(() => false); } } /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function __metadata(metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; let PatternPersistenceStrategy = class PatternPersistenceStrategy extends index.PersistenceStrategy { _targetPathBuilder; _serializationStrategy; constructor(_targetPathBuilder, _serializationStrategy) { super(); this._targetPathBuilder = _targetPathBuilder; this._serializationStrategy = _serializationStrategy; } async create(target) { await this._write(target); console.log(`${index.timestamp()}: Created translation file for ${target.language} at ${this._targetPathBuilder.createPath(target)}`); } async update(target) { await this._write(target); console.log(`${index.timestamp()}: Updated translation file for ${target.language} at ${this._targetPathBuilder.createPath(target)}`); } async _write(target) { const filePath = this._targetPathBuilder.createPath(target); await this._serializationStrategy.serializeTarget(target, filePath); } }; PatternPersistenceStrategy = __decorate([ common.Injectable(), __metadata("design:paramtypes", [index.TargetPathBuilder, index.SerializationStrategy]) ], PatternPersistenceStrategy); function init(name = 't9n.conf.json') { name = name.endsWith('.json') ? name : `${name}.json`; const options = { $schema: 'https://raw.githubusercontent.com/kyubisation/angular-t9n/master/t9n.schema.json', translationFile: 'messages.xlf', targetTranslationPath: '', includeContextInTarget: false, port: 4300, }; fs.writeFileSync(path.join(process.cwd(), name), JSON.stringify(options, null, 2), 'utf8'); } async function runT9nStandalone(configFile) { const configFilePath = path.resolve(configFile); let config; try { const content = fs.readFileSync(configFilePath, 'utf8'); config = JSON.parse(content); } catch (e) { throw new Error(`Unable to parse file ${configFilePath}: ${e}`); } await t9nStandalone(config); } async function t9nStandalone(options, currentWorkingDirectory) { const host = new AsyncWorkspaceHost(); const workspaceRoot = path.resolve(currentWorkingDirectory || process.cwd()); const sourceFile = path.join(workspaceRoot, options.translationFile); const targetTranslationPath = options.targetTranslationPath || path.dirname(options.translationFile); const targetDirectory = path.join(workspaceRoot, targetTranslationPath); if (!(await host.isFile(sourceFile))) { throw new Error(`${options.translationFile} does not exist or is not a file!`); } else if (!(await host.isDirectory(targetDirectory))) { throw new Error(`targetTranslationPath ${targetTranslationPath} is not a valid directory!`); } const xliffVersion = await detectXliffVersion(); console.log(`Detected version ${xliffVersion} of XLIFF`); const targetPathBuilder = new index.TargetPathBuilder(targetDirectory, sourceFile); console.log(`Loading translations. Depending on the amount, this might take a moment.`); const app = await core.NestFactory.create(index.AppModule.forRoot([ { provide: index.TargetPathBuilder, useValue: targetPathBuilder }, { provide: index.WorkspaceHost, useValue: host }, { provide: index.TargetInfo, useFactory: (source) => new index.TargetInfo('-', options.translationFile, source.language), inject: [index.TranslationSource], }, { provide: index.SerializationOptions, useValue: options }, { provide: index.TranslationDeserializer, useExisting: xliffVersion === '1.2' ? index.XlfDeserializer : index.Xlf2Deserializer, }, { provide: index.TranslationSerializer, useExisting: xliffVersion === '1.2' ? index.XlfSerializer : index.Xlf2Serializer, }, { provide: index.TranslationSource, useFactory: TRANSLATION_SOURCE_FACTORY, inject: [index.SerializationStrategy], }, { provide: index.TranslationTargetRegistry, useFactory: TRANSLATION_TARGET_REGISTRY_FACTORY, inject: [index.TranslationSource, index.SerializationStrategy, index.PersistenceStrategy], }, { provide: index.PersistenceStrategy, useClass: PatternPersistenceStrategy }, ]), { cors: true, logger: ['error', 'warn'], }); app.setGlobalPrefix('api'); app.useWebSocketAdapter(new platformWs.WsAdapter(app)); app.useGlobalPipes(new common.ValidationPipe({ skipMissingProperties: true, whitelist: true })); await app.listen(options.port ?? 4300, () => console.log(`Translation server started: http://localhost:${options.port}\n`)); return new Promise(() => { /* empty */ }); async function detectXliffVersion() { const content = await host.readFile(sourceFile); const doc = new index.XmlParser().parse(content); const version = doc.documentElement.getAttribute('version'); if (doc.documentElement.tagName !== 'xliff') { throw new Error('Only xliff is supported!'); } else if (version !== '2.0' && version !== '1.2') { throw new Error('Unsupported xliff version!'); } else { return version; } } async function TRANSLATION_SOURCE_FACTORY(serializationStrategy) { const result = await serializationStrategy.deserializeSource(sourceFile); return new index.TranslationSource(result.language, result.unitMap); } async function TRANSLATION_TARGET_REGISTRY_FACTORY(source, serializationStrategy, persistenceStrategy) { const targetRegistry = new index.TranslationTargetRegistry(source, persistenceStrategy); await Promise.all(fs.readdirSync(targetDirectory, { withFileTypes: true }) .filter((d) => d.isFile()) .map(async (d) => { const targetPath = path.join(targetDirectory, d.name); if (sourceFile === targetPath) { return; } try { const result = await serializationStrategy.deserializeTarget(targetPath); if (targetPath !== targetPathBuilder.createPath(result.language)) { return; } console.log(`Detected ${path.relative(workspaceRoot, targetPath)}`); targetRegistry.register(result.language, result.unitMap); } catch { /* empty */ } })); return targetRegistry; } } exports.init = init; exports.runT9nStandalone = runT9nStandalone; exports.t9nStandalone = t9nStandalone;