feat(i18n): localize global app shell announcement bar and widgets

This commit is contained in:
Poyraz
2026-06-27 15:32:18 +03:00
parent d0d3c17ba6
commit 79b37e209a
6 changed files with 49 additions and 16 deletions
+10 -4
View File
@@ -2,11 +2,13 @@
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import Link from "next/link"; import Link from "next/link";
import { usePathname } from "next/navigation"; import { usePathname } from "@/i18n/routing";
import { AnnouncementBar } from "poyraz-ui/organisms"; import { AnnouncementBar } from "poyraz-ui/organisms";
import { SiteNavbar } from "@/components/site-navbar"; import { SiteNavbar } from "@/components/site-navbar";
import { NekoFollower } from "@/components/neko-follower"; import { NekoFollower } from "@/components/neko-follower";
import { ANNOUNCEMENT_ITEMS, ENABLE_NEKO_FOLLOWER } from "@/data/site-settings"; import { ANNOUNCEMENT_ITEMS, ENABLE_NEKO_FOLLOWER } from "@/data/site-settings";
import { useLocale } from "next-intl";
import { getLocalizedValue } from "@/lib/locale";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
const AtaturkWidgetModal = dynamic( const AtaturkWidgetModal = dynamic(
@@ -20,6 +22,7 @@ type AppShellProps = {
export function AppShell({ children }: AppShellProps) { export function AppShell({ children }: AppShellProps) {
const pathname = usePathname(); const pathname = usePathname();
const locale = useLocale();
const announcement = ANNOUNCEMENT_ITEMS[0]; const announcement = ANNOUNCEMENT_ITEMS[0];
const isStandaloneLinksPage = const isStandaloneLinksPage =
pathname === "/links" || pathname.startsWith("/links/"); pathname === "/links" || pathname.startsWith("/links/");
@@ -28,6 +31,9 @@ export function AppShell({ children }: AppShellProps) {
return children; return children;
} }
const localizedText = announcement ? getLocalizedValue(announcement.text, locale) : "";
const localizedActionLabel = announcement ? getLocalizedValue(announcement.actionLabel, locale) : "";
return ( return (
<> <>
<AtaturkWidgetModal /> <AtaturkWidgetModal />
@@ -40,19 +46,19 @@ export function AppShell({ children }: AppShellProps) {
dismissible={false} dismissible={false}
icon={<Icon icon="mdi:sparkles" width={16} height={16} />} icon={<Icon icon="mdi:sparkles" width={16} height={16} />}
action={ action={
announcement.actionLabel && announcement.actionHref ? ( localizedActionLabel && announcement.actionHref ? (
<Link <Link
href={announcement.actionHref} href={announcement.actionHref}
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="text-xs font-bold underline" className="text-xs font-bold underline"
> >
{announcement.actionLabel} {localizedActionLabel}
</Link> </Link>
) : null ) : null
} }
> >
{announcement.text} {localizedText}
</AnnouncementBar> </AnnouncementBar>
) : null} ) : null}
<main className="flex-1 py-4">{children}</main> <main className="flex-1 py-4">{children}</main>
+10 -6
View File
@@ -5,22 +5,26 @@ import Script from "next/script";
import Image from "next/image"; import Image from "next/image";
import { Modal, ModalContent, ModalTrigger, ModalTitle } from "poyraz-ui/molecules"; import { Modal, ModalContent, ModalTrigger, ModalTitle } from "poyraz-ui/molecules";
import { Skeleton } from "poyraz-ui/atoms"; import { Skeleton } from "poyraz-ui/atoms";
import { useLocale, useTranslations } from "next-intl";
export function AtaturkWidgetModal() { export function AtaturkWidgetModal() {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const t = useTranslations("AtaturkWidget");
const locale = useLocale();
return ( return (
<Modal> <Modal>
<ModalTrigger asChild> <ModalTrigger asChild>
<button <button
type="button" type="button"
title="Bugünün Atatürk Sözü" title={t("title")}
className="fixed bottom-4 left-4 z-50 flex h-14 w-14 items-center justify-center overflow-hidden rounded-full border-2 border-red-600 bg-background shadow-lg transition-transform hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2" className="fixed bottom-4 left-4 z-50 flex h-14 w-14 items-center justify-center overflow-hidden rounded-full border-2 border-red-600 bg-background shadow-lg transition-transform hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
aria-label="Bugünün Atatürk Sözü" aria-label={t("title")}
> >
<div className="relative h-full w-full"> <div className="relative h-full w-full">
<Image <Image
src="/ataturk.png" src="/ataturk.png"
alt="Mustafa Kemal Atatürk" alt={t("alt")}
fill fill
sizes="56px" sizes="56px"
className="object-cover" className="object-cover"
@@ -30,7 +34,7 @@ export function AtaturkWidgetModal() {
</ModalTrigger> </ModalTrigger>
<ModalContent className="flex flex-col justify-center p-6 sm:max-w-[425px] min-h-[160px] transition-all duration-300"> <ModalContent className="flex flex-col justify-center p-6 sm:max-w-[425px] min-h-[160px] transition-all duration-300">
<ModalTitle className="sr-only">Bugünün Atatürk Sözü</ModalTitle> <ModalTitle className="sr-only">{t("title")}</ModalTitle>
{isLoading && ( {isLoading && (
<div className="flex w-full flex-col space-y-3"> <div className="flex w-full flex-col space-y-3">
@@ -44,11 +48,11 @@ export function AtaturkWidgetModal() {
)} )}
<div className={`w-full ${isLoading ? "hidden" : "block"}`}> <div className={`w-full ${isLoading ? "hidden" : "block"}`}>
<div data-ataturk-quote-widget data-language="tr" data-theme="light"></div> <div data-ataturk-quote-widget data-language={locale} data-theme="light"></div>
<Script <Script
src="https://ataturk-kronolojisi.org/widget/quote.js" src="https://ataturk-kronolojisi.org/widget/quote.js"
strategy="lazyOnload" strategy="lazyOnload"
data-language="tr" data-language={locale}
data-theme="light" data-theme="light"
onReady={() => setIsLoading(false)} onReady={() => setIsLoading(false)}
/> />
+4 -1
View File
@@ -1,8 +1,11 @@
import { Card } from "poyraz-ui/atoms"; import { Card } from "poyraz-ui/atoms";
import { YOUTUBE_VIDEO_LINKS } from "@/data/youtube-videos"; import { YOUTUBE_VIDEO_LINKS } from "@/data/youtube-videos";
import { YoutubeLiteEmbed } from "@/components/youtube-lite-embed"; import { YoutubeLiteEmbed } from "@/components/youtube-lite-embed";
import { useTranslations } from "next-intl";
export function HomeVideosSection() { export function HomeVideosSection() {
const t = useTranslations("Content");
return ( return (
<section className="space-y-2"> <section className="space-y-2">
<div className="grid gap-2 md:grid-cols-3"> <div className="grid gap-2 md:grid-cols-3">
@@ -11,7 +14,7 @@ export function HomeVideosSection() {
key={link} key={link}
className="overflow-hidden rounded-sm border-border p-0" className="overflow-hidden rounded-sm border-border p-0"
> >
<YoutubeLiteEmbed link={link} title="YouTube video oynatici" /> <YoutubeLiteEmbed link={link} title={t("youtubeEmbedTitle")} />
</Card> </Card>
))} ))}
</div> </div>
+17 -5
View File
@@ -1,7 +1,13 @@
export type AnnouncementItem = { export type AnnouncementItem = {
id: string; id: string;
text: string; text: {
actionLabel: string; tr: string;
en: string;
};
actionLabel: {
tr: string;
en: string;
};
actionHref: string; actionHref: string;
}; };
@@ -10,8 +16,14 @@ export const ENABLE_NEKO_FOLLOWER = true;
export const ANNOUNCEMENT_ITEMS: AnnouncementItem[] = [ export const ANNOUNCEMENT_ITEMS: AnnouncementItem[] = [
{ {
id: "main-announcement", id: "main-announcement",
text: 'Yeni Projem "Neta" Yayında!', text: {
actionLabel: "İncele ->", tr: 'Yeni Projem "Neta" Yayında!',
en: 'My New Project "Neta" is Live!',
},
actionLabel: {
tr: "İncele ->",
en: "Explore ->",
},
actionHref: "https://www.takeneta.com", actionHref: "https://www.takeneta.com",
}, },
]; ];
+4
View File
@@ -111,5 +111,9 @@
"email": "Email", "email": "Email",
"linkedin": "LinkedIn", "linkedin": "LinkedIn",
"instagram": "Instagram" "instagram": "Instagram"
},
"AtaturkWidget": {
"title": "Atatürk's Quote of the Day",
"alt": "Mustafa Kemal Atatürk"
} }
} }
+4
View File
@@ -111,5 +111,9 @@
"email": "E-posta", "email": "E-posta",
"linkedin": "LinkedIn", "linkedin": "LinkedIn",
"instagram": "Instagram" "instagram": "Instagram"
},
"AtaturkWidget": {
"title": "Bugünün Atatürk Sözü",
"alt": "Mustafa Kemal Atatürk"
} }
} }