From 0058660b3f8bd820abb4494ff53fa67f49f0f6b4 Mon Sep 17 00:00:00 2001 From: Patrik Date: Mon, 22 Jul 2024 16:55:35 -0400 Subject: [PATCH] fix(db-mongodb): removes precedence of regular chars over international chars in sort (#6923) ## Description Fixes #6719 - [x] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## Checklist: - [x] I have added tests that prove my fix is effective or that my feature works - [x] Existing test suite passes locally with my changes --- packages/db-mongodb/src/find.ts | 4 ++ packages/db-mongodb/src/findGlobalVersions.ts | 4 ++ packages/db-mongodb/src/findVersions.ts | 4 ++ packages/db-mongodb/src/queryDrafts.ts | 4 ++ test/localization/config.ts | 12 ++++ test/localization/int.spec.ts | 65 ++++++++++++++++++- test/localization/shared.ts | 1 + 7 files changed, 93 insertions(+), 1 deletion(-) diff --git a/packages/db-mongodb/src/find.ts b/packages/db-mongodb/src/find.ts index 65da0675c0..05e0410ee3 100644 --- a/packages/db-mongodb/src/find.ts +++ b/packages/db-mongodb/src/find.ts @@ -55,6 +55,10 @@ export const find: Find = async function find( useEstimatedCount, } + if (locale && locale !== 'all' && locale !== '*') { + paginationOptions.collation = { locale, strength: 1 } + } + if (!useEstimatedCount && Object.keys(query).length === 0 && this.disableIndexHints !== true) { // Improve the performance of the countDocuments query which is used if useEstimatedCount is set to false by adding // a hint. By default, if no hint is provided, MongoDB does not use an indexed field to count the returned documents, diff --git a/packages/db-mongodb/src/findGlobalVersions.ts b/packages/db-mongodb/src/findGlobalVersions.ts index 68b2ae4fed..b8de110994 100644 --- a/packages/db-mongodb/src/findGlobalVersions.ts +++ b/packages/db-mongodb/src/findGlobalVersions.ts @@ -74,6 +74,10 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV useEstimatedCount, } + if (locale && locale !== 'all' && locale !== '*') { + paginationOptions.collation = { locale, strength: 1 } + } + if (!useEstimatedCount && Object.keys(query).length === 0 && this.disableIndexHints !== true) { // Improve the performance of the countDocuments query which is used if useEstimatedCount is set to false by adding // a hint. By default, if no hint is provided, MongoDB does not use an indexed field to count the returned documents, diff --git a/packages/db-mongodb/src/findVersions.ts b/packages/db-mongodb/src/findVersions.ts index c07a34b096..8986f9c561 100644 --- a/packages/db-mongodb/src/findVersions.ts +++ b/packages/db-mongodb/src/findVersions.ts @@ -70,6 +70,10 @@ export const findVersions: FindVersions = async function findVersions( useEstimatedCount, } + if (locale && locale !== 'all' && locale !== '*') { + paginationOptions.collation = { locale, strength: 1 } + } + if (!useEstimatedCount && Object.keys(query).length === 0 && this.disableIndexHints !== true) { // Improve the performance of the countDocuments query which is used if useEstimatedCount is set to false by adding // a hint. By default, if no hint is provided, MongoDB does not use an indexed field to count the returned documents, diff --git a/packages/db-mongodb/src/queryDrafts.ts b/packages/db-mongodb/src/queryDrafts.ts index 65c5774c2b..bac8c91f4f 100644 --- a/packages/db-mongodb/src/queryDrafts.ts +++ b/packages/db-mongodb/src/queryDrafts.ts @@ -58,6 +58,10 @@ export const queryDrafts: QueryDrafts = async function queryDrafts( useEstimatedCount, } + if (locale && locale !== 'all' && locale !== '*') { + paginationOptions.collation = { locale, strength: 1 } + } + if ( !useEstimatedCount && Object.keys(versionQuery).length === 0 && diff --git a/test/localization/config.ts b/test/localization/config.ts index 77be1acefd..c5365ae158 100644 --- a/test/localization/config.ts +++ b/test/localization/config.ts @@ -10,6 +10,7 @@ import { blocksWithLocalizedSameName, defaultLocale, englishTitle, + hungarianLocale, localizedPostsSlug, localizedSortSlug, portugueseLocale, @@ -80,6 +81,11 @@ export default buildConfigWithDefaults({ name: 'description', type: 'text', }, + { + name: 'localizedDescription', + localized: true, + type: 'text', + }, { name: 'localizedCheckbox', localized: true, @@ -321,6 +327,11 @@ export default buildConfigWithDefaults({ label: 'Arabic', rtl: true, }, + { + code: hungarianLocale, + label: 'Hungarian', + rtl: false, + }, ], }, onInit: async (payload) => { @@ -381,6 +392,7 @@ export default buildConfigWithDefaults({ title: relationEnglishTitle2, }, }) + await payload.update({ id: localizedPost.id, collection, diff --git a/test/localization/int.spec.ts b/test/localization/int.spec.ts index 6d214b83de..e6629f2498 100644 --- a/test/localization/int.spec.ts +++ b/test/localization/int.spec.ts @@ -13,7 +13,7 @@ import { RESTClient } from '../helpers/rest' import { arrayCollectionSlug } from './collections/Array' import { nestedToArrayAndBlockCollectionSlug } from './collections/NestedToArrayAndBlock' import configPromise from './config' -import { defaultLocale, localizedSortSlug } from './shared' +import { defaultLocale, hungarianLocale, localizedSortSlug } from './shared' import { englishTitle, localizedPostsSlug, @@ -292,6 +292,69 @@ describe('Localization', () => { expect(result.docs.map(({ id }) => id)).toContain(localizedPost.id) }) }) + + if (['mongoose'].includes(process.env.PAYLOAD_DATABASE)) { + describe('Localized sorting', () => { + let localizedAccentPostOne: LocalizedPost + let localizedAccentPostTwo: LocalizedPost + beforeEach(async () => { + // @ts-expect-error Force typing + localizedAccentPostOne = await payload.create({ + collection, + data: { + title: 'non accent post', + localizedDescription: 'something', + }, + locale: englishLocale, + }) + + // @ts-expect-error Force typing + localizedAccentPostTwo = await payload.create({ + collection, + data: { + title: 'accent post', + localizedDescription: 'veterinarian', + }, + locale: englishLocale, + }) + + await payload.update({ + id: localizedAccentPostOne.id, + collection, + data: { + title: 'non accent post', + localizedDescription: 'valami', + }, + locale: hungarianLocale, + }) + + await payload.update({ + id: localizedAccentPostTwo.id, + collection, + data: { + title: 'accent post', + localizedDescription: 'állatorvos', + }, + locale: hungarianLocale, + }) + }) + + it('should sort alphabetically even with accented letters', async () => { + const sortByDescriptionQuery = await payload.find({ + collection, + sort: 'description', + where: { + title: { + like: 'accent', + }, + }, + locale: hungarianLocale, + }) + + expect(sortByDescriptionQuery.docs[0].id).toEqual(localizedAccentPostTwo.id) + }) + }) + } }) describe('Localized Sort Count', () => { diff --git a/test/localization/shared.ts b/test/localization/shared.ts index 9056969f6e..0fb3e182c4 100644 --- a/test/localization/shared.ts +++ b/test/localization/shared.ts @@ -8,6 +8,7 @@ export const relationSpanishTitle2 = `${relationSpanishTitle}2` export const defaultLocale = 'en' export const spanishLocale = 'es' export const portugueseLocale = 'pt' +export const hungarianLocale = 'hu' // Slugs export const localizedPostsSlug = 'localized-posts'