From 36de3ee4b4309ace60d2f7d7bdc69faf7e7c4e54 Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Thu, 30 Apr 2026 09:49:00 +0900 Subject: [PATCH 1/4] feat: add useText hook for locale-aware UI strings Introduce per-locale UI string dictionaries under src/locals/{en,ja}/ui.json and a useText hook in src/shared/locale that picks the dictionary off the active locale from useLocale. Components can now read UI labels from a single typed source instead of hard-coding English strings. Co-Authored-By: Claude Opus 4.7 (1M context) --- client/src/locals/en/ui.json | 16 ++++++++++++++++ client/src/locals/ja/ui.json | 16 ++++++++++++++++ client/src/shared/locale/ui-text.ts | 13 +++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 client/src/locals/en/ui.json create mode 100644 client/src/locals/ja/ui.json create mode 100644 client/src/shared/locale/ui-text.ts diff --git a/client/src/locals/en/ui.json b/client/src/locals/en/ui.json new file mode 100644 index 0000000..04acca6 --- /dev/null +++ b/client/src/locals/en/ui.json @@ -0,0 +1,16 @@ +{ + "heritageCategory": "Heritage Category", + "criteria": "Criteria", + "viewDetails": "View details", + "danger": "DANGER", + "noImage": "No image", + "noOverview": "No overview available.", + "region": "Region", + "category": "Category", + "yearInscribed": "Year Inscribed", + "description": "Description", + "maps": "Maps", + "gallery": "Gallery", + "overview": "Overview", + "viewOnUnesco": "View on UNESCO" +} diff --git a/client/src/locals/ja/ui.json b/client/src/locals/ja/ui.json new file mode 100644 index 0000000..b44d404 --- /dev/null +++ b/client/src/locals/ja/ui.json @@ -0,0 +1,16 @@ +{ + "heritageCategory": "遺産カテゴリ", + "criteria": "登録基準", + "viewDetails": "詳細を見る", + "danger": "危機", + "noImage": "画像なし", + "noOverview": "概要はありません。", + "region": "地域", + "category": "カテゴリ", + "yearInscribed": "登録年", + "description": "説明", + "maps": "地図", + "gallery": "ギャラリー", + "overview": "概要", + "viewOnUnesco": "UNESCO で見る" +} diff --git a/client/src/shared/locale/ui-text.ts b/client/src/shared/locale/ui-text.ts new file mode 100644 index 0000000..29a9c43 --- /dev/null +++ b/client/src/shared/locale/ui-text.ts @@ -0,0 +1,13 @@ +import en from "../../locals/en/ui.json"; +import ja from "../../locals/ja/ui.json"; +import { type Locale } from "../../domain/criteria.ts"; +import { useLocale } from "./LocaleHooks.ts"; + +export type UiText = typeof en; + +const TEXTS: Record = { en, ja }; + +export const useText = (): UiText => { + const { locale } = useLocale(); + return TEXTS[locale]; +}; From 861c5671157924004b2969e915409c21740f9f2b Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Thu, 30 Apr 2026 09:56:01 +0900 Subject: [PATCH 2/4] refactor: localize HeritageCard via useText and useLocale Pull static labels (DANGER, No image, Heritage Category, Criteria, View details, No overview available) through useText so the card follows the active locale, and fix the title fallback so it returns item.name in EN mode instead of always favouring heritageNameJp. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../app/features/top/cards/HeritageCard.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/client/src/app/features/top/cards/HeritageCard.tsx b/client/src/app/features/top/cards/HeritageCard.tsx index c1139a8..d816e1a 100644 --- a/client/src/app/features/top/cards/HeritageCard.tsx +++ b/client/src/app/features/top/cards/HeritageCard.tsx @@ -1,6 +1,8 @@ import type { ReactNode, MouseEvent } from "react"; import type { WorldHeritageVm, CriteriaCode } from "../../../../domain/types.ts"; import { BaseCard } from "@shared/uis/BaseCard.tsx"; +import { useLocale } from "@shared/locale/LocaleHooks.ts"; +import { useText } from "@shared/locale/ui-text.ts"; function MetaChip({ children }: { children: ReactNode }) { return ( @@ -40,6 +42,9 @@ export function HeritageCard({ item: WorldHeritageVm; onClickItem?: (id: number) => void; }) { + const { locale } = useLocale(); + const t = useText(); + const goDetail = () => { if (!onClickItem) return; onClickItem(item.id); @@ -54,7 +59,7 @@ export function HeritageCard({ goDetail(); }; - const title = item.heritageNameJp || "World Heritage"; + const title = locale === "ja" && item.heritageNameJp ? item.heritageNameJp : item.name; const subtitle = item.subtitle ?? ""; const desc = (item.shortDescription ?? "").trim(); @@ -74,7 +79,7 @@ export function HeritageCard({ /> ) : (
- No image + {t.noImage}
)} @@ -83,7 +88,7 @@ export function HeritageCard({ {item.isEndangered && (
- DANGER + {t.danger}
)} @@ -101,7 +106,7 @@ export function HeritageCard({ {item.category && (
- Heritage Category + {t.heritageCategory}
{item.category} @@ -112,7 +117,7 @@ export function HeritageCard({ {criteria.length > 0 && (
- Criteria + {t.criteria}
{criteria.map((c: CriteriaCode) => ( @@ -134,7 +139,7 @@ export function HeritageCard({ {desc}

) : ( -

No overview available.

+

{t.noOverview}

)}
From 68a54810fc8f48b53982d088f2b8a3031bb60f65 Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Thu, 30 Apr 2026 10:04:28 +0900 Subject: [PATCH 3/4] refactor: localize heritage detail components via useText Pull static labels (Region, Category, Year Inscribed, Criteria, Description, Maps, Gallery, Overview, View on UNESCO) through useText in HeritageDetailLayout, HeritageHero, HeritageOverViewSection, and HeritageSidebar so the detail screen follows the active locale. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../heritage-detail/HeritageDetailLayout.tsx | 24 ++++++++++--------- .../heritage-detail/HeritageHero.tsx | 4 +++- .../HeritageOverviewSection.tsx | 6 +++-- .../heritage-detail/HeritageSidebar.tsx | 6 +++-- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx b/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx index 7302450..fc565de 100644 --- a/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx +++ b/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx @@ -11,6 +11,7 @@ import { textType } from "@shared/styles/typography"; import { useSetBreadcrumbLabel } from "@features/breadcrumbs/BreadCrumbHooks.ts"; import { BreadcrumbList } from "@shared/components/BreadcrumbList.tsx"; import { useLocale } from "@shared/locale/LocaleHooks.ts"; +import { useText } from "@shared/locale/ui-text.ts"; const DEFAULT_SEARCH: SearchValues = { region: "", @@ -20,12 +21,6 @@ const DEFAULT_SEARCH: SearchValues = { yearInscribedTo: "", }; -const TABS: readonly { label: string; href: `#${string}` }[] = [ - { label: "Description", href: "#content" }, - { label: "Maps", href: "#geo-map" }, - { label: "Gallery", href: "#gallery" }, -] as const; - const formatCriteriaInline = (criteria: string[] | undefined) => criteria?.length ? criteria.map((c) => `(${c})`).join("") : "—"; @@ -59,30 +54,31 @@ function HeritageDetailTabs({ // Key exam info: visible without scrolling on all screen sizes. function KeyExamInfo({ item }: { item: WorldHeritageDetailVm }) { + const t = useText(); return (
- Region + {t.region}
{item.region ?? "—"}
- Category + {t.category}
{item.category ?? "—"}
- Year Inscribed + {t.yearInscribed}
{item.yearInscribed ?? "—"}
- Criteria + {t.criteria}
{formatCriteriaInline(item.criteria)} @@ -98,6 +94,12 @@ export function HeritageDetailLayout({ item }: { item: WorldHeritageDetailVm }) const setLabel = useSetBreadcrumbLabel(); const navigate = useNavigate(); const { locale, toggleLocale } = useLocale(); + const t = useText(); + const tabs: readonly { label: string; href: `#${string}` }[] = [ + { label: t.description, href: "#content" }, + { label: t.maps, href: "#geo-map" }, + { label: t.gallery, href: "#gallery" }, + ]; const handleSubmit = (q: Partial) => { const next = { ...search, ...q }; @@ -124,7 +126,7 @@ export function HeritageDetailLayout({ item }: { item: WorldHeritageDetailVm })
- +
From 4324a835ce3b7dbd40c845f79c01cdfd2bcb319b Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Thu, 30 Apr 2026 16:02:46 +0900 Subject: [PATCH 4/4] fix: const naming changed --- client/src/app/features/top/cards/HeritageCard.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/src/app/features/top/cards/HeritageCard.tsx b/client/src/app/features/top/cards/HeritageCard.tsx index d816e1a..81857af 100644 --- a/client/src/app/features/top/cards/HeritageCard.tsx +++ b/client/src/app/features/top/cards/HeritageCard.tsx @@ -43,7 +43,7 @@ export function HeritageCard({ onClickItem?: (id: number) => void; }) { const { locale } = useLocale(); - const t = useText(); + const text = useText(); const goDetail = () => { if (!onClickItem) return; @@ -79,7 +79,7 @@ export function HeritageCard({ /> ) : (
- {t.noImage} + {text.noImage}
)} @@ -88,7 +88,7 @@ export function HeritageCard({ {item.isEndangered && (
- {t.danger} + {text.danger}
)} @@ -106,7 +106,7 @@ export function HeritageCard({ {item.category && (
- {t.heritageCategory} + {text.heritageCategory}
{item.category} @@ -117,7 +117,7 @@ export function HeritageCard({ {criteria.length > 0 && (
- {t.criteria} + {text.criteria}
{criteria.map((c: CriteriaCode) => ( @@ -139,7 +139,7 @@ export function HeritageCard({ {desc}

) : ( -

{t.noOverview}

+

{text.noOverview}

)}