From 1c2d27fecd3e68c8ab19a60464593ad7bd2449ea Mon Sep 17 00:00:00 2001 From: Rafal Dziegielewski Date: Mon, 24 Jul 2023 09:14:41 +0200 Subject: [PATCH] feat: allow to translate resources in resource options --- src/adminjs.ts | 3 -- .../resource/resource-options.interface.ts | 7 ++++ .../utils/build-feature/build-feature.ts | 2 +- .../utils/options-parser/options-parser.ts | 36 ++++++++++++++++++- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/adminjs.ts b/src/adminjs.ts index 247bc44c8..3d0350dab 100644 --- a/src/adminjs.ts +++ b/src/adminjs.ts @@ -115,9 +115,6 @@ class AdminJS { this.resolveBabelConfigPath() - // To be removed when Login page will be renedered on client side - this.locale = defaultLocale - const { databases, resources } = this.options this.componentLoader = options.componentLoader ?? new ComponentLoader() diff --git a/src/backend/decorators/resource/resource-options.interface.ts b/src/backend/decorators/resource/resource-options.interface.ts index 076470085..b66e99889 100644 --- a/src/backend/decorators/resource/resource-options.interface.ts +++ b/src/backend/decorators/resource/resource-options.interface.ts @@ -7,6 +7,7 @@ import { CurrentAdmin } from '../../../current-admin.interface.js' import BaseResource from '../../adapters/resource/base-resource.js' import ViewHelpers from '../../utils/view-helpers/view-helpers.js' import { SearchActionResponse } from '../../actions/search/search-action.js' +import { LocaleTranslationsBlock } from '../../../index.js' /** * @alias HrefContext @@ -129,4 +130,10 @@ export interface ResourceOptions { } | { [key: string]: Partial>; }; + /** + * Resource-specific translations + */ + translations?: { + [language: string]: LocaleTranslationsBlock; + } } diff --git a/src/backend/utils/build-feature/build-feature.ts b/src/backend/utils/build-feature/build-feature.ts index afd3a2e09..28e705c48 100644 --- a/src/backend/utils/build-feature/build-feature.ts +++ b/src/backend/utils/build-feature/build-feature.ts @@ -30,7 +30,7 @@ function mergeActionHooks( return hooks.length ? { [key]: hooks } : {} } -const basicOptions = ['id', 'href', 'parent', 'sort', 'navigation', 'titleProperty'] as const +const basicOptions = ['id', 'href', 'parent', 'sort', 'navigation', 'titleProperty', 'translations'] as const const listOptions = [ 'listProperties', 'showProperties', 'editProperties', 'filterProperties', ] as const diff --git a/src/backend/utils/options-parser/options-parser.ts b/src/backend/utils/options-parser/options-parser.ts index e6d0971a7..0134d62f0 100644 --- a/src/backend/utils/options-parser/options-parser.ts +++ b/src/backend/utils/options-parser/options-parser.ts @@ -47,7 +47,41 @@ export const getLocales = async (admin: AdminJS, currentAdmin?: CurrentAdmin): P const { locale = {} } = admin.options || {} const computed = typeof locale === 'function' ? await locale(currentAdmin) : locale - return flat.unflatten(merge({}, flat.flatten(defaultLocale), flat.flatten(computed))) + let baseLocale: Locale = merge( + {} as Partial, + flat.flatten(defaultLocale) as Locale, + flat.flatten(computed) as Locale, + ) + + if (!baseLocale.translations) { + baseLocale.translations = {} + } + + // Merging translations defined in resource options + admin.resources.forEach((baseResource) => { + const decorated = baseResource._decorated ?? baseResource.decorate() + + const { translations: resourceTranslations } = decorated.options + + if (resourceTranslations) { + // Assure that translations object structure is consistent so we can use lodash#merge + const resourceLocale: Omit = { + translations: {}, + } + + Object.keys(resourceTranslations).forEach((language) => { + resourceLocale.translations![language] = { + resources: { + [decorated.id()]: resourceTranslations[language], + }, + } + }) + + baseLocale = merge(baseLocale, resourceLocale) + } + }) + + return flat.unflatten(baseLocale) } export const getTheme = async (