import { useRouter } from 'next/router' import { GlobeIcon } from '@primer/octicons-react' import { useLanguages } from 'components/context/LanguagesContext' import { useTranslation } from 'components/hooks/useTranslation' import { useUserLanguage } from 'components/hooks/useUserLanguage' import { ActionList, ActionMenu, IconButton, Link } from '@primer/react' type Props = { xs?: boolean mediumOrLower?: boolean } export const LanguagePicker = ({ xs, mediumOrLower }: Props) => { const router = useRouter() const { languages } = useLanguages() const { setUserLanguageCookie } = useUserLanguage() const locale = router.locale || 'en' const { t } = useTranslation('picker') // Remember, in this context `languages` is only the active ones // that are available. I.e. no wip ones. // Also, if the current context has a page and that page has own ideas // about which languages it's available in (e.g. early-access) // it would already have been paired down. const langs = Object.values(languages) if (langs.length < 2) { return null } const selectedLang = languages[locale] // The `router.asPath` will always be without a hash in SSR // So to avoid a hydraration failure on the client, we have to // normalize it to be without the hash. That way the path is treated // in a "denormalized" way. const routerPath = router.asPath.split('#')[0] // languageList is specifically 's which are reused // for menus that behave differently at the breakpoints. const languageList = langs.map((lang) => ( { if (lang.code) { try { setUserLanguageCookie(lang.code) } catch (err) { // You can never be too careful because setting a cookie // can fail. For example, some browser // extensions disallow all setting of cookies and attempts // at the `document.cookie` setter could throw. Just swallow // and move on. console.warn('Unable to set preferred language cookie', err) } } }} > {lang.nativeName || lang.name} )) // At large breakpoints, we return the full with just the languages, // at smaller breakpoints, we return just the with its items so that // the
component can place it inside its own with multiple // groups, language being just one of those groups. return (
{xs ? ( <> {/* XS Mobile Menu */} {t('language_picker_label') + '\n'} {selectedLang.name} {languageList} ) : mediumOrLower ? ( {languageList} ) : ( {languageList} )}
) }