diff --git a/ADDING_TRANSLATIONS.md b/ADDING_TRANSLATIONS.md index e4a26f9fefb1..5a340038b321 100644 --- a/ADDING_TRANSLATIONS.md +++ b/ADDING_TRANSLATIONS.md @@ -3,10 +3,10 @@ We appreciate your valuable contributions to the AsyncAPI website, whether it's adding or improving existing translations. ## Table of contents -- [Improving existing translations:](#improving-existing-translations) -- [Adding translations to a partially localized page:](#adding-translations-to-a-partially-localized-page) -- [Adding translations to a new page:](#adding-translations-to-a-new-page) -- [Adding a new locale:](#adding-a-new-locale) +- [Improving existing translations](#improving-existing-translations) +- [Adding translations to a partially localized page](#adding-translations-to-a-partially-localized-page) +- [Adding translations to a new page](#adding-translations-to-a-new-page) +- [Adding a new locale](#adding-a-new-locale) ## Improving existing translations @@ -18,12 +18,12 @@ The file `common.json` contains common translation keys such as buttons and CTAs ``` 📦locales - ┣ 📂de + ┣ 📂deutsch ┃ ┣ 📜common.json ┃ ┣ 📜landing-page.json ┃ ┗ 📜tools.json ┃ ┗ 📜....json - ┗ 📂en + ┗ 📂english ┃ ┣ 📜common.json ┃ ┣ 📜landing-page.json ┃ ┗ 📜tools.json @@ -32,7 +32,7 @@ The file `common.json` contains common translation keys such as buttons and CTAs To modify a `Landing Page`'s heading: - Navigate to the `locales` folder. -- Select a language, e.g. `de` (German) - go to the `de` folder. +- Select a language, e.g. `deutsch` (German) - go to the `deutsch` folder. - Open `landing-page.json`. - Change the values according to your needs. - Create a pull request with the changes. @@ -45,7 +45,7 @@ Use the translation hook with the key specified in the `locales` folder. Suppose the Landing Page has a button that is still in English when the language is set to German: - Navigate to the file where the component is defined. -- Import the `useTranslation` hook from `lib/i18n`. +- Import the `useTranslation` hook from `utils/i18n`. - Extract the translation function from the hook `const { t } = useTranslation();`. - Use it to pass the key of the required translation value. Make sure to add the required key to the `locales` folder according to the page's scope. In this example, we are adding translation for a button, since all translation keys related to buttons need to be specified in `common.json`. @@ -74,14 +74,14 @@ export default function ICSFButton({ } ``` -`en/common.json` +`english/common.json` ```diff { + "icsFileBtn": "Download ICS File", } ``` -`de/common.json` +`deutsch/common.json` ```diff { + "icsFileBtn": "ICS-Datei herunterladen", @@ -131,22 +131,22 @@ The process for adding translations to a page that is not yet available in any e **4. Configure i18n routing** After adding a new internationalized page, test it to sure the page is being served on the website when someone visits it. - - Replace the `next/link` component with the `LinkComponent` from `components/link.js` in the files where the page's `href` is being referenced. - - Make sure to add the exact same `href` to the `lib/i18nPaths.js` in the respective locales which support that `href`. + - Replace the `next/link` component with the `LinkComponent` from `components/link.tsx` in the files where the page's `href` is being referenced. + - Make sure to add the exact same `href` to the `utils/i18n.ts` in the respective locales which support that `href`. - For example, if you want to translate the `pages/newsletter/index.js` page, so that if someone visits `asyncapi.com/de/newsletter`, it shows the page in the `German` locale. + For example, if you want to translate the `pages/newsletter.tsx` page, so that if someone visits `asyncapi.com/deutsch/newsletter`, it shows the page in the `German` locale. - - Add new `JSON` files to the `locales/en` and `locales/de` folder. + - Add new `JSON` files to the `locales/english` and `locales/deutsch` folder. `locales` folder directory structure ```diff locales - ┣ de + ┣ deutsch ┃ ┣ common.json ┃ ┣ landing-page.json + ┃ ┣ newsletter.json ┃ ┗ tools.json - ┗ en + ┗ english ┃ ┣ common.json ┃ ┣ landing-page.json + ┃ ┣ newsletter.json @@ -158,8 +158,8 @@ After adding a new internationalized page, test it to sure the page is being ser ```diff module.exports = { i18n: { - languages: ["en", "de"], - defaultLanguage: "en", + languages: ["english", "deutsch"], + defaultLanguage: "english", - namespaces: ["landing-page", "common", "tools"], + namespaces: ["landing-page", "common", "tools", "newsletter"], defaultNamespace: "landing-page", @@ -167,7 +167,7 @@ After adding a new internationalized page, test it to sure the page is being ser }; ``` - - Copy and add static site functions to the `newsletter/index.js` page. + - Copy and add static site functions to the `newsletter.tsx` page. `pages` folder directory structure ```diff @@ -179,7 +179,7 @@ After adding a new internationalized page, test it to sure the page is being ser ┗ index.js ``` - `newsletter/index.js` + `newsletter.tsx` ```diff ... + import { @@ -217,14 +217,14 @@ After adding a new internationalized page, test it to sure the page is being ser - Add custom route `LinkComponent` wherever the `next/link` is used for routing to the `/newsletter` href. - `lib/i18nPaths.js` + `utils/i18n.ts` ```diff const i18nPaths = { - en: [ + english: [ "/tools/cli" + "/newsletter" ], - de: [ + deutsch: [ "/tools/cli" + "/newsletter" ] @@ -241,52 +241,52 @@ You are now done with adding the localization to the `newsletter` page. AsyncAPI welcomes people from all over the world. -There exist a few locales like `en` (English) and `de` (German) which have available localizations present. +There exist a few locales like `english` (English) and `deutsch` (German) which have available localizations present. -If you want to add a new locale like `fr` to serve pages in the French locale on the AsyncAPI website, follow these steps. +If you want to add a new locale like `french` to serve pages in the French locale on the AsyncAPI website, follow these steps. **1. Create new JSON Files** - Navigate to the `locales` folder. - Create a new folder with the name of the locale you want to introduce. - Create new `JSON` files with the same name as present in each of the other `locales` folders. - - Copy the existing `JSON` files present in the `en` folder. Change the values of those translation keys according to the new localization. + - Copy the existing `JSON` files present in the `english` folder. Change the values of those translation keys according to the new localization. **2. Modify i18n configuration** - - Navigate to the `next-i18next-static-site.config.js` file in the root of the project folder. + - Navigate to the `next-i18next.config.js` file in the root of the project folder. - Add the name of the newly added `locale` to the `languages` array. **3. Configure i18n routing** After adding a new internationalized page, ensure it is being served on the website when someone visits. - - Make sure to add the same `href` to the `lib/i18nPaths.js` in the respective locales supporting that `href`. + - Make sure to add the same `href` to the `utils/i18n.ts` in the respective locales supporting that `href`. -If you have added the 'fr' locale and translated the 'tools/cli' page, clicking 'Tools -> CLI' in the navigation menu will redirect the user to 'asyncapi.com/fr/tools/cli'. +If you have added the 'french' locale and translated the 'tools/cli' page, clicking 'Tools -> CLI' in the navigation menu will redirect the user to 'asyncapi.com/french/tools/cli'. `locales` folder structure ```diff locales - ┣ de + ┣ deutsch ┃ ┣ common.json ┃ ┣ landing-page.json ┃ ┗ tools.json - ┣ en + ┣ english ┃ ┣ common.json ┃ ┣ landing-page.json ┃ ┗ tools.json -+ ┗ fr ++ ┗ french + ┃ ┣ common.json + ┃ ┣ landing-page.json + ┃ ┗ tools.json ``` -- Change the `next-i18next-static-site.config.js` config. +- Change the `next-i18next.config.js` config. -`next-i18next-static-site.config.js` +`next-i18next.config.js` ```diff module.exports = { i18n: { -- languages: ["en", "de"], -+ languages: ["en", "de", "fr"], - defaultLanguage: "en", +- languages: ["english", "deutsch"], ++ languages: ["english", "deutsch", "french"], + defaultLanguage: "english", namespaces: ["landing-page", "common", "tools"], defaultNamespace: "landing-page", }, @@ -294,16 +294,16 @@ module.exports = { ``` - Add new locale routing. -`lib/i18nPaths.js` +`utils/i18n.ts` ```diff const i18nPaths = { - en: [ + english: [ "/tools/cli" ], - de: [ + deutsch: [ "/tools/cli" ], -+ fr: [ ++ french: [ + "/tools/cli" + ] }; diff --git a/components/icons/Icons.mdx b/components/icons/Icons.mdx index cb6496377a38..81743e573ba2 100644 --- a/components/icons/Icons.mdx +++ b/components/icons/Icons.mdx @@ -30,6 +30,7 @@ import IconGuide from './Guide'; import IconHome from './Home'; import IconHub from './Hub'; import InfoIcon from './InfoIcon'; +import IconLanguage from './Language'; import IconLightBulb from './LightBulb'; import IconLinkedIn from './LinkedIn'; import IconLoupe from './Loupe'; @@ -236,6 +237,10 @@ These are the icons used in the AsyncAPI website. + + + + diff --git a/components/icons/Language.tsx b/components/icons/Language.tsx new file mode 100644 index 000000000000..01847ceeaaae --- /dev/null +++ b/components/icons/Language.tsx @@ -0,0 +1,24 @@ +import React from 'react'; + +/* eslint-disable max-len */ +/** + * @description Language Icon for language selector component + */ +export default function IconLanguage({ className = '' }) { + return ( + + + + ); +} diff --git a/components/languageSelector/LanguageSelect.tsx b/components/languageSelector/LanguageSelect.tsx index d2d4f0750514..317dc9809d0f 100644 --- a/components/languageSelector/LanguageSelect.tsx +++ b/components/languageSelector/LanguageSelect.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { twMerge } from 'tailwind-merge'; import type { SelectProps } from '../form/Select'; +import IconLanguage from '../icons/Language'; /** * @description LanguageSelect component for selecting a language. @@ -12,19 +13,25 @@ import type { SelectProps } from '../form/Select'; */ export default function LanguageSelect({ className = '', onChange = () => {}, options = [], selected }: SelectProps) { return ( - +
+
+ {/* Display Icon Next to the Select Box */} + + +
+
); } diff --git a/components/navigation/MobileNavMenu.tsx b/components/navigation/MobileNavMenu.tsx index 8b0ccd740374..29eb933c0b56 100644 --- a/components/navigation/MobileNavMenu.tsx +++ b/components/navigation/MobileNavMenu.tsx @@ -2,6 +2,7 @@ import Link from 'next/link'; import React, { useState } from 'react'; import { SearchButton } from '../AlgoliaSearch'; +import IconLanguage from '../icons/Language'; import NavItemDropdown from '../icons/NavItemDropdown'; import SearchIcon from '../icons/SearchIcon'; import AsyncAPILogo from '../logos/AsyncAPILogo'; @@ -19,13 +20,21 @@ interface MenuItem { interface MobileNavMenuProps { onClickClose?: () => void; + uniqueLangs: { key: string; text: string; value: string }[]; + currentLanguage: string; + changeLanguage: (locale: string, langPicker: boolean) => void; } /** * @description MobileNavMenu component for displaying a responsive navigation menu on mobile devices. * @param {MobileNavMenuProps} props - The props for the MobileNavMenu component. */ -export default function MobileNavMenu({ onClickClose = () => {} }: MobileNavMenuProps) { +export default function MobileNavMenu({ + onClickClose = () => {}, + uniqueLangs, + currentLanguage, + changeLanguage +}: MobileNavMenuProps) { const [open, setOpen] = useState(null); /** @@ -104,7 +113,7 @@ export default function MobileNavMenu({ onClickClose = () => {} }: MobileNavMenu {open === 'community' && } -
showMenu('others')} data-testid='MobileNav-others'> +
showMenu('others')} data-testid='MobileNav-others'>

@@ -127,6 +136,29 @@ export default function MobileNavMenu({ onClickClose = () => {} }: MobileNavMenu

+
showMenu('language')}> +
+
+

+ + Language + + +

+ {open === 'language' && + uniqueLangs.map((lang) => ( + + ))} +
+
+
diff --git a/components/navigation/NavBar.tsx b/components/navigation/NavBar.tsx index d0fd2ca6fa02..f4408dbb059e 100644 --- a/components/navigation/NavBar.tsx +++ b/components/navigation/NavBar.tsx @@ -43,7 +43,7 @@ export default function NavBar({ className = '', hideLogo = false }: NavBarProps /** * Retrieves unique language options based on the current path and i18nPaths configuration. * - * @returns {string[]} - An array of unique language options in uppercase. + * @returns {string[]} - An array of unique language options with first letter in uppercase. */ const getUniqueLangs = (): string[] => { let pathnameWithoutLocale = pathname; @@ -56,10 +56,10 @@ export default function NavBar({ className = '', hideLogo = false }: NavBarProps // Filter unique languages based on i18nPaths that include the modified pathnameWithoutLocale const uniqueLangs = Object.keys(i18nPaths) .filter((lang) => i18nPaths[lang].includes(pathnameWithoutLocale)) - .map((lang) => lang.toUpperCase()); + .map((lang) => lang.charAt(0).toUpperCase() + lang.slice(1)); - // If no unique languages are found, default to ["EN"] - return uniqueLangs.length === 0 ? ['EN'] : uniqueLangs; + // If no unique languages are found, default to ["English"] + return uniqueLangs.length === 0 ? ['English'] : uniqueLangs; }; const uniqueLangs = getUniqueLangs().map((lang) => ({ @@ -147,7 +147,7 @@ export default function NavBar({ className = '', hideLogo = false }: NavBarProps return (
-
+
{!hideLogo && (
@@ -178,7 +178,7 @@ export default function NavBar({ className = '', hideLogo = false }: NavBarProps