Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor simple example to typescript #1975

Merged
merged 10 commits into from
Oct 20, 2022
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ jobs:
- name: E2E tests
run: npm run test:e2e

- name: Build example with experimental.esmExternals
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is the part that I want to merge into the peer-deps change and new publishing. It will help me cover edge cases

run: npm run build:example:simple
env:
NEXTJS_ESM_EXTERNALS: true
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import pkg from 'next-i18next/package.json'
import { useTranslation, Trans } from 'next-i18next'
import type { FC } from 'react'

export const Footer = () => {
export const Footer: FC = () => {

const { t } = useTranslation('footer')

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import Head from 'next/head'
import type { FC } from 'react'

export const Header = ({ heading, title }) => (
type Props = {
heading: string
title: string
}

export const Header: FC<Props> = ({ heading, title }) => (
<>
<Head>
<title>{title}</title>
Expand Down
5 changes: 5 additions & 0 deletions examples/simple/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.
13 changes: 8 additions & 5 deletions examples/simple/next-i18next.config.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// used for SSR (getServerSideProps)
// const path = require('path')
// const localePath = path.resolve('./public/locales')

// @link https://github.com/i18next/next-i18next
module.exports = {
// https://www.i18next.com/overview/configuration-options#logging
debug: process.env.NODE_ENV === 'development',
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
},
// localePath,
reloadOnPrerender: process.env.NODE_ENV === 'development',
/**
* @link https://github.com/i18next/next-i18next#6-advanced-configuration
*
localePath: typeof window === 'undefined' ?
require('path').resolve('./my-custom/path'):
'/public/my-custom/path',
*/
// serializeConfig: false,
}
26 changes: 26 additions & 0 deletions examples/simple/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,
}
20 changes: 18 additions & 2 deletions examples/simple/next.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
const { i18n } = require('./next-i18next.config')
// @ts-check
const { i18n } = require('./next-i18next.config.js')

module.exports = {
// You can remove the following 2 lines when integrating our example.
const { loadCustomBuildParams } = require('./next-utils.config')
adrai marked this conversation as resolved.
Show resolved Hide resolved
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

10 changes: 8 additions & 2 deletions examples/simple/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@
"dependencies": {
"next": "12.3.1",
"next-i18next": "12.1.0",
"prop-types": "15.8.1",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@types/node": "^18.11.3",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"picocolors": "^1.0.0",
"typescript": "^4.8.4"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { AppProps } from 'next/app'
import { appWithTranslation } from 'next-i18next'
// import nextI18NextConfig from '../next-i18next.config.js'

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

// https://github.com/i18next/next-i18next#unserialisable-configs
export default appWithTranslation(MyApp/*, nextI18NextConfig */)
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import Document, { Html, Head, Main, NextScript } from 'next/document'
import type { DocumentProps } from 'next/document'
import i18nextConfig from '../next-i18next.config'

class MyDocument extends Document {
type Props = DocumentProps & {
// add custom document props
}

class MyDocument extends Document<Props> {
render() {
const currentLocale =
this.props.__NEXT_DATA__.locale || i18nextConfig.i18n.defaultLocale
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' />
Expand Down
15 changes: 10 additions & 5 deletions examples/simple/pages/index.js → examples/simple/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import type { GetStaticProps, InferGetStaticPropsType } from 'next'

import { useTranslation, Trans } from 'next-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'

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

const Homepage = () => {
type Props = {
// Add custom props here
}

const Homepage = (_props: InferGetStaticPropsType<typeof getStaticProps>) => {

const router = useRouter()
const { t } = useTranslation('common')

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const onToggleLanguageClick = (newLocale) => {
const onToggleLanguageClick = (newLocale: string) => {
const { pathname, asPath, query } = router
router.push({ pathname, query }, asPath, { locale: newLocale })
}
Expand Down Expand Up @@ -77,10 +82,10 @@ const Homepage = () => {
)
}

// export const getServerSideProps = async ({ locale }) => ({
export const getStaticProps = async ({ locale }) => ({
// or getServerSideProps: GetServerSideProps<Props> = async ({ locale })
export const getStaticProps: GetStaticProps<Props> = async ({ locale }) => ({
props: {
...await serverSideTranslations(locale, ['common', 'footer']),
...await serverSideTranslations(locale ?? 'en', ['common', 'footer']),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really necessary? Shouldn't it fallback automatically?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is not the case, we may move this check down here and fallback to defaultLocale if undefined.

Copy link
Contributor Author

@belgattitude belgattitude Oct 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

locale is always there (except maybe for nextjs prior to when locale was added)

I don't really want to the throw Error in there. I feel it's enough with the ??.

Second for the sake of the simple example I don't really want to require/import the next-i18next.config.js to get the fallback. At least not yet, cause it wasn't working in olders version without the localePath trick. I mean all those next-i18next, nextjs legacy but supported. At least If I remember well.

That said a more advanced example should be great.

One that typechecks the keys and handle properly localePath in all scenarios (getStatic, getServer, app and csr pages + monorepo), but for that the example will look a bit like bryanprimus/layout-reproduce-i18next#1. Which will make the simple example less simple.

So for now, I'm just focusing on whatever help me for publishing in a safe way.

Doing so I saw a lot more to do in the codebase and those little might not be necessary anymore once I've cleaned'up. (not sure I can but let's hope)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean in the library code, not in the example code... check the links in my previous comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tldr; I would remove the ?? 'en' part, as this should already work and if not, we'll adapt the library code to automatically fallback.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes. To be sure we're talking about the same

Here nextjs type the locale as string | undefined, and I want it as string.

Even if we would accept an undefined as first parameter to serverSideTranslations and do the job there, I feel would worsen the signature (I mean having optional as first param is not living well, ie myFunction(undefined, undefined, {param: 1})

I don't feel neither than nextjs is at fault here. It's good that the developer handles the fallback. I mean in how next-i18next works right now. And mysefl I tend to create my own function (that will deal with more)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

},
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import Link from 'next/link'
import type { GetStaticProps, InferGetStaticPropsType } from 'next'

import { useTranslation } from 'next-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'

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

const SecondPage = () => {
type Props = {
// Add custom props here
}

const SecondPage = (_props: InferGetStaticPropsType<typeof getStaticProps>) => {

const { t } = useTranslation('second-page')

Expand All @@ -27,10 +32,10 @@ const SecondPage = () => {
)
}

// export const getServerSideProps = async ({ locale }) => ({
export const getStaticProps = async ({ locale }) => ({
// or getServerSideProps: GetServerSideProps<Props> = async ({ locale })
export const getStaticProps: GetStaticProps<Props> = async ({ locale }) => ({
props: {
...await serverSideTranslations(locale, ['second-page', 'footer']),
...await serverSideTranslations(locale ?? 'en', ['second-page', 'footer']),
},
})

Expand Down
40 changes: 40 additions & 0 deletions examples/simple/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"baseUrl": ".",
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/backend": ["./src/backend/index"],
"@/lib": ["./src/lib/index"],
"@belgattitude/http-exception": [
"../../packages/http-exception/src/index"
],
"@belgattitude/http-exception/serializer": [
"../../packages/http-exception/src/serializer/index"
]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.js",
"**/*.jsx",
"**/*.cjs",
"**/*.mjs"
],
"exclude": ["**/node_modules", "**/.*/"]
}