最近在写next的项目,用到了国际化,使用了 react-i18next 但是感觉很费劲,配置起来很麻烦,所以换了一种方式,那就是:next-intl
发现还不错,后来要做接口,发现跨域,然后增加反向代理,则两者出现了冲突
国际化
第一步,需要安装
npm install next-intl
第二步,配置
import createNextIntlPlugin from 'next-intl/plugin';
const withNextIntl = createNextIntlPlugin();
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default withNextIntl(nextConfig)
src 目录下创建 i18n-config.ts
i18n.ts
middleware.ts
文件 与 messages 目录
export const i18n = {
defaultLocale: "en",
locales: ["en", "zh"],
} as const;
export const locales = i18n.locales;
export const defaultLocale = i18n.defaultLocale;
import { notFound } from "next/navigation";
import { getRequestConfig } from 'next-intl/server';
import { locales } from '@/i18n-config'
export default getRequestConfig(async ({ locale }: any) => {
if (!locales.includes(locale)) notFound();
console.log(locale)
return {
messages: (await import(`./messages/${locale}.json`)).default
};
});
import createMiddleware from 'next-intl/middleware';
import { locales, defaultLocale } from '@/i18n-config';
export default createMiddleware({
locales,
defaultLocale,
// 默认语言不重定向
localePrefix: 'as-needed'
});
export const config = {
matcher: ['/((?!api|_next|_vercel|.*\\..*).*)']
};
messages目录结构
{
"head": {
"Login":"Login"
}
}
项目结构:
要把以前写的页面 放到 [locale] 中,这样路由则会走 /语言/index
第三步:使用
服务端:
import {useTranslations} from 'next-intl';
export default function Page() {
const t = useTranslations('Head');
return (
<div className="note--empty-state">
<span className="note-text--empty-state">
{t('login')}
</span>
</div>
)
}
import {getTranslations} from 'next-intl/server';
export default async function Page() {
const t = await getTranslations('Head');
return (
<div className="note--empty-state">
<span className="note-text--empty-state">
{t('initText')}
</span>
</div>
)
}
客户端:
import {useTranslations} from 'next-intl';
export default function Sidebar() {
const t = useTranslations('Head');
return (
<>
<section className="col sidebar">
<section className="sidebar-menu" role="menubar">
<SidebarSearchField search={t('search')} />
<EditButton noteId={null}>{t('new')}</EditButton>
</section>
</section>
</>
)
}
如果不能如期使用则需要在父组件增加 NextIntlClientProvider 传递message参数 完成该结果
// 部分代码省略
import { NextIntlClientProvider, useMessages } from "next-intl";
// 渲染部分
const RootLayout = ({
children,
params,
}: Readonly<{
children: React.ReactNode;
params: { lang: Locale };
}>) => {
const messages = useMessages();
return (
<html lang={params.lang}>
<body className={inter.className}>
<Provider>
<NextIntlClientProvider messages={{ head: messages.head }}>
<LayoutHead ></LayoutHead>
{children}
<LayoutFoot></LayoutFoot>
</NextIntlClientProvider>
</Provider>
</body>
</html>
);
}
接口反向代理
为了配置反向代理,我以为需要配置 proxy
才可以,next 则不需要,只需要更改重写规则即可。
/** @type {import('next').NextConfig} */
const nextConfig = {
async rewrites() {
return {
fallback: [
{
source: '/capi/:path*',
destination: `http://127.0.0.1:3000/:path*`,
},
],
}
},
};
export default nextConfig;
import axios from 'axios'
let baseURL: string = "";
baseURL = "/capi"
// 拦截器
axios.interceptors.response.use((response) => {
return response
}, (error) => {
return Promise.reject(error)
})
axios.interceptors.request.use((config) => {
console.log(config)
config.headers['Accept'] = 'application/vnd.dpexpo.v1+json'
config.baseURL = baseURL;
config.timeout = 10000
return config;
}, (error) => {
return Promise.reject(error)
})
// axios的get请求
export function getAxios({
url,
params = {}
}: { url: string, params: any }) {
return new Promise((resolve, reject) => {
axios.get(url, {
params,
}).then(res => {
resolve(res.data)
}).catch(err => {
console.log(err, '1')
reject(err)
})
})
}
// axios的post请求
export function postAxios({
url,
data
}: any) {
return new Promise((resolve, reject) => {
axios({
url,
method: 'post',
data
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
})
}
export default axios
import { getAxios, postAxios } from '@/utils/axios'
export const getArticle = (params: any) => {
return getAxios({
url: "/getArticleList",
params
})
}
请求 /getArticleList
则对应请求的是 /capi/getArticleList
重写规则,则重定向到 [http://127.0.0.1:3000](http://127.0.0.1:3000)/getArticleList
问题来了
现在都可以实现,但是两者结合,则会报错,请求404
那怎么办?
很简单
import createMiddleware from 'next-intl/middleware';
import { locales, defaultLocale } from '@/i18n-config';
export default createMiddleware({
locales,
defaultLocale,
// 默认语言不重定向
localePrefix: 'as-needed'
});
export const config = {
//注意观察这一样的不同 多了capi 忽略了capi的路由
matcher: ['/((?!api|_next|_vercel|capi|.*\\..*).*)']
};