// Type definitions interface LocalizationResource { texts: Record baseResources: string[] } interface LocalizationState { resources: Record } interface LocalizationKey { key: string defaultValue?: string } const getBaseResources = (state: LocalizationState, resourceNames: string[]): Record => { if (!resourceNames.length) { return {} } // [{}, {}, {}] const texts = resourceNames.map((resourceName: string) => { const resource = state.resources[resourceName] return { ...resource.texts, ...getBaseResources(state, resource.baseResources), } }) return Object.assign({}, ...texts) } export const setLocalization = (state: LocalizationState): Record> => { const values: Record> = {} Object.entries(state.resources).forEach(([key, value]) => { values[key] = { ...value.texts, ...getBaseResources(state, value.baseResources), } }) return values } // 🔑 Interpolation helper const interpolate = (text: string, params: Record) => { if (!params || typeof params !== 'object') return text return Object.entries(params).reduce((acc, [key, value]) => { const pattern = new RegExp(`{{\\s*${key}\\s*}}`, 'g') return acc.replace(pattern, String(value)) }, text) } export const getLocalization = ( texts: Record>, defaultResourceName: string | undefined, key: string | LocalizationKey, params?: Record ): string => { let keyString = '' let defaultValue = '' if (typeof key === 'string') { keyString = key || '' } else { defaultValue = key.defaultValue || '' keyString = key.key } const keys = keyString.split('::') const warn = (message: string) => { if (import.meta.env.DEV) console.warn(message) } if (keys.length < 2) { warn('The localization source separator (::) not found.') return defaultValue || keyString } if (!texts) return defaultValue || keys[1] const sourceName = keys[0] || defaultResourceName const sourceKey = keys[1] if (sourceName === '_') { return defaultValue || sourceKey } if (!sourceName) { warn('Localization source name is not specified and the defaultResourceName was not defined!') return defaultValue || sourceKey } const source = texts[sourceName] if (!source) { warn('Could not find localization source: ' + sourceName) return defaultValue || sourceKey } let localization = source[sourceKey] if (typeof localization === 'undefined') { return defaultValue || sourceKey } if (typeof localization !== 'string') localization = '' // ✅ Interpolation using the helper function if (localization && params && typeof params === 'object') { localization = interpolate(localization, params) } return localization || defaultValue || keyString }