erp-platform/ui/src/services/localization.service.ts
2025-08-17 22:07:04 +03:00

113 lines
2.9 KiB
TypeScript

// Type definitions
interface LocalizationResource {
texts: Record<string, string>
baseResources: string[]
}
interface LocalizationState {
resources: Record<string, LocalizationResource>
}
interface LocalizationKey {
key: string
defaultValue?: string
}
const getBaseResources = (state: LocalizationState, resourceNames: string[]): Record<string, string> => {
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<string, Record<string, string>> => {
const values: Record<string, Record<string, string>> = {}
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<string, string | number>) => {
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<string, Record<string, string>>,
defaultResourceName: string | undefined,
key: string | LocalizationKey,
params?: Record<string, string | number>
): 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
}