From 9f089578febf33b4aee609afb742e054eabe8734 Mon Sep 17 00:00:00 2001 From: Valentyne Stigloher Date: Sun, 27 Apr 2025 16:54:50 +0200 Subject: [PATCH] (helper) create minimal translations.suml --- server/translationsHelper.ts | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/server/translationsHelper.ts b/server/translationsHelper.ts index eb981e4d8..d201425b0 100644 --- a/server/translationsHelper.ts +++ b/server/translationsHelper.ts @@ -1,8 +1,16 @@ import fs from 'node:fs/promises'; +import { deepKeys } from 'dot-prop'; +import Suml from 'suml'; + +import type { Config } from '~/locale/config.ts'; +import type { Translations } from '~/locale/translations.ts'; +import { loadSuml } from '~/server/loader.ts'; import { rootDir } from '~/server/paths.ts'; import { DictNode, parse } from '~/server/sumlAst.ts'; import type { Node } from '~/server/sumlAst.ts'; +import { deepGet, deepListKeys, deepSet } from '~/src/helpers.ts'; +import { listMissingTranslations } from '~/src/missingTranslations.ts'; const loadDocument = async (name: string) => { return parse(await fs.readFile(`${rootDir}/${name}.suml`, 'utf-8')); @@ -60,6 +68,42 @@ const merge = (source: DictNode, base: DictNode, target: DictNode) => { } }; +const createTranslationFiles = async (locale: string) => { + const baseTranslations = await loadSuml('locale/_base/translations.suml'); + const config = await loadSuml('locale/_base/config.suml'); + + const configDocument = await loadDocument('locale/_base/config'); + const translationsDocument = await loadDocument('locale/_base/translations'); + + const requiredTranslationKeys = listMissingTranslations({}, baseTranslations, config); + for (const key of deepListKeys(baseTranslations)) { + if (!requiredTranslationKeys.includes(key)) { + remove(translationsDocument, key.split('.')); + } + } + + await fs.mkdir(`${rootDir}/locale/${locale}`, { recursive: true }); + await saveDocument(`locale/${locale}/config`, configDocument); + await saveDocument(`locale/${locale}/translations`, translationsDocument); +}; + +const remove = (node: Node, path: string[]) => { + if (!(node instanceof DictNode)) { + throw new Error('node must be DictNode'); + } + + if (path.length === 1) { + node.items = node.items.filter((item) => item.key !== path[0]); + return; + } + const childNode = node.items.find((item) => item.key === path[0])?.value; + if (!childNode) { + return; + } + remove(childNode, path.slice(1)); + node.items = node.items.filter((item) => !(item.value instanceof DictNode) || item.value.items.length > 0); +}; + const main = async () => { if (process.argv.length < 2) { console.log('Missing action.'); @@ -73,6 +117,9 @@ const main = async () => { } await mergeTranslationProposals(process.argv[3], process.argv[4]); break; + case 'create': + await createTranslationFiles(process.argv[3]); + break; default: console.error(`Unknown action ${process.argv[2]}`); }