Skip to content

Commit

Permalink
Only overwrite ns config if it provided (#2270)
Browse files Browse the repository at this point in the history
* draft: test fail when process.browser eq false

* fix: remove deprecated process.browser and fix test fail

* feat: only overwrite `ns` config if it provided

* test: add example for auto-static-optimize and e2e test

* fix: use ns and initImmediate: false to fix mismatch ssr
  • Loading branch information
NamPNQ authored Apr 15, 2024
1 parent d4ee4ff commit 0736495
Show file tree
Hide file tree
Showing 30 changed files with 750 additions and 8 deletions.
30 changes: 29 additions & 1 deletion cypress/e2e/spec.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ describe('basic e2e test run', () => {
cy.contains('Back to home').click()
cy.location('pathname', { timeout: 10000 }).should('equal', '/')
cy.contains('A simple example')
cy.contains('To auto static page (en)').click()
cy.location('pathname', { timeout: 10000 }).should(
'equal',
'/auto-static'
)
cy.contains('hello_en')
cy.contains('Back to home').click()
cy.location('pathname', { timeout: 10000 }).should('equal', '/')
cy.contains('A simple example')

// Test German content
cy.contains('Change locale').click()
Expand All @@ -33,9 +42,28 @@ describe('basic e2e test run', () => {
'/de'
)
cy.contains('Ein einfaches Beispiel')

cy.contains('To auto static page (de)').click()
cy.location('pathname', { timeout: 10000 }).should(
'equal',
'/de/auto-static'
)
cy.contains('hello_de')
cy.contains('Zurück zur Hauptseite').click()
cy.location('pathname', { timeout: 10000 }).should(
'equal',
'/de'
)
cy.contains('Ein einfaches Beispiel')
cy.contains('Sprache wechseln zu').click()
cy.location('pathname', { timeout: 10000 }).should('equal', '/')
cy.contains('A simple example')

// Test generated version of auto static
cy.request('/auto-static')
.its('body')
.should('include', '<h2>hello_en</h2>')
cy.request('/de/auto-static')
.its('body')
.should('include', '<h2>hello_de</h2>')
})
})
18 changes: 18 additions & 0 deletions examples/auto-static-optimize/@types/i18next.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* If you want to enable locale keys typechecking and enhance IDE experience.
*
* Requires `resolveJsonModule:true` in your tsconfig.json.
*
* @link https://www.i18next.com/overview/typescript
*/
import 'i18next'

// resources.ts file is generated with `npm run toc`
import resources from './resources.ts'

declare module 'i18next' {
interface CustomTypeOptions {
defaultNS: 'common'
resources: typeof resources
}
}
13 changes: 13 additions & 0 deletions examples/auto-static-optimize/@types/resources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import common from '../public/locales/en/common.json'
import footer from '../public/locales/en/footer.json'
import secondpage from '../public/locales/en/second-page.json'
import staticpage from '../public/locales/en/staticpage.json'

const resources = {
common,
footer,
'second-page': secondpage,
staticpage,
} as const

export default resources
33 changes: 33 additions & 0 deletions examples/auto-static-optimize/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pkg from 'next-i18next/package.json'
import { useTranslation, Trans } from 'next-i18next'
import type { FC } from 'react'

export const Footer: FC = () => {
const { t } = useTranslation('footer')

return (
<footer>
<p>{t('description')}</p>
<p>next-i18next v{pkg.version}</p>
<p
style={{
fontSize: 'smaller',
fontStyle: 'italic',
marginTop: 20,
}}
>
<Trans i18nKey="helpLocize" t={t}>
With using
<a href="https://locize.com" target="_new">
locize
</a>
you directly support the future of
<a href="https://www.i18next.com" target="_new">
i18next
</a>
.
</Trans>
</p>
</footer>
)
}
23 changes: 23 additions & 0 deletions examples/auto-static-optimize/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Head from 'next/head'
import type { FC } from 'react'

type Props = {
heading: string
title: string
}

export const Header: FC<Props> = ({ heading, title }) => (
<>
<Head>
<title>{title}</title>
</Head>
<h2>
next-i18next
<hr />
</h2>
<h1>{heading}</h1>
<a className="github" href="//github.com/i18next/next-i18next">
<i className="typcn typcn-social-github-circular" />
</a>
</>
)
5 changes: 5 additions & 0 deletions examples/auto-static-optimize/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
46 changes: 46 additions & 0 deletions examples/auto-static-optimize/next-i18next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// @ts-check

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 isDev = process.env.NODE_ENV === 'development'

/**
* @type {import('next-i18next').UserConfig}
*/
module.exports = {
// It should config backend, use, partialBundledLanguages in case you want translate for auto static page
backend: {
backendOptions: [
{ expirationTime: isDev ? 60 * 1000 : 60 * 60 * 1000 },
{},
], // 1 hour
backends: isBrowser ? [LocalStorageBackend, HttpBackend] : [],
},
// https://www.i18next.com/overview/configuration-options#logging
debug: isDev,
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
},
initImmediate: false,
/** To avoid issues when deploying to some paas (vercel...) */
localePath:
typeof window === 'undefined'
? require('path').resolve('./public/locales')
: '/locales',
ns: ['common', 'footer', 'second-page', 'staticpage'],
partialBundledLanguages: isBrowser,
reloadOnPrerender: process.env.NODE_ENV === 'development',
use: isBrowser ? [ChainedBackend] : [],
/**
* @link https://github.com/i18next/next-i18next#6-advanced-configuration
*/
// saveMissing: false,
// strictMode: true,
// serializeConfig: false,
// react: { useSuspense: false }
}
26 changes: 26 additions & 0 deletions examples/auto-static-optimize/next-utils.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const pc = require('picocolors')

const nextUtilsConfig = () => {
const trueEnv = ['true', '1', 'yes']
const esmExternals = trueEnv.includes(
process.env?.NEXTJS_ESM_EXTERNALS ?? 'false'
)
const tsconfigPath = process.env.NEXTJS_TSCONFIG_PATH
? process.env.NEXTJS_TSCONFIG_PATH
: './tsconfig.json'

// eslint-disable-next-line no-console
console.warn(
`${pc.green('warn -')} experimental.esmExternals is ${
esmExternals ? 'enabled' : 'disabled'
}`
)
return {
esmExternals,
tsconfigPath,
}
}

module.exports = {
loadCustomBuildParams: nextUtilsConfig,
}
21 changes: 21 additions & 0 deletions examples/auto-static-optimize/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// @ts-check
const { i18n } = require('./next-i18next.config.js')

// You can remove the following 2 lines when integrating our example.
const { loadCustomBuildParams } = require('./next-utils.config')
const { esmExternals = false, tsconfigPath } =
loadCustomBuildParams()

/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
esmExternals, // https://nextjs.org/blog/next-11-1#es-modules-support
},
i18n,
reactStrictMode: true,
typescript: {
tsconfigPath,
},
}

module.exports = nextConfig
38 changes: 38 additions & 0 deletions examples/auto-static-optimize/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "next-i18next-example-simple",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start -p ${PORT:=3000}",
"typecheck": "tsc --project ./tsconfig.json --noEmit",
"clean": "rimraf .next",
"nuke:install": "rimraf ./node_modules ./package-lock.json",
"toc": "i18next-resources-for-ts toc -i ./public/locales/en -o ./@types/resources.ts",
"merge": "i18next-resources-for-ts merge -i ./public/locales/en -o ./@types/resources.json",
"interface": "i18next-resources-for-ts interface -i ./public/locales/en -o ./@types/resources.d.ts"
},
"dependencies": {
"i18next": "23.7.13",
"i18next-chained-backend": "^4.6.2",
"i18next-http-backend": "^2.5.0",
"i18next-localstorage-backend": "^4.2.0",
"next": "^14.0.4",
"next-i18next": "^15.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.0.0"
},
"devDependencies": {
"@types/node": "^20.10.6",
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
"eslint-config-next": "^14.0.4",
"i18next-resources-for-ts": "1.4.0",
"picocolors": "^1.0.0",
"rimraf": "^5.0.5",
"typescript": "^5.3.3"
}
}
10 changes: 10 additions & 0 deletions examples/auto-static-optimize/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { AppProps } from 'next/app'
import { appWithTranslation } from 'next-i18next'
import nextI18NextConfig from '../next-i18next.config'

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

// https://github.com/i18next/next-i18next#unserializable-configs
export default (appWithTranslation as any)(MyApp, nextI18NextConfig)
51 changes: 51 additions & 0 deletions examples/auto-static-optimize/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Document, {
Html,
Head,
Main,
NextScript,
} from 'next/document'
import type { DocumentProps } from 'next/document'
import i18nextConfig from '../next-i18next.config'

type Props = DocumentProps & {
// add custom document props
}

class MyDocument extends Document<Props> {
render() {
const currentLocale =
this.props.__NEXT_DATA__.locale ??
i18nextConfig.i18n.defaultLocale
return (
<Html lang={currentLocale}>
<Head>
<meta charSet="utf-8" />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"
rel="stylesheet"
/>
<link href="/app.css" rel="stylesheet" />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/typicons/2.0.9/typicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Open+Sans:300,400|Oswald:600"
rel="stylesheet"
/>
<link
data-react-helmet="true"
rel="icon"
href="https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/spaces%2F-L9iS6Wm2hynS5H9Gj7j%2Favatar.png?generation=1523462254548780&amp;alt=media"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}

export default MyDocument
39 changes: 39 additions & 0 deletions examples/auto-static-optimize/pages/auto-static.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Link from 'next/link'

import { useTranslation } from 'next-i18next'

import { Header } from '../components/Header'
import { Footer } from '../components/Footer'

const StaticPage = () => {
const { t } = useTranslation([
'common',
'second-page',
'staticpage',
])

return (
<>
<main>
<Header
heading={t('second-page:h1')}
title={t('second-page:title')}
/>
<h2>{t('h1')}</h2>
<h2>{t('staticpage:hi')}</h2>
<Link href="/">
<button type="button">
{t('second-page:back-to-home')}
</button>
</Link>
</main>
<Footer />
</>
)
}

StaticPage._nextI18Next = {
ns: ['common', 'second-page', 'staticpage', 'footer'],
}

export default StaticPage
Loading

0 comments on commit 0736495

Please sign in to comment.