import _ from 'lodash'; type ILocale = { name: string; locale: string; }; type ILocalizedValue = { [key: string]: T }; function localizedValueHasAllLocales( value: ILocalizedValue = {}, locales: Array = [], options: { isEmpty?: (v: T) => boolean } = {} ): boolean { const { isEmpty = _.isEmpty } = options; return !_.some(locales, (l) => isEmpty((value ?? {})[l.locale])); } function localizedValueHasAtLeastOneLocale( value: ILocalizedValue = {}, locales: Array = [], options: { isEmpty?: (v: T) => boolean } = {} ): boolean { const { isEmpty = _.isEmpty } = options; return _.some(locales, (l) => !isEmpty((value ?? {})[l.locale])); } type IGetLocalizedValueOptions = { fallback?: boolean; fallbackLocales?: Array; }; function getLocalizedValue( value: ILocalizedValue, locale: string, options?: IGetLocalizedValueOptions ): T | undefined { if (!_.isPlainObject(value) || locale === undefined) { return undefined; } const _options: IGetLocalizedValueOptions = _.isPlainObject(options) ? (options as IGetLocalizedValueOptions) : {}; const fallback = Boolean(_options?.fallback ?? true); let localizedValue: T | undefined = value[String(locale)]; if (localizedValue === undefined && fallback) { const fallbackLocales = _.isArray(_options.fallbackLocales) && !_.isEmpty(_options.fallbackLocales) ? _options.fallbackLocales : ['en']; localizedValue = _.chain(fallbackLocales) .map((l) => value[String(l)]) .reject(_.isUndefined) .first() .value() as T | undefined; if (localizedValue === undefined) { localizedValue = _.chain(value).values().first().value() as T | undefined; } } return localizedValue; } export type { IGetLocalizedValueOptions, ILocalizedValue }; export { getLocalizedValue, localizedValueHasAllLocales, localizedValueHasAtLeastOneLocale };