Skip to content

Commit

Permalink
feat: enable i18n support for AsyncAPI website (#2184)
Browse files Browse the repository at this point in the history
* add custom i18n link

Signed-off-by: Ansh Goyal <[email protected]>

* fix link.js

Signed-off-by: Ansh Goyal <[email protected]>

* Enable i18n

Signed-off-by: Ansh Goyal <[email protected]>

* Fix type error

Signed-off-by: Ansh Goyal <[email protected]>

* change select value

Signed-off-by: Ansh Goyal <[email protected]>

* make changes to LanguageSelect

Signed-off-by: Ansh Goyal <[email protected]>

* add changes

Signed-off-by: Ansh Goyal <[email protected]>

* add comments and fix router

Signed-off-by: Ansh Goyal <[email protected]>

* remove unused import

Signed-off-by: Ansh Goyal <[email protected]>

* updated js doc comments

* update jsdoc comments

Signed-off-by: Ansh Goyal <[email protected]>

* add navbar and centered logo

Signed-off-by: Ansh Goyal <[email protected]>

* add infinite loop fix

Signed-off-by: Ansh Goyal <[email protected]>

* update UI of LanguageSelect

---------

Signed-off-by: Ansh Goyal <[email protected]>
Co-authored-by: Akshat Nema <[email protected]>
Co-authored-by: Akshat Nema <[email protected]@Akshats-MacBook-Pro.local>
Co-authored-by: akshatnema <[email protected]>
  • Loading branch information
4 people authored Feb 11, 2024
1 parent bbc5760 commit 7543a56
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 264 deletions.
4 changes: 2 additions & 2 deletions components/languageSelector/LanguageSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ export default function LanguageSelect({
return (
<select data-testid="Select-form"
onChange={(ev) => onChange(ev.target.value)}
className={twMerge(`form-select h-full py-0 px-3 pr-7 inline-flex justify-center rounded-md border border-gray-300 shadow-sm py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500 ${className}`)}
className={twMerge(`form-select h-full py-0 px-3 pr-7 inline-flex justify-center rounded-md border border-gray-300 shadow-sm py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:border-gray-500 focus:outline-none focus:ring-0 focus:ring-black ${className}`)}
value={selected}
>
{options.map((option, index) => (
<option key={index} selected={option.value === selected} value={option.value} data-testid="Option-form">
<option key={index} value={option.value} data-testid="Option-form">
{option.text}
</option>
))}
Expand Down
28 changes: 27 additions & 1 deletion components/link.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,55 @@
import Link from "next/link";
import { useRouter } from "next/router";
import { defaultLanguage, languages } from "../lib/i18n";
import i18nPaths from "../lib/i18nPaths";

const LinkComponent = ({ children, locale, ...props }) => {
const router = useRouter();

// If there is no router available (e.g., during server-side rendering & cypress tests), render a standard Link
if (!router) {
return (
<Link href={props.href} passHref>
{children}
</Link>
);
}

const { pathname, query, asPath } = router;

// Detect current language
// Detect current language based on the path or query parameter
const slug = asPath.split("/")[1];
const langSlug = languages.includes(slug) && slug;
const language = query.lang || langSlug || defaultLanguage;

let href = props.href || pathname;

/*
If explicit href is provided, and the language-specific paths for the current language do not include the href, or if the href starts with "http", render a standard Link
*/
if ((props.href && i18nPaths[language] && !i18nPaths[language].includes(href)) || href.includes("http", 0)) {
return (
<Link href={href} passHref>
{children}
</Link>
);
}

// If a locale is provided, update the href with the locale
if (locale) {
if (props.href) {
href = `/${locale}${href}`;
} else {
// If the current path starts with "/404", update href to be the root path with the locale
// Otherwise, replace "[lang]" placeholder with the locale
if (pathname.startsWith("/404")) {
href = `/${locale}`;
} else {
href = pathname.replace("[lang]", locale);
}
}
} else {
// If no locale is provided, update the href with the current language or keep it as is
if (language) {
href = `/${language}${href}`;
} else {
Expand Down
6 changes: 3 additions & 3 deletions components/navigation/MenuBlocks.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import LinkComponent from '../link';
import Paragraph from '../typography/Paragraph';
import Label from './Label'
import Link from 'next/link'
import { useRouter } from 'next/router';


Expand All @@ -14,7 +14,7 @@ export default function MenuBlocks ({
items.map((item, index) => {
const isExternalHref = item.href && item.href.startsWith('http');
return (
<Link href={item.comingSoon ? '' : item.href} key={index}>
<LinkComponent href={item.comingSoon ? '' : item.href} key={index}>
<a data-testid="MenuBlocks-Link"
className={`flex items-start p-3 -m-3 space-x-4 transition duration-150 ease-in-out rounded-lg ${router.asPath === item.href ? 'bg-secondary-100 shadow-sm': 'hover:bg-gray-50'}`}
target={isExternalHref ? "_blank" : undefined}
Expand All @@ -32,7 +32,7 @@ export default function MenuBlocks ({
</Paragraph>
</div>
</a>
</Link>
</LinkComponent>
)
})
}
Expand Down
54 changes: 41 additions & 13 deletions components/navigation/NavBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,9 @@ import {
useTranslation,
} from "../../lib/i18n";
import browserLanguageDetector from "../../lib/browserLanguageDetector";
import i18nPaths from "../../lib/i18nPaths";

const isMobile = isMobileDevice();
const uniqueLangs = [...new Set(["EN", "DE"])].map((repo) => ({
key: repo,
text: repo,
}));

export default function NavBar({
className = '',
Expand All @@ -37,10 +34,46 @@ export default function NavBar({
const [mobileMenuOpen, setMobileMenuOpen] = useState();
const { i18n } = useTranslation();

/**
* Retrieves unique language options based on the current path and i18nPaths configuration.
*
* @returns {string[]} - An array of unique language options in uppercase.
*/
const getUniqueLangs = () => {
let pathnameWithoutLocale = pathname;

// Check if the pathname includes "/[lang]", if so, replace it with an empty string
if (pathname && pathname.includes("/[lang]")) {
pathnameWithoutLocale = pathname.replace("/[lang]", "");
}

// Filter unique languages based on i18nPaths that include the modified pathnameWithoutLocale
let uniqueLangs = Object.keys(i18nPaths).filter(lang => i18nPaths[lang].includes(pathnameWithoutLocale)).map(lang => lang.toUpperCase());

// If no unique languages are found, default to ["EN"]
return uniqueLangs.length === 0 ? ["EN"] : uniqueLangs;
}

const uniqueLangs = getUniqueLangs().map((lang) => ({
key: lang,
text: lang,
value: lang
}));

/**
* Changes the language and updates the URL accordingly.
*
* @async
* @param {string} locale - The new locale/language to set.
* @param {boolean} langPicker - Indicates whether the change is from the language picker.
* If true, stores the language in local storage.
* @returns {Promise<void>} - A promise representing the completion of the language change.
* @throws {Error} - If an error occurs during the language change process.
*/
const changeLanguage = async (locale, langPicker) => {

// Verifies if the language change is from langPicker or the browser-api
if(langPicker){
if (langPicker) {
localStorage.setItem('i18nLang', locale);
}

Expand Down Expand Up @@ -71,11 +104,6 @@ export default function NavBar({
router.push(href);
};

// To be enabled on the last PR
// useEffect(() => {
// changeLanguage(browserLanguageDetector(), false);
// }, []);

function outsideClick(menu) {
if (open !== menu) return;
setOpen(null);
Expand Down Expand Up @@ -179,14 +207,14 @@ export default function NavBar({
</SearchButton>

{/* // Language Picker Component */}
{/* <LanguageSelect
<LanguageSelect
options={uniqueLangs}
onChange={(value) => {
changeLanguage(value.toLowerCase(), true);
}}
className=""
selected={i18n.language.toLocaleUpperCase()}
/> */}
selected={i18n.language ? i18n.language.toUpperCase() : "EN"}
/>

<GithubButton text="Star on GitHub" href="https://github.com/asyncapi/spec" className="py-2 ml-2" inNav="true" />
</div>
Expand Down
12 changes: 12 additions & 0 deletions lib/i18nPaths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const i18nPaths = {
en: [
"", //Homepage Route
"/tools/cli"
],
de: [
"", //Homepage Route
"/tools/cli"
]
};

export default i18nPaths;
Loading

0 comments on commit 7543a56

Please sign in to comment.