如何从API端点正确加载next-i18 next中的i18 n资源?

smdncfj3  于 2023-08-04  发布在  其他
关注(0)|答案(2)|浏览(141)

我有一个nextjs应用程序,我想使用i18 next和next-i18 next(https://github.com/isaachinman/next-i18next)扩展它。
默认配置是在./public/locales/{lng}/{ns}.json下查找json文件,其中lng是语言,ns是命名空间。
然而,我的要求是,这应该从一个API端点提供服务。我正在努力找到正确的配置,因为next-i18next现在忽略了我的设置,并且没有向我的后端发出任何xhr请求。
next-i18next.config.js:

const HttpApi = require('i18next-http-backend')

module.exports = {
    i18n: {
        defaultLocale: 'de',
        locales: ['en', 'de'],
    },
    backend: {
        referenceLng: 'de',
        loadPath: `https://localhost:5001/locales/de/common`,
        parse: (data) => {
            console.log(data)
            return data 
        }
    },
    debug: true,
    ns: ['common', 'footer', 'second-page'], // the namespaces needs to be listed here, to make sure they got preloaded
    serializeConfig: false, // because of the custom use i18next plugin
    use: [HttpApi],
}

字符集
我在这里不知所措。我做错了什么?

50few1ms

50few1ms1#

最后我把它拼凑在一起。

const I18NextHttpBackend = require('i18next-http-backend')

module.exports = {
    i18n: {
        defaultLocale: 'de',
        locales: ['de'],

        backend: {
            loadPath: `${process.env.INTERNAL_API_URI}/api/locales/{{lng}}/{{ns}}`
        },
    },
    debug: true,
    ns: ["common", "employees", "projects"],
    serializeConfig: false,
    use: [I18NextHttpBackend]
}

字符集
您可能会遇到一个错误,显示为You are passing a wrong module! Please check the object you are passing to i18next.use()。如果是这种情况,你可以强制http后端加载为commonjs,通过使用以下导入:

const I18NextHttpBackend = require('i18next-http-backend/cjs')


第一个可以在webpack 5上使用,而我必须在webpack 4上使用cjs导入。虽然我找不到原因。
此后,其一帆风顺:
_app.tsx:

/*i18n */
import { appWithTranslation } from 'next-i18next'
import NextI18nextConfig from '../../next-i18next.config'

const MyApp = ({ Component, pageProps }: AppProps) => {
  return (
    <>
      <MsalProvider instance={msalApp}>
        <PageLayout>
          <Component {...pageProps} />
        </PageLayout>
      </MsalProvider>
    </>
  )
}

export default appWithTranslation(MyApp, NextI18nextConfig)


anypage.tsx:

export const getServerSideProps: GetServerSideProps = async ({ locale }) => {
  return {
    props: {
      ...(await serverSideTranslations(locale, ['common', 'employees'])),
      // Will be passed to the page component as props
    },
  };
}


如果你只需要在构建过程中获取一次locale,你可以使用getStaticProps来代替--这取决于你。

h5qlskok

h5qlskok2#

经过长时间的寻找解决方案,我最终得到了这个工作示例。也许它帮助了别人。
第一个月

const HttpBackend = require('i18next-http-backend/cjs');
const ChainedBackend = require('i18next-chained-backend').default;
const LocalStorageBackend = require('i18next-localstorage-backend').default;

const isBrowser = typeof window !== 'undefined';

const path = !isBrowser ? require('path') : false;

const localePath = path !== false ? `${path.resolve('./public/locales')}/` : 'locales';

module.exports = {
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'nl'],
  },
  debug: process.env.NODE_ENV === 'development',
  localePath,
  backend: {
    backendOptions: [
      {
        expirationTime: 60 * 60 * 1000, // 1 hour
      },
    ],
    loadPath: `${localePath}{{lng}}/{{ns}}.json`,
    backends: typeof window !== 'undefined' ? [LocalStorageBackend, HttpBackend] : [require('i18next-fs-backend/cjs')],
  },
  serializeConfig: false,
  use: typeof window !== 'undefined' ? [ChainedBackend] : [require('i18next-fs-backend/cjs')],
};

字符集
pages/_app.tsx

import { appWithTranslation } from 'next-i18next'
import NextI18nextConfig from '../next-i18next.config'

const MyApp = ({ Component, pageProps }: AppProps) => {
  return (
     <Component {...pageProps} />
  )
}

export default appWithTranslation(MyApp, NextI18nextConfig)


next.config.js

/** @type {import('next').NextConfig} */
const { i18n } = require('./next-i18next.config');

const nextConfig = {
  ...
  i18n: {
    ...i18n,
    localeDetection: false,
  },
  ...
};

module.exports = nextConfig;


而在API端点需要调用loadNamespaces函数
pages/api/some-page.ts

import { i18n } from 'next-i18next';

async function handler(req: NextApiRequest, res: NextApiResponse) {
    ...
    if (!i18n?.hasLoadedNamespace('common')) {
        await i18n?.loadNamespaces('common');
    }
    const { t } = i18n!;

    const result = await sendEmail({
       subject: t('_EMAIL_FORGOT_PASSWORD_SUBJECT'),
       sendToEmail: email,
       content,
    });
    ...
 }


我的区域设置文件位于此文件夹public/locales/中,因此“common”命名空间的完整路径为public/locales/en/common.json

相关问题