diff --git a/packages/next-intl/src/extractor/ExtractionCompiler.test.tsx b/packages/next-intl/src/extractor/ExtractionCompiler.test.tsx index b3a5dc17f..e5c6f4d1f 100644 --- a/packages/next-intl/src/extractor/ExtractionCompiler.test.tsx +++ b/packages/next-intl/src/extractor/ExtractionCompiler.test.tsx @@ -674,24 +674,25 @@ describe('json format', () => { await waitForWriteFileCalls(1); - expect(JSON.parse(filesystem.project.messages!['en.json'])).toEqual({ - OpKKos: 'Hello!', - '7kKG3Q': 'World!' - }); + expect(JSON.parse(filesystem.project.messages!['en.json'])) + .toMatchInlineSnapshot(` + { + "7kKG3Q": "World!", + "OpKKos": "Hello!", + } + `); filesystem.project.messages!['de.json'] = '{}'; simulateFileEvent('/project/messages', 'rename', 'de.json'); await waitForWriteFileCalls(2); - expect(vi.mocked(fs.writeFile).mock.calls.slice(1)).toMatchInlineSnapshot(` + expect(vi.mocked(fs.writeFile).mock.calls.at(-1)).toMatchInlineSnapshot(` [ - [ - "messages/de.json", - "{ - "OpKKos": "", - "7kKG3Q": "" + "messages/de.json", + "{ + "7kKG3Q": "", + "OpKKos": "" }", - ], ] `); }); @@ -1213,11 +1214,11 @@ msgstr "Hallo!" "X-Crowdin-SourceKey: msgstr\\n" #: src/Greeting.tsx - msgid "OpKKos" + msgid "7kKG3Q" msgstr "" #: src/Greeting.tsx - msgid "7kKG3Q" + msgid "OpKKos" msgstr "" ", ], diff --git a/packages/next-intl/src/extractor/formatters/utils.test.tsx b/packages/next-intl/src/extractor/formatters/utils.test.tsx new file mode 100644 index 000000000..a7dded9db --- /dev/null +++ b/packages/next-intl/src/extractor/formatters/utils.test.tsx @@ -0,0 +1,43 @@ +import {describe, expect, it} from 'vitest'; +import {getSortedMessages} from './utils.js'; + +describe('getSortedMessages', () => { + it('sorts by reference path', () => { + expect( + getSortedMessages([ + { + id: 'a', + message: 'a', + references: [{path: 'components/B.tsx'}] + }, + { + id: 'b', + message: 'b', + references: [{path: 'components/A.tsx'}] + } + ]).map((message) => message.id) + ).toEqual(['b', 'a']); + }); + + it('uses message ids to break ties when reference paths match', () => { + expect( + getSortedMessages([ + { + id: 'c', + message: 'b', + references: [{path: 'components/B.tsx'}] + }, + { + id: 'b', + message: 'a', + references: [{path: 'components/A.tsx'}] + }, + { + id: 'a', + message: 'c', + references: [{path: 'components/A.tsx'}] + } + ]).map((message) => message.id) + ).toEqual(['a', 'b', 'c']); + }); +}); diff --git a/packages/next-intl/src/extractor/formatters/utils.tsx b/packages/next-intl/src/extractor/formatters/utils.tsx index ccf8973e5..782b506c2 100644 --- a/packages/next-intl/src/extractor/formatters/utils.tsx +++ b/packages/next-intl/src/extractor/formatters/utils.tsx @@ -3,13 +3,14 @@ import type {ExtractedMessage} from '../types.js'; export function getSortedMessages( messages: Array ): Array { - return messages.toSorted((a, b) => { - const aPath = a.references?.[0]?.path ?? a.message; - const bPath = b.references?.[0]?.path ?? b.message; - if (aPath === bPath) { - return a.message.localeCompare(b.message); + return messages.toSorted((messageA, messageB) => { + const pathA = messageA.references?.[0]?.path ?? ''; + const pathB = messageB.references?.[0]?.path ?? ''; + + if (pathA === pathB) { + return messageA.id.localeCompare(messageB.id); } else { - return aPath.localeCompare(bPath); + return pathA.localeCompare(pathB); } }); }