-
-
Notifications
You must be signed in to change notification settings - Fork 762
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: enabling i18n feature for smaller screens #3556
base: master
Are you sure you want to change the base?
Changes from all commits
d152a10
57955e1
6879ec8
eec0f74
9e7a307
ac2f811
616595b
00edd38
3c64066
2e48227
f2fd10f
2e8e958
18aaff7
ecf4f1a
a0e3fe7
86b09fc
b9a7d0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3,10 +3,10 @@ | |||||||||||||||||||||||||||||||||||||||||
We appreciate your valuable contributions to the AsyncAPI website, whether it's adding or improving existing translations. | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
## Table of contents <!-- omit in toc --> | ||||||||||||||||||||||||||||||||||||||||||
- [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 | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
|
@@ -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`. | ||||||||||||||||||||||||||||||||||||||||||
devilkiller-ag marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||
- 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`. | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
|
@@ -54,7 +54,7 @@ Example: | |||||||||||||||||||||||||||||||||||||||||
`ICSFileButton.js` | ||||||||||||||||||||||||||||||||||||||||||
```diff | ||||||||||||||||||||||||||||||||||||||||||
... | ||||||||||||||||||||||||||||||||||||||||||
+ import { useTranslation } from '../../lib/i18n'; | ||||||||||||||||||||||||||||||||||||||||||
+ import { useTranslation } from '../../utils/i18n'; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export default function ICSFButton({ | ||||||||||||||||||||||||||||||||||||||||||
- text = 'Download ICS File', | ||||||||||||||||||||||||||||||||||||||||||
|
@@ -131,10 +131,10 @@ 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/de/newsletter`, it shows the page in the `German` locale. | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
- Add new `JSON` files to the `locales/en` and `locales/de` folder. | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
|
@@ -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,14 +179,14 @@ After adding a new internationalized page, test it to sure the page is being ser | |||||||||||||||||||||||||||||||||||||||||
┗ index.js | ||||||||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
`newsletter/index.js` | ||||||||||||||||||||||||||||||||||||||||||
`newsletter.tsx` | ||||||||||||||||||||||||||||||||||||||||||
```diff | ||||||||||||||||||||||||||||||||||||||||||
... | ||||||||||||||||||||||||||||||||||||||||||
+ import { | ||||||||||||||||||||||||||||||||||||||||||
+ getAllLanguageSlugs, | ||||||||||||||||||||||||||||||||||||||||||
+ getLanguage, | ||||||||||||||||||||||||||||||||||||||||||
+ useTranslation | ||||||||||||||||||||||||||||||||||||||||||
+ } from "../../lib/i18n"; | ||||||||||||||||||||||||||||||||||||||||||
+ } from "../../utils/i18n"; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export default function NewsletterIndexPage() { | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
|
@@ -217,7 +217,7 @@ 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: [ | ||||||||||||||||||||||||||||||||||||||||||
|
@@ -252,14 +252,14 @@ If you want to add a new locale like `fr` to serve pages in the French locale on | |||||||||||||||||||||||||||||||||||||||||
- Copy the existing `JSON` files present in the `en` 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'. | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
`locales` folder structure | ||||||||||||||||||||||||||||||||||||||||||
```diff | ||||||||||||||||||||||||||||||||||||||||||
|
@@ -278,23 +278,23 @@ If you have added the 'fr' locale and translated the 'tools/cli' page, clicking | |||||||||||||||||||||||||||||||||||||||||
+ ┃ ┗ 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", | ||||||||||||||||||||||||||||||||||||||||||
defaultLanguage: "english", | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
namespaces: ["landing-page", "common", "tools"], | ||||||||||||||||||||||||||||||||||||||||||
defaultNamespace: "landing-page", | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+283
to
293
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revert locale names to short forms in examples. Based on the past review comments, we should use short locale codes instead of full names in the examples. module.exports = {
i18n: {
- languages: ["en", "de", "fr"],
+ locales: ["en", "de", "fr"],
- defaultLanguage: "english",
+ defaultLocale: "en",
namespaces: ["landing-page", "common", "tools"],
defaultNamespace: "landing-page",
},
}; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||||||||
- Add new locale routing. | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
`lib/i18nPaths.js` | ||||||||||||||||||||||||||||||||||||||||||
`utils/i18n.ts` | ||||||||||||||||||||||||||||||||||||||||||
```diff | ||||||||||||||||||||||||||||||||||||||||||
const i18nPaths = { | ||||||||||||||||||||||||||||||||||||||||||
en: [ | ||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<svg | ||
xmlns='http://www.w3.org/2000/svg' | ||
fill='none' | ||
viewBox='0 0 24 24' | ||
strokeWidth={1.5} | ||
stroke='currentColor' | ||
className={`size-5 ${className}`} | ||
> | ||
<path | ||
strokeLinecap='round' | ||
strokeLinejoin='round' | ||
d='m10.5 21 5.25-11.25L21 21m-9-3h7.5M3 5.621a48.474 48.474 0 0 1 6-.371m0 0c1.12 0 2.233.038 3.334.114M9 5.25V3m3.334 2.364C11.176 10.658 7.69 15.08 3 17.502m9.334-12.138c.896.061 1.785.147 2.666.257m-4.589 8.495a18.023 18.023 0 0 1-3.827-5.802' | ||
/> | ||
</svg> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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<string | null>(null); | ||
|
||
/** | ||
|
@@ -104,7 +113,7 @@ export default function MobileNavMenu({ onClickClose = () => {} }: MobileNavMenu | |
</h4> | ||
{open === 'community' && <MenuBlocks items={communityItems} />} | ||
</div> | ||
<div className='space-y-2 px-5 py-2' onClick={() => showMenu('others')} data-testid='MobileNav-others'> | ||
<div className='space-y-2 px-5 pt-2' onClick={() => showMenu('others')} data-testid='MobileNav-others'> | ||
<div className='grid gap-4'> | ||
<div> | ||
<h4 className='mb-4 flex justify-between font-medium text-gray-800'> | ||
|
@@ -127,6 +136,29 @@ export default function MobileNavMenu({ onClickClose = () => {} }: MobileNavMenu | |
</div> | ||
</div> | ||
</div> | ||
<div className='space-y-2 px-5 py-2' onClick={() => showMenu('language')}> | ||
<div className='grid gap-4'> | ||
<div> | ||
<h4 className='mb-4 flex justify-between font-medium text-gray-800'> | ||
<a className='flex cursor-pointer items-center gap-x-2'> | ||
Language <IconLanguage /> | ||
</a> | ||
<NavItemDropdown /> | ||
</h4> | ||
{open === 'language' && | ||
uniqueLangs.map((lang) => ( | ||
<button | ||
key={lang.key} | ||
onClick={() => changeLanguage(lang.value.toLowerCase(), true)} | ||
className={`mb-4 ml-2 block w-full rounded-lg py-1 text-start text-sm font-medium leading-6 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-50 ${currentLanguage.toLowerCase() === lang.text.toLowerCase() ? 'text-secondary-500' : ''}`} | ||
data-testid='MobileNav-language-item' | ||
> | ||
{lang.text} | ||
</button> | ||
))} | ||
</div> | ||
</div> | ||
</div> | ||
Comment on lines
+139
to
+161
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve accessibility of the language selection menu. The current implementation has two potential accessibility issues:
Consider this improvement: - <div className='space-y-2 px-5 py-2' onClick={() => showMenu('language')}>
+ <div className='space-y-2 px-5 py-2'>
+ <button
+ onClick={() => showMenu('language')}
+ aria-expanded={open === 'language'}
+ aria-controls="language-menu"
+ className="w-full text-left"
+ >
<div className='grid gap-4'>
<div>
<h4 className='mb-4 flex justify-between font-medium text-gray-800'>
<a className='flex cursor-pointer items-center gap-x-2'>
Language <IconLanguage />
</a>
<NavItemDropdown />
</h4>
- {open === 'language' &&
+ <div
+ id="language-menu"
+ role="menu"
+ className={open === 'language' ? 'block' : 'hidden'}
+ >
uniqueLangs.map((lang) => (
<button
key={lang.key}
onClick={() => changeLanguage(lang.value.toLowerCase(), true)}
+ role="menuitem"
className={`mb-4 ml-2 block w-full rounded-lg py-1 text-start text-sm font-medium leading-6 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-50 ${
currentLanguage.toLowerCase() === lang.text.toLowerCase() ? 'text-secondary-500' : ''
}`}
data-testid='MobileNav-language-item'
>
{lang.text}
</button>
- ))}
+ )}
+ </div>
</div>
</div>
+ </button>
</div>
|
||
</div> | ||
</div> | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,5 +6,5 @@ module.exports = { | |
defaultNamespace: 'landing-page', | ||
react: { useSuspense: false },// this line | ||
}, | ||
|
||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert the changes related to
en
->english
here and in i18n config file since URLs should be having smaller prefixThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I will do that!