UNPKG

@sap-ux/i18n

Version:

Library for i18n

131 lines 5.01 kB
import { TextDocument } from 'vscode-languageserver-textdocument'; import { getI18nConfiguration, jsonPath, discoverIndent, applyIndent, discoverLineEnding, doesExist, readFile, writeFile } from '../../utils/index.js'; import { Range } from '@sap-ux/text-document-utils'; import { parseTree } from 'jsonc-parser'; /** * Create full bundle. * * @param fallbackLocale fallback local * @param newEntries new i18n entries that will be maintained * @returns fallback key with i18n bundle */ function createFullBundle(fallbackLocale, newEntries) { const fallbackBundle = newEntries.reduce((acc, entry) => { acc[entry.key] = entry.value; return acc; }, {}); return { [fallbackLocale]: fallbackBundle }; } /** * Get text document. * * @param text json text * @returns text document instance */ const getTextDocument = (text) => TextDocument.create('', '', 0, text); /** * Add json text to fallback node. * * @param text json text * @param fallbackLocale fallback node * @param fallbackLocaleNode fallback local node * @param indent indentation * @param eol end of line * @param newEntries new i18n entries that will be maintained * @returns text string */ function addToExistingFallbackLocalNode(text, fallbackLocale, fallbackLocaleNode, indent, eol, newEntries) { const bundleNode = (fallbackLocaleNode.children ?? [])[1]; const textNodes = bundleNode?.children ?? []; if (textNodes.length) { const document = getTextDocument(text); const position = document.positionAt(textNodes[0].offset); let newText = ''; for (const entry of newEntries) { newText += `${indent + indent}"${entry.key}": "${entry.value}",${eol}`; } const edit = { newText: newText, range: Range.create(position.line, 0, position.line, 0) }; return TextDocument.applyEdits(document, [edit]); } if (bundleNode?.offset) { const document = getTextDocument(text); const start = document.positionAt(bundleNode.offset); const end = document.positionAt(bundleNode.offset + bundleNode.length); const bundle = createFullBundle(fallbackLocale, newEntries); const newText = JSON.stringify(bundle[fallbackLocale], undefined, indent); const indented = applyIndent(`${newText}`, indent, eol, false); const edit = { newText: indented, range: Range.create(start, end) }; return TextDocument.applyEdits(document, [edit]); } return text; } /** * Add json text. * * @param text json text * @param fallbackLocale fallback local i18n * @param newEntries new i18n entries that will be maintained * @returns text string */ export function addJsonTexts(text, fallbackLocale, newEntries) { if (text === '') { const bundle = createFullBundle(fallbackLocale, newEntries); return JSON.stringify(bundle, undefined, 4); } const rootNode = parseTree(text); if (rootNode?.type !== 'object') { return text; } const localeNodes = rootNode.children ?? []; const eol = discoverLineEnding(text); const indent = discoverIndent(text); if (localeNodes.length === 0) { const bundle = createFullBundle(fallbackLocale, newEntries); return JSON.stringify(bundle, undefined, 4); } const fallbackLocaleNode = localeNodes.find((node) => (node.children ?? [])[0]?.value === fallbackLocale); if (fallbackLocaleNode) { return addToExistingFallbackLocalNode(text, fallbackLocale, fallbackLocaleNode, indent, eol, newEntries); } // create new entries with local fallback const document = getTextDocument(text); const [last] = localeNodes.slice(-1); const position = document.positionAt(last.offset); const bundle = createFullBundle(fallbackLocale, newEntries); const newText = JSON.stringify(bundle[fallbackLocale], undefined, indent); const indented = applyIndent(`"${fallbackLocale}": ${newText},`, indent, eol); const edit = { newText: indented + eol, range: Range.create(position.line, 0, position.line, 0) }; return TextDocument.applyEdits(document, [edit]); } /** * Try add new i18n entries to json file. * * @param env cds environment * @param path file path * @param newI18nEntries new i18n entries that will be maintained * @param fs optional `mem-fs-editor` instance. If provided, `mem-fs-editor` api is used instead of `fs` of node * @returns boolean */ export async function tryAddJsonTexts(env, path, newI18nEntries, fs) { const i18nFilePath = jsonPath(path); if (!(await doesExist(i18nFilePath))) { return false; } const { fallbackLanguage } = getI18nConfiguration(env); const content = await readFile(i18nFilePath, fs); const newContent = addJsonTexts(content, fallbackLanguage, newI18nEntries); await writeFile(i18nFilePath, newContent, fs); return true; } //# sourceMappingURL=json.js.map