Next.js客户端渲染:如何用next-intl实现映射数据的动态翻译
Next.js next-intl 动态卡片数据国际化翻译实现方案
我是Next.js新手,使用客户端渲染结合next-intl做国际化,目前已完成静态文本(如标题、按钮)的翻译,但在遍历apartmentData生成卡片组件时,不知道如何动态翻译card.title、card.rating、card.locationText等字段。
现有组件代码
"use client"; import { useState } from "react"; import Slider from "react-slick"; import "slick-carousel/slick/slick.css"; import "slick-carousel/slick/slick-theme.css"; import { useTranslations } from "next-intl"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faDollarSign, faStar, faLocationDot, faChevronLeft, faChevronRight, } from "@fortawesome/free-solid-svg-icons"; import apartmentData from "../apartmentData"; export default function CardSlider() { const [sliderRef, setSliderRef] = useState(null); const t = useTranslations("Popular Apartments"); const sliderSettings = { arrows: false, slidesToShow: 3, responsive: [ { breakpoint: 1280, settings: { slidesToShow: 2, }, }, { breakpoint: 900, settings: { slidesToShow: 1, }, }, ], }; const cards = apartmentData; return ( <div> <div> <div> <h2>{t("section title")}</h2> <div> <button onClick={sliderRef?.slickPrev}> <FontAwesomeIcon icon={faChevronLeft} color="white" /> </button> <button onClick={sliderRef?.slickNext}> <FontAwesomeIcon icon={faChevronRight} color="white" /> </button> </div> </div> <Slider ref={setSliderRef} {...sliderSettings}> {cards.map((card, index) => ( <div key={index}> <div style={{ backgroundImage: `url(${card.imageSrc})` }}></div> <div> <div> <h5>{card.title}</h5> <div> <FontAwesomeIcon icon={faStar} /> <span className="ml-2 font-bold">{card.rating}</span> </div> </div> <div> <div> <div> <FontAwesomeIcon icon={faLocationDot} /> </div> <div>{card.locationText}</div> </div> <div> <div> <FontAwesomeIcon icon={faDollarSign} className="h-3 w-6" /> </div> <div>{card.pricingText}</div> </div> </div> <p>{card.description}</p> </div> <button>{t("btn")}</button> </div> ))} </Slider> </div> </div> ); }
已完成的静态翻译
<h2>{t("section title")}</h2> <button>{t("btn")}</button>
现有bhs.json翻译文件
{ "Popular Apartments": { "section title": "Popularni Apartmani", "btn": "Rezervišite", "cards": [ { "title": "Soho Paradise", "rating": "4.9", "locationText": "Ibiza, Španija", "pricingText": "USD 50/dan", "description": "fantastičan pogled na more" }, { "title": "Hotel Baja", "rating": "5.0", "locationText": "Palo Alto, CA", "pricingText": "USD 19/dan", "description": "najbolje ocenjen smeštaj" }, { "title": "Hudak Homes", "rating": "4.5", "locationText": "Arizoa, RAK", "pricingText": "USD 99/dan", "description": "cela vila za one sa dubokim džepom" }, { "title": "Wyatt Residency", "rating": "4.8", "locationText": "Rim, Italija", "pricingText": "USD 39/dan", "description": "sakriven dragulj u srcu Rima" } ] } }
解决方案
方案1:通过数组索引匹配翻译(快速适配现有结构)
利用next-intl的路径访问语法,直接通过遍历的index定位到翻译文件中对应位置的卡片内容:
修改卡片遍历的代码片段:
{cards.map((card, index) => ( <div key={index}> <div style={{ backgroundImage: `url(${card.imageSrc})` }}></div> <div> <div> <h5>{t(`cards[${index}].title`)}</h5> <div> <FontAwesomeIcon icon={faStar} /> <span className="ml-2 font-bold">{t(`cards[${index}].rating`)}</span> </div> </div> <div> <div> <div> <FontAwesomeIcon icon={faLocationDot} /> </div> <div>{t(`cards[${index}].locationText`)}</div> </div> <div> <div> <FontAwesomeIcon icon={faDollarSign} className="h-3 w-6" /> </div> <div>{t(`cards[${index}].pricingText`)}</div> </div> </div> <p>{t(`cards[${index}].description`)}</p> </div> <button>{t("btn")}</button> </div> ))}
注意:此方案依赖apartmentData和翻译文件中cards数组的顺序完全一致,若后续数据顺序调整,翻译会对应错误。
方案2:通过唯一ID匹配翻译(更可靠)
为了避免顺序依赖问题,给每个卡片添加唯一标识,修改数据结构和翻译文件:
- 更新apartmentData.js,给每个卡片对象添加
id字段:
export default [ { id: "soho-paradise", imageSrc: "your-image-url", title: "Soho Paradise", // ...其他原有字段 }, { id: "hotel-baja", imageSrc: "your-image-url", title: "Hotel Baja", // ...其他原有字段 }, // ...剩余卡片 ];
- 修改bhs.json,将
cards从数组改为对象,用id作为键:
{ "Popular Apartments": { "section title": "Popularni Apartmani", "btn": "Rezervišite", "cards": { "soho-paradise": { "title": "Soho Paradise", "rating": "4.9", "locationText": "Ibiza, Španija", "pricingText": "USD 50/dan", "description": "fantastičan pogled na more" }, "hotel-baja": { "title": "Hotel Baja", "rating": "5.0", "locationText": "Palo Alto, CA", "pricingText": "USD 19/dan", "description": "najbolje ocenjen smeštaj" }, // ...剩余卡片翻译 } } }
- 修改组件中的遍历代码:
{cards.map((card) => ( <div key={card.id}> <div style={{ backgroundImage: `url(${card.imageSrc})` }}></div> <div> <div> <h5>{t(`cards.${card.id}.title`)}</h5> <div> <FontAwesomeIcon icon={faStar} /> <span className="ml-2 font-bold">{t(`cards.${card.id}.rating`)}</span> </div> </div> <div> <div> <div> <FontAwesomeIcon icon={faLocationDot} /> </div> <div>{t(`cards.${card.id}.locationText`)}</div> </div> <div> <div> <FontAwesomeIcon icon={faDollarSign} className="h-3 w-6" /> </div> <div>{t(`cards.${card.id}.pricingText`)}</div> </div> </div> <p>{t(`cards.${card.id}.description`)}</p> </div> <button>{t("btn")}</button> </div> ))}
此方案不受数据顺序影响,更适合长期维护。
内容的提问来源于stack exchange,提问作者IvanaS
相关产品推荐
相关产品推荐

