diff --git a/package/shared/index.ts b/package/shared/index.ts index c1cb5de..16f2c12 100644 --- a/package/shared/index.ts +++ b/package/shared/index.ts @@ -1 +1,8 @@ export * from './resource'; + +// https://www.raygesualdo.com/posts/flattening-object-keys-with-typescript-types/ +export type FlattenObjectKeys, Key = keyof T> = Key extends string + ? T[Key] extends Record + ? `${Key}.${FlattenObjectKeys}` + : `${Key}` + : never; diff --git a/package/shared/resource/locale/index.ts b/package/shared/resource/locale/index.ts index 8a264d5..67c24ee 100644 --- a/package/shared/resource/locale/index.ts +++ b/package/shared/resource/locale/index.ts @@ -3,6 +3,18 @@ import { printf } from 'fast-printf'; const dict: Record = {}; +function flattenDict(source: Record, target: Record, prefix?: string) { + for (const key in source) { + const fullKey = prefix ? `${prefix}.${key}` : key; + const value = source[key]; + + if (typeof value === 'object') flattenDict(value, target, fullKey); + else target[fullKey] = String(value); + } + + return target; +} + export const locale = (str: string, ...args: any[]) => { const lstr = dict[str]; @@ -21,15 +33,28 @@ export const locale = (str: string, ...args: any[]) => { export const getLocales = () => dict; +export function getLocale(resource: string, key: string) { + let locale = dict[key]; + + if (locale) console.warn(`overwritin existing locale '${key} (${locale})`); + + locale = exports[resource].getLocale(key); + dict[key] = locale; + + if (!locale) console.warn(`no locale exists with key '${key} in resource '${resource}`); + + return locale; +} + export const initLocale = () => { const lang = GetConvar('ox:locale', 'en'); - let locales: unknown = JSON.parse(LoadResourceFile(cache.resource, `locales/${lang}.json`)); + let locales: typeof dict = JSON.parse(LoadResourceFile(cache.resource, `locales/${lang}.json`)); if (!locales) { console.warn(`could not load 'locales/${lang}.json'`); if (lang !== 'en') { - locales = LoadResourceFile(cache.resource, 'locales/en.json'); + locales = JSON.parse(LoadResourceFile(cache.resource, 'locales/en.json')); if (!locales) { console.warn(`could not load 'locales/en.json'`); @@ -39,7 +64,9 @@ export const initLocale = () => { if (!locales) return; } - for (let [k, v] of Object.entries(locales)) { + const flattened = flattenDict(locales, {}); + + for (let [k, v] of Object.entries(flattened)) { if (typeof v === 'string') { const regExp = new RegExp(/\$\{([^}]+)\}/g); @@ -49,7 +76,7 @@ export const initLocale = () => { for (const match of matches) { if (!match) break; const variable = match.substring(2, match.length - 1) as keyof typeof locales; - let locale: string = locales[variable]; + let locale: string = flattened[variable]; if (locale) { v = v.replace(match, locale);