clean up - remove playwright, i18n

main
radex 2023-07-14 19:13:01 +02:00
parent 925635cd01
commit 137e028a3f
13 changed files with 4 additions and 316 deletions

View File

@ -1,42 +1,9 @@
import { NextRequest, NextResponse } from "next/server";
import acceptLanguage from "accept-language";
import { fallbackLng, languages } from "./src/app/i18n/settings";
acceptLanguage.languages(languages as any as string[]);
export const config = {
// matcher: '/:lng*'
matcher: ["/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)"],
};
const cookieName = "i18next";
export function middleware(req: NextRequest) {
let lng;
if (req.cookies.has(cookieName))
lng = acceptLanguage.get(req.cookies.get(cookieName)!.value);
if (!lng) lng = acceptLanguage.get(req.headers.get("Accept-Language"));
if (!lng) lng = fallbackLng;
// Redirect if lng in path is not supported
if (
!languages.some((loc) => req.nextUrl.pathname.startsWith(`/${loc}`)) &&
!req.nextUrl.pathname.startsWith("/_next")
) {
return NextResponse.redirect(
new URL(`/${lng}${req.nextUrl.pathname}`, req.url)
);
}
if (req.headers.has("referer")) {
const refererUrl = new URL(req.headers.get("referer")!);
const lngInReferer = languages.find((l) =>
refererUrl.pathname.startsWith(`/${l}`)
);
const response = NextResponse.next();
if (lngInReferer) response.cookies.set(cookieName, lngInReferer);
return response;
}
return NextResponse.next();
}

View File

@ -1,7 +0,0 @@
/** @type {import('next-i18next').UserConfig} */
module.exports = {
i18n: {
defaultLocale: "en",
locales: ["en", "pl"],
},
};

View File

@ -1,8 +1,6 @@
const { i18n } = require("./next-i18next.config");
/** @type {import('next').NextConfig} */
const nextConfig = {
i18n,
};
module.exports = nextConfig;

View File

@ -7,8 +7,7 @@
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "vitest",
"test:e2e": "playwright test"
"test": "vitest"
},
"dependencies": {
"@hookform/resolvers": "^3.1.1",
@ -22,22 +21,17 @@
"@types/node": "20.4.0",
"@types/react": "18.2.14",
"@types/react-dom": "18.2.6",
"accept-language": "^3.0.18",
"autoprefixer": "10.4.14",
"class-variance-authority": "^0.6.1",
"clsx": "^1.2.1",
"eslint": "8.44.0",
"eslint-config-next": "13.4.8",
"i18next": "^23.2.7",
"i18next-browser-languagedetector": "^7.1.0",
"i18next-resources-to-backend": "^1.1.4",
"next": "13.4.8",
"next-themes": "^0.2.1",
"postcss": "8.4.25",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.45.1",
"react-i18next": "^13.0.1",
"tailwind-merge": "^1.13.2",
"tailwindcss": "3.3.2",
"tailwindcss-animate": "^1.0.6",
@ -45,7 +39,6 @@
"zod": "^3.21.4"
},
"devDependencies": {
"@playwright/test": "^1.35.1",
"@testing-library/react": "^14.0.0",
"@vitejs/plugin-react": "^4.0.2",
"vite": "^4.4.0",

View File

@ -1,23 +0,0 @@
'use client'
import { ReactNode, createContext, useContext, useEffect, useState } from "react";
import { SupportedLanguages, fallbackLng } from "./settings";
const LanguageContext = createContext(fallbackLng);
export function LanguageProvider({ lng, children }: {
lng: SupportedLanguages,
children: ReactNode
}) {
const [language, setLanguage] = useState<SupportedLanguages>(fallbackLng)
useEffect(() => {
setLanguage(lng)
}, [lng])
return <LanguageContext.Provider value={language}>{children}</LanguageContext.Provider>
}
export function useProvidedLanguage() {
const lng = useContext(LanguageContext);
return lng;
}

View File

@ -1,60 +0,0 @@
"use client";
import { useEffect, useState } from "react";
import i18next from "i18next";
import {
UseTranslationOptions,
initReactI18next,
useTranslation as useTranslationOrg,
} from "react-i18next";
import resourcesToBackend from "i18next-resources-to-backend";
import LanguageDetector from "i18next-browser-languagedetector";
import { getOptions, languages } from "./settings";
import { useProvidedLanguage } from "./LanguageProvider";
const runsOnServerSide = typeof window === "undefined";
//
i18next
.use(initReactI18next)
.use(LanguageDetector)
.use(
resourcesToBackend(
(language: string, namespace: string) =>
import(`./locales/${language}/${namespace}.json`)
)
)
.init({
...getOptions(),
lng: undefined, // let detect the language on client side
detection: {
order: ["path", "htmlTag", "cookie", "navigator"],
},
preload: runsOnServerSide ? languages : [],
});
export function useTranslation(
ns: string,
options: UseTranslationOptions<undefined> | undefined
) {
const lng = useProvidedLanguage();
const ret = useTranslationOrg(ns, options);
const { i18n } = ret;
if (runsOnServerSide && lng && i18n.resolvedLanguage !== lng) {
i18n.changeLanguage(lng);
} else {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [activeLng, setActiveLng] = useState(i18n.resolvedLanguage);
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
if (activeLng === i18n.resolvedLanguage) return;
setActiveLng(i18n.resolvedLanguage);
}, [activeLng, i18n.resolvedLanguage]);
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
if (!lng || i18n.resolvedLanguage === lng) return;
i18n.changeLanguage(lng);
}, [lng, i18n]);
}
return ret;
}

View File

@ -1,34 +0,0 @@
import { createInstance } from "i18next";
import resourcesToBackend from "i18next-resources-to-backend";
import { initReactI18next } from "react-i18next/initReactI18next";
import { getOptions } from "./settings";
const initI18next = async (lng: string, ns: string) => {
const i18nInstance = createInstance();
await i18nInstance
.use(initReactI18next)
.use(
resourcesToBackend(
(language: string, namespace: string) =>
import(`./locales/${language}/${namespace}.json`)
)
)
.init(getOptions(lng, ns));
return i18nInstance;
};
export async function useTranslation(
lng: string,
ns: string,
options: any = {}
) {
const i18nextInstance = await initI18next(lng, ns);
return {
t: i18nextInstance.getFixedT(
lng,
Array.isArray(ns) ? ns[0] : ns,
options.keyPrefix
),
i18n: i18nextInstance,
};
}

View File

@ -1,4 +0,0 @@
{
"APPNAME": "spejstore-ui",
"form.login": "login"
}

View File

@ -1,4 +0,0 @@
{
"APPNAME": "spejstore-ui",
"form.login": "login"
}

View File

@ -1,20 +0,0 @@
type Languages = readonly ["en", "pl"];
export const fallbackLng = "en";
export const languages: string[] = [fallbackLng, "pl"] satisfies Languages;
export type SupportedLanguages = (typeof languages)[number];
export const defaultNS = "translation";
export function getOptions(lng = fallbackLng, ns = defaultNS) {
return {
// debug: true,
supportedLngs: languages,
fallbackLng,
lng,
fallbackNS: defaultNS,
defaultNS,
ns,
};
}

View File

@ -2,15 +2,6 @@ import './globals.css'
import { Inter } from 'next/font/google'
import { ThemeProvider } from '@/components/ThemeProvider'
import { dir } from 'i18next'
import { SupportedLanguages, languages } from './i18n/settings'
import { LanguageProvider } from './i18n/LanguageProvider'
export async function generateStaticParams() {
return languages.map((lng) => ({ lng }))
}
const inter = Inter({ subsets: ['latin'] })
export const metadata = {
@ -20,22 +11,14 @@ export const metadata = {
export default function RootLayout({
children,
params: {
lng
}
}: {
children: React.ReactNode,
params: {
lng: SupportedLanguages
}
}) {
return (
<html lang={lng} dir={dir(lng)} suppressHydrationWarning>
<html lang="en" suppressHydrationWarning>
<body className={inter.className}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<LanguageProvider lng={lng}>
{children}
</LanguageProvider>
</ThemeProvider>
</body>
</html>

View File

@ -1,27 +0,0 @@
import { languages } from '@spejstore-ui/app/i18n/settings'
import { TFunction } from 'i18next'
import Link from 'next/link'
import { Trans } from 'react-i18next/TransWithoutContext'
export const FooterBase = ({ t, lng }: {
t: TFunction<string, unknown>
lng: string
}) => {
return (
<footer style={{ marginTop: 50 }}>
<Trans i18nKey="languageSwitcher" t={t}>
Switch from <strong>{lng}</strong> to:{' '}
</Trans>
{languages.filter((l) => lng !== l).map((l, index) => {
return (
<span key={l}>
{index > 0 && (' or ')}
<Link href={`/${l}`}>
{l}
</Link>
</span>
)
})}
</footer>
)
}

View File

@ -183,7 +183,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.5", "@babel/runtime@^7.22.5":
"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.20.7":
version "7.22.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438"
integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==
@ -543,16 +543,6 @@
picocolors "^1.0.0"
tslib "^2.6.0"
"@playwright/test@^1.35.1":
version "1.36.0"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.36.0.tgz#df2c0b09bbd27016adf1892b0c3502c4ce88d307"
integrity sha512-yN+fvMYtiyLFDCQos+lWzoX4XW3DNuaxjBu68G0lkgLgC6BP+m/iTxJQoSicz/x2G5EsrqlZTqTIP9sTgLQerg==
dependencies:
"@types/node" "*"
playwright-core "1.36.0"
optionalDependencies:
fsevents "2.3.2"
"@radix-ui/number@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.0.1.tgz#644161a3557f46ed38a042acf4a770e826021674"
@ -1096,14 +1086,6 @@
loupe "^2.3.6"
pretty-format "^29.5.0"
accept-language@^3.0.18:
version "3.0.18"
resolved "https://registry.yarnpkg.com/accept-language/-/accept-language-3.0.18.tgz#f5025f17bf65a466a845838ccf98cdb877d83384"
integrity sha512-sUofgqBPzgfcF20sPoBYGQ1IhQLt2LSkxTnlQSuLF3n5gPEqd5AimbvOvHEi0T1kLMiGVqPWzI5a9OteBRth3A==
dependencies:
bcp47 "^1.1.2"
stable "^0.1.6"
acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
@ -1296,11 +1278,6 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
bcp47@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/bcp47/-/bcp47-1.1.2.tgz#354be3307ffd08433a78f5e1e2095845f89fc7fe"
integrity sha512-JnkkL4GUpOvvanH9AZPX38CxhiLsXMBicBY2IAtqiVN8YulGDQybUydWA4W6yAMtw6iShtw+8HEF6cfrTHU+UQ==
big-integer@^1.6.44:
version "1.6.51"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
@ -2109,7 +2086,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@2.3.2, fsevents@~2.3.2:
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@ -2339,13 +2316,6 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"
html-parse-stringify@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2"
integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==
dependencies:
void-elements "3.1.0"
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
@ -2356,27 +2326,6 @@ human-signals@^4.3.0:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2"
integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==
i18next-browser-languagedetector@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.1.0.tgz#01876fac51f86b78975e79b48ccb62e2313a2d7d"
integrity sha512-cr2k7u1XJJ4HTOjM9GyOMtbOA47RtUoWRAtt52z43r3AoMs2StYKyjS3URPhzHaf+mn10hY9dZWamga5WPQjhA==
dependencies:
"@babel/runtime" "^7.19.4"
i18next-resources-to-backend@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/i18next-resources-to-backend/-/i18next-resources-to-backend-1.1.4.tgz#d139ca0cacc270dcc90b7926e192f4cd5aa4db60"
integrity sha512-hMyr9AOmIea17AOaVe1srNxK/l3mbk81P7Uf3fdcjlw3ehZy3UNTd0OP3EEi6yu4J02kf9jzhCcjokz6AFlEOg==
dependencies:
"@babel/runtime" "^7.21.5"
i18next@^23.2.7:
version "23.2.11"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.2.11.tgz#0c6f3a637fa87d3243e64b78ad285b7f77d41353"
integrity sha512-MA4FsxOjyCaOZtRDB4yuwjCvqYEioD4G4LlXOn7SO3rnQUlxTufyLsOqfL9MKakeLRBkefe8bqcs0D6Z/xFk1w==
dependencies:
"@babel/runtime" "^7.22.5"
ignore@^5.2.0, ignore@^5.2.4:
version "5.2.4"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
@ -3126,11 +3075,6 @@ pkg-types@^1.0.3:
mlly "^1.2.0"
pathe "^1.1.0"
playwright-core@1.36.0:
version "1.36.0"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.36.0.tgz#35d1ed5f364a31e58bc8f06688ab02d538b96eb6"
integrity sha512-7RTr8P6YJPAqB+8j5ATGHqD6LvLLM39sYVNsslh78g8QeLcBs5750c6+msjrHUwwGt+kEbczBj1XB22WMwn+WA==
postcss-import@^15.1.0:
version "15.1.0"
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
@ -3257,14 +3201,6 @@ react-hook-form@^7.45.1:
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.45.1.tgz#e352c7f4dbc7540f0756abbb4dcfd1122fecc9bb"
integrity sha512-6dWoFJwycbuFfw/iKMcl+RdAOAOHDiF11KWYhNDRN/OkUt+Di5qsZHwA0OwsVnu9y135gkHpTw9DJA+WzCeR9w==
react-i18next@^13.0.1:
version "13.0.2"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-13.0.2.tgz#1708a9bdabc1fe1dd4a8534f4c3a80ab784b01e9"
integrity sha512-NEVxC32v0oR4egwYM0QM0WE93AiJG5r0NTXTL8mhQfAhsMfDS2fSO6jpluyfsfypP988KzUQrAXncspcJ7+GHA==
dependencies:
"@babel/runtime" "^7.22.5"
html-parse-stringify "^3.0.1"
react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@ -3483,11 +3419,6 @@ source-map-js@^1.0.2:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
stable@^0.1.6:
version "0.1.8"
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
stackback@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b"
@ -3909,11 +3840,6 @@ vitest@^0.32.4:
vite-node "0.32.4"
why-is-node-running "^2.2.2"
void-elements@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
watchpack@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"