Skip to content

Commit 046b2a7

Browse files
committedFeb 24, 2025
dont allow null entries
1 parent 983ad53 commit 046b2a7

File tree

5 files changed

+48
-72
lines changed

5 files changed

+48
-72
lines changed
 

‎packages/next-intl/src/middleware/getAlternateLinksHeaderValue.test.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ describe.each([{basePath: undefined}, {basePath: '/base'}])(
159159
]);
160160
});
161161

162-
it('works for partial pathnames with undefined and null entries', () => {
162+
it('works for partial pathnames with undefined entries', () => {
163163
const routing = receiveRoutingConfig({
164164
defaultLocale: 'en',
165165
locales: ['en', 'de', 'ja'],
@@ -168,8 +168,7 @@ describe.each([{basePath: undefined}, {basePath: '/base'}])(
168168
const pathnames = {
169169
'/': '/',
170170
'/about': {
171-
de: '/ueber',
172-
ja: null
171+
de: '/ueber'
173172
}
174173
};
175174

@@ -184,6 +183,7 @@ describe.each([{basePath: undefined}, {basePath: '/base'}])(
184183
).toEqual([
185184
`<https://example.com${basePath}/about>; rel="alternate"; hreflang="en"`,
186185
`<https://example.com${basePath}/de/ueber>; rel="alternate"; hreflang="de"`,
186+
`<https://example.com${basePath}/ja/about>; rel="alternate"; hreflang="ja"`,
187187
`<https://example.com${basePath}/about>; rel="alternate"; hreflang="x-default"`
188188
]);
189189
});

‎packages/next-intl/src/middleware/getAlternateLinksHeaderValue.tsx

+43-54
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,12 @@ export default function getAlternateLinksHeaderValue<
7474

7575
function getLocalizedPathname(pathname: string, locale: AppLocales[number]) {
7676
if (localizedPathnames && typeof localizedPathnames === 'object') {
77-
if (localizedPathnames[locale] === null) return;
7877
const sourceTemplate = localizedPathnames[resolvedLocale];
7978

8079
return formatTemplatePathname(
8180
pathname,
82-
sourceTemplate ?? internalTemplateName ?? pathname,
83-
localizedPathnames[locale] ?? internalTemplateName ?? pathname
81+
sourceTemplate ?? internalTemplateName!,
82+
localizedPathnames[locale] ?? internalTemplateName!
8483
);
8584
} else {
8685
return pathname;
@@ -91,69 +90,59 @@ export default function getAlternateLinksHeaderValue<
9190
routing.locales as AppLocales,
9291
routing.localePrefix,
9392
false
94-
)
95-
.flatMap(([locale, prefix]) => {
96-
function prefixPathname(pathname: string) {
97-
if (pathname === '/') {
98-
return prefix;
99-
} else {
100-
return prefix + pathname;
101-
}
93+
).flatMap(([locale, prefix]) => {
94+
function prefixPathname(pathname: string) {
95+
if (pathname === '/') {
96+
return prefix;
97+
} else {
98+
return prefix + pathname;
10299
}
100+
}
103101

104-
let url: URL;
105-
106-
if (routing.domains) {
107-
const domainConfigs = routing.domains.filter((cur) =>
108-
isLocaleSupportedOnDomain(locale, cur)
109-
);
110-
111-
return domainConfigs.map((domainConfig) => {
112-
const pathname = getLocalizedPathname(normalizedUrl.pathname, locale);
113-
if (!pathname) return undefined;
102+
let url: URL;
114103

115-
url = new URL(normalizedUrl);
116-
url.port = '';
117-
url.host = domainConfig.domain;
104+
if (routing.domains) {
105+
const domainConfigs = routing.domains.filter((cur) =>
106+
isLocaleSupportedOnDomain(locale, cur)
107+
);
118108

119-
// Important: Use `normalizedUrl` here, as `url` potentially uses
120-
// a `basePath` that automatically gets applied to the pathname
121-
url.pathname = pathname;
109+
return domainConfigs.map((domainConfig) => {
110+
url = new URL(normalizedUrl);
111+
url.port = '';
112+
url.host = domainConfig.domain;
122113

123-
if (
124-
locale !== domainConfig.defaultLocale ||
125-
routing.localePrefix.mode === 'always'
126-
) {
127-
url.pathname = prefixPathname(url.pathname);
128-
}
129-
130-
return getAlternateEntry(url, locale);
131-
});
132-
} else {
133-
let pathname: string;
134-
if (localizedPathnames && typeof localizedPathnames === 'object') {
135-
const candidate = getLocalizedPathname(
136-
normalizedUrl.pathname,
137-
locale
138-
);
139-
if (!candidate) return undefined;
140-
pathname = candidate;
141-
} else {
142-
pathname = normalizedUrl.pathname;
143-
}
114+
// Important: Use `normalizedUrl` here, as `url` potentially uses
115+
// a `basePath` that automatically gets applied to the pathname
116+
url.pathname = getLocalizedPathname(normalizedUrl.pathname, locale);
144117

145118
if (
146-
locale !== routing.defaultLocale ||
119+
locale !== domainConfig.defaultLocale ||
147120
routing.localePrefix.mode === 'always'
148121
) {
149-
pathname = prefixPathname(pathname);
122+
url.pathname = prefixPathname(url.pathname);
150123
}
151-
url = new URL(pathname, normalizedUrl);
124+
125+
return getAlternateEntry(url, locale);
126+
});
127+
} else {
128+
let pathname: string;
129+
if (localizedPathnames && typeof localizedPathnames === 'object') {
130+
pathname = getLocalizedPathname(normalizedUrl.pathname, locale);
131+
} else {
132+
pathname = normalizedUrl.pathname;
152133
}
153134

154-
return getAlternateEntry(url, locale);
155-
})
156-
.filter((link) => link != null);
135+
if (
136+
locale !== routing.defaultLocale ||
137+
routing.localePrefix.mode === 'always'
138+
) {
139+
pathname = prefixPathname(pathname);
140+
}
141+
url = new URL(pathname, normalizedUrl);
142+
}
143+
144+
return getAlternateEntry(url, locale);
145+
});
157146

158147
// Add x-default entry
159148
const shouldAddXDefault =

‎packages/next-intl/src/middleware/middleware.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ describe('prefix-based routing', () => {
482482
},
483483
'/partially-available': {
484484
de: '/teilweise-verfuegbar',
485-
'de-AT': null
485+
'de-AT': '/teilweise-verfuegbar'
486486
// (ja inherits en)
487487
}
488488
} satisfies Pathnames<ReadonlyArray<'en' | 'de' | 'de-AT' | 'ja'>>

‎packages/next-intl/src/routing/defineRouting.test.tsx

-13
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ describe('pathnames', () => {
3535
routing.pathnames['/about'].en;
3636
});
3737

38-
3938
it('accepts a partial config for only some locales', () => {
4039
defineRouting({
4140
locales: ['en', 'de'],
@@ -47,18 +46,6 @@ describe('pathnames', () => {
4746
}
4847
});
4948
});
50-
51-
it('allows to mark locales as not supported', () => {
52-
defineRouting({
53-
locales: ['en', 'de'],
54-
defaultLocale: 'en',
55-
pathnames: {
56-
'/about': {
57-
de: null
58-
}
59-
}
60-
});
61-
});
6249
});
6350

6451
describe('domains', () => {

‎packages/next-intl/src/routing/types.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export type LocalePrefix<
3636

3737
export type Pathnames<AppLocales extends Locales> = Record<
3838
Pathname,
39-
Partial<Record<AppLocales[number], Pathname | null>> | Pathname
39+
Partial<Record<AppLocales[number], Pathname>> | Pathname
4040
>;
4141

4242
export type DomainConfig<AppLocales extends Locales> = {

0 commit comments

Comments
 (0)