This commit is contained in:
Your Name committed 2026-06-20 18:39:03 -04:00
1 parent 3c4bb06003
commit f7aa4d099f
36 files changed
+528 -180

No files matched your search

@@ -7,11 +7,13 @@ import i18n from '../lib/i18n';
export default function ClientProviders({ children }: { children: ReactNode }) {
useEffect(() => {
const savedLang = localStorage.getItem('homaroma_lang')
// Hydrate from the user's persisted language only after the first client render.
if (savedLang && savedLang !== i18n.language) {
void i18n.changeLanguage(savedLang)
// With Locale Routing, the URL is the source of truth for language.
// Sync i18n to match the current URL if needed.
const pathLang = window.location.pathname.split('/')[1];
const targetLang = pathLang && ['th', 'en', 'ja', 'zh', 'vi', 'ko'].includes(pathLang) ? pathLang : 'th';
if (targetLang !== i18n.language) {
void i18n.changeLanguage(targetLang);
}
}, [])
+1 -1
View File
@@ -1,7 +1,7 @@
"use client";
import { useState, useEffect } from 'react'
import Link from 'next/link'
import Link from './LocalizedLink'
import type { Category, MenuItem, StoreSettings } from '@homaroma/types'
import { useTranslation } from 'react-i18next'
import { resolveLocalized } from '../lib/localization'
@@ -0,0 +1,63 @@
'use client';
import Link, { LinkProps } from 'next/link';
import { usePathname } from 'next/navigation';
import { useMemo } from 'react';
import { getPathWithLocale, SUPPORTED_LOCALES } from '../lib/locales';
interface LocalizedLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps>, LinkProps {
children: React.ReactNode;
activeClassName?: string;
exact?: boolean;
}
export default function LocalizedLink({
href,
children,
className = '',
activeClassName = '',
exact = false,
...props
}: LocalizedLinkProps) {
const pathname = usePathname();
// Extract current locale from pathname
const currentLocale = useMemo(() => {
const segments = pathname.split('/').filter(Boolean);
if (segments.length > 0 && SUPPORTED_LOCALES.includes(segments[0] as any)) {
return segments[0];
}
return 'th'; // Fallback
}, [pathname]);
// Resolve the localized href
const localizedHref = useMemo(() => {
if (typeof href === 'string') {
return getPathWithLocale(href, currentLocale);
}
if (typeof href === 'object' && href.pathname) {
return {
...href,
pathname: getPathWithLocale(href.pathname, currentLocale)
};
}
return href;
}, [href, currentLocale]);
// Check if link is active
const isActive = useMemo(() => {
const targetPath = typeof localizedHref === 'string' ? localizedHref : localizedHref.pathname || '';
if (exact) {
return pathname === targetPath;
}
return pathname.startsWith(targetPath) && targetPath !== `/${currentLocale}`;
}, [pathname, localizedHref, exact, currentLocale]);
const combinedClassName = `${className} ${isActive ? activeClassName : ''}`.trim();
return (
<Link href={localizedHref} className={combinedClassName} {...props}>
{children}
</Link>
);
}
+8 -1
View File
@@ -1,6 +1,7 @@
"use client"
import Link from 'next/link'
import Link from './LocalizedLink'
import { getPathWithoutLocale, getPathWithLocale } from '../lib/locales'
import { useRouter, usePathname } from 'next/navigation'
import { useState, useEffect, useMemo, useRef } from 'react'
import type { Category } from '@homaroma/types'
@@ -89,7 +90,13 @@ export default function Navbar({ categories = [], initialMenu = [], settings = n
const changeLanguage = (code: string) => {
i18n.changeLanguage(code)
localStorage.setItem('homaroma_lang', code)
document.cookie = `homaroma_lang=${code}; path=/; max-age=31536000`
const currentPathWithoutLang = getPathWithoutLocale(pathname)
const newPath = getPathWithLocale(currentPathWithoutLang, code)
setLangSheetOpen(false)
router.push(newPath)
}
const loginWithLine = () => {
@@ -1,6 +1,6 @@
"use client"
import Link from 'next/link'
import Link from '../LocalizedLink'
import { useState, useRef } from 'react'
import type { MegaMenuPayload } from './menuTypes'
import { getLocalizedMenuText } from './menuTypes'
@@ -1,7 +1,7 @@
"use client"
import { useEffect, useState } from 'react'
import Link from 'next/link'
import Link from '../LocalizedLink'
import { ChevronLeft, ChevronRight, Globe, X } from 'lucide-react'
import type { MegaMenuPayload, MenuColumn, MenuLink } from './menuTypes'
import { getLocalizedMenuText } from './menuTypes'