diff --git a/fyo/core/dbHandler.ts b/fyo/core/dbHandler.ts index 65e5a5e1..3eab4495 100644 --- a/fyo/core/dbHandler.ts +++ b/fyo/core/dbHandler.ts @@ -3,9 +3,12 @@ import { Fyo } from 'fyo'; import { DatabaseDemux } from 'fyo/demux/db'; import { ValueError } from 'fyo/utils/errors'; import Observable from 'fyo/utils/observable'; +import { translateSchema } from 'fyo/utils/translation'; import { Field, RawValue, SchemaMap } from 'schemas/types'; import { getMapFromList } from 'utils'; import { DatabaseBase, DatabaseDemuxBase, GetAllOptions } from 'utils/db/types'; +import { schemaTranslateables } from 'utils/translationHelpers'; +import { LanguageMap } from 'utils/types'; import { Converter } from './converter'; import { DatabaseDemuxConstructor, @@ -26,7 +29,7 @@ export class DatabaseHandler extends DatabaseBase { converter: Converter; #demux: DatabaseDemuxBase; dbPath?: string; - schemaMap: Readonly = {}; + #schemaMap: SchemaMap = {}; observer: Observable = new Observable(); fieldValueMap: Record> = {}; @@ -42,6 +45,10 @@ export class DatabaseHandler extends DatabaseBase { } } + get schemaMap(): Readonly { + return this.#schemaMap; + } + get isConnected() { return !!this.dbPath; } @@ -61,7 +68,7 @@ export class DatabaseHandler extends DatabaseBase { } async init() { - this.schemaMap = (await this.#demux.getSchemaMap()) as Readonly; + this.#schemaMap = (await this.#demux.getSchemaMap()) as SchemaMap; for (const schemaName in this.schemaMap) { const fields = this.schemaMap[schemaName]!.fields!; @@ -70,9 +77,17 @@ export class DatabaseHandler extends DatabaseBase { this.observer = new Observable(); } + async translateSchemaMap(languageMap?: LanguageMap) { + if (languageMap) { + translateSchema(this.#schemaMap, languageMap, schemaTranslateables); + } else { + this.#schemaMap = (await this.#demux.getSchemaMap()) as SchemaMap; + } + } + purgeCache() { this.dbPath = undefined; - this.schemaMap = {}; + this.#schemaMap = {}; this.fieldValueMap = {}; } diff --git a/fyo/utils/translation.ts b/fyo/utils/translation.ts index 316cebbe..944c275a 100644 --- a/fyo/utils/translation.ts +++ b/fyo/utils/translation.ts @@ -1,4 +1,4 @@ -import { LanguageMap } from 'utils/types'; +import { LanguageMap, UnknownMap } from 'utils/types'; import { getIndexFormat, getIndexList, @@ -95,3 +95,41 @@ export function setLanguageMapOnTranslationString( ) { TranslationString.prototype.languageMap = languageMap; } + +export function translateSchema( + map: UnknownMap | UnknownMap[], + languageMap: LanguageMap, + translateables: string[] +) { + if (Array.isArray(map)) { + for (const item of map) { + translateSchema(item, languageMap, translateables); + } + return; + } + + if (typeof map !== 'object') { + return; + } + + for (const key of Object.keys(map)) { + const value = map[key]; + if ( + typeof value === 'string' && + translateables.includes(key) && + languageMap[value]?.translation + ) { + map[key] = languageMap[value].translation; + } + + if (typeof value !== 'object') { + continue; + } + + translateSchema( + value as UnknownMap | UnknownMap[], + languageMap, + translateables + ); + } +} diff --git a/scripts/generateTranslations.ts b/scripts/generateTranslations.ts index 6df7f38e..6460141c 100644 --- a/scripts/generateTranslations.ts +++ b/scripts/generateTranslations.ts @@ -1,16 +1,17 @@ import fs from 'fs/promises'; import path from 'path'; +import { UnknownMap } from 'utils/types'; import { generateCSV, parseCSV } from '../utils/csvParser'; import { getIndexFormat, getWhitespaceSanitized, + schemaTranslateables, } from '../utils/translationHelpers'; const translationsFolder = path.resolve(__dirname, '..', 'translations'); const PATTERN = /(?; function shouldIgnore(p: string, ignoreList: string[]): boolean { const name = p.split(path.sep).at(-1) ?? ''; @@ -229,11 +230,7 @@ async function getTStringsFromJsonFileList( .then((content) => { const schema = JSON.parse(content) as Record; const tStrings: string[] = []; - pushTStringsFromSchema(schema, tStrings, [ - 'label', - 'description', - 'placeholder', - ]); + pushTStringsFromSchema(schema, tStrings, schemaTranslateables); return tStrings; }) .then((ts) => { @@ -250,11 +247,11 @@ async function getTStringsFromJsonFileList( function pushTStringsFromSchema( map: UnknownMap | UnknownMap[], array: string[], - translateable: string[] + translateables: string[] ) { if (Array.isArray(map)) { for (const item of map) { - pushTStringsFromSchema(item, array, translateable); + pushTStringsFromSchema(item, array, translateables); } return; } @@ -265,7 +262,7 @@ function pushTStringsFromSchema( for (const key of Object.keys(map)) { const value = map[key]; - if (translateable.includes(key) && typeof value === 'string') { + if (translateables.includes(key) && typeof value === 'string') { array.push(value); } @@ -276,7 +273,7 @@ function pushTStringsFromSchema( pushTStringsFromSchema( value as UnknownMap | UnknownMap[], array, - translateable + translateables ); } } diff --git a/src/utils/language.ts b/src/utils/language.ts index 5d67ae95..977547ee 100644 --- a/src/utils/language.ts +++ b/src/utils/language.ts @@ -65,6 +65,7 @@ async function fetchAndSetLanguageMap(code: string) { showToast({ type: 'error', message }); } else { setLanguageMapOnTranslationString(languageMap); + fyo.db.translateSchemaMap(languageMap); } return success; diff --git a/utils/translationHelpers.ts b/utils/translationHelpers.ts index 84d7a995..a0ec73ed 100644 --- a/utils/translationHelpers.ts +++ b/utils/translationHelpers.ts @@ -1,3 +1,4 @@ +export const schemaTranslateables = ['label', 'description', 'placeholder']; export function getIndexFormat(inp: string | string[]) { // converts: // ['This is an ', ,' interpolated ',' string.'] and diff --git a/utils/types.ts b/utils/types.ts index 359e26ee..f3924494 100644 --- a/utils/types.ts +++ b/utils/types.ts @@ -1,3 +1,4 @@ +export type UnknownMap = Record; export type Translation = { translation: string; context?: string }; export type LanguageMap = Record;