Files
simple-react-app-kit/apps/web/src/i18n/app-language-switcher.tsx
T
2026-09-20 15:52:22 +08:00

92 lines
2.5 KiB
TypeScript

import { Icon } from "@icones/react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuTrigger,
} from "@workspace/ui/components/dropdown-menu"
import { cn } from "@workspace/ui/lib/utils"
import { HeaderActionButton } from "@workspace/blocks/layout"
import { appLocales, isAppLocale, type AppLocaleCountry } from "./app-locales"
import { useAppLocale } from "./app-i18n-provider"
function LocaleFlag({
country,
className,
}: {
className?: string
country: AppLocaleCountry
}) {
return (
<span
aria-hidden="true"
className={cn(
"inline-flex shrink-0 overflow-hidden rounded-full ring-1 ring-foreground/15",
className
)}
>
{country === "CN" ? (
<Icon name="flag:cn-square" className="size-full" />
) : (
<Icon name="flag:us-square" className="size-full" />
)}
</span>
)
}
export function AppLanguageSwitcher() {
const { locale, setLocale } = useAppLocale()
const activeLocale =
appLocales.find((definition) => definition.locale === locale) ??
appLocales[0]
const menuLabel = locale === "zh-Hans" ? "语言" : "Language"
const triggerLabel =
locale === "zh-Hans"
? `切换语言,当前为${activeLocale.label}`
: `Change language, currently ${activeLocale.label}`
return (
<DropdownMenu>
<DropdownMenuTrigger
render={
<HeaderActionButton
aria-label={triggerLabel}
className="rounded-full"
/>
}
>
<LocaleFlag country={activeLocale.country} className="size-6" />
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="w-44"
showArrow={{ cornerRadius: "lg", tailSize: "sm" }}
>
<DropdownMenuRadioGroup
value={locale}
onValueChange={(value) => {
if (isAppLocale(value)) {
setLocale(value)
}
}}
>
<DropdownMenuLabel>{menuLabel}</DropdownMenuLabel>
{appLocales.map((definition) => (
<DropdownMenuRadioItem
key={definition.locale}
className="py-2"
value={definition.locale}
>
<LocaleFlag country={definition.country} className="size-5" />
<span lang={definition.languageTag}>{definition.label}</span>
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
)
}