From ff49825eaba062a169e496680c7ccde3dcf69187 Mon Sep 17 00:00:00 2001 From: headlessdev Date: Mon, 28 Apr 2025 23:19:55 +0200 Subject: [PATCH] i18n implementation & Login i18n --- app/layout.tsx | 6 +- app/page.tsx | 16 ++--- i18n/languages/en.json | 12 ++++ i18n/request.ts | 12 ++++ next.config.ts | 14 ++--- package-lock.json | 139 ++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 7 files changed, 183 insertions(+), 17 deletions(-) create mode 100644 i18n/languages/en.json create mode 100644 i18n/request.ts diff --git a/app/layout.tsx b/app/layout.tsx index 332c576..63afec7 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,6 +2,8 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; import { ThemeProvider } from "@/components/theme-provider" +import {NextIntlClientProvider} from 'next-intl'; +import {getLocale} from 'next-intl/server'; const geistSans = Geist({ variable: "--font-geist-sans", @@ -34,7 +36,9 @@ export default function RootLayout({ enableSystem disableTransitionOnChange > - {children} + + {children} + diff --git a/app/page.tsx b/app/page.tsx index e03f7b5..3dfafff 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -14,8 +14,10 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" +import {useTranslations} from 'next-intl'; export default function Home() { + const t = useTranslations('Home'); const [username, setUsername] = useState("") const [password, setPassword] = useState("") const [rememberMe, setRememberMe] = useState(false) @@ -75,20 +77,20 @@ export default function Home() {

CoreControl

-

Sign in to access your dashboard

+

{t('LoginCardDescription')}

- Login - Enter your credentials to continue + {t('LoginCardTitle')} + {t('LoginCardDescription')} {errorVisible && ( - Authentication Error + {t('AuthenticationError')} {error} )} @@ -96,7 +98,7 @@ export default function Home() {
@@ -116,7 +118,7 @@ export default function Home() {
@@ -138,7 +140,7 @@ export default function Home() { diff --git a/i18n/languages/en.json b/i18n/languages/en.json new file mode 100644 index 0000000..5280769 --- /dev/null +++ b/i18n/languages/en.json @@ -0,0 +1,12 @@ +{ + "Home": { + "TitleUnder": "Dashboard to manage your entire server infrastructure", + "LoginCardTitle": "Login", + "LoginCardDescription": "Enter your credentials to continue", + "AuthenticationError": "Authentication Error", + "Email": "Email", + "Password": "Password", + "SigninButton": "Sign in", + "SigninButtonSigningIn": "Signing in..." + } +} \ No newline at end of file diff --git a/i18n/request.ts b/i18n/request.ts new file mode 100644 index 0000000..a299eb7 --- /dev/null +++ b/i18n/request.ts @@ -0,0 +1,12 @@ +import {getRequestConfig} from 'next-intl/server'; + +export default getRequestConfig(async () => { + // Provide a static locale, fetch a user setting, + // read from `cookies()`, `headers()`, etc. + const locale = 'en'; + + return { + locale, + messages: (await import(`./languages/${locale}.json`)).default + }; +}); \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index e9ffa30..13bcffe 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,7 @@ -import type { NextConfig } from "next"; - -const nextConfig: NextConfig = { - /* config options here */ -}; - -export default nextConfig; +import {NextConfig} from 'next'; +import createNextIntlPlugin from 'next-intl/plugin'; + +const nextConfig: NextConfig = {}; + +const withNextIntl = createNextIntlPlugin('./i18n/request.ts'); +export default withNextIntl(nextConfig); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e7b3393..124391e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "corecontrol", - "version": "0.0.10", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "corecontrol", - "version": "0.0.10", + "version": "1.0.0", "dependencies": { "@prisma/client": "^6.6.0", "@prisma/extension-accelerate": "^1.3.0", @@ -39,6 +39,7 @@ "jsonwebtoken": "^9.0.2", "lucide-react": "^0.487.0", "next": "15.3.0", + "next-intl": "^4.1.0", "next-themes": "^0.4.6", "postcss-loader": "^8.1.1", "react": "^19.0.0", @@ -569,6 +570,66 @@ "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", "license": "MIT" }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz", + "integrity": "sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/intl-localematcher": "0.6.1", + "decimal.js": "^10.4.3", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/ecma402-abstract/node_modules/@formatjs/intl-localematcher": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.1.tgz", + "integrity": "sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz", + "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.2.tgz", + "integrity": "sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.4", + "@formatjs/icu-skeleton-parser": "1.8.14", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.14.tgz", + "integrity": "sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.4", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.10.tgz", + "integrity": "sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q==", + "license": "MIT", + "dependencies": { + "tslib": "2" + } + }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.34.1", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz", @@ -2128,6 +2189,12 @@ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, + "node_modules/@schummar/icu-type-parser": { + "version": "1.21.5", + "resolved": "https://registry.npmjs.org/@schummar/icu-type-parser/-/icu-type-parser-1.21.5.tgz", + "integrity": "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==", + "license": "MIT" + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -3068,6 +3135,12 @@ } } }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "license": "MIT" + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3604,6 +3677,18 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/intl-messageformat": { + "version": "10.7.16", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.16.tgz", + "integrity": "sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.4", + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/icu-messageformat-parser": "2.11.2", + "tslib": "^2.8.0" + } + }, "node_modules/is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", @@ -4138,6 +4223,15 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/next": { "version": "15.3.0", "resolved": "https://registry.npmjs.org/next/-/next-15.3.0.tgz", @@ -4192,6 +4286,33 @@ } } }, + "node_modules/next-intl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.1.0.tgz", + "integrity": "sha512-JNJRjc7sdnfUxhZmGcvzDszZ60tQKrygV/VLsgzXhnJDxQPn1cN2rVpc53adA1SvBJwPK2O6Sc6b4gYSILjCzw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/amannn" + } + ], + "license": "MIT", + "dependencies": { + "@formatjs/intl-localematcher": "^0.5.4", + "negotiator": "^1.0.0", + "use-intl": "^4.1.0" + }, + "peerDependencies": { + "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0", + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/next-themes": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", @@ -4972,6 +5093,20 @@ } } }, + "node_modules/use-intl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.1.0.tgz", + "integrity": "sha512-mQvDYFvoGn+bm/PWvlQOtluKCknsQ5a9F1Cj0hMfBjMBVTwnOqLPd6srhjvVdEQEQFVyHM1PfyifKqKYb11M9Q==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "^2.2.0", + "@schummar/icu-type-parser": "1.21.5", + "intl-messageformat": "^10.5.14" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0" + } + }, "node_modules/use-sidecar": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", diff --git a/package.json b/package.json index 9d7ddc2..ffe241e 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "jsonwebtoken": "^9.0.2", "lucide-react": "^0.487.0", "next": "15.3.0", + "next-intl": "^4.1.0", "next-themes": "^0.4.6", "postcss-loader": "^8.1.1", "react": "^19.0.0",