From 8c470e23a60c2ce7e21ad2996d39b06fb34329eb Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Wed, 22 Apr 2026 18:32:09 +0900 Subject: [PATCH 1/3] feat: add locale toggle on heritage detail Wire toggleLocale callback from container to layout, render a flag button in the tab bar, and switch HeritageHero between Japanese and English titles based on locale. --- .../heritage-detail/HeritageDetailLayout.tsx | 13 +++++++++++-- .../components/heritage-detail/HeritageHero.tsx | 6 +++--- .../containers/world-heritage-detail-container.tsx | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 7 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 1191158..2679b43 100644 --- a/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx +++ b/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx @@ -15,6 +15,7 @@ import { BreadcrumbList } from "@shared/components/BreadcrumbList.tsx"; type Props = { item: WorldHeritageDetailVm; locale: Locale; + toggleLocale: () => void; }; const DEFAULT_SEARCH: SearchValues = { @@ -96,7 +97,7 @@ function KeyExamInfo({ item }: { item: WorldHeritageDetailVm }) { ); } -export function HeritageDetailLayout({ item, locale }: Props) { +export function HeritageDetailLayout({ item, locale, toggleLocale }: Props) { const [search, setSearch] = useState(DEFAULT_SEARCH); const setLabel = useSetBreadcrumbLabel(); @@ -115,7 +116,15 @@ export function HeritageDetailLayout({ item, locale }: Props) {
- +
+ + +
diff --git a/client/src/app/features/top/components/heritage-detail/HeritageHero.tsx b/client/src/app/features/top/components/heritage-detail/HeritageHero.tsx index 1f378cf..c287805 100644 --- a/client/src/app/features/top/components/heritage-detail/HeritageHero.tsx +++ b/client/src/app/features/top/components/heritage-detail/HeritageHero.tsx @@ -6,7 +6,7 @@ type Props = { locale: Locale; }; -export function HeritageHero({ item }: Props) { +export function HeritageHero({ item, locale }: Props) { const primaryImage: WorldHeritageImageVm | undefined = item.images.find((img) => img.isPrimary) ?? item.images[0]; @@ -14,8 +14,8 @@ export function HeritageHero({ item }: Props) {

- {item.heritageNameJp} - {item.name && ( + {locale === "ja" && item.heritageNameJp ? item.heritageNameJp : item.name} + {locale === "ja" && item.heritageNameJp && item.name && ( ({item.name}) diff --git a/client/src/app/features/top/containers/world-heritage-detail-container.tsx b/client/src/app/features/top/containers/world-heritage-detail-container.tsx index ea25291..9c78c75 100644 --- a/client/src/app/features/top/containers/world-heritage-detail-container.tsx +++ b/client/src/app/features/top/containers/world-heritage-detail-container.tsx @@ -13,9 +13,19 @@ function resolveLocale(raw: string | null): Locale { export function WorldHeritageDetailContainer() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); - const [searchParams] = useSearchParams(); + const [searchParams, setSearchParams] = useSearchParams(); const locale = useMemo(() => resolveLocale(searchParams.get("lang")), [searchParams]); + const toggleLanguageLocation = () => { + const theOther = locale === "ja" ? "en" : "ja"; + setSearchParams((prev) => { + const nowLocal = new URLSearchParams(prev); + nowLocal.set("lang", theOther); + + return nowLocal; + }); + }; + useEffect(() => { if (!id) navigate("/heritages", { replace: true }); }, [id, navigate]); @@ -51,5 +61,5 @@ export function WorldHeritageDetailContainer() { ); } - return ; + return ; } From cff933d8248698dd704c41ef9253adfeec3f5b75 Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Wed, 22 Apr 2026 18:32:38 +0900 Subject: [PATCH 2/3] feat: render Japanese short description on heritage detail Branch on locale in the overview section to show shortDescriptionJp when ja locale is active, falling back to the English shortDescription otherwise. Plumb locale through HeritageDetailLayout and update fixtures accordingly. --- .../mappers/__tests__/to-world-heritage-vm.test.ts | 1 + .../components/heritage-detail/HeritageDetailLayout.tsx | 2 +- .../components/heritage-detail/HeritageOverviewSection.tsx | 7 +++++-- .../__tests__/world-heritage-detail-container.test.tsx | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/client/src/app/features/heritages/mappers/__tests__/to-world-heritage-vm.test.ts b/client/src/app/features/heritages/mappers/__tests__/to-world-heritage-vm.test.ts index da79ac7..00eeac2 100644 --- a/client/src/app/features/heritages/mappers/__tests__/to-world-heritage-vm.test.ts +++ b/client/src/app/features/heritages/mappers/__tests__/to-world-heritage-vm.test.ts @@ -19,6 +19,7 @@ const base: ApiWorldHeritageDto = { area_hectares: 442, buffer_zone_hectares: 320, short_description: "desc", + short_description_jp: "ダミー", unesco_site_url: "https://whc.unesco.org/en/list/663", state_party: "JPN", state_party_codes: ["JPN"], 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 2679b43..bd9bf39 100644 --- a/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx +++ b/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx @@ -145,7 +145,7 @@ export function HeritageDetailLayout({ item, locale, toggleLocale }: Props) {
{/* Left: Overview → Gallery */}
- +
diff --git a/client/src/app/features/top/components/heritage-detail/HeritageOverviewSection.tsx b/client/src/app/features/top/components/heritage-detail/HeritageOverviewSection.tsx index 2b722df..5d97514 100644 --- a/client/src/app/features/top/components/heritage-detail/HeritageOverviewSection.tsx +++ b/client/src/app/features/top/components/heritage-detail/HeritageOverviewSection.tsx @@ -3,9 +3,10 @@ import { textType } from "@shared/styles/typography.ts"; type Props = { item: WorldHeritageDetailVm; + locale: string; }; -export function HeritageOverViewSection({ item }: Props) { +export function HeritageOverViewSection({ item, locale }: Props) { return (
- {item.shortDescription} + {locale === "ja" && item.shortDescriptionJp + ? item.shortDescriptionJp + : item.shortDescription}

) : (

—

diff --git a/client/src/app/features/top/containers/__tests__/world-heritage-detail-container.test.tsx b/client/src/app/features/top/containers/__tests__/world-heritage-detail-container.test.tsx index f5c1945..d84a9bb 100644 --- a/client/src/app/features/top/containers/__tests__/world-heritage-detail-container.test.tsx +++ b/client/src/app/features/top/containers/__tests__/world-heritage-detail-container.test.tsx @@ -145,6 +145,7 @@ describe("WorldHeritageDetailContainer", () => { latitude: null, longitude: null, shortDescription: "dummy", + shortDescriptionJp: "ダミー", unescoSiteUrl: "https://example.com", statePartyCodes: [], statePartiesMeta: {}, From 6695fec980c1c4b40bdb5c23043b408bc0e58a5b Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Wed, 22 Apr 2026 18:33:20 +0900 Subject: [PATCH 3/3] feat: navigate to results page on detail search submit Build a URLSearchParams from the current search values and push to /heritages/results when the sub-header form is submitted so submissions from the detail page reach the results view instead of staying in place. --- .../heritage-detail/HeritageDetailLayout.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 bd9bf39..c794974 100644 --- a/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx +++ b/client/src/app/features/top/components/heritage-detail/HeritageDetailLayout.tsx @@ -1,4 +1,5 @@ import { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; import type { WorldHeritageDetailVm } from "../../../../../domain/types.ts"; import type { Locale } from "../../../../../domain/criteria"; import { HeritageSubHeader } from "../HeritageSubHeader.tsx"; @@ -100,10 +101,20 @@ function KeyExamInfo({ item }: { item: WorldHeritageDetailVm }) { export function HeritageDetailLayout({ item, locale, toggleLocale }: Props) { const [search, setSearch] = useState(DEFAULT_SEARCH); const setLabel = useSetBreadcrumbLabel(); + const navigate = useNavigate(); const handleSubmit = (q: Partial) => { const next = { ...search, ...q }; setSearch(next); + + const params = new URLSearchParams(); + if (next.keyword) params.set("search_query", next.keyword); + if (next.region) params.set("region", next.region); + if (next.category) params.set("category", next.category); + if (next.yearInscribedFrom) params.set("year_inscribed_from", next.yearInscribedFrom); + if (next.yearInscribedTo) params.set("year_inscribed_to", next.yearInscribedTo); + + navigate(`/heritages/results?${params.toString()}`); }; useEffect(() => {