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 Link from "next/link";
import { usePathname } from "next/navigation";
import { usePathname } from "@/i18n/routing";
import { AnnouncementBar } from "poyraz-ui/organisms";
import { SiteNavbar } from "@/components/site-navbar";
import { NekoFollower } from "@/components/neko-follower";
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";
const AtaturkWidgetModal = dynamic(
@@ -20,6 +22,7 @@ type AppShellProps = {
export function AppShell({ children }: AppShellProps) {
const pathname = usePathname();
const locale = useLocale();
const announcement = ANNOUNCEMENT_ITEMS[0];
const isStandaloneLinksPage =
pathname === "/links" || pathname.startsWith("/links/");
@@ -28,6 +31,9 @@ export function AppShell({ children }: AppShellProps) {
return children;
}
const localizedText = announcement ? getLocalizedValue(announcement.text, locale) : "";
const localizedActionLabel = announcement ? getLocalizedValue(announcement.actionLabel, locale) : "";
return (
<>
<AtaturkWidgetModal />
@@ -40,19 +46,19 @@ export function AppShell({ children }: AppShellProps) {
dismissible={false}
icon={<Icon icon="mdi:sparkles" width={16} height={16} />}
action={
announcement.actionLabel && announcement.actionHref ? (
localizedActionLabel && announcement.actionHref ? (
<Link
href={announcement.actionHref}
target="_blank"
rel="noreferrer"
className="text-xs font-bold underline"
>
{announcement.actionLabel}
{localizedActionLabel}
</Link>
) : null
}
>
{announcement.text}
{localizedText}
</AnnouncementBar>
) : null}
<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 { Modal, ModalContent, ModalTrigger, ModalTitle } from "poyraz-ui/molecules";
import { Skeleton } from "poyraz-ui/atoms";
import { useLocale, useTranslations } from "next-intl";
export function AtaturkWidgetModal() {
const [isLoading, setIsLoading] = useState(true);
const t = useTranslations("AtaturkWidget");
const locale = useLocale();
return (
<Modal>
<ModalTrigger asChild>
<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"
aria-label="Bugünün Atatürk Sözü"
aria-label={t("title")}
>
<div className="relative h-full w-full">
<Image
src="/ataturk.png"
alt="Mustafa Kemal Atatürk"
alt={t("alt")}
fill
sizes="56px"
className="object-cover"
@@ -30,7 +34,7 @@ export function AtaturkWidgetModal() {
</ModalTrigger>
<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 && (
<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 data-ataturk-quote-widget data-language="tr" data-theme="light"></div>
<div data-ataturk-quote-widget data-language={locale} data-theme="light"></div>
<Script
src="https://ataturk-kronolojisi.org/widget/quote.js"
strategy="lazyOnload"
data-language="tr"
data-language={locale}
data-theme="light"
onReady={() => setIsLoading(false)}
/>
+4 -1
View File
@@ -1,8 +1,11 @@
import { Card } from "poyraz-ui/atoms";
import { YOUTUBE_VIDEO_LINKS } from "@/data/youtube-videos";
import { YoutubeLiteEmbed } from "@/components/youtube-lite-embed";
import { useTranslations } from "next-intl";
export function HomeVideosSection() {
const t = useTranslations("Content");
return (
<section className="space-y-2">
<div className="grid gap-2 md:grid-cols-3">
@@ -11,7 +14,7 @@ export function HomeVideosSection() {
key={link}
className="overflow-hidden rounded-sm border-border p-0"
>
<YoutubeLiteEmbed link={link} title="YouTube video oynatici" />
<YoutubeLiteEmbed link={link} title={t("youtubeEmbedTitle")} />
</Card>
))}
</div>
+17 -5
View File
@@ -1,7 +1,13 @@
export type AnnouncementItem = {
export type AnnouncementItem = {
id: string;
text: string;
actionLabel: string;
text: {
tr: string;
en: string;
};
actionLabel: {
tr: string;
en: string;
};
actionHref: string;
};
@@ -10,8 +16,14 @@ export const ENABLE_NEKO_FOLLOWER = true;
export const ANNOUNCEMENT_ITEMS: AnnouncementItem[] = [
{
id: "main-announcement",
text: 'Yeni Projem "Neta" Yayında!',
actionLabel: "İncele ->",
text: {
tr: 'Yeni Projem "Neta" Yayında!',
en: 'My New Project "Neta" is Live!',
},
actionLabel: {
tr: "İncele ->",
en: "Explore ->",
},
actionHref: "https://www.takeneta.com",
},
];
+4
View File
@@ -111,5 +111,9 @@
"email": "Email",
"linkedin": "LinkedIn",
"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",
"linkedin": "LinkedIn",
"instagram": "Instagram"
},
"AtaturkWidget": {
"title": "Bugünün Atatürk Sözü",
"alt": "Mustafa Kemal Atatürk"
}
}