diff --git a/next-i18next.config.js b/next-i18next.config.js new file mode 100644 index 0000000..d2a5e87 --- /dev/null +++ b/next-i18next.config.js @@ -0,0 +1,12 @@ +module.exports = { + i18n: { + defaultLocale: 'fr', + locales: ['fr', 'en'], + }, + localePath: + typeof window === 'undefined' + ? require('path').resolve('./public/locales') + : '/locales', + + reloadOnPrerender: process.env.NODE_ENV === 'development', +} diff --git a/next.config.js b/next.config.js index e993beb..a7d1e82 100644 --- a/next.config.js +++ b/next.config.js @@ -2,6 +2,11 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + i18n: { + defaultLocale: 'fr', + locales: ['fr', 'en'], + localeDetection: true, + }, reactStrictMode: true, webpack(config) { config.module.rules.push({ @@ -9,7 +14,7 @@ const nextConfig = { use: ['@svgr/webpack'] }); return config; - }, + } } module.exports = nextConfig; diff --git a/package-lock.json b/package-lock.json index 52a1fa0..b4a5b8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,14 @@ "version": "0.1.0", "dependencies": { "classnames": "^2.5", + "i18next": "^24.2.2", + "i18next-browser-languagedetector": "^8.0.2", + "i18next-resources-to-backend": "^1.2.1", "next": "^15.1", + "next-i18next": "^15.4.1", "react": "^19.0", "react-dom": "^19.0", + "react-i18next": "^15.4.0", "react-icons": "^5.4", "swiper": "^11.2.1" }, @@ -1683,7 +1688,6 @@ "version": "7.26.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", - "dev": true, "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -3899,6 +3903,17 @@ "dev": true, "license": "MIT" }, + "node_modules/core-js": { + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz", + "integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-js-compat": { "version": "3.40.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz", @@ -5502,6 +5517,79 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/i18next": { + "version": "24.2.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.2.tgz", + "integrity": "sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.2.tgz", + "integrity": "sha512-shBvPmnIyZeD2VU5jVGIOWP7u9qNG3Lj7mpaiPFpbJ3LVfHZJvVzKR4v1Cb91wAOFpNw442N+LGPzHOHsten2g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-fs-backend": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.6.0.tgz", + "integrity": "sha512-3ZlhNoF9yxnM8pa8bWp5120/Ob6t4lVl1l/tbLmkml/ei3ud8IWySCHt2lrY5xWRlSU5D9IV2sm5bEbGuTqwTw==", + "license": "MIT" + }, + "node_modules/i18next-resources-to-backend": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/i18next-resources-to-backend/-/i18next-resources-to-backend-1.2.1.tgz", + "integrity": "sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -6432,6 +6520,41 @@ } } }, + "node_modules/next-i18next": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-15.4.1.tgz", + "integrity": "sha512-n3cFqBKDpEDLXZVYD52H6k2QzLAnUSuBie02BmVpfywNZGxcNgq6QXdpVpvONQ7WkBVntPtldt867ZgtEcP1Og==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + }, + { + "type": "individual", + "url": "https://locize.com" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "core-js": "^3", + "hoist-non-react-statics": "^3.3.2", + "i18next-fs-backend": "^2.6.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "i18next": ">= 23.7.13", + "next": ">= 12.0.0", + "react": ">= 17.0.2", + "react-i18next": ">= 13.5.0" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -7074,6 +7197,28 @@ "react": "^19.0.0" } }, + "node_modules/react-i18next": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.0.tgz", + "integrity": "sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-icons": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", @@ -7087,7 +7232,6 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, "license": "MIT" }, "node_modules/read-cache": { @@ -7160,7 +7304,6 @@ "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, "license": "MIT" }, "node_modules/regenerator-transform": { @@ -8292,7 +8435,7 @@ "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -8420,6 +8563,15 @@ "dev": true, "license": "MIT" }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 6355f85..e2903ce 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", + "dev": "NODE_OPTIONS='--inspect' next dev", "build": "next build", "start": "next start", "lint": "next lint", @@ -12,9 +12,14 @@ }, "dependencies": { "classnames": "^2.5", + "i18next": "^24.2.2", + "i18next-browser-languagedetector": "^8.0.2", + "i18next-resources-to-backend": "^1.2.1", "next": "^15.1", + "next-i18next": "^15.4.1", "react": "^19.0", "react-dom": "^19.0", + "react-i18next": "^15.4.0", "react-icons": "^5.4", "swiper": "^11.2.1" }, diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json new file mode 100644 index 0000000..a2be1ab --- /dev/null +++ b/public/locales/fr/common.json @@ -0,0 +1,8 @@ +{ + "linkedinUrl": "https://www.linkedin.com/company/meet-magento-france", + "youtubeUrl": "https://www.youtube.com/@MeetMagentoFrance", + "ticketingUrl": "https://www.eventbrite.fr/e/billets-meet-magento-2025-france-1124570503649", + "days": "Jours", + "hours": "Heures", + "minutes": "Minutes" +} diff --git a/public/locales/fr/hero.json b/public/locales/fr/hero.json new file mode 100644 index 0000000..d900b41 --- /dev/null +++ b/public/locales/fr/hero.json @@ -0,0 +1,8 @@ +{ + "title" : "Save the date!", + "subtitle" : "Meet Magento arrive en France", + "content" : "Rejoignez la communauté Magento et Adobe Commerce pour une journée d'innovations, d'échanges et d'expertise, à ne pas manquer !", + "date": "Mardi 25 Mars 2025", + "place": "L'Étoile Business Center, Paris", + "ticket": "Je prends mon billet" +} diff --git a/public/locales/fr/place.json b/public/locales/fr/place.json new file mode 100644 index 0000000..98c2a49 --- /dev/null +++ b/public/locales/fr/place.json @@ -0,0 +1,10 @@ +{ + "data": { + "title": "L’Étoile Business Center", + "subtitle": "En plein coeur de Paris, à deux pas des Champs-Élysées", + "address": "21-25 Rue Balzac, 75008 Paris", + "description": "Le 25 mars 2025, Meet Magento France se tiendra dans un cadre d’exception : l’Étoile Business Center, à Paris. Situé à deux pas des Champs-Élysées, ce lieu prestigieux, alliant élégance et modernité, incarne la classe française. Son architecture lumineuse et ses espaces raffinés en font l’écrin idéal pour une journée riche en échanges, partages d’expériences et exploration des dernières innovations autour de Magento et Adobe Commerce.", + "label": "Préparer ma venue", + "url": "" + } +} diff --git a/public/locales/fr/speakers.json b/public/locales/fr/speakers.json new file mode 100644 index 0000000..681bb38 --- /dev/null +++ b/public/locales/fr/speakers.json @@ -0,0 +1,84 @@ +{ + "data": { + "title": "Appel à speakers", + "subtitle": "Vous êtes expert du E-Commerce ou passionné de Magento ?", + "description": "Partagez vos connaissances sur la scène de Meet Magento 2025 France, le 25 mars à Paris.", + "registrationLabel": "Rejoignez les conférenciers de MM25FR", + "registrationFormUrl": "https://forms.gle/M6Y8V2xP7PGw5VD8A", + "speakers": [ + { + "id": 1, + "name": "Régis Quintin", + "title": "lorem ipsum", + "company": "Adobe", + "role": "Head of Commerce for Western Europe", + "image": "/images/speakers/speaker.png", + "biography": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.", + "sessions": [ + { + "title": "Utilisation de l'IA dans le parcours d'achat du client", + "room": "Salle Orion", + "start": "9h00", + "end": "10h30", + "tags": ["Ouverture", "technique", "Expertise"] + }, + { + "title": "Utilisation de l'IA dans le parcours d'achat du client", + "room": "Salle Orion", + "start": "9h00", + "end": "10h30", + "tags": ["Ouverture", "technique", "Expertise"] + } + ] + }, + { + "id": 2, + "name": "Balvesh Rakkar", + "title": "lorem ipsum", + "company": "Scandiweb", + "role": "Responsable technique", + "image": "/images/speakers/speaker.png" + }, + { + "id": 3, + "name": "Balvesh Rakkar", + "title": "lorem ipsum", + "company": "Scandiweb", + "role": "Responsable technique", + "image": "/images/speakers/speaker.png" + }, + { + "id": 4, + "name": "Balvesh Rakkar", + "title": "lorem ipsum", + "company": "Scandiweb", + "role": "Responsable technique", + "image": "/images/speakers/speaker.png" + }, + { + "id": 5, + "name": "Balvesh Rakkar", + "title": "lorem ipsum", + "company": "Scandiweb", + "role": "Responsable technique", + "image": "/images/speakers/speaker.png" + }, + { + "id": 6, + "name": "Balvesh Rakkar", + "title": "lorem ipsum", + "company": "Scandiweb", + "role": "Responsable technique", + "image": "/images/speakers/speaker.png" + }, + { + "id": 7, + "name": "Balvesh Rakkar", + "title": "lorem ipsum", + "company": "Scandiweb", + "role": "Responsable technique", + "image": "/images/speakers/speaker.png" + } + ] + } +} diff --git a/public/locales/fr/sponsors.json b/public/locales/fr/sponsors.json new file mode 100644 index 0000000..21c61ae --- /dev/null +++ b/public/locales/fr/sponsors.json @@ -0,0 +1,74 @@ +{ + "data": [ + { + "type": "platinum", + "name": "Adobe", + "description": "Création d’expériences B2B et B2C personnalisées par l'IA basées sur notre plateforme composable et évolutive Adobe Commerce", + "url": "https://www.adobe.com/", + "logoSrc": "adobe.svg" + }, + { + "type": "gold", + "name": "Dn'D", + "description": "Du conseil au delivery d'expériences digitales et E-Commerce B2C & B2B", + "url": "https://www.dnd.fr/", + "logoSrc": "dnd.svg" + }, + { + "type": "silver", + "name": "PH2M", + "description": "Agence e-commerce créatrice de solutions sur mesure pour marques et distributeurs", + "url": "https://www.ph2m.com/", + "logoSrc": "ph2m.svg" + }, + { + "type": "gold", + "name": "Hyvä", + "description": "Le frontend Magento le plus populaire avec 5,000 sites lives dans le monde, dont Somfy, Purina, Bultex ou Boucheron. Découvrez comment optimiser votre web perf tout en réduisant votre temps et coût de développement avec Hyvä", + "url": "https://www.hyva.io/", + "logoSrc": "hyva.svg" + }, + { + "type": "gold", + "name": "Ati4 Group", + "description": "ATI4 Group, agence e-commerce, construisons ensemble votre réussite digitale", + "url": "https://ati4group.com/", + "logoSrc": "ati4group.svg" + }, + { + "type": "gold", + "name": "Blackbird", + "description": "La mission de Blackbird est d'aider les e-commerçants dans toutes les phases de leur projet : conseil stratégique, design créatif, conception et pilotage de plateformes e-commerce sur-mesure, accompagnement proche et réactif et formation.", + "url": "https://black.bird.eu/", + "logoSrc": "blackbird.svg" + }, + { + "type": "gold", + "name": "Platform.sh", + "description": "Platform.sh: near-instant, full-stack previews that end staging delays", + "url": "https://platform.sh/", + "logoSrc": "platformsh.svg" + }, + { + "type": "silver", + "name": "LupaSearch", + "description": "", + "url": "https://www.lupasearch.com/", + "logoSrc": "lupasearch.svg" + }, + { + "type": "gold", + "name": "DATASOLUTION", + "description": "", + "url": "https://www.datasolution.fr/", + "logoSrc": "datasolution.svg" + }, + { + "type": "gold", + "name": "Decade", + "description": "", + "url": "https://www.datasolution.fr/", + "logoSrc": "decade.svg" + } + ] +} diff --git a/src/app/i18n.ts b/src/app/i18n.ts new file mode 100644 index 0000000..65cf5a8 --- /dev/null +++ b/src/app/i18n.ts @@ -0,0 +1,25 @@ +"use client"; + +import i18next from 'i18next' +import { initReactI18next } from 'react-i18next' +import LanguageDetector from 'i18next-browser-languagedetector' +import resourcesToBackend from 'i18next-resources-to-backend' + +i18next + .use(initReactI18next) + .use(LanguageDetector) + .use(resourcesToBackend((language: string, namespace: string) => + import(`/public/locales/${language}/${namespace}.json`) + )) + .init({ + defaultNS: 'common', + fallbackLng: 'fr', + supportedLngs: ['fr', 'en'], + lng: 'fr', // default language + ns: ['common', 'hero', 'place', 'speakers', 'sponsors'], + interpolation: { + escapeValue: false, + }, + }) + +export default i18next diff --git a/src/app/layout.tsx b/src/app/layout.tsx index af60176..f73dfbf 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,8 +1,9 @@ -import type {Metadata} from "next"; -import {IBM_Plex_Sans_Condensed, Montserrat} from "next/font/google"; +import type { Metadata } from "next"; +import { IBM_Plex_Sans_Condensed, Montserrat } from "next/font/google"; import "/public/styles.css"; import Header from "@/layouts/Header/Header"; import Footer from "@/layouts/Footer/Footer"; +import TranslationsProvider from '../components/TranslationsProvider/TranslationsProvider'; const ibmPlexSansCondensed = IBM_Plex_Sans_Condensed({ variable: "--font-ibm-plex-sans-condensed", @@ -27,16 +28,18 @@ export const metadata: Metadata = { }; export default function RootLayout({ - children, - }: Readonly<{ + children, +}: Readonly<{ children: React.ReactNode; }>) { return ( -
-
{children}
-