Skip to content

Commit

Permalink
fix: Handle overlapping custom locale prefixes correctly (#1343)
Browse files Browse the repository at this point in the history
Consider this config:

```tsx
export const routing = defineRouting({
  locales: ["en-US", "es-US"],
  defaultLocale: "en-US",
  localePrefix: {
    mode: "always",
    prefixes: {
      "es-US": "/us/es",
      "en-US": "/us"
    },
  }
});
```

… a pathname like `/us/es` would previously be incorrectly rewritten to
`/en-US/es` internally. With this change, we now prioritize more
specific prefixes in order to rewrite this request correctly to
`/es-US`.

Fixes #1329
  • Loading branch information
amannn authored Sep 17, 2024
1 parent 172e535 commit 72c1731
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
34 changes: 34 additions & 0 deletions packages/next-intl/src/middleware/utils.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
formatPathnameTemplate,
getInternalTemplate,
getNormalizedPathname,
getPathnameMatch,
getRouteParams
} from './utils';

Expand Down Expand Up @@ -168,3 +169,36 @@ describe('getInternalTemplate', () => {
]);
});
});

describe('getPathnameMatch', () => {
it('prioritizes more specific custom prefixes for overlapping ones', () => {
const locales = ['de', 'de-at', 'de-at-x-test'] as const;
const localePrefix = {
mode: 'always',
prefixes: {
de: '/de',
'de-at': '/de/at',
// Longer locale, shorter prefix
'de-at-x-test': '/de/a'
}
} as const;

expect(getPathnameMatch('/de/at/test', locales, localePrefix)).toEqual({
locale: 'de-at',
prefix: '/de/at',
exact: true,
matchedPrefix: '/de/at'
});
});

it('does not confuse unrelated parts of the pathname with a locale', () => {
expect(
getPathnameMatch('/de/ats', ['de', 'de-at'], {mode: 'always'})
).toEqual({
locale: 'de',
prefix: '/de',
exact: true,
matchedPrefix: '/de'
});
});
});
3 changes: 3 additions & 0 deletions packages/next-intl/src/middleware/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ export function getPathnameMatch<AppLocales extends Locales>(
| undefined {
const localePrefixes = getLocalePrefixes(locales, localePrefix);

// More specific ones first
localePrefixes.sort((a, b) => b[1].length - a[1].length);

for (const [locale, prefix] of localePrefixes) {
let exact, matches;
if (pathname === prefix || pathname.startsWith(prefix + '/')) {
Expand Down

0 comments on commit 72c1731

Please sign in to comment.