UNPKG

otus-localization

Version:

A translation tool for Angular i18n(angular-t9n)

227 lines (214 loc) 9.67 kB
'use strict'; var child_process = require('child_process'); var fs = require('fs'); var path = require('path'); var common = require('@nestjs/common'); var core = require('@nestjs/core'); var platformWs = require('@nestjs/platform-ws'); var server = require('../server'); 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 */ 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 server.PersistenceStrategy { constructor(_targetPathBuilder, _serializationStrategy) { super(); this._targetPathBuilder = _targetPathBuilder; this._serializationStrategy = _serializationStrategy; } async create(target) { await this._write(target); console.log(`${server.timestamp()}: Created translation file for ${target.language} at ${this._targetPathBuilder.createPath(target)}`); } async update(target) { await this._write(target); console.log(`${server.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", [server.TargetPathBuilder, server.SerializationStrategy]) ], PatternPersistenceStrategy); function init(name = 't9n.conf.json') { name = name.endsWith('.json') ? name : `${name}.json`; const options = { $schema: 'https://raw.githubusercontent.com/kyubisation/otus-translation/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}`); } await t9nStandalone(config); } function extractI18n() { return new Promise((resolve, reject) => { child_process.exec('npx nx extract-i18n --skip-nx-cache', (err) => { if (!err) { resolve(); } reject(err); }); }); } async function t9nStandalone(options, currentWorkingDirectory) { var _a; 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!`); } try { await extractI18n(); } catch (error) { console.log(error); } const xliffVersion = await detectXliffVersion(); console.log(`Detected version ${xliffVersion} of XLIFF`); const targetPathBuilder = new server.TargetPathBuilder(targetDirectory, sourceFile); console.log(`Loading translations. Depending on the amount, this might take a moment.`); const app = await core.NestFactory.create(server.AppModule.forRoot([ { provide: server.TargetPathBuilder, useValue: targetPathBuilder }, { provide: server.WorkspaceHost, useValue: host }, { provide: server.TargetInfo, useFactory: (source) => new server.TargetInfo('-', options.translationFile, source.language, options.autoTargetFile), inject: [server.TranslationSource], }, { provide: server.SerializationOptions, useValue: options }, { provide: server.TranslationDeserializer, useExisting: xliffVersion === '1.2' ? server.XlfDeserializer : server.Xlf2Deserializer, }, { provide: server.TranslationSerializer, useExisting: xliffVersion === '1.2' ? server.XlfSerializer : server.Xlf2Serializer, }, { provide: server.TranslationSource, useFactory: TRANSLATION_SOURCE_FACTORY, inject: [server.SerializationStrategy], }, { provide: server.TranslationTargetRegistry, useFactory: TRANSLATION_TARGET_REGISTRY_FACTORY, inject: [server.TranslationSource, server.SerializationStrategy, server.PersistenceStrategy], }, { provide: server.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((_a = options.port) !== null && _a !== void 0 ? _a : 4300, () => console.log(`Translation server started: http://localhost:${options.port}\n`)); return new Promise(() => { }); async function detectXliffVersion() { const content = await host.readFile(sourceFile); const doc = new server.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 server.TranslationSource(result.language, result.unitMap); } async function TRANSLATION_TARGET_REGISTRY_FACTORY(source, serializationStrategy, persistenceStrategy) { const targetRegistry = new server.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 (_a) { } })); return targetRegistry; } } exports.init = init; exports.runT9nStandalone = runT9nStandalone; exports.t9nStandalone = t9nStandalone;