diff --git a/.eslintrc.js b/.eslintrc.js index 7f3e3988821..a7ae59ed8d2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,7 +3,7 @@ module.exports = { "browser": true, "es6": true, }, - "extends": ["eslint:recommended", "plugin:react/recommended" , "plugin:cypress/recommended"], + "extends": ["eslint:recommended", "plugin:react/recommended", "plugin:cypress/recommended"], "globals": { "Atomics": "readonly", "SharedArrayBuffer": "readonly", diff --git a/components/Hero.js b/components/Hero.js index b6327942d60..81000be487c 100644 --- a/components/Hero.js +++ b/components/Hero.js @@ -8,18 +8,24 @@ import Heading from './typography/Heading' import Paragraph from './typography/Paragraph' import AlgoliaSearch, { SearchButton } from './AlgoliaSearch'; // Import AlgoliaSearch component import IconLoupe from './icons/Loupe'; +import { + useTranslation, +} from "next-i18next-static-site"; export default function Hero({ className = ''}) { + + const { t } = useTranslation(); + return ( <>
- Building the future of {` `} + {t('main.header')} {` `} {" "} - Event-Driven Architectures (EDA) + {t('main.subHeader')} @@ -69,5 +75,4 @@ export default function Hero({ className = ''}) {
); -} - +} \ No newline at end of file diff --git a/components/languageSelector/LanguageSelect.js b/components/languageSelector/LanguageSelect.js new file mode 100644 index 00000000000..b8d931a7d6f --- /dev/null +++ b/components/languageSelector/LanguageSelect.js @@ -0,0 +1,21 @@ +import { twMerge } from 'tailwind-merge' +export default function LanguageSelect({ + className = '', + onChange = () => { }, + options = [], + selected, +}) { + return ( + + ) +} \ No newline at end of file diff --git a/components/link.js b/components/link.js new file mode 100644 index 00000000000..4fe488bf107 --- /dev/null +++ b/components/link.js @@ -0,0 +1,48 @@ +import Link from "next/link"; +import { useRouter } from "next/router"; +import { defaultLanguage, languages } from "next-i18next-static-site"; + +const LinkComponent = ({ children, locale, ...props }) => { + const router = useRouter(); + const { pathname, query, asPath } = router; + + // Detect current language + const slug = asPath.split("/")[1]; + const langSlug = languages.includes(slug) && slug; + const language = query.lang || langSlug || defaultLanguage; + + let href = props.href || pathname; + + if (locale) { + if (props.href) { + href = `/${locale}${href}`; + } else { + if (pathname.startsWith("/404")) { + href = `/${locale}`; + } else { + href = pathname.replace("[lang]", locale); + } + } + } else { + if (language) { + href = `/${language}${href}`; + } else { + href = `/${href}`; + } + } + + // Fix double slashes + href = href.replace(/([^:]\/)\/+/g, "$1").replace("//", "/"); + + return ( + + {children} + + ); +}; + +export const LinkText = ({ href, children, ...props }) => { + return {children}; +}; + +export default LinkComponent; \ No newline at end of file diff --git a/components/navigation/NavBar.js b/components/navigation/NavBar.js index 71ee7ab6502..0505adfe386 100644 --- a/components/navigation/NavBar.js +++ b/components/navigation/NavBar.js @@ -14,16 +14,57 @@ import GithubButton from "../buttons/GithubButton" import { SearchButton } from '../AlgoliaSearch'; import IconLoupe from '../icons/Loupe'; import Link from 'next/link'; +import LanguageSelect from '../languageSelector/LanguageSelect'; +import { + defaultLanguage, + languages, + useTranslation, +} from "next-i18next-static-site"; const isMobile = isMobileDevice(); +const uniqueLangs = [...new Set(["EN", "DE"])].map((repo) => ({ + key: repo, + text: repo, +})); export default function NavBar({ className = '', hideLogo = false, }) { - const { asPath } = useRouter(); + const router = useRouter(); + const { pathname, query, asPath } = router; const [open, setOpen] = useState(); const [mobileMenuOpen, setMobileMenuOpen] = useState(); + const [lang, setLang] = useState("en"); + const { i18n } = useTranslation(); + + const changeLanguage = async (locale) => { + // Detect current language + const slug = asPath.split("/")[1]; + const langSlug = languages.includes(slug) && slug; + const language = query.lang || langSlug || defaultLanguage; + + let href = pathname; + + if (locale) { + if (pathname.startsWith("/404")) { + href = `/${locale}`; + } else { + href = pathname.replace("[lang]", locale); + } + } else { + if (language) { + href = `/${language}${href}`; + } else { + href = `/${href}`; + } + } + + // Fix double slashes + href = href.replace(/([^:]\/)\/+/g, "$1").replace("//", "/"); + + router.push(href); + }; function outsideClick(menu) { if (open !== menu) return; @@ -107,9 +148,9 @@ export default function NavBar({
showMenu(null)} ref={communityRef}> showOnClickMenu('community')} - onMouseEnter={() => showMenu('community')} + href="/community" + onClick={() => showOnClickMenu('community')} + onMouseEnter={() => showMenu('community')} hasDropdown /> {open === 'community' && } @@ -127,6 +168,17 @@ export default function NavBar({ + {/* // Language Picker Component */} + {/* { + setLang(value.toLowerCase()); + changeLanguage(value.toLowerCase()); + }} + className="" + selected={i18n.language.toLocaleUpperCase()} + /> */} +
diff --git a/lib/locales.js b/lib/locales.js new file mode 100644 index 00000000000..fe5067a7675 --- /dev/null +++ b/lib/locales.js @@ -0,0 +1,19 @@ +import { languages, namespaces } from "next-i18next-static-site"; + +function loadLocales() { + // Load all locales, required for next-i18n-static-site + const locales = {}; + languages.map((language) => { + locales[language] = {}; + namespaces.map((namespace) => { + locales[language][namespace] = require("./../locales/" + + language + + "/" + + namespace + + ".json"); + }); + }); + return locales; +} + +export default loadLocales; \ No newline at end of file diff --git a/locales/de/landing-page.json b/locales/de/landing-page.json new file mode 100644 index 00000000000..58efb8c52a3 --- /dev/null +++ b/locales/de/landing-page.json @@ -0,0 +1,6 @@ +{ + "main": { + "header": "Die Zukunft gestalten", + "subHeader": "Ereignisgesteuerte Architekturen (EDA)" + } +} \ No newline at end of file diff --git a/locales/en/landing-page.json b/locales/en/landing-page.json new file mode 100644 index 00000000000..130ec90f16c --- /dev/null +++ b/locales/en/landing-page.json @@ -0,0 +1,6 @@ +{ + "main": { + "header": "Building the future of", + "subHeader": "Event-Driven Architectures (EDA)" + } +} \ No newline at end of file diff --git a/next-i18next-static-site.config.js b/next-i18next-static-site.config.js new file mode 100644 index 00000000000..e42b98ca03e --- /dev/null +++ b/next-i18next-static-site.config.js @@ -0,0 +1,8 @@ +module.exports = { + i18n: { + languages: ["en", "de"], + defaultLanguage: "en", + namespaces: ["landing-page"], + defaultNamespace: "landing-page", + }, +}; \ No newline at end of file diff --git a/next.config.js b/next.config.js index 4fee80f9ea7..3795898a677 100644 --- a/next.config.js +++ b/next.config.js @@ -1,9 +1,10 @@ -const frontmatter = require('remark-frontmatter') -const images = require('remark-images') -const gemoji = require('remark-gemoji-to-emoji') -const a11yEmoji = require('@fec/remark-a11y-emoji') -const slug = require('remark-slug') -const headingId = require('remark-heading-id') +const frontmatter = require('remark-frontmatter'); +const images = require('remark-images'); +const gemoji = require('remark-gemoji-to-emoji'); +const a11yEmoji = require('@fec/remark-a11y-emoji'); +const slug = require('remark-slug'); +const headingId = require('remark-heading-id'); +const { i18n } = require("./next-i18next-static-site.config"); const withMDX = require('@next/mdx')({ extension: /\.mdx?$/, @@ -18,8 +19,11 @@ const withMDX = require('@next/mdx')({ ], rehypePlugins: [], }, -}) -module.exports = withMDX({ +}); + +const withTM = require("next-transpile-modules")(["next-i18next-static-site"]); + +module.exports = withTM(withMDX({ pageExtensions: ['js', 'md'], eslint: { ignoreDuringBuilds: true, @@ -33,6 +37,9 @@ module.exports = withMDX({ // config.resolve.alias["react/jsx-dev-runtime"] = require.resolve('react/jsx-dev-runtime'); // config.resolve.alias["react/jsx-runtime"] = require.resolve('react/jsx-runtime'); - return config + return config; + }, + publicRuntimeConfig: { + i18n, }, -}) \ No newline at end of file +})); diff --git a/package-lock.json b/package-lock.json index a816679fecd..7a9f82c3214 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,13 +42,16 @@ "mermaid": "9.3.0", "moment": "^2.29.4", "next": "^12.0.0", + "next-i18next-static-site": "^0.3.1", "next-mdx-remote": "^4.4.1", + "next-transpile-modules": "^10.0.0", "node-fetch": "^2.6.7", "postcss": "^8.4.14", "react": "^17.0.2", "react-dom": "^17.0.2", "react-ga": "^3.1.2", "react-gtm-module": "^2.0.11", + "react-i18next": "^13.0.1", "react-scrollspy": "^3.4.2", "react-syntax-highlighter": "12.2.1", "react-text-truncate": "^0.16.0", @@ -482,11 +485,14 @@ } }, "node_modules/@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/template": { @@ -4849,6 +4855,18 @@ "once": "^1.4.0" } }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -5985,8 +6003,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/gray-matter": { "version": "4.0.3", @@ -6383,6 +6400,14 @@ "node": "*" } }, + "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==", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/html-void-elements": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", @@ -6439,6 +6464,29 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, + "node_modules/i18next": { + "version": "21.10.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", + "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "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" + } + ], + "peer": true, + "dependencies": { + "@babel/runtime": "^7.17.2" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -7196,6 +7244,14 @@ "resolved": "https://registry.npmjs.org/jgexml/-/jgexml-0.4.4.tgz", "integrity": "sha512-j0AzSWT7LXy3s3i1cdv5NZxUtscocwiBxgOLiEBfitCehm8STdXVrcOlbAWsJFLCq1elZYpQlGqA9k8Z+n9iJA==" }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9049,6 +9105,21 @@ } } }, + "node_modules/next-i18next-static-site": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/next-i18next-static-site/-/next-i18next-static-site-0.3.1.tgz", + "integrity": "sha512-rl5kdst++xucZz6kVOQfXNc/ZGYJyjq8sfSkFxthV3qnnP17bWq6C8uLyDOHMV98DbujG28To7MW5yH+//Od+g==", + "dependencies": { + "js-cookie": "^3.0.1" + }, + "peerDependencies": { + "i18next": "^21.10.0", + "js-cookie": "^3.0.1", + "next": "^13.0.0", + "react": "^18.2.0", + "react-i18next": "^11.18.6" + } + }, "node_modules/next-mdx-remote": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz", @@ -9084,6 +9155,14 @@ "react": ">=16" } }, + "node_modules/next-transpile-modules": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-10.0.0.tgz", + "integrity": "sha512-FyeJ++Lm2Fq31gbThiRCrJlYpIY9QaI7A3TjuhQLzOix8ChQrvn5ny4MhfIthS5cy6+uK1AhDRvxVdW17y3Xdw==", + "dependencies": { + "enhanced-resolve": "^5.10.0" + } + }, "node_modules/node-abi": { "version": "3.40.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.40.0.tgz", @@ -10478,11 +10557,6 @@ "react-is": "^16.8.1" } }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/property-information": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", @@ -10719,6 +10793,32 @@ "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz", "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==" }, + "node_modules/react-i18next": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.0.1.tgz", + "integrity": "sha512-gMO6N2GfSfuH7xlHSsZ/mZf+Py9bLm/+EDKIn5fNTuDTjcCcwmMU5UEuGCDk5mdfivbo7ySyYXBN7B9tbGUxiA==", + "dependencies": { + "@babel/runtime": "^7.22.5", + "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-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/react-scrollspy": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/react-scrollspy/-/react-scrollspy-3.4.3.tgz", @@ -10933,9 +11033,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regexp-tree": { "version": "0.1.27", @@ -12046,6 +12146,14 @@ "node": ">= 6" } }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -12793,6 +12901,14 @@ "url": "https://opencollective.com/unified" } }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -13330,11 +13446,11 @@ } }, "@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" } }, "@babel/template": { @@ -16666,6 +16782,15 @@ "once": "^1.4.0" } }, + "enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -17669,8 +17794,7 @@ "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "gray-matter": { "version": "4.0.3", @@ -17984,6 +18108,14 @@ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz", "integrity": "sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw==" }, + "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==", + "requires": { + "void-elements": "3.1.0" + } + }, "html-void-elements": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", @@ -18026,6 +18158,15 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, + "i18next": { + "version": "21.10.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", + "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "peer": true, + "requires": { + "@babel/runtime": "^7.17.2" + } + }, "iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -18670,6 +18811,11 @@ "resolved": "https://registry.npmjs.org/jgexml/-/jgexml-0.4.4.tgz", "integrity": "sha512-j0AzSWT7LXy3s3i1cdv5NZxUtscocwiBxgOLiEBfitCehm8STdXVrcOlbAWsJFLCq1elZYpQlGqA9k8Z+n9iJA==" }, + "js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -20055,6 +20201,14 @@ "use-sync-external-store": "1.2.0" } }, + "next-i18next-static-site": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/next-i18next-static-site/-/next-i18next-static-site-0.3.1.tgz", + "integrity": "sha512-rl5kdst++xucZz6kVOQfXNc/ZGYJyjq8sfSkFxthV3qnnP17bWq6C8uLyDOHMV98DbujG28To7MW5yH+//Od+g==", + "requires": { + "js-cookie": "^3.0.1" + } + }, "next-mdx-remote": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz", @@ -20077,6 +20231,14 @@ } } }, + "next-transpile-modules": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-10.0.0.tgz", + "integrity": "sha512-FyeJ++Lm2Fq31gbThiRCrJlYpIY9QaI7A3TjuhQLzOix8ChQrvn5ny4MhfIthS5cy6+uK1AhDRvxVdW17y3Xdw==", + "requires": { + "enhanced-resolve": "^5.10.0" + } + }, "node-abi": { "version": "3.40.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.40.0.tgz", @@ -21140,13 +21302,6 @@ "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.8.1" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - } } }, "property-information": { @@ -21343,6 +21498,20 @@ "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz", "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==" }, + "react-i18next": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.0.1.tgz", + "integrity": "sha512-gMO6N2GfSfuH7xlHSsZ/mZf+Py9bLm/+EDKIn5fNTuDTjcCcwmMU5UEuGCDk5mdfivbo7ySyYXBN7B9tbGUxiA==", + "requires": { + "@babel/runtime": "^7.22.5", + "html-parse-stringify": "^3.0.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "react-scrollspy": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/react-scrollspy/-/react-scrollspy-3.4.3.tgz", @@ -21536,9 +21705,9 @@ } }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regexp-tree": { "version": "0.1.27", @@ -22429,6 +22598,11 @@ } } }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -23000,6 +23174,11 @@ "unist-util-stringify-position": "^3.0.0" } }, + "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==" + }, "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/package.json b/package.json index 859c6017879..ddc7761fc15 100644 --- a/package.json +++ b/package.json @@ -70,13 +70,16 @@ "mermaid": "9.3.0", "moment": "^2.29.4", "next": "^12.0.0", + "next-i18next-static-site": "^0.3.1", "next-mdx-remote": "^4.4.1", + "next-transpile-modules": "^10.0.0", "node-fetch": "^2.6.7", "postcss": "^8.4.14", "react": "^17.0.2", "react-dom": "^17.0.2", "react-ga": "^3.1.2", "react-gtm-module": "^2.0.11", + "react-i18next": "^13.0.1", "react-scrollspy": "^3.4.2", "react-syntax-highlighter": "12.2.1", "react-text-truncate": "^0.16.0", diff --git a/pages/[lang]/index.js b/pages/[lang]/index.js new file mode 100644 index 00000000000..36bf2189bda --- /dev/null +++ b/pages/[lang]/index.js @@ -0,0 +1,271 @@ +import React from 'react'; +import Container from '../../components/layout/Container'; +import NavBar from '../../components/navigation/NavBar'; +import Hero from '../../components/Hero'; +import NewsletterSubscribe from '../../components/NewsletterSubscribe'; +import Sponsors from '../../components/sponsors/Sponsors'; +import Head from '../../components/Head'; +import Slack from '../../components/slack'; +import Button from '../../components/buttons/Button'; +import Calendar from '../../components/Calendar'; +import AdidasLogo from '../../components/logos/Adidas'; +import AxwayLogo from '../../components/logos/Axway'; +import SlackLogo from '../../components/logos/Slack'; +import SalesforceLogo from '../../components/logos/Salesforce'; +import SapLogo from '../../components/logos/SAP'; +import Testimonial from '../../components/Testimonial'; +import Heading from '../../components/typography/Heading'; +import Paragraph from '../../components/typography/Paragraph'; +import TextLink from '../../components/typography/TextLink'; +import GoldSponsors from '../../components/sponsors/GoldSponsors'; +import SilverSponsors from '../../components/sponsors/SilverSponsors'; +import SupportUs from '../../components/SupportUs/SupportUs'; +import StickyNavbar from '../../components/navigation/StickyNavbar'; +import GoogleCalendarButton from '../../components/buttons/GoogleCalendarButton'; +import ICSFileButton from '../../components/buttons/ICSFileButton'; +import SubscribeButton from '../../components/buttons/SubscribeButton'; +import NewsroomSection from '../../components/newsroom/NewsroomSection'; +import { + getAllLanguageSlugs, + getLanguage, +} from "next-i18next-static-site"; + +function HomePage() { + return ( + <> + + + + + +
+ + + + + + + Adopted by the world leading brands + + + These brands are already using AsyncAPI in production. Is your company using AsyncAPI and wants to be included in this list? + + Let us know here! + + +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+ +
+ + + +
+ + + + Join our great community! + + + We're a community of great people who are passionate about AsyncAPI and event-driven architectures. + +
+ +
+
+ +
+
+
+ + Join our Slack workspace + + + We welcome everyone to join our Slack workspace. If you have a question on how to use AsyncAPI, want to contribute, or simply want to say hello 👋  you're welcome to join us. We're nice people 🙂 + +
+
+
+
+
+ +
+
+ +
+
+
+ + Join our public meetings + + + AsyncAPI hosts different meetings every week. They are focused on different topics, sometimes purely technical and sometimes about community building. Pick one and join us! + + + Learn more about our meetings. + + +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+
+
+ + + +
+
+ +
+ + + Platinum Sponsors + + + + + + + Gold Sponsors + + + + + + + Silver Sponsors + + + + + + + Want to Sponsor Us? + + + These great organizations are already supporting AsyncAPI. Want to become a sponsor? + + Support us! + + + +
+ + + Supported by + + + The following companies support us by letting us use their products for free. Interested in supporting us too? + + Email us + for more info. + + + + + + What the experts are saying + +
    + + + + +
+
+
+ + ); +} + +export default HomePage; + +export async function getStaticPaths() { + const paths = getAllLanguageSlugs(); + return { + paths, + fallback: false, + }; +} + +export async function getStaticProps({ params }) { + const language = getLanguage(params.lang); + return { + props: { + language, + }, + }; +} diff --git a/pages/_app.js b/pages/_app.js index 7b3a41781ac..3f61b533ff4 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -6,29 +6,49 @@ import Footer from '../components/footer/Footer' import { MDXProvider } from '../components/MDX'; import AlgoliaSearch from '../components/AlgoliaSearch'; import ScrollButton from '../components/buttons/ScrollButton'; - +import { + I18nProvider, + languages, + defaultLanguage, + namespaces, + defaultNamespace, +} from "next-i18next-static-site"; +import loadLocales from "../lib/locales"; import '../styles/globals.css' -export default function App({ Component, pageProps, router }) { +function App({ Component, pageProps, router }) { + + const i18n = { + languages, + defaultLanguage, + namespaces, + defaultNamespace, + locales: loadLocales(), + }; + return ( - - - - - - -
- - - - - -
-
+ + + + + + + +
+ + + + + +
+
+
-
- - - + + + + ) } + +export default App; \ No newline at end of file diff --git a/pages/casestudies/index.js b/pages/casestudies/index.js index f7300637164..567a154e3ff 100644 --- a/pages/casestudies/index.js +++ b/pages/casestudies/index.js @@ -4,6 +4,8 @@ import Paragraph from '../../components/typography/Paragraph'; import TextLink from '../../components/typography/TextLink'; import Heading from "../../components/typography/Heading"; import CaseStudiesList from "../../config/case-studies.json"; +import { +} from "next-i18next-static-site"; export default function casestudies() { const description = @@ -21,29 +23,27 @@ export default function casestudies() {
-
+
- {title} - + {title} + - The best way to learn how to use AsyncAPI is not only through documentation that usually is focused on recommendations and best practices. - It is also good to confront with real-life case studies that explain how people really use AsyncAPI and what are their flows. + The best way to learn how to use AsyncAPI is not only through documentation that usually is focused on recommendations and best practices. + It is also good to confront with real-life case studies that explain how people really use AsyncAPI and what are their flows. - Feel free to submit your case study. We have a template for you. For more details - - read our FAQ - . + Feel free to submit your case study. We have a template for you. For more details + + read our FAQ + .
- +
); } - - diff --git a/pages/index.js b/pages/index.js index 11d5ca96b21..876e6e42566 100644 --- a/pages/index.js +++ b/pages/index.js @@ -24,8 +24,10 @@ import GoogleCalendarButton from '../components/buttons/GoogleCalendarButton'; import ICSFileButton from '../components/buttons/ICSFileButton'; import SubscribeButton from '../components/buttons/SubscribeButton'; import NewsroomSection from '../components/newsroom/NewsroomSection' +import { languageDetection } from "next-i18next-static-site"; function HomePage() { + languageDetection(); return ( <> @@ -257,4 +259,4 @@ function HomePage() { ) } -export default HomePage \ No newline at end of file +export default HomePage