feat(i18n): Hebrew locale + full RTL support
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { useLocale } from 'next-intl';
|
||||
import { useLocaleStore } from '@/stores/locale-store';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { flagComponents } from './flag-icons';
|
||||
|
||||
const languages = [
|
||||
{ value: 'auto', label: 'Auto' },
|
||||
{ value: 'cs', label: 'Česky' },
|
||||
{ value: 'sk', label: 'Slovenčina' },
|
||||
{ value: 'da', label: 'Dansk' },
|
||||
@@ -16,6 +16,7 @@ const languages = [
|
||||
{ value: 'fa', label: 'فارسی' },
|
||||
{ value: 'es', label: 'Español' },
|
||||
{ value: 'fr', label: 'Français' },
|
||||
{ value: 'he', label: 'עברית' },
|
||||
{ value: 'it', label: 'Italiano' },
|
||||
{ value: 'hu', label: 'Magyar' },
|
||||
{ value: 'lv', label: 'Latviešu' },
|
||||
@@ -38,13 +39,13 @@ function FlagIcon({ locale }: { locale: string }) {
|
||||
}
|
||||
|
||||
export function LanguageSwitcher({ className }: { className?: string }) {
|
||||
const currentLocale = useLocale();
|
||||
const setLocale = useLocaleStore((state) => state.setLocale);
|
||||
const choice = useLocaleStore((state) => state.locale) || 'auto';
|
||||
const [open, setOpen] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const listRef = useRef<HTMLUListElement>(null);
|
||||
|
||||
const current = languages.find((l) => l.value === currentLocale) ?? languages[0];
|
||||
const current = languages.find((l) => l.value === choice) ?? languages[0];
|
||||
|
||||
// Close on outside click
|
||||
useEffect(() => {
|
||||
@@ -78,7 +79,7 @@ export function LanguageSwitcher({ className }: { className?: string }) {
|
||||
aria-expanded={open}
|
||||
>
|
||||
<FlagIcon locale={current.value} />
|
||||
<span className="flex-1 text-left">{current.label}</span>
|
||||
<span className="flex-1 text-start">{current.label}</span>
|
||||
<ChevronDown className={cn("h-3.5 w-3.5 text-muted-foreground transition-transform duration-150", open && "rotate-180")} />
|
||||
</button>
|
||||
|
||||
@@ -86,22 +87,22 @@ export function LanguageSwitcher({ className }: { className?: string }) {
|
||||
<ul
|
||||
ref={listRef}
|
||||
role="listbox"
|
||||
aria-activedescendant={`lang-${currentLocale}`}
|
||||
className="absolute z-50 mt-1 w-full max-h-60 overflow-auto rounded-md border border-border bg-background shadow-lg py-1"
|
||||
aria-activedescendant={`lang-${choice}`}
|
||||
className="absolute start-0 z-50 mt-1 min-w-full w-max max-w-[min(16rem,80vw)] max-h-60 overflow-auto rounded-md border border-border bg-background shadow-lg py-1"
|
||||
>
|
||||
{languages.map((lang) => (
|
||||
<li
|
||||
key={lang.value}
|
||||
id={`lang-${lang.value}`}
|
||||
role="option"
|
||||
aria-selected={lang.value === currentLocale}
|
||||
aria-selected={lang.value === choice}
|
||||
onClick={() => {
|
||||
setLocale(lang.value);
|
||||
setOpen(false);
|
||||
}}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-3 py-1.5 text-sm cursor-pointer transition-colors duration-100",
|
||||
lang.value === currentLocale
|
||||
"flex items-center gap-2 px-3 py-1.5 text-sm cursor-pointer whitespace-nowrap transition-colors duration-100",
|
||||
lang.value === choice
|
||||
? "bg-accent text-accent-foreground font-medium"
|
||||
: "text-foreground hover:bg-accent/50"
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user