From d7b5b81b5d6ec55d0847b5171c3800a8f7b5c001 Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Tue, 7 Oct 2025 17:25:43 -0700 Subject: feat: add i18n translation (initial JP and EN) --- site/src/components/LanguageSwitcher.tsx | 109 +++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 site/src/components/LanguageSwitcher.tsx (limited to 'site/src/components/LanguageSwitcher.tsx') diff --git a/site/src/components/LanguageSwitcher.tsx b/site/src/components/LanguageSwitcher.tsx new file mode 100644 index 0000000..8cceb35 --- /dev/null +++ b/site/src/components/LanguageSwitcher.tsx @@ -0,0 +1,109 @@ +import { useTranslation } from 'react-i18next'; +import { useSearchParams } from 'react-router-dom'; +import { useRef, useState, useEffect } from 'react'; + +const languages = [ + { code: 'en', name: 'English' }, + { code: 'ja', name: '日本語' } +]; + +interface LanguageSwitcherProps { + variant?: 'compact' | 'standard'; +} + +function LanguageSwitcher({ variant = 'standard' }: LanguageSwitcherProps) { + const { i18n } = useTranslation(); + const [searchParams] = useSearchParams(); + const isMoe = searchParams.has("moe"); + const [isOpen, setIsOpen] = useState(false); + const dropdownRef = useRef(null); + + const currentLanguage = languages.find(lang => lang.code === i18n.language) || languages[0]; + + // Close the dropdown when clicking outside + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { + setIsOpen(false); + } + }; + + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, []); + + return ( +
+ + + {isOpen && ( +
+
+ {languages.map((lang) => ( + + ))} +
+
+ )} +
+ ); +} + +export default LanguageSwitcher; -- cgit v1.2.3