From c43891b2ba50fdee02d1138a4a45ac1da402a3c4 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 10 May 2025 17:15:15 -0700 Subject: [PATCH] fix(db-mongodb): localized dates being returned as date objects instead of strings (#12354) Fixes https://github.com/payloadcms/payload/issues/12334 We weren't passing locale through to the Date transformer function so localized dates were being read as objects instead of strings. --- .../db-mongodb/src/utilities/transform.ts | 1 + .../collections/LocalizedDateFields/index.ts | 21 ++++++++++++++ test/localization/config.ts | 11 +++++++ test/localization/int.spec.ts | 27 +++++++++++++++++ test/localization/payload-types.ts | 29 +++++++++++++++++++ test/localization/shared.ts | 1 + 6 files changed, 90 insertions(+) create mode 100644 test/localization/collections/LocalizedDateFields/index.ts diff --git a/packages/db-mongodb/src/utilities/transform.ts b/packages/db-mongodb/src/utilities/transform.ts index 7f1dae84a7..e5633f1acf 100644 --- a/packages/db-mongodb/src/utilities/transform.ts +++ b/packages/db-mongodb/src/utilities/transform.ts @@ -425,6 +425,7 @@ export const transform = ({ for (const locale of config.localization.localeCodes) { sanitizeDate({ field, + locale, ref: fieldRef, value: fieldRef[locale], }) diff --git a/test/localization/collections/LocalizedDateFields/index.ts b/test/localization/collections/LocalizedDateFields/index.ts new file mode 100644 index 0000000000..3fefa1fbb7 --- /dev/null +++ b/test/localization/collections/LocalizedDateFields/index.ts @@ -0,0 +1,21 @@ +import type { CollectionConfig } from 'payload' + +import { localizedDateFieldsSlug } from '../../shared.js' + +export const LocalizedDateFields: CollectionConfig = { + slug: localizedDateFieldsSlug, + versions: { + drafts: true, + }, + fields: [ + { + type: 'date', + name: 'localizedDate', + localized: true, + }, + { + type: 'date', + name: 'date', + }, + ], +} diff --git a/test/localization/config.ts b/test/localization/config.ts index fea76d5e60..912dd5610e 100644 --- a/test/localization/config.ts +++ b/test/localization/config.ts @@ -11,6 +11,7 @@ import { devUser } from '../credentials.js' import { ArrayCollection } from './collections/Array/index.js' import { BlocksCollection } from './collections/Blocks/index.js' import { Group } from './collections/Group/index.js' +import { LocalizedDateFields } from './collections/LocalizedDateFields/index.js' import { LocalizedDrafts } from './collections/LocalizedDrafts/index.js' import { LocalizedWithinLocalized } from './collections/LocalizedWithinLocalized/index.js' import { NestedArray } from './collections/NestedArray/index.js' @@ -25,6 +26,7 @@ import { defaultLocale, englishTitle, hungarianLocale, + localizedDateFieldsSlug, localizedPostsSlug, localizedSortSlug, portugueseLocale, @@ -64,6 +66,7 @@ export default buildConfigWithDefaults({ NestedArray, NestedFields, LocalizedDrafts, + LocalizedDateFields, { admin: { listSearchableFields: 'name', @@ -478,6 +481,14 @@ export default buildConfigWithDefaults({ }, }) + await payload.create({ + collection: localizedDateFieldsSlug, + data: { + localizedDate: new Date().toISOString(), + date: new Date().toISOString(), + }, + }) + console.log('SEED 1') await payload.create({ diff --git a/test/localization/int.spec.ts b/test/localization/int.spec.ts index b134bf586f..8a184a9f0e 100644 --- a/test/localization/int.spec.ts +++ b/test/localization/int.spec.ts @@ -27,6 +27,7 @@ import { defaultLocale as englishLocale, englishTitle, hungarianLocale, + localizedDateFieldsSlug, localizedPostsSlug, localizedSortSlug, portugueseLocale, @@ -431,6 +432,32 @@ describe('Localization', () => { }) }) + describe('Localized date', () => { + it('can create a localized date', async () => { + const document = await payload.create({ + collection: localizedDateFieldsSlug, + data: { + localizedDate: new Date().toISOString(), + date: new Date().toISOString(), + }, + }) + expect(document.localizedDate).toBeTruthy() + }) + + it('data is typed as string', async () => { + const document = await payload.create({ + collection: localizedDateFieldsSlug, + data: { + localizedDate: new Date().toISOString(), + date: new Date().toISOString(), + }, + }) + + expect(typeof document.localizedDate).toBe('string') + expect(typeof document.date).toBe('string') + }) + }) + describe('Localized Sort Count', () => { const expectedTotalDocs = 5 const posts: LocalizedSort[] = [] diff --git a/test/localization/payload-types.ts b/test/localization/payload-types.ts index eaa842d809..4eba191eec 100644 --- a/test/localization/payload-types.ts +++ b/test/localization/payload-types.ts @@ -72,6 +72,7 @@ export interface Config { 'nested-arrays': NestedArray; 'nested-field-tables': NestedFieldTable; 'localized-drafts': LocalizedDraft; + 'localized-date-fields': LocalizedDateField; users: User; 'localized-posts': LocalizedPost; 'no-localized-fields': NoLocalizedField; @@ -97,6 +98,7 @@ export interface Config { 'nested-arrays': NestedArraysSelect | NestedArraysSelect; 'nested-field-tables': NestedFieldTablesSelect | NestedFieldTablesSelect; 'localized-drafts': LocalizedDraftsSelect | LocalizedDraftsSelect; + 'localized-date-fields': LocalizedDateFieldsSelect | LocalizedDateFieldsSelect; users: UsersSelect | UsersSelect; 'localized-posts': LocalizedPostsSelect | LocalizedPostsSelect; 'no-localized-fields': NoLocalizedFieldsSelect | NoLocalizedFieldsSelect; @@ -330,6 +332,18 @@ export interface LocalizedDraft { createdAt: string; _status?: ('draft' | 'published') | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "localized-date-fields". + */ +export interface LocalizedDateField { + id: string; + localizedDate?: string | null; + date?: string | null; + updatedAt: string; + createdAt: string; + _status?: ('draft' | 'published') | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users". @@ -713,6 +727,10 @@ export interface PayloadLockedDocument { relationTo: 'localized-drafts'; value: string | LocalizedDraft; } | null) + | ({ + relationTo: 'localized-date-fields'; + value: string | LocalizedDateField; + } | null) | ({ relationTo: 'users'; value: string | User; @@ -952,6 +970,17 @@ export interface LocalizedDraftsSelect { createdAt?: T; _status?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "localized-date-fields_select". + */ +export interface LocalizedDateFieldsSelect { + localizedDate?: T; + date?: T; + updatedAt?: T; + createdAt?: T; + _status?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "users_select". diff --git a/test/localization/shared.ts b/test/localization/shared.ts index 747d755b18..fd5c54ab29 100644 --- a/test/localization/shared.ts +++ b/test/localization/shared.ts @@ -12,6 +12,7 @@ export const hungarianLocale = 'hu' // Slugs export const localizedPostsSlug = 'localized-posts' +export const localizedDateFieldsSlug = 'localized-date-fields' export const withLocalizedRelSlug = 'with-localized-relationship' export const relationshipLocalizedSlug = 'relationship-localized' export const withRequiredLocalizedFields = 'localized-required'