@depup/next-intl 4.8.3-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/changes.json +18 -0
- package/config.d.ts +4 -0
- package/dist/cjs/development/ExtractorCodec-D9Tw618d.cjs +7 -0
- package/dist/cjs/development/JSONCodec-rhejs716.cjs +50 -0
- package/dist/cjs/development/POCodec-Cv3VdXQG.cjs +105 -0
- package/dist/cjs/development/plugin-YzBhQjAo.cjs +1457 -0
- package/dist/cjs/development/plugin.cjs +13 -0
- package/dist/esm/development/config.js +5 -0
- package/dist/esm/development/extractor/ExtractionCompiler.js +38 -0
- package/dist/esm/development/extractor/catalog/CatalogLocales.js +84 -0
- package/dist/esm/development/extractor/catalog/CatalogManager.js +370 -0
- package/dist/esm/development/extractor/catalog/CatalogPersister.js +63 -0
- package/dist/esm/development/extractor/catalog/SaveScheduler.js +85 -0
- package/dist/esm/development/extractor/catalogLoader.js +96 -0
- package/dist/esm/development/extractor/extractMessages.js +15 -0
- package/dist/esm/development/extractor/extractionLoader.js +26 -0
- package/dist/esm/development/extractor/extractor/LRUCache.js +30 -0
- package/dist/esm/development/extractor/extractor/MessageExtractor.js +66 -0
- package/dist/esm/development/extractor/format/ExtractorCodec.js +5 -0
- package/dist/esm/development/extractor/format/codecs/JSONCodec.js +42 -0
- package/dist/esm/development/extractor/format/codecs/POCodec.js +93 -0
- package/dist/esm/development/extractor/format/index.js +44 -0
- package/dist/esm/development/extractor/source/SourceFileFilter.js +29 -0
- package/dist/esm/development/extractor/source/SourceFileScanner.js +31 -0
- package/dist/esm/development/extractor/source/SourceFileWatcher.js +132 -0
- package/dist/esm/development/extractor/utils.js +46 -0
- package/dist/esm/development/extractor.js +2 -0
- package/dist/esm/development/index.react-client.js +4 -0
- package/dist/esm/development/index.react-server.js +9 -0
- package/dist/esm/development/middleware/getAlternateLinksHeaderValue.js +91 -0
- package/dist/esm/development/middleware/middleware.js +168 -0
- package/dist/esm/development/middleware/resolveLocale.js +129 -0
- package/dist/esm/development/middleware/syncCookie.js +27 -0
- package/dist/esm/development/middleware/utils.js +194 -0
- package/dist/esm/development/middleware.js +1 -0
- package/dist/esm/development/navigation/react-client/createNavigation.js +80 -0
- package/dist/esm/development/navigation/react-client/useBasePathname.js +36 -0
- package/dist/esm/development/navigation/react-server/createNavigation.js +22 -0
- package/dist/esm/development/navigation/react-server/getServerLocale.js +12 -0
- package/dist/esm/development/navigation/shared/BaseLink.js +51 -0
- package/dist/esm/development/navigation/shared/createSharedNavigationFns.js +105 -0
- package/dist/esm/development/navigation/shared/syncLocaleCookie.js +47 -0
- package/dist/esm/development/navigation/shared/utils.js +165 -0
- package/dist/esm/development/navigation.react-client.js +1 -0
- package/dist/esm/development/navigation.react-server.js +1 -0
- package/dist/esm/development/plugin/config.js +10 -0
- package/dist/esm/development/plugin/createNextIntlPlugin.js +26 -0
- package/dist/esm/development/plugin/declaration/createMessagesDeclaration.js +70 -0
- package/dist/esm/development/plugin/extractor/initExtractionCompiler.js +59 -0
- package/dist/esm/development/plugin/getNextConfig.js +267 -0
- package/dist/esm/development/plugin/nextFlags.js +32 -0
- package/dist/esm/development/plugin/utils.js +26 -0
- package/dist/esm/development/plugin/watchFile.js +21 -0
- package/dist/esm/development/plugin.js +1 -0
- package/dist/esm/development/react-client/index.js +34 -0
- package/dist/esm/development/react-server/NextIntlClientProviderServer.js +34 -0
- package/dist/esm/development/react-server/useConfig.js +21 -0
- package/dist/esm/development/react-server/useExtracted.js +9 -0
- package/dist/esm/development/react-server/useFormatter.js +9 -0
- package/dist/esm/development/react-server/useLocale.js +8 -0
- package/dist/esm/development/react-server/useMessages.js +9 -0
- package/dist/esm/development/react-server/useNow.js +12 -0
- package/dist/esm/development/react-server/useTimeZone.js +8 -0
- package/dist/esm/development/react-server/useTranslations.js +9 -0
- package/dist/esm/development/routing/config.js +26 -0
- package/dist/esm/development/routing/defineRouting.js +25 -0
- package/dist/esm/development/routing.js +1 -0
- package/dist/esm/development/server/react-client/index.js +32 -0
- package/dist/esm/development/server/react-server/RequestLocale.js +36 -0
- package/dist/esm/development/server/react-server/RequestLocaleCache.js +18 -0
- package/dist/esm/development/server/react-server/createRequestConfig.js +2 -0
- package/dist/esm/development/server/react-server/getConfig.js +59 -0
- package/dist/esm/development/server/react-server/getConfigNow.js +10 -0
- package/dist/esm/development/server/react-server/getDefaultNow.js +9 -0
- package/dist/esm/development/server/react-server/getExtracted.js +24 -0
- package/dist/esm/development/server/react-server/getFormats.js +10 -0
- package/dist/esm/development/server/react-server/getFormatter.js +21 -0
- package/dist/esm/development/server/react-server/getLocale.js +10 -0
- package/dist/esm/development/server/react-server/getMessages.js +19 -0
- package/dist/esm/development/server/react-server/getNow.js +8 -0
- package/dist/esm/development/server/react-server/getRequestConfig.js +8 -0
- package/dist/esm/development/server/react-server/getServerExtractor.js +38 -0
- package/dist/esm/development/server/react-server/getServerFormatter.js +17 -0
- package/dist/esm/development/server/react-server/getServerTranslator.js +12 -0
- package/dist/esm/development/server/react-server/getTimeZone.js +13 -0
- package/dist/esm/development/server/react-server/getTranslations.js +28 -0
- package/dist/esm/development/server/react-server/validateLocale.js +12 -0
- package/dist/esm/development/server.react-client.js +1 -0
- package/dist/esm/development/server.react-server.js +9 -0
- package/dist/esm/development/shared/NextIntlClientProvider.js +18 -0
- package/dist/esm/development/shared/constants.js +4 -0
- package/dist/esm/development/shared/use.js +13 -0
- package/dist/esm/development/shared/utils.js +140 -0
- package/dist/esm/production/config.js +1 -0
- package/dist/esm/production/extractor/ExtractionCompiler.js +1 -0
- package/dist/esm/production/extractor/catalog/CatalogLocales.js +1 -0
- package/dist/esm/production/extractor/catalog/CatalogManager.js +1 -0
- package/dist/esm/production/extractor/catalog/CatalogPersister.js +1 -0
- package/dist/esm/production/extractor/catalog/SaveScheduler.js +1 -0
- package/dist/esm/production/extractor/catalogLoader.js +1 -0
- package/dist/esm/production/extractor/extractMessages.js +1 -0
- package/dist/esm/production/extractor/extractionLoader.js +1 -0
- package/dist/esm/production/extractor/extractor/LRUCache.js +1 -0
- package/dist/esm/production/extractor/extractor/MessageExtractor.js +1 -0
- package/dist/esm/production/extractor/format/ExtractorCodec.js +1 -0
- package/dist/esm/production/extractor/format/codecs/JSONCodec.js +1 -0
- package/dist/esm/production/extractor/format/codecs/POCodec.js +1 -0
- package/dist/esm/production/extractor/format/index.js +1 -0
- package/dist/esm/production/extractor/source/SourceFileFilter.js +1 -0
- package/dist/esm/production/extractor/source/SourceFileScanner.js +1 -0
- package/dist/esm/production/extractor/source/SourceFileWatcher.js +1 -0
- package/dist/esm/production/extractor/utils.js +1 -0
- package/dist/esm/production/extractor.js +1 -0
- package/dist/esm/production/index.react-client.js +1 -0
- package/dist/esm/production/index.react-server.js +1 -0
- package/dist/esm/production/middleware/getAlternateLinksHeaderValue.js +1 -0
- package/dist/esm/production/middleware/middleware.js +1 -0
- package/dist/esm/production/middleware/resolveLocale.js +1 -0
- package/dist/esm/production/middleware/syncCookie.js +1 -0
- package/dist/esm/production/middleware/utils.js +1 -0
- package/dist/esm/production/middleware.js +1 -0
- package/dist/esm/production/navigation/react-client/createNavigation.js +1 -0
- package/dist/esm/production/navigation/react-client/useBasePathname.js +1 -0
- package/dist/esm/production/navigation/react-server/createNavigation.js +1 -0
- package/dist/esm/production/navigation/react-server/getServerLocale.js +1 -0
- package/dist/esm/production/navigation/shared/BaseLink.js +2 -0
- package/dist/esm/production/navigation/shared/createSharedNavigationFns.js +1 -0
- package/dist/esm/production/navigation/shared/syncLocaleCookie.js +1 -0
- package/dist/esm/production/navigation/shared/utils.js +1 -0
- package/dist/esm/production/navigation.react-client.js +1 -0
- package/dist/esm/production/navigation.react-server.js +1 -0
- package/dist/esm/production/plugin/config.js +1 -0
- package/dist/esm/production/plugin/createNextIntlPlugin.js +1 -0
- package/dist/esm/production/plugin/declaration/createMessagesDeclaration.js +1 -0
- package/dist/esm/production/plugin/extractor/initExtractionCompiler.js +1 -0
- package/dist/esm/production/plugin/getNextConfig.js +1 -0
- package/dist/esm/production/plugin/nextFlags.js +1 -0
- package/dist/esm/production/plugin/utils.js +1 -0
- package/dist/esm/production/plugin/watchFile.js +1 -0
- package/dist/esm/production/plugin.js +1 -0
- package/dist/esm/production/react-client/index.js +1 -0
- package/dist/esm/production/react-server/NextIntlClientProviderServer.js +1 -0
- package/dist/esm/production/react-server/useConfig.js +1 -0
- package/dist/esm/production/react-server/useExtracted.js +1 -0
- package/dist/esm/production/react-server/useFormatter.js +1 -0
- package/dist/esm/production/react-server/useLocale.js +1 -0
- package/dist/esm/production/react-server/useMessages.js +1 -0
- package/dist/esm/production/react-server/useNow.js +1 -0
- package/dist/esm/production/react-server/useTimeZone.js +1 -0
- package/dist/esm/production/react-server/useTranslations.js +1 -0
- package/dist/esm/production/routing/config.js +1 -0
- package/dist/esm/production/routing/defineRouting.js +1 -0
- package/dist/esm/production/routing.js +1 -0
- package/dist/esm/production/server/react-client/index.js +1 -0
- package/dist/esm/production/server/react-server/RequestLocale.js +1 -0
- package/dist/esm/production/server/react-server/RequestLocaleCache.js +1 -0
- package/dist/esm/production/server/react-server/createRequestConfig.js +1 -0
- package/dist/esm/production/server/react-server/getConfig.js +1 -0
- package/dist/esm/production/server/react-server/getConfigNow.js +1 -0
- package/dist/esm/production/server/react-server/getDefaultNow.js +1 -0
- package/dist/esm/production/server/react-server/getExtracted.js +1 -0
- package/dist/esm/production/server/react-server/getFormats.js +1 -0
- package/dist/esm/production/server/react-server/getFormatter.js +1 -0
- package/dist/esm/production/server/react-server/getLocale.js +1 -0
- package/dist/esm/production/server/react-server/getMessages.js +1 -0
- package/dist/esm/production/server/react-server/getNow.js +1 -0
- package/dist/esm/production/server/react-server/getRequestConfig.js +1 -0
- package/dist/esm/production/server/react-server/getServerExtractor.js +1 -0
- package/dist/esm/production/server/react-server/getServerFormatter.js +1 -0
- package/dist/esm/production/server/react-server/getServerTranslator.js +1 -0
- package/dist/esm/production/server/react-server/getTimeZone.js +1 -0
- package/dist/esm/production/server/react-server/getTranslations.js +1 -0
- package/dist/esm/production/server.react-client.js +1 -0
- package/dist/esm/production/server.react-server.js +1 -0
- package/dist/esm/production/shared/NextIntlClientProvider.js +2 -0
- package/dist/esm/production/shared/constants.js +1 -0
- package/dist/esm/production/shared/use.js +1 -0
- package/dist/esm/production/shared/utils.js +1 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/extractor/ExtractionCompiler.d.ts +15 -0
- package/dist/types/extractor/catalog/CatalogLocales.d.ts +29 -0
- package/dist/types/extractor/catalog/CatalogManager.d.ts +59 -0
- package/dist/types/extractor/catalog/CatalogPersister.d.ts +20 -0
- package/dist/types/extractor/catalog/SaveScheduler.d.ts +18 -0
- package/dist/types/extractor/extractMessages.d.ts +2 -0
- package/dist/types/extractor/extractor/KeyGenerator.d.ts +3 -0
- package/dist/types/extractor/extractor/LRUCache.d.ts +7 -0
- package/dist/types/extractor/extractor/MessageExtractor.bench.d.ts +1 -0
- package/dist/types/extractor/extractor/MessageExtractor.d.ts +21 -0
- package/dist/types/extractor/format/ExtractorCodec.d.ts +33 -0
- package/dist/types/extractor/format/codecs/JSONCodec.d.ts +2 -0
- package/dist/types/extractor/format/codecs/POCodec.d.ts +2 -0
- package/dist/types/extractor/format/codecs/fixtures/JSONCodecStructured.d.ts +2 -0
- package/dist/types/extractor/format/codecs/fixtures/POCodecSourceMessageKey.d.ts +2 -0
- package/dist/types/extractor/format/index.d.ts +15 -0
- package/dist/types/extractor/format/types.d.ts +8 -0
- package/dist/types/extractor/index.d.ts +2 -0
- package/dist/types/extractor/source/SourceFileFilter.d.ts +8 -0
- package/dist/types/extractor/source/SourceFileScanner.d.ts +4 -0
- package/dist/types/extractor/source/SourceFileWatcher.d.ts +15 -0
- package/dist/types/extractor/types.d.ts +28 -0
- package/dist/types/extractor/utils.d.ts +7 -0
- package/dist/types/extractor.d.ts +1 -0
- package/dist/types/index.react-client.d.ts +8 -0
- package/dist/types/index.react-server.d.ts +1 -0
- package/dist/types/middleware/getAlternateLinksHeaderValue.d.ts +13 -0
- package/dist/types/middleware/index.d.ts +4 -0
- package/dist/types/middleware/middleware.d.ts +4 -0
- package/dist/types/middleware/resolveLocale.d.ts +9 -0
- package/dist/types/middleware/syncCookie.d.ts +7 -0
- package/dist/types/middleware/utils.d.ts +26 -0
- package/dist/types/middleware.d.ts +1 -0
- package/dist/types/navigation/react-client/createNavigation.d.ts +464 -0
- package/dist/types/navigation/react-client/index.d.ts +2 -0
- package/dist/types/navigation/react-client/useBasePathname.d.ts +5 -0
- package/dist/types/navigation/react-server/createNavigation.d.ts +384 -0
- package/dist/types/navigation/react-server/getServerLocale.d.ts +5 -0
- package/dist/types/navigation/react-server/index.d.ts +2 -0
- package/dist/types/navigation/shared/BaseLink.d.ts +11 -0
- package/dist/types/navigation/shared/StrictParams.d.ts +8 -0
- package/dist/types/navigation/shared/createSharedNavigationFns.d.ts +370 -0
- package/dist/types/navigation/shared/syncLocaleCookie.d.ts +8 -0
- package/dist/types/navigation/shared/utils.d.ts +53 -0
- package/dist/types/navigation.react-client.d.ts +1 -0
- package/dist/types/navigation.react-server.d.ts +1 -0
- package/dist/types/plugin/catalog/catalogLoader.d.ts +10 -0
- package/dist/types/plugin/config.d.ts +3 -0
- package/dist/types/plugin/createNextIntlPlugin.d.ts +3 -0
- package/dist/types/plugin/declaration/createMessagesDeclaration.d.ts +1 -0
- package/dist/types/plugin/declaration/index.d.ts +1 -0
- package/dist/types/plugin/extractor/extractionLoader.d.ts +3 -0
- package/dist/types/plugin/extractor/initExtractionCompiler.d.ts +2 -0
- package/dist/types/plugin/getNextConfig.d.ts +3 -0
- package/dist/types/plugin/index.d.ts +1 -0
- package/dist/types/plugin/nextFlags.d.ts +2 -0
- package/dist/types/plugin/types.d.ts +29 -0
- package/dist/types/plugin/utils.d.ts +8 -0
- package/dist/types/plugin/watchFile.d.ts +6 -0
- package/dist/types/plugin.d.ts +1 -0
- package/dist/types/react-client/index.d.ts +16 -0
- package/dist/types/react-server/NextIntlClientProviderServer.d.ts +5 -0
- package/dist/types/react-server/index.d.ts +16 -0
- package/dist/types/react-server/testUtils.d.ts +2 -0
- package/dist/types/react-server/useConfig.d.ts +2 -0
- package/dist/types/react-server/useExtracted.d.ts +2 -0
- package/dist/types/react-server/useFormatter.d.ts +2 -0
- package/dist/types/react-server/useLocale.d.ts +2 -0
- package/dist/types/react-server/useMessages.d.ts +2 -0
- package/dist/types/react-server/useNow.d.ts +2 -0
- package/dist/types/react-server/useTimeZone.d.ts +2 -0
- package/dist/types/react-server/useTranslations.d.ts +2 -0
- package/dist/types/routing/config.d.ts +73 -0
- package/dist/types/routing/defineRouting.d.ts +3 -0
- package/dist/types/routing/index.d.ts +3 -0
- package/dist/types/routing/types.d.ts +24 -0
- package/dist/types/routing.d.ts +1 -0
- package/dist/types/server/react-client/index.d.ts +10 -0
- package/dist/types/server/react-server/RequestLocale.d.ts +1 -0
- package/dist/types/server/react-server/RequestLocaleCache.d.ts +3 -0
- package/dist/types/server/react-server/createRequestConfig.d.ts +3 -0
- package/dist/types/server/react-server/getConfig.d.ts +13 -0
- package/dist/types/server/react-server/getConfigNow.d.ts +4 -0
- package/dist/types/server/react-server/getDefaultNow.d.ts +3 -0
- package/dist/types/server/react-server/getExtracted.d.ts +10 -0
- package/dist/types/server/react-server/getFormats.d.ts +3 -0
- package/dist/types/server/react-server/getFormatter.d.ts +10 -0
- package/dist/types/server/react-server/getLocale.d.ts +4 -0
- package/dist/types/server/react-server/getMessages.d.ts +6 -0
- package/dist/types/server/react-server/getNow.d.ts +4 -0
- package/dist/types/server/react-server/getRequestConfig.d.ts +35 -0
- package/dist/types/server/react-server/getServerExtractor.d.ts +5 -0
- package/dist/types/server/react-server/getServerFormatter.d.ts +25 -0
- package/dist/types/server/react-server/getServerTranslator.d.ts +4 -0
- package/dist/types/server/react-server/getTimeZone.d.ts +4 -0
- package/dist/types/server/react-server/getTranslations.d.ts +8 -0
- package/dist/types/server/react-server/index.d.ts +12 -0
- package/dist/types/server/react-server/validateLocale.d.ts +1 -0
- package/dist/types/server.react-client.d.ts +1 -0
- package/dist/types/server.react-server.d.ts +1 -0
- package/dist/types/shared/NextIntlClientProvider.d.ts +9 -0
- package/dist/types/shared/constants.d.ts +1 -0
- package/dist/types/shared/types.d.ts +5 -0
- package/dist/types/shared/use.d.ts +3 -0
- package/dist/types/shared/utils.d.ts +20 -0
- package/extractor/catalogLoader.d.ts +4 -0
- package/extractor/extractionLoader.d.ts +4 -0
- package/extractor.d.ts +2 -0
- package/middleware.d.ts +4 -0
- package/navigation.d.ts +2 -0
- package/package.json +175 -0
- package/plugin.d.cts +3 -0
- package/plugin.d.ts +4 -0
- package/routing.d.ts +2 -0
- package/server.d.ts +2 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useRouter, usePathname } from 'next/navigation';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useLocale } from 'use-intl';
|
|
4
|
+
import createSharedNavigationFns from '../shared/createSharedNavigationFns.js';
|
|
5
|
+
import syncLocaleCookie from '../shared/syncLocaleCookie.js';
|
|
6
|
+
import { getRoute } from '../shared/utils.js';
|
|
7
|
+
import useBasePathname from './useBasePathname.js';
|
|
8
|
+
|
|
9
|
+
function createNavigation(routing) {
|
|
10
|
+
const {
|
|
11
|
+
Link,
|
|
12
|
+
config,
|
|
13
|
+
getPathname,
|
|
14
|
+
...redirects
|
|
15
|
+
} = createSharedNavigationFns(useLocale, routing);
|
|
16
|
+
|
|
17
|
+
/** @see https://next-intl.dev/docs/routing/navigation#usepathname */
|
|
18
|
+
function usePathname$1() {
|
|
19
|
+
const pathname = useBasePathname(config);
|
|
20
|
+
const locale = useLocale();
|
|
21
|
+
|
|
22
|
+
// @ts-expect-error -- Mirror the behavior from Next.js, where `null` is returned when `usePathname` is used outside of Next, but the types indicate that a string is always returned.
|
|
23
|
+
return useMemo(() => pathname &&
|
|
24
|
+
// @ts-expect-error -- This is fine
|
|
25
|
+
config.pathnames ? getRoute(locale, pathname,
|
|
26
|
+
// @ts-expect-error -- This is fine
|
|
27
|
+
config.pathnames) : pathname, [locale, pathname]);
|
|
28
|
+
}
|
|
29
|
+
function useRouter$1() {
|
|
30
|
+
const router = useRouter();
|
|
31
|
+
const curLocale = useLocale();
|
|
32
|
+
const nextPathname = usePathname();
|
|
33
|
+
return useMemo(() => {
|
|
34
|
+
function createHandler(fn) {
|
|
35
|
+
return function handler(href, options) {
|
|
36
|
+
const {
|
|
37
|
+
locale: nextLocale,
|
|
38
|
+
...rest
|
|
39
|
+
} = options || {};
|
|
40
|
+
const pathname = getPathname({
|
|
41
|
+
href,
|
|
42
|
+
locale: nextLocale || curLocale,
|
|
43
|
+
// Always include a prefix when changing locales. Theoretically,
|
|
44
|
+
// this is only necessary for the case described in #2020. However,
|
|
45
|
+
// the full detection is rather expensive, and this behavior is
|
|
46
|
+
// consistent with the `Link` component. The downside is an
|
|
47
|
+
// additional redirect for users in other situations. Locale
|
|
48
|
+
// changes should be rare though, so this might be fine.
|
|
49
|
+
forcePrefix: nextLocale != null || undefined
|
|
50
|
+
});
|
|
51
|
+
const args = [pathname];
|
|
52
|
+
if (Object.keys(rest).length > 0) {
|
|
53
|
+
// @ts-expect-error -- This is fine
|
|
54
|
+
args.push(rest);
|
|
55
|
+
}
|
|
56
|
+
syncLocaleCookie(config.localeCookie, nextPathname, curLocale, nextLocale);
|
|
57
|
+
fn(...args);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
...router,
|
|
62
|
+
/** @see https://next-intl.dev/docs/routing/navigation#userouter */
|
|
63
|
+
push: createHandler(router.push),
|
|
64
|
+
/** @see https://next-intl.dev/docs/routing/navigation#userouter */
|
|
65
|
+
replace: createHandler(router.replace),
|
|
66
|
+
/** @see https://next-intl.dev/docs/routing/navigation#userouter */
|
|
67
|
+
prefetch: createHandler(router.prefetch)
|
|
68
|
+
};
|
|
69
|
+
}, [curLocale, nextPathname, router]);
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
...redirects,
|
|
73
|
+
Link,
|
|
74
|
+
usePathname: usePathname$1,
|
|
75
|
+
useRouter: useRouter$1,
|
|
76
|
+
getPathname
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { createNavigation as default };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { usePathname } from 'next/navigation';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useLocale } from 'use-intl';
|
|
4
|
+
import { hasPathnamePrefixed, unprefixPathname, getLocalePrefix, getLocaleAsPrefix } from '../../shared/utils.js';
|
|
5
|
+
|
|
6
|
+
function useBasePathname(config) {
|
|
7
|
+
// The types aren't entirely correct here. Outside of Next.js
|
|
8
|
+
// `useParams` can be called, but the return type is `null`.
|
|
9
|
+
|
|
10
|
+
// Notes on `useNextPathname`:
|
|
11
|
+
// - Types aren't entirely correct. Outside of Next.js the
|
|
12
|
+
// hook will return `null` (e.g. unit tests)
|
|
13
|
+
// - A base path is stripped from the result
|
|
14
|
+
// - Rewrites *are* taken into account (i.e. the pathname
|
|
15
|
+
// that the user sees in the browser is returned)
|
|
16
|
+
const pathname = usePathname();
|
|
17
|
+
const locale = useLocale();
|
|
18
|
+
return useMemo(() => {
|
|
19
|
+
if (!pathname) return pathname;
|
|
20
|
+
let unlocalizedPathname = pathname;
|
|
21
|
+
const prefix = getLocalePrefix(locale, config.localePrefix);
|
|
22
|
+
const isPathnamePrefixed = hasPathnamePrefixed(prefix, pathname);
|
|
23
|
+
if (isPathnamePrefixed) {
|
|
24
|
+
unlocalizedPathname = unprefixPathname(pathname, prefix);
|
|
25
|
+
} else if (config.localePrefix.mode !== 'never' && config.localePrefix.prefixes) {
|
|
26
|
+
// Workaround for https://github.com/vercel/next.js/issues/73085
|
|
27
|
+
const localeAsPrefix = getLocaleAsPrefix(locale);
|
|
28
|
+
if (hasPathnamePrefixed(localeAsPrefix, pathname)) {
|
|
29
|
+
unlocalizedPathname = unprefixPathname(pathname, localeAsPrefix);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return unlocalizedPathname;
|
|
33
|
+
}, [config.localePrefix, locale, pathname]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { useBasePathname as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import createSharedNavigationFns from '../shared/createSharedNavigationFns.js';
|
|
2
|
+
import getServerLocale from './getServerLocale.js';
|
|
3
|
+
|
|
4
|
+
function createNavigation(routing) {
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
6
|
+
const {
|
|
7
|
+
config,
|
|
8
|
+
...fns
|
|
9
|
+
} = createSharedNavigationFns(getServerLocale, routing);
|
|
10
|
+
function notSupported(hookName) {
|
|
11
|
+
return () => {
|
|
12
|
+
throw new Error(`\`${hookName}\` is not supported in Server Components. You can use this hook if you convert the calling component to a Client Component.`);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
...fns,
|
|
17
|
+
usePathname: notSupported('usePathname'),
|
|
18
|
+
useRouter: notSupported('useRouter')
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { createNavigation as default };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import getConfig from '../../server/react-server/getConfig.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This is only moved to a separate module for easier mocking in
|
|
5
|
+
* `../createNavigatoin.test.tsx` in order to avoid suspending.
|
|
6
|
+
*/
|
|
7
|
+
async function getServerLocale() {
|
|
8
|
+
const config = await getConfig();
|
|
9
|
+
return config.locale;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { getServerLocale as default };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import NextLink from 'next/link';
|
|
3
|
+
import { usePathname } from 'next/navigation';
|
|
4
|
+
import { forwardRef } from 'react';
|
|
5
|
+
import { useLocale } from 'use-intl';
|
|
6
|
+
import syncLocaleCookie from './syncLocaleCookie.js';
|
|
7
|
+
import { jsx } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function BaseLink({
|
|
10
|
+
href,
|
|
11
|
+
locale,
|
|
12
|
+
localeCookie,
|
|
13
|
+
onClick,
|
|
14
|
+
prefetch,
|
|
15
|
+
...rest
|
|
16
|
+
}, ref) {
|
|
17
|
+
const curLocale = useLocale();
|
|
18
|
+
const isChangingLocale = locale != null && locale !== curLocale;
|
|
19
|
+
|
|
20
|
+
// The types aren't entirely correct here. Outside of Next.js
|
|
21
|
+
// `useParams` can be called, but the return type is `null`.
|
|
22
|
+
const pathname = usePathname();
|
|
23
|
+
function onLinkClick(event) {
|
|
24
|
+
// Even though we force a prefix when changing locales,
|
|
25
|
+
// this could be a cache hit of the client-side router,
|
|
26
|
+
// therefore we sync the cookie to ensure it's up to date.
|
|
27
|
+
syncLocaleCookie(localeCookie, pathname, curLocale, locale);
|
|
28
|
+
if (onClick) onClick(event);
|
|
29
|
+
}
|
|
30
|
+
if (isChangingLocale) {
|
|
31
|
+
if (prefetch && "development" !== 'production') {
|
|
32
|
+
console.error('The `prefetch` prop is currently not supported when using the `locale` prop on `Link` to switch the locale.`');
|
|
33
|
+
}
|
|
34
|
+
prefetch = false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Somehow the types for `next/link` don't work as expected
|
|
38
|
+
// when `moduleResolution: "nodenext"` is used.
|
|
39
|
+
const Link = NextLink;
|
|
40
|
+
return /*#__PURE__*/jsx(Link, {
|
|
41
|
+
ref: ref,
|
|
42
|
+
href: href,
|
|
43
|
+
hrefLang: isChangingLocale ? locale : undefined,
|
|
44
|
+
onClick: onLinkClick,
|
|
45
|
+
prefetch: prefetch,
|
|
46
|
+
...rest
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
var BaseLink$1 = /*#__PURE__*/forwardRef(BaseLink);
|
|
50
|
+
|
|
51
|
+
export { BaseLink$1 as default };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { redirect, permanentRedirect } from 'next/navigation';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { receiveRoutingConfig } from '../../routing/config.js';
|
|
4
|
+
import use from '../../shared/use.js';
|
|
5
|
+
import { isLocalizableHref, isPromise } from '../../shared/utils.js';
|
|
6
|
+
import BaseLink from './BaseLink.js';
|
|
7
|
+
import { validateReceivedConfig, serializeSearchParams, compileLocalizedPathname, applyPathnamePrefix, normalizeNameOrNameWithParams } from './utils.js';
|
|
8
|
+
import { jsx } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Shared implementations for `react-server` and `react-client`
|
|
12
|
+
*/
|
|
13
|
+
function createSharedNavigationFns(getLocale, routing) {
|
|
14
|
+
const config = receiveRoutingConfig(routing || {});
|
|
15
|
+
{
|
|
16
|
+
validateReceivedConfig(config);
|
|
17
|
+
}
|
|
18
|
+
const pathnames = config.pathnames;
|
|
19
|
+
function Link({
|
|
20
|
+
href,
|
|
21
|
+
locale,
|
|
22
|
+
...rest
|
|
23
|
+
}, ref) {
|
|
24
|
+
let pathname, params;
|
|
25
|
+
if (typeof href === 'object') {
|
|
26
|
+
pathname = href.pathname;
|
|
27
|
+
// @ts-expect-error -- This is ok
|
|
28
|
+
params = href.params;
|
|
29
|
+
} else {
|
|
30
|
+
pathname = href;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// @ts-expect-error -- This is ok
|
|
34
|
+
const isLocalizable = isLocalizableHref(href);
|
|
35
|
+
const localePromiseOrValue = getLocale();
|
|
36
|
+
const curLocale = isPromise(localePromiseOrValue) ? use(localePromiseOrValue) : localePromiseOrValue;
|
|
37
|
+
const finalPathname = isLocalizable ? getPathname({
|
|
38
|
+
locale: locale || curLocale,
|
|
39
|
+
// @ts-expect-error -- This is ok
|
|
40
|
+
href: pathnames == null ? pathname : {
|
|
41
|
+
pathname,
|
|
42
|
+
params
|
|
43
|
+
},
|
|
44
|
+
// Always include a prefix when changing locales
|
|
45
|
+
forcePrefix: locale != null || undefined
|
|
46
|
+
}) : pathname;
|
|
47
|
+
return /*#__PURE__*/jsx(BaseLink, {
|
|
48
|
+
ref: ref
|
|
49
|
+
// @ts-expect-error -- This is ok
|
|
50
|
+
,
|
|
51
|
+
href: typeof href === 'object' ? {
|
|
52
|
+
...href,
|
|
53
|
+
pathname: finalPathname
|
|
54
|
+
} : finalPathname,
|
|
55
|
+
locale: locale,
|
|
56
|
+
localeCookie: config.localeCookie,
|
|
57
|
+
...rest
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
const LinkWithRef = /*#__PURE__*/forwardRef(Link);
|
|
61
|
+
function getPathname(args) {
|
|
62
|
+
const {
|
|
63
|
+
forcePrefix,
|
|
64
|
+
href,
|
|
65
|
+
locale
|
|
66
|
+
} = args;
|
|
67
|
+
let pathname;
|
|
68
|
+
if (pathnames == null) {
|
|
69
|
+
if (typeof href === 'object') {
|
|
70
|
+
pathname = href.pathname;
|
|
71
|
+
if (href.query) {
|
|
72
|
+
pathname += serializeSearchParams(href.query);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
pathname = href;
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
pathname = compileLocalizedPathname({
|
|
79
|
+
locale,
|
|
80
|
+
// @ts-expect-error -- This is ok
|
|
81
|
+
...normalizeNameOrNameWithParams(href),
|
|
82
|
+
// @ts-expect-error -- This is ok
|
|
83
|
+
pathnames: config.pathnames
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return applyPathnamePrefix(pathname, locale, config, forcePrefix);
|
|
87
|
+
}
|
|
88
|
+
function getRedirectFn(fn) {
|
|
89
|
+
/** @see https://next-intl.dev/docs/routing/navigation#redirect */
|
|
90
|
+
return function redirectFn(args, ...rest) {
|
|
91
|
+
return fn(getPathname(args), ...rest);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const redirect$1 = getRedirectFn(redirect);
|
|
95
|
+
const permanentRedirect$1 = getRedirectFn(permanentRedirect);
|
|
96
|
+
return {
|
|
97
|
+
config,
|
|
98
|
+
Link: LinkWithRef,
|
|
99
|
+
redirect: redirect$1,
|
|
100
|
+
permanentRedirect: permanentRedirect$1,
|
|
101
|
+
getPathname
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { createSharedNavigationFns as default };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getBasePath } from './utils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* We have to keep the cookie value in sync as Next.js might
|
|
5
|
+
* skip a request to the server due to its router cache.
|
|
6
|
+
* See https://github.com/amannn/next-intl/issues/786.
|
|
7
|
+
*/
|
|
8
|
+
function syncLocaleCookie(localeCookie, pathname, locale, nextLocale) {
|
|
9
|
+
const isSwitchingLocale = nextLocale !== locale && nextLocale != null;
|
|
10
|
+
if (!localeCookie || !isSwitchingLocale ||
|
|
11
|
+
// Theoretical case, we always have a pathname in a real app,
|
|
12
|
+
// only not when running e.g. in a simulated test environment
|
|
13
|
+
!pathname) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const basePath = getBasePath(pathname);
|
|
17
|
+
const hasBasePath = basePath !== '';
|
|
18
|
+
const defaultPath = hasBasePath ? basePath : '/';
|
|
19
|
+
const {
|
|
20
|
+
name,
|
|
21
|
+
...rest
|
|
22
|
+
} = localeCookie;
|
|
23
|
+
if (!rest.path) {
|
|
24
|
+
rest.path = defaultPath;
|
|
25
|
+
}
|
|
26
|
+
let localeCookieString = `${name}=${nextLocale};`;
|
|
27
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
28
|
+
// Map object properties to cookie properties.
|
|
29
|
+
// Interestingly, `maxAge` corresponds to `max-age`,
|
|
30
|
+
// while `sameSite` corresponds to `SameSite`.
|
|
31
|
+
// Also, keys are case-insensitive.
|
|
32
|
+
const targetKey = key === 'maxAge' ? 'max-age' : key;
|
|
33
|
+
localeCookieString += `${targetKey}`;
|
|
34
|
+
if (typeof value !== 'boolean') {
|
|
35
|
+
localeCookieString += '=' + value;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// A trailing ";" is allowed by browsers
|
|
39
|
+
localeCookieString += ';';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Note that writing to `document.cookie` doesn't overwrite all
|
|
43
|
+
// cookies, but only the ones referenced via the name here.
|
|
44
|
+
document.cookie = localeCookieString;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { syncLocaleCookie as default };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { getSortedPathnames, matchesPathname, isLocalizableHref, prefixPathname, getLocalizedTemplate, normalizeTrailingSlash, getLocalePrefix } from '../../shared/utils.js';
|
|
2
|
+
|
|
3
|
+
// Minor false positive: A route that has both optional and
|
|
4
|
+
// required params will allow optional params.
|
|
5
|
+
|
|
6
|
+
// For `Link`
|
|
7
|
+
|
|
8
|
+
// For `getPathname` (hence also its consumers: `redirect`, `useRouter`, …)
|
|
9
|
+
|
|
10
|
+
function normalizeNameOrNameWithParams(href) {
|
|
11
|
+
return typeof href === 'string' ? {
|
|
12
|
+
pathname: href
|
|
13
|
+
} : href;
|
|
14
|
+
}
|
|
15
|
+
function serializeSearchParams(searchParams) {
|
|
16
|
+
function serializeValue(value) {
|
|
17
|
+
return String(value);
|
|
18
|
+
}
|
|
19
|
+
const urlSearchParams = new URLSearchParams();
|
|
20
|
+
for (const [key, value] of Object.entries(searchParams)) {
|
|
21
|
+
if (Array.isArray(value)) {
|
|
22
|
+
value.forEach(cur => {
|
|
23
|
+
urlSearchParams.append(key, serializeValue(cur));
|
|
24
|
+
});
|
|
25
|
+
} else {
|
|
26
|
+
urlSearchParams.set(key, serializeValue(value));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return '?' + urlSearchParams.toString();
|
|
30
|
+
}
|
|
31
|
+
function compileLocalizedPathname({
|
|
32
|
+
pathname,
|
|
33
|
+
locale,
|
|
34
|
+
params,
|
|
35
|
+
pathnames,
|
|
36
|
+
query
|
|
37
|
+
}) {
|
|
38
|
+
function compilePath(value) {
|
|
39
|
+
const pathnameConfig = pathnames[value];
|
|
40
|
+
let compiled;
|
|
41
|
+
if (pathnameConfig) {
|
|
42
|
+
const template = getLocalizedTemplate(pathnameConfig, locale, value);
|
|
43
|
+
compiled = template;
|
|
44
|
+
if (params) {
|
|
45
|
+
Object.entries(params).forEach(([key, paramValue]) => {
|
|
46
|
+
let regexp, replacer;
|
|
47
|
+
if (Array.isArray(paramValue)) {
|
|
48
|
+
regexp = `(\\[)?\\[...${key}\\](\\])?`;
|
|
49
|
+
replacer = paramValue.map(v => String(v)).join('/');
|
|
50
|
+
} else {
|
|
51
|
+
regexp = `\\[${key}\\]`;
|
|
52
|
+
replacer = String(paramValue);
|
|
53
|
+
}
|
|
54
|
+
compiled = compiled.replace(new RegExp(regexp, 'g'), replacer);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Clean up optional catch-all segments that were not replaced
|
|
59
|
+
compiled = compiled.replace(/\[\[\.\.\..+\]\]/g, '');
|
|
60
|
+
if (compiled.includes('[')) {
|
|
61
|
+
// Next.js throws anyway, therefore better provide a more helpful error message
|
|
62
|
+
throw new Error(`Insufficient params provided for localized pathname.\nTemplate: ${template}\nParams: ${JSON.stringify(params)}`);
|
|
63
|
+
}
|
|
64
|
+
compiled = encodePathname(compiled);
|
|
65
|
+
} else {
|
|
66
|
+
// Unknown pathnames
|
|
67
|
+
compiled = value;
|
|
68
|
+
}
|
|
69
|
+
compiled = normalizeTrailingSlash(compiled);
|
|
70
|
+
if (query) {
|
|
71
|
+
// This also encodes non-ASCII characters by
|
|
72
|
+
// using `new URLSearchParams()` internally
|
|
73
|
+
compiled += serializeSearchParams(query);
|
|
74
|
+
}
|
|
75
|
+
return compiled;
|
|
76
|
+
}
|
|
77
|
+
if (typeof pathname === 'string') {
|
|
78
|
+
return compilePath(pathname);
|
|
79
|
+
} else {
|
|
80
|
+
const {
|
|
81
|
+
pathname: internalPathname,
|
|
82
|
+
...rest
|
|
83
|
+
} = pathname;
|
|
84
|
+
const compiled = compilePath(internalPathname);
|
|
85
|
+
const result = {
|
|
86
|
+
...rest,
|
|
87
|
+
pathname: compiled
|
|
88
|
+
};
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function encodePathname(pathname) {
|
|
93
|
+
// Generally, to comply with RFC 3986 and Google's best practices for URL structures
|
|
94
|
+
// (https://developers.google.com/search/docs/crawling-indexing/url-structure),
|
|
95
|
+
// we should always encode non-ASCII characters.
|
|
96
|
+
//
|
|
97
|
+
// There are two places where next-intl interacts with potentially non-ASCII URLs:
|
|
98
|
+
// 1. Middleware: When mapping a localized pathname to a non-localized pathname internally
|
|
99
|
+
// 2. Navigation APIs: When generating a URLs to be used for <Link /> & friends
|
|
100
|
+
//
|
|
101
|
+
// Next.js normalizes incoming pathnames to always be encoded, therefore we can safely
|
|
102
|
+
// decode them there (see middleware.tsx). On the other hand, Next.js doesn't consistently
|
|
103
|
+
// encode non-ASCII characters that are passed to navigation APIs:
|
|
104
|
+
// 1. <Link /> doesn't encode non-ASCII characters
|
|
105
|
+
// 2. useRouter() uses `new URL()` internally, which will encode—but only if necessary
|
|
106
|
+
// 3. redirect() uses useRouter() on the client, but on the server side only
|
|
107
|
+
// assigns the location header without encoding.
|
|
108
|
+
//
|
|
109
|
+
// In addition to this, for getPathname() we need to encode non-ASCII characters.
|
|
110
|
+
//
|
|
111
|
+
// Therefore, the bottom line is that next-intl should take care of encoding non-ASCII
|
|
112
|
+
// characters in all cases, but can rely on `new URL()` to not double-encode characters.
|
|
113
|
+
return new URL(pathname, 'http://l').pathname;
|
|
114
|
+
}
|
|
115
|
+
function getRoute(locale, pathname, pathnames) {
|
|
116
|
+
const sortedPathnames = getSortedPathnames(Object.keys(pathnames));
|
|
117
|
+
const decoded = decodeURI(pathname);
|
|
118
|
+
for (const internalPathname of sortedPathnames) {
|
|
119
|
+
const localizedPathnamesOrPathname = pathnames[internalPathname];
|
|
120
|
+
if (typeof localizedPathnamesOrPathname === 'string') {
|
|
121
|
+
const localizedPathname = localizedPathnamesOrPathname;
|
|
122
|
+
if (matchesPathname(localizedPathname, decoded)) {
|
|
123
|
+
return internalPathname;
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
if (matchesPathname(getLocalizedTemplate(localizedPathnamesOrPathname, locale, internalPathname), decoded)) {
|
|
127
|
+
return internalPathname;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return pathname;
|
|
132
|
+
}
|
|
133
|
+
function getBasePath(pathname, windowPathname = window.location.pathname) {
|
|
134
|
+
if (pathname === '/') {
|
|
135
|
+
return windowPathname;
|
|
136
|
+
} else {
|
|
137
|
+
return windowPathname.replace(pathname, '');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function applyPathnamePrefix(pathname, locale, routing, force) {
|
|
141
|
+
const {
|
|
142
|
+
mode
|
|
143
|
+
} = routing.localePrefix;
|
|
144
|
+
let shouldPrefix;
|
|
145
|
+
if (force !== undefined) {
|
|
146
|
+
shouldPrefix = force;
|
|
147
|
+
} else if (isLocalizableHref(pathname)) {
|
|
148
|
+
if (mode === 'always') {
|
|
149
|
+
shouldPrefix = true;
|
|
150
|
+
} else if (mode === 'as-needed') {
|
|
151
|
+
shouldPrefix = routing.domains ?
|
|
152
|
+
// Since locales are unique per domain, any locale that is a
|
|
153
|
+
// default locale of a domain doesn't require a prefix
|
|
154
|
+
!routing.domains.some(cur => cur.defaultLocale === locale) : locale !== routing.defaultLocale;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return shouldPrefix ? prefixPathname(getLocalePrefix(locale, routing.localePrefix), pathname) : pathname;
|
|
158
|
+
}
|
|
159
|
+
function validateReceivedConfig(config) {
|
|
160
|
+
if (config.localePrefix?.mode === 'as-needed' && !('defaultLocale' in config)) {
|
|
161
|
+
throw new Error("`localePrefix: 'as-needed' requires a `defaultLocale`.");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export { applyPathnamePrefix, compileLocalizedPathname, getBasePath, getRoute, normalizeNameOrNameWithParams, serializeSearchParams, validateReceivedConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as createNavigation } from './navigation/react-client/createNavigation.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as createNavigation } from './navigation/react-server/createNavigation.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Avoid rollup's `replace` plugin to compile this away
|
|
2
|
+
const nodeEnvKey = 'NODE_ENV'.trim();
|
|
3
|
+
|
|
4
|
+
// We avoid reading `argv.includes('dev')` related to
|
|
5
|
+
// https://github.com/amannn/next-intl/issues/2006
|
|
6
|
+
const isDevelopment = process.env[nodeEnvKey] === 'development';
|
|
7
|
+
const isNextBuild = process.argv.includes('build');
|
|
8
|
+
const isDevelopmentOrNextBuild = isDevelopment || isNextBuild;
|
|
9
|
+
|
|
10
|
+
export { isDevelopment, isDevelopmentOrNextBuild, isNextBuild };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import initExtractionCompiler from './extractor/initExtractionCompiler.js';
|
|
2
|
+
import getNextConfig from './getNextConfig.js';
|
|
3
|
+
import { warn } from './utils.js';
|
|
4
|
+
import createMessagesDeclaration from './declaration/createMessagesDeclaration.js';
|
|
5
|
+
|
|
6
|
+
function initPlugin(pluginConfig, nextConfig) {
|
|
7
|
+
if (nextConfig?.i18n != null) {
|
|
8
|
+
warn("An `i18n` property was found in your Next.js config. This likely causes conflicts and should therefore be removed if you use the App Router.\n\nIf you're in progress of migrating from the Pages Router, you can refer to this example: https://next-intl.dev/examples#app-router-migration\n");
|
|
9
|
+
}
|
|
10
|
+
const messagesPathOrPaths = pluginConfig.experimental?.createMessagesDeclaration;
|
|
11
|
+
if (messagesPathOrPaths) {
|
|
12
|
+
createMessagesDeclaration(typeof messagesPathOrPaths === 'string' ? [messagesPathOrPaths] : messagesPathOrPaths);
|
|
13
|
+
}
|
|
14
|
+
initExtractionCompiler(pluginConfig);
|
|
15
|
+
return getNextConfig(pluginConfig, nextConfig);
|
|
16
|
+
}
|
|
17
|
+
function createNextIntlPlugin(i18nPathOrConfig = {}) {
|
|
18
|
+
const config = typeof i18nPathOrConfig === 'string' ? {
|
|
19
|
+
requestConfig: i18nPathOrConfig
|
|
20
|
+
} : i18nPathOrConfig;
|
|
21
|
+
return function withNextIntl(nextConfig) {
|
|
22
|
+
return initPlugin(config, nextConfig);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { createNextIntlPlugin as default };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { once, throwError } from '../utils.js';
|
|
4
|
+
import watchFile from '../watchFile.js';
|
|
5
|
+
|
|
6
|
+
const runOnce = once('_NEXT_INTL_COMPILE_MESSAGES');
|
|
7
|
+
function createMessagesDeclaration(messagesPaths) {
|
|
8
|
+
// Instead of running _only_ in certain cases, it's
|
|
9
|
+
// safer to _avoid_ running for certain known cases.
|
|
10
|
+
// https://github.com/amannn/next-intl/issues/2006
|
|
11
|
+
const shouldBailOut = ['info', 'start'
|
|
12
|
+
|
|
13
|
+
// Note: These commands don't consult the
|
|
14
|
+
// Next.js config, so we can't detect them here.
|
|
15
|
+
// - telemetry
|
|
16
|
+
// - lint
|
|
17
|
+
//
|
|
18
|
+
// What remains are:
|
|
19
|
+
// - dev
|
|
20
|
+
// - build
|
|
21
|
+
// - typegen
|
|
22
|
+
].some(arg => process.argv.includes(arg));
|
|
23
|
+
if (shouldBailOut) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
runOnce(() => {
|
|
27
|
+
for (const messagesPath of messagesPaths) {
|
|
28
|
+
const fullPath = path.resolve(messagesPath);
|
|
29
|
+
if (!fs.existsSync(fullPath)) {
|
|
30
|
+
throwError(`\`createMessagesDeclaration\` points to a non-existent file: ${fullPath}`);
|
|
31
|
+
}
|
|
32
|
+
if (!fullPath.endsWith('.json')) {
|
|
33
|
+
throwError(`\`createMessagesDeclaration\` needs to point to a JSON file. Received: ${fullPath}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Keep this as a runtime check and don't replace
|
|
37
|
+
// this with a constant during the build process
|
|
38
|
+
const env = process.env['NODE_ENV'.trim()];
|
|
39
|
+
compileDeclaration(messagesPath);
|
|
40
|
+
if (env === 'development') {
|
|
41
|
+
startWatching(messagesPath);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function startWatching(messagesPath) {
|
|
47
|
+
const watcher = watchFile(messagesPath, () => {
|
|
48
|
+
compileDeclaration(messagesPath, true);
|
|
49
|
+
});
|
|
50
|
+
process.on('exit', () => {
|
|
51
|
+
watcher.close();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function compileDeclaration(messagesPath, async = false) {
|
|
55
|
+
const declarationPath = messagesPath.replace(/\.json$/, '.d.json.ts');
|
|
56
|
+
function createDeclaration(content) {
|
|
57
|
+
return `// This file is auto-generated by next-intl, do not edit directly.
|
|
58
|
+
// See: https://next-intl.dev/docs/workflows/typescript#messages-arguments
|
|
59
|
+
|
|
60
|
+
declare const messages: ${content.trim()};
|
|
61
|
+
export default messages;`;
|
|
62
|
+
}
|
|
63
|
+
if (async) {
|
|
64
|
+
return fs.promises.readFile(messagesPath, 'utf-8').then(content => fs.promises.writeFile(declarationPath, createDeclaration(content)));
|
|
65
|
+
}
|
|
66
|
+
const content = fs.readFileSync(messagesPath, 'utf-8');
|
|
67
|
+
fs.writeFileSync(declarationPath, createDeclaration(content));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { createMessagesDeclaration as default };
|