chore: upgrade next-intl to version 4.0.0 and update type definitions
- Update `next-intl` dependency from version 3.26.5 to 4.0.0 - Modify global type definitions to include new `Locale` and `Messages` types - Refactor various components and pages to use `Locale` type for params - Enhance internationalization handling by integrating `hasLocale` checks - Clean up imports and ensure consistent usage of `next-intl` features
This commit is contained in:
parent
d7389eef47
commit
df1c75f56a
18
global.d.ts
vendored
18
global.d.ts
vendored
@ -1,8 +1,14 @@
|
|||||||
import en from './messages/en.json';
|
import { routing } from '@/i18n/routing';
|
||||||
|
import messages from './messages/en.json';
|
||||||
|
|
||||||
type Messages = typeof en;
|
/**
|
||||||
|
* next-intl 4.0.0
|
||||||
declare global {
|
*
|
||||||
// Use type safe message keys with `next-intl`
|
* https://github.com/amannn/next-intl/blob/main/examples/example-app-router/global.d.ts
|
||||||
interface IntlMessages extends Messages {}
|
*/
|
||||||
|
declare module 'next-intl' {
|
||||||
|
interface AppConfig {
|
||||||
|
Locale: (typeof routing.locales)[number];
|
||||||
|
Messages: typeof messages;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
"mdast-util-toc": "^7.1.0",
|
"mdast-util-toc": "^7.1.0",
|
||||||
"motion": "^12.4.3",
|
"motion": "^12.4.3",
|
||||||
"next": "15.2.1",
|
"next": "15.2.1",
|
||||||
"next-intl": "^3.26.5",
|
"next-intl": "^4.0.0",
|
||||||
"next-plausible": "^3.12.4",
|
"next-plausible": "^3.12.4",
|
||||||
"next-safe-action": "^7.10.4",
|
"next-safe-action": "^7.10.4",
|
||||||
"next-themes": "^0.4.4",
|
"next-themes": "^0.4.4",
|
||||||
|
37
pnpm-lock.yaml
generated
37
pnpm-lock.yaml
generated
@ -132,8 +132,8 @@ importers:
|
|||||||
specifier: 15.2.1
|
specifier: 15.2.1
|
||||||
version: 15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
next-intl:
|
next-intl:
|
||||||
specifier: ^3.26.5
|
specifier: ^4.0.0
|
||||||
version: 3.26.5(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
|
version: 4.0.0(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(typescript@5.7.3)
|
||||||
next-plausible:
|
next-plausible:
|
||||||
specifier: ^3.12.4
|
specifier: ^3.12.4
|
||||||
version: 3.12.4(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 3.12.4(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
@ -2231,6 +2231,9 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^18.0 || ^19.0 || ^19.0.0-rc
|
react: ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
|
||||||
|
'@schummar/icu-type-parser@1.21.5':
|
||||||
|
resolution: {integrity: sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==}
|
||||||
|
|
||||||
'@selderee/plugin-htmlparser2@0.11.0':
|
'@selderee/plugin-htmlparser2@0.11.0':
|
||||||
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
||||||
|
|
||||||
@ -3641,11 +3644,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
next-intl@3.26.5:
|
next-intl@4.0.0:
|
||||||
resolution: {integrity: sha512-EQlCIfY0jOhRldiFxwSXG+ImwkQtDEfQeSOEQp6ieAGSLWGlgjdb/Ck/O7wMfC430ZHGeUKVKax8KGusTPKCgg==}
|
resolution: {integrity: sha512-l+I1PLAFrjzYzrc340n1vssDJ7pP1gtYT1jOWlRWIHkyrPdyosEIHPC+LiqJP4vWvWtCZzzqTn9AaBF+x5Ja8g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
|
next: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
||||||
|
typescript: ^5.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
|
||||||
next-plausible@3.12.4:
|
next-plausible@3.12.4:
|
||||||
resolution: {integrity: sha512-cD3+ixJxf8yBYvsideTxqli3fvrB7R4BXcvsNJz8Sm2X1QN039WfiXjCyNWkub4h5++rRs6fHhchUMnOuJokcg==}
|
resolution: {integrity: sha512-cD3+ixJxf8yBYvsideTxqli3fvrB7R4BXcvsNJz8Sm2X1QN039WfiXjCyNWkub4h5++rRs6fHhchUMnOuJokcg==}
|
||||||
@ -4518,6 +4525,11 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
||||||
|
|
||||||
|
use-intl@4.0.0:
|
||||||
|
resolution: {integrity: sha512-/fmC7haEMVNa0isXGRGUir56fD4I9LRnOgbeBmji+bow6U8pE7WD+2X2sjqh+0h3yJ0T36PA6JXZ6PlVeRyt8w==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
||||||
|
|
||||||
use-sidecar@1.1.3:
|
use-sidecar@1.1.3:
|
||||||
resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
|
resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -6293,6 +6305,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
|
|
||||||
|
'@schummar/icu-type-parser@1.21.5': {}
|
||||||
|
|
||||||
'@selderee/plugin-htmlparser2@0.11.0':
|
'@selderee/plugin-htmlparser2@0.11.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
domhandler: 5.0.3
|
domhandler: 5.0.3
|
||||||
@ -8054,13 +8068,15 @@ snapshots:
|
|||||||
|
|
||||||
negotiator@1.0.0: {}
|
negotiator@1.0.0: {}
|
||||||
|
|
||||||
next-intl@3.26.5(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0):
|
next-intl@4.0.0(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)(typescript@5.7.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/intl-localematcher': 0.5.10
|
'@formatjs/intl-localematcher': 0.5.10
|
||||||
negotiator: 1.0.0
|
negotiator: 1.0.0
|
||||||
next: 15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
next: 15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
use-intl: 3.26.5(react@19.0.0)
|
use-intl: 4.0.0(react@19.0.0)
|
||||||
|
optionalDependencies:
|
||||||
|
typescript: 5.7.3
|
||||||
|
|
||||||
next-plausible@3.12.4(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
next-plausible@3.12.4(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -9109,6 +9125,13 @@ snapshots:
|
|||||||
intl-messageformat: 10.7.15
|
intl-messageformat: 10.7.15
|
||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
|
|
||||||
|
use-intl@4.0.0(react@19.0.0):
|
||||||
|
dependencies:
|
||||||
|
'@formatjs/fast-memoize': 2.2.6
|
||||||
|
'@schummar/icu-type-parser': 1.21.5
|
||||||
|
intl-messageformat: 10.7.15
|
||||||
|
react: 19.0.0
|
||||||
|
|
||||||
use-sidecar@1.1.3(@types/react@19.0.9)(react@19.0.0):
|
use-sidecar@1.1.3(@types/react@19.0.9)(react@19.0.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-node-es: 1.1.0
|
detect-node-es: 1.1.0
|
||||||
|
@ -14,7 +14,7 @@ import Testimonials from '@/components/blocks/testimonials/testimonials';
|
|||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
|
|
||||||
interface HomePageProps {
|
interface HomePageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function HomePage(props: HomePageProps) {
|
export default async function HomePage(props: HomePageProps) {
|
||||||
|
@ -3,7 +3,7 @@ import CallToAction2 from '@/components/blocks/call-to-action/call-to-action-2';
|
|||||||
import CallToAction3 from '@/components/blocks/call-to-action/call-to-action-3';
|
import CallToAction3 from '@/components/blocks/call-to-action/call-to-action-3';
|
||||||
|
|
||||||
interface CallToActionPageProps {
|
interface CallToActionPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,7 +6,7 @@ import Content5 from '@/components/blocks/content/content-5';
|
|||||||
import Content6 from '@/components/blocks/content/content-6';
|
import Content6 from '@/components/blocks/content/content-6';
|
||||||
|
|
||||||
interface ContentPageProps {
|
interface ContentPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function ContentPage(props: ContentPageProps) {
|
export default async function ContentPage(props: ContentPageProps) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import FAQs from '@/components/blocks/faq/faqs';
|
import FAQs from '@/components/blocks/faq/faqs';
|
||||||
|
|
||||||
interface FAQPageProps {
|
interface FAQPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,7 +8,7 @@ import Features8 from '@/components/blocks/features/features-8';
|
|||||||
import Features9 from '@/components/blocks/features/features-9';
|
import Features9 from '@/components/blocks/features/features-9';
|
||||||
|
|
||||||
interface FeaturesPageProps {
|
interface FeaturesPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function FeaturesPage(props: FeaturesPageProps) {
|
export default async function FeaturesPage(props: FeaturesPageProps) {
|
||||||
|
@ -4,7 +4,7 @@ import HeroSection3 from '@/components/blocks/hero/hero-section-3';
|
|||||||
import HeroSection4 from '@/components/blocks/hero/hero-section-4';
|
import HeroSection4 from '@/components/blocks/hero/hero-section-4';
|
||||||
|
|
||||||
interface HeroPageProps {
|
interface HeroPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,7 +5,7 @@ import PricingComparator from '@/components/pricing-comparator';
|
|||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
|
|
||||||
interface PricingPageProps {
|
interface PricingPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,7 +4,7 @@ import Stats3 from '@/components/blocks/stats/stats-3';
|
|||||||
import Stats4 from '@/components/blocks/stats/stats-4';
|
import Stats4 from '@/components/blocks/stats/stats-4';
|
||||||
|
|
||||||
interface StatsPageProps {
|
interface StatsPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,7 +5,7 @@ import Testimonials5 from '@/components/blocks/testimonials/testimonials-5';
|
|||||||
import Testimonials6 from '@/components/blocks/testimonials/testimonials-6';
|
import Testimonials6 from '@/components/blocks/testimonials/testimonials-6';
|
||||||
|
|
||||||
interface TestimonialsPageProps {
|
interface TestimonialsPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,7 +13,7 @@ import { getBaseUrl } from '@/lib/urls/get-base-url';
|
|||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: Promise<{ slug: string; locale: string }>;
|
params: Promise<{ slug: string; locale: Locale }>;
|
||||||
}): Promise<Metadata | undefined> {
|
}): Promise<Metadata | undefined> {
|
||||||
const resolvedParams = await params;
|
const resolvedParams = await params;
|
||||||
const { slug, locale } = resolvedParams;
|
const { slug, locale } = resolvedParams;
|
||||||
|
@ -5,7 +5,7 @@ import PricingComparator from '@/components/pricing-comparator';
|
|||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
|
|
||||||
interface PricingPageProps {
|
interface PricingPageProps {
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function PricingPage(props: PricingPageProps) {
|
export default async function PricingPage(props: PricingPageProps) {
|
||||||
|
@ -4,8 +4,7 @@ import { routing } from '@/i18n/routing';
|
|||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { GeistMono } from 'geist/font/mono';
|
import { GeistMono } from 'geist/font/mono';
|
||||||
import { GeistSans } from 'geist/font/sans';
|
import { GeistSans } from 'geist/font/sans';
|
||||||
import { NextIntlClientProvider } from 'next-intl';
|
import { Locale, hasLocale, NextIntlClientProvider } from 'next-intl';
|
||||||
import { getMessages } from 'next-intl/server';
|
|
||||||
import { notFound } from 'next/navigation';
|
import { notFound } from 'next/navigation';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { Toaster } from 'sonner';
|
import { Toaster } from 'sonner';
|
||||||
@ -15,7 +14,7 @@ import '@/styles/globals.css';
|
|||||||
|
|
||||||
interface LocaleLayoutProps {
|
interface LocaleLayoutProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,13 +31,10 @@ export default async function LocaleLayout({
|
|||||||
const { locale } = await params;
|
const { locale } = await params;
|
||||||
|
|
||||||
// Ensure that the incoming `locale` is valid
|
// Ensure that the incoming `locale` is valid
|
||||||
if (!routing.locales.includes(locale as any)) {
|
if (!hasLocale(routing.locales, locale)) {
|
||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Providing all messages to the client side
|
|
||||||
const messages = await getMessages();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang={locale} suppressHydrationWarning>
|
<html lang={locale} suppressHydrationWarning>
|
||||||
<body
|
<body
|
||||||
@ -53,7 +49,7 @@ export default async function LocaleLayout({
|
|||||||
GeistMono.variable
|
GeistMono.variable
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<NextIntlClientProvider messages={messages}>
|
<NextIntlClientProvider>
|
||||||
<Providers>
|
<Providers>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ import {
|
|||||||
SelectValue,
|
SelectValue,
|
||||||
} from '@/components/ui/select';
|
} from '@/components/ui/select';
|
||||||
import { useLocalePathname, useLocaleRouter } from '@/i18n/navigation';
|
import { useLocalePathname, useLocaleRouter } from '@/i18n/navigation';
|
||||||
import { DEFAULT_LOCALE, Locale, LOCALE_LIST, routing } from '@/i18n/routing';
|
import { DEFAULT_LOCALE, LOCALE_LIST, routing } from '@/i18n/routing';
|
||||||
import { useLocaleStore } from '@/stores/locale-store';
|
import { useLocaleStore } from '@/stores/locale-store';
|
||||||
import { useLocale } from 'next-intl';
|
import { Locale, useLocale } from 'next-intl';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
import { useEffect, useTransition } from 'react';
|
import { useEffect, useTransition } from 'react';
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { useLocalePathname, useLocaleRouter } from '@/i18n/navigation';
|
import { useLocalePathname, useLocaleRouter } from '@/i18n/navigation';
|
||||||
import { Locale, LOCALE_LIST, routing } from '@/i18n/routing';
|
import { LOCALE_LIST, routing } from '@/i18n/routing';
|
||||||
import { useLocaleStore } from '@/stores/locale-store';
|
import { useLocaleStore } from '@/stores/locale-store';
|
||||||
import { Languages } from 'lucide-react';
|
import { Languages } from 'lucide-react';
|
||||||
import { useLocale, useTranslations } from 'next-intl';
|
import { Locale, useLocale, useTranslations } from 'next-intl';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
import { useEffect, useTransition } from 'react';
|
import { useEffect, useTransition } from 'react';
|
||||||
|
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import deepmerge from 'deepmerge';
|
import deepmerge from 'deepmerge';
|
||||||
import { routing } from './routing';
|
import { routing } from './routing';
|
||||||
|
import { Locale, Messages } from 'next-intl';
|
||||||
|
|
||||||
import type messages from '../../messages/en.json';
|
const importLocale = async (locale: Locale): Promise<Messages> => {
|
||||||
|
|
||||||
export type Messages = typeof messages;
|
|
||||||
|
|
||||||
export const importLocale = async (locale: string): Promise<Messages> => {
|
|
||||||
return (await import(`../../messages/${locale}.json`)).default as Messages;
|
return (await import(`../../messages/${locale}.json`)).default as Messages;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,7 +13,7 @@ export const importLocale = async (locale: string): Promise<Messages> => {
|
|||||||
* https://next-intl.dev/docs/usage/configuration#messages
|
* https://next-intl.dev/docs/usage/configuration#messages
|
||||||
*/
|
*/
|
||||||
export const getMessagesForLocale = async (
|
export const getMessagesForLocale = async (
|
||||||
locale: string
|
locale: Locale
|
||||||
): Promise<Messages> => {
|
): Promise<Messages> => {
|
||||||
const localeMessages = await importLocale(locale);
|
const localeMessages = await importLocale(locale);
|
||||||
if (locale === routing.defaultLocale) {
|
if (locale === routing.defaultLocale) {
|
||||||
|
@ -5,6 +5,7 @@ import { routing } from './routing';
|
|||||||
* Navigation APIs
|
* Navigation APIs
|
||||||
*
|
*
|
||||||
* https://next-intl.dev/docs/routing/navigation
|
* https://next-intl.dev/docs/routing/navigation
|
||||||
|
* https://github.com/amannn/next-intl/blob/main/examples/example-app-router/src/i18n/navigation.ts
|
||||||
*/
|
*/
|
||||||
export const {
|
export const {
|
||||||
Link: LocaleLink,
|
Link: LocaleLink,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { hasLocale } from 'next-intl';
|
||||||
import { getRequestConfig } from 'next-intl/server';
|
import { getRequestConfig } from 'next-intl/server';
|
||||||
import { getMessagesForLocale } from './messages';
|
import { getMessagesForLocale } from './messages';
|
||||||
import { routing } from './routing';
|
import { routing } from './routing';
|
||||||
@ -11,15 +12,17 @@ import { routing } from './routing';
|
|||||||
* The first component to use internationalization will call the function defined with getRequestConfig.
|
* The first component to use internationalization will call the function defined with getRequestConfig.
|
||||||
*
|
*
|
||||||
* https://next-intl.dev/docs/usage/configuration
|
* https://next-intl.dev/docs/usage/configuration
|
||||||
|
* https://github.com/amannn/next-intl/blob/main/examples/example-app-router/src/i18n/request.ts
|
||||||
*/
|
*/
|
||||||
export default getRequestConfig(async ({ requestLocale }) => {
|
export default getRequestConfig(async ({ requestLocale }) => {
|
||||||
// This typically corresponds to the `[locale]` segment
|
// This typically corresponds to the `[locale]` segment
|
||||||
let locale = await requestLocale;
|
let requested = await requestLocale;
|
||||||
|
|
||||||
// Ensure that the incoming `locale` is valid
|
// Ensure that the incoming `locale` is valid
|
||||||
if (!locale || !routing.locales.includes(locale as any)) {
|
// https://next-intl.dev/blog/next-intl-4-0?s#strictly-typed-locale
|
||||||
locale = routing.defaultLocale;
|
const locale = hasLocale(routing.locales, requested)
|
||||||
}
|
? requested
|
||||||
|
: routing.defaultLocale;
|
||||||
|
|
||||||
// https://next-intl.dev/docs/usage/configuration#messages
|
// https://next-intl.dev/docs/usage/configuration#messages
|
||||||
// If you have incomplete messages for a given locale and would like to use messages
|
// If you have incomplete messages for a given locale and would like to use messages
|
||||||
|
@ -14,6 +14,7 @@ export const LOCALE_COOKIE_NAME = 'NEXT_LOCALE';
|
|||||||
* Next.js internationalized routing
|
* Next.js internationalized routing
|
||||||
*
|
*
|
||||||
* https://next-intl.dev/docs/routing
|
* https://next-intl.dev/docs/routing
|
||||||
|
* https://github.com/amannn/next-intl/blob/main/examples/example-app-router/src/i18n/routing.ts
|
||||||
*/
|
*/
|
||||||
export const routing = defineRouting({
|
export const routing = defineRouting({
|
||||||
// A list of all locales that are supported
|
// A list of all locales that are supported
|
||||||
@ -46,4 +47,4 @@ export const routing = defineRouting({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// export type Pathnames = keyof typeof routing.pathnames;
|
// export type Pathnames = keyof typeof routing.pathnames;
|
||||||
export type Locale = (typeof routing.locales)[number];
|
// export type Locale = (typeof routing.locales)[number];
|
||||||
|
@ -6,7 +6,7 @@ import { allPages } from 'content-collections';
|
|||||||
* @param locale The locale to get the page for
|
* @param locale The locale to get the page for
|
||||||
* @returns The custom page or undefined if not found
|
* @returns The custom page or undefined if not found
|
||||||
*/
|
*/
|
||||||
export async function getCustomPage(type: string, locale: string) {
|
export async function getCustomPage(type: string, locale: Locale) {
|
||||||
// Find page with matching slug and locale
|
// Find page with matching slug and locale
|
||||||
const page = allPages.find(
|
const page = allPages.find(
|
||||||
(page) => page.slugAsParams === `${type}` && page.locale === locale
|
(page) => page.slugAsParams === `${type}` && page.locale === locale
|
||||||
|
@ -5,7 +5,7 @@ import { allReleases } from 'content-collections';
|
|||||||
* @param locale The locale to get releases for
|
* @param locale The locale to get releases for
|
||||||
* @returns An array of releases sorted by date (newest first)
|
* @returns An array of releases sorted by date (newest first)
|
||||||
*/
|
*/
|
||||||
export async function getReleases(locale: string) {
|
export async function getReleases(locale: Locale) {
|
||||||
// Find all published releases with matching locale
|
// Find all published releases with matching locale
|
||||||
const releases = allReleases.filter(
|
const releases = allReleases.filter(
|
||||||
(release) => release.published && release.locale === locale
|
(release) => release.published && release.locale === locale
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { getWebsiteInfo } from '@/config';
|
import { getWebsiteInfo } from '@/config';
|
||||||
import { Locale, LOCALE_COOKIE_NAME, routing } from '@/i18n/routing';
|
import { LOCALE_COOKIE_NAME, routing } from '@/i18n/routing';
|
||||||
import { createTranslator } from '@/i18n/translator';
|
import { createTranslator } from '@/i18n/translator';
|
||||||
import { type ClassValue, clsx } from 'clsx';
|
import { type ClassValue, clsx } from 'clsx';
|
||||||
import { parse as parseCookies } from 'cookie';
|
import { parse as parseCookies } from 'cookie';
|
||||||
|
import { Locale } from 'next-intl';
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
@ -19,7 +20,7 @@ export function cn(...inputs: ClassValue[]) {
|
|||||||
export function createTitle(
|
export function createTitle(
|
||||||
title: string,
|
title: string,
|
||||||
addSuffix: boolean = true,
|
addSuffix: boolean = true,
|
||||||
locale: string = 'en'
|
locale: Locale = routing.defaultLocale
|
||||||
): string {
|
): string {
|
||||||
// Create a simple translator function for default values
|
// Create a simple translator function for default values
|
||||||
const t = createTranslator((key: string) => key);
|
const t = createTranslator((key: string) => key);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import type { Messages } from '@/i18n/messages';
|
|
||||||
import { getMessagesForLocale } from '@/i18n/messages';
|
import { getMessagesForLocale } from '@/i18n/messages';
|
||||||
import { Locale, routing } from '@/i18n/routing';
|
import { routing } from '@/i18n/routing';
|
||||||
import { mailTemplates } from '@/mail/emails';
|
import { mailTemplates } from '@/mail/emails';
|
||||||
import { sendEmail } from '@/mail/provider/resend';
|
import { sendEmail } from '@/mail/provider/resend';
|
||||||
import { render } from '@react-email/render';
|
import { render } from '@react-email/render';
|
||||||
|
import { Locale, Messages } from 'next-intl';
|
||||||
|
|
||||||
type Template = keyof typeof mailTemplates;
|
type Template = keyof typeof mailTemplates;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { Locale } from '@/i18n/routing';
|
import { Locale, Messages } from 'next-intl';
|
||||||
import type { Messages } from '@/i18n/messages';
|
|
||||||
|
|
||||||
export interface EmailParams {
|
export interface EmailParams {
|
||||||
to: string;
|
to: string;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { MetadataRoute } from 'next';
|
import { MetadataRoute } from 'next';
|
||||||
import { routing, Locale } from '@/i18n/routing';
|
import { routing } from '@/i18n/routing';
|
||||||
import { getLocalePathname } from '@/i18n/navigation';
|
import { getLocalePathname } from '@/i18n/navigation';
|
||||||
import { getBaseUrl } from './lib/urls/get-base-url';
|
import { getBaseUrl } from './lib/urls/get-base-url';
|
||||||
|
import { Locale } from 'next-intl';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/javayhu/cnblocks/blob/main/app/sitemap.ts
|
* https://github.com/javayhu/cnblocks/blob/main/app/sitemap.ts
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Locale } from '@/i18n/routing';
|
import { Locale } from 'next-intl';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
|
|
||||||
interface LocaleState {
|
interface LocaleState {
|
||||||
|
Loading…
Reference in New Issue
Block a user