Skip to content

Commit

Permalink
fix: Export DomainsConfig (#1175)
Browse files Browse the repository at this point in the history
  • Loading branch information
amannn authored Jul 8, 2024
1 parent 5596ae8 commit c4d1bb0
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 51 deletions.
4 changes: 3 additions & 1 deletion docs/pages/docs/routing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ If you want to serve your localized content based on different domains, you can
- `ca.example.com/fr`

```tsx filename="config.ts"
import {DomainsConfig} from 'next-intl/routing';

export const locales = ['en', 'fr'] as const;

export const domains: DomainsConfig<typeof locales> = [
Expand All @@ -342,4 +344,4 @@ export const domains: DomainsConfig<typeof locales> = [
**Note that:**

1. You can optionally remove the locale prefix in pathnames by changing the [`localePrefix`](#locale-prefix) setting.
2. If no domain matches, the middleware will fall back to the [`defaultLocale`](/docs/routing/middleware#default-locale) (e.g. on `localhost`).
2. If no domain matches, the middleware will fall back to the [`defaultLocale`](/docs/routing/middleware#default-locale) (e.g. on `localhost`).
8 changes: 4 additions & 4 deletions packages/next-intl/src/middleware/middleware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function createMiddleware<
? domain.defaultLocale === locale
: locale === config.defaultLocale;

const domainConfigs =
const domainsConfig =
config.domains?.filter((curDomain) =>
isLocaleSupportedOnDomain(locale, curDomain)
) || [];
Expand All @@ -64,11 +64,11 @@ export default function createMiddleware<
function redirect(url: string, redirectDomain?: string) {
const urlObj = new URL(normalizeTrailingSlash(url), request.url);

if (domainConfigs.length > 0 && !redirectDomain) {
if (domainsConfig.length > 0 && !redirectDomain) {
const bestMatchingDomain = getBestMatchingDomain(
domain,
locale,
domainConfigs
domainsConfig
);
if (bestMatchingDomain) {
redirectDomain = bestMatchingDomain.domain;
Expand Down Expand Up @@ -237,7 +237,7 @@ export default function createMiddleware<
const pathDomain = getBestMatchingDomain(
domain,
pathnameMatch.locale,
domainConfigs
domainsConfig
);

if (domain?.domain !== pathDomain?.domain && !hasUnknownHost) {
Expand Down
9 changes: 7 additions & 2 deletions packages/next-intl/src/middleware/resolveLocale.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import {match} from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';
import {RequestCookies} from 'next/dist/server/web/spec-extension/cookies';
import {Locales, DomainConfig, Pathnames} from '../routing/types';
import {
Locales,
Pathnames,
DomainsConfig,
DomainConfig
} from '../routing/types';
import {COOKIE_LOCALE_NAME} from '../shared/constants';
import {MiddlewareRoutingConfig} from './config';
import {getHost, getPathnameMatch, isLocaleSupportedOnDomain} from './utils';

function findDomainFromHost<AppLocales extends Locales>(
requestHeaders: Headers,
domains: Array<DomainConfig<AppLocales>>
domains: DomainsConfig<AppLocales>
) {
let host = getHost(requestHeaders);

Expand Down
11 changes: 6 additions & 5 deletions packages/next-intl/src/middleware/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {
Locales,
LocalePrefixConfigVerbose,
DomainConfig,
Pathnames
Pathnames,
DomainsConfig
} from '../routing/types';
import {
getLocalePrefix,
Expand Down Expand Up @@ -238,7 +239,7 @@ export function isLocaleSupportedOnDomain<AppLocales extends Locales>(
export function getBestMatchingDomain<AppLocales extends Locales>(
curHostDomain: DomainConfig<AppLocales> | undefined,
locale: string,
domainConfigs: Array<DomainConfig<AppLocales>>
domainsConfig: DomainsConfig<AppLocales>
) {
let domainConfig;

Expand All @@ -249,12 +250,12 @@ export function getBestMatchingDomain<AppLocales extends Locales>(

// Prio 2: Use alternative domain with matching default locale
if (!domainConfig) {
domainConfig = domainConfigs.find((cur) => cur.defaultLocale === locale);
domainConfig = domainsConfig.find((cur) => cur.defaultLocale === locale);
}

// Prio 3: Use alternative domain with restricted matching locale
if (!domainConfig) {
domainConfig = domainConfigs.find(
domainConfig = domainsConfig.find(
(cur) => cur.locales != null && cur.locales.includes(locale)
);
}
Expand All @@ -266,7 +267,7 @@ export function getBestMatchingDomain<AppLocales extends Locales>(

// Prio 5: Use alternative domain that supports all locales
if (!domainConfig) {
domainConfig = domainConfigs.find((cur) => !cur.locales);
domainConfig = domainsConfig.find((cur) => !cur.locales);
}

return domainConfig;
Expand Down
6 changes: 3 additions & 3 deletions packages/next-intl/src/routing/config.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
Locales,
DomainConfig,
LocalePrefix,
LocalePrefixConfigVerbose
LocalePrefixConfigVerbose,
DomainsConfig
} from './types';

/**
Expand All @@ -15,7 +15,7 @@ export type RoutingBaseConfigInput<AppLocales extends Locales> = {
/** @see https://next-intl-docs.vercel.app/docs/routing#locale-prefix */
localePrefix?: LocalePrefix<AppLocales>;
/** Can be used to change the locale handling per domain. */
domains?: Array<DomainConfig<AppLocales>>;
domains?: DomainsConfig<AppLocales>;
};

export function receiveLocalePrefixConfig<AppLocales extends Locales>(
Expand Down
3 changes: 1 addition & 2 deletions packages/next-intl/src/routing/index.tsx
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export type {LocalePrefix} from './types';
export type {Pathnames} from './types';
export type {Pathnames, LocalePrefix, DomainsConfig} from './types';
6 changes: 5 additions & 1 deletion packages/next-intl/src/routing/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,9 @@ export type DomainConfig<AppLocales extends Locales> = {
domain: string;

/** Optionally restrict which locales are available on this domain. */
locales?: AppLocales;
locales?: Array<AppLocales[number]>;
};

export type DomainsConfig<AppLocales extends Locales> = Array<
DomainConfig<AppLocales>
>;
95 changes: 62 additions & 33 deletions packages/next-intl/test/routing/types.test.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,69 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import {it} from 'vitest';
import {LocalePrefix} from '../../src/routing/types';
import {describe, it} from 'vitest';
import {LocalePrefix, DomainConfig} from '../../src/routing/types';

it('does not require a type param for simple values', () => {
const config: LocalePrefix = 'always';
});
describe('LocalePrefix', () => {
it('does not require a type param for simple values', () => {
const config: LocalePrefix = 'always';
});

it('provides strict typing for locales', () => {
const locales = ['en', 'de'] as const;
const config: LocalePrefix<typeof locales> = {
mode: 'always',
prefixes: {
en: '/en',
// @ts-expect-error
unknown: '/unknown'
}
};
});
it('provides strict typing for locales', () => {
const locales = ['en', 'de'] as const;
const config: LocalePrefix<typeof locales> = {
mode: 'always',
prefixes: {
en: '/en',
// @ts-expect-error
unknown: '/unknown'
}
};
});

it('allows partial config', () => {
const locales = ['en', 'de'] as const;
const config: LocalePrefix<typeof locales> = {
mode: 'always',
prefixes: {
en: '/en'
}
};
});

it('allows partial config', () => {
const locales = ['en', 'de'] as const;
const config: LocalePrefix<typeof locales> = {
mode: 'always',
prefixes: {
en: '/en'
}
};
it('provides optional typing for locales in prefixes', () => {
const config: LocalePrefix = {
mode: 'always',
prefixes: {
de: '/de',
en: '/en',
unknown: '/unknown'
}
};
});
});

it('provides optional typing for locales in prefixes', () => {
const config: LocalePrefix = {
mode: 'always',
prefixes: {
de: '/de',
en: '/en',
unknown: '/unknown'
}
};
describe('DomainConfig', () => {
it('allows to handle all locales', () => {
const config: DomainConfig<['en', 'de']> = {
defaultLocale: 'en',
domain: 'example.com'
};
});

it('allows to restrict locales', () => {
const config: DomainConfig<['en', 'de']> = {
defaultLocale: 'en',
domain: 'example.com',
locales: ['en']
};
});

it('errors for unknown locales', () => {
const config: DomainConfig<['en', 'de']> = {
// @ts-expect-error
defaultLocale: 'unknown',
domain: 'example.com',
// @ts-expect-error
locales: ['unknown']
};
});
});

0 comments on commit c4d1bb0

Please sign in to comment.