msg: issue-55 - #59
Conversation
❌ Deploy Preview for smartrentsystem failed. Why did it fail? →Built without sensitive environment variables
|
There was a problem hiding this comment.
Pull request overview
This PR aims to add internationalization (i18n) support across the application, with a stated focus on the Safety page. However, the changes extend far beyond just the Safety page to include Terms, ReportConcern, Register, Login, Home, Help, FAQ, Contact, Cancellation, Blog, BecomeHost, Account, and About pages. Translation files have been added for Chinese (zh), Russian (ru), Japanese (ja), and Hindi (hi) locales.
Key Issues Found:
- Critical bugs in Safety.jsx with placeholder comments left in production code
- Invalid JSON structure in multiple translation files (duplicate keys, malformed objects)
- Broken functionality on Register page (removed Terms/Privacy links)
- Massive code deletion on Account page without replacement
- Fragile string manipulation using split(':') that will break with different translations
- Mismatch between PR description (Safety page only) and actual changes (15+ pages)
Reviewed changes
Copilot reviewed 166 out of 166 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/pages/Safety.jsx | Added i18n support but left comment placeholders that break UI rendering |
| frontend/src/pages/Terms.jsx | Added i18n with problematic string splitting logic |
| frontend/src/pages/ReportConcern.jsx | Added i18n translation support |
| frontend/src/pages/Register.jsx | Added i18n but removed critical links to Terms/Privacy documents |
| frontend/src/pages/Login.jsx | Added i18n translation support |
| frontend/src/pages/Home.jsx | Added i18n translation support |
| frontend/src/pages/Help.jsx | Added i18n translation support |
| frontend/src/pages/FAQ.jsx | Added i18n translation support |
| frontend/src/pages/Contact.jsx | Added i18n with duplicate/incorrect translation key usage |
| frontend/src/pages/Cancellation.jsx | Added i18n with fragile string splitting |
| frontend/src/pages/Blog.jsx | Added i18n translation support |
| frontend/src/pages/BecomeHost.jsx | Added i18n translation support |
| frontend/src/pages/Account.jsx | Added partial i18n but deleted entire profile form implementation |
| frontend/src/pages/About.jsx | Added i18n translation support |
| frontend/src/locales/zh/* | Added Chinese translations with duplicate keys and invalid JSON |
| frontend/src/locales/ru/* | Added Russian translations with duplicate keys in FAQ.json |
| frontend/src/locales/ja/* | Added Japanese translations |
| frontend/src/locales/hi/NotFound.json | Added Hindi translation for NotFound page |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| "house": "房子", | ||
| "apartment": "公寓", | ||
| "guesthouse": "民宿", | ||
| "hotel": "酒店", | ||
| "cabin": "小屋", | ||
| "villa": "别墅", | ||
| "beach": "海滩", | ||
| "mountain": "山", | ||
| "city": "城市", | ||
| "countryside": "乡村", | ||
| "lake": "湖泊", | ||
| "desert": "沙漠", | ||
| "wifi": "无线网络", | ||
| "kitchen": "厨房", | ||
| "washer": "洗衣机", | ||
| "dryer": "烘干机", | ||
| "ac": "空调", | ||
| "heating": "暖气", | ||
| "tv": "电视", | ||
| "parking": "免费停车", | ||
| "pool": "游泳池", | ||
| "hottub": "热水浴缸", | ||
| "gym": "健身房", | ||
| "pets": "允许携带宠物", | ||
| "usd": "美元", | ||
| "eur": "欧元", | ||
| "gbp": "英镑", | ||
| "jpy": "日元", | ||
| "cad": "加元", | ||
| "aud": "澳元", | ||
| "inr": "印度卢比" |
There was a problem hiding this comment.
The BecomeHost.json file has malformed structure with a closing brace on line 39 followed by additional property definitions. The JSON structure is invalid and will fail to parse.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| <p className="text-neutral-600">San Francisco, CA 94103</p> | ||
| <p className="text-sm text-neutral-500 mt-1"> | ||
| Visit us during business hours | ||
| {t("officeHours")} |
There was a problem hiding this comment.
Line 60 has "officeHours" translation but it's being used in a context where "Visit us during business hours" should be displayed. The translation key name doesn't match its usage context. Consider renaming to something like "visitDuringBusinessHours" for clarity.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| import React from 'react'; | ||
| import { Link } from 'react-router-dom'; | ||
| import { useTranslation } from 'react-i18next'; | ||
|
|
||
| const Safety = () => { | ||
| const { t } = useTranslation('Safety'); |
There was a problem hiding this comment.
The PR description states this focuses on "fixing language translation" for the Safety page, but the diff shows extensive changes across many pages (Terms, ReportConcern, Register, Login, Home, Help, FAQ, Contact, Cancellation, Blog, BecomeHost, Account, About). This creates a mismatch between what the PR claims to do and what it actually does. Consider splitting this into multiple focused PRs: one for Safety page translation and separate PRs for other pages.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| <li className="flex items-start">{/* ...existing code... */}<span>{t('tipsGuests1')}</span></li> | ||
| <li className="flex items-start">{/* ...existing code... */}<span>{t('tipsGuests2')}</span></li> | ||
| <li className="flex items-start">{/* ...existing code... */}<span>{t('tipsGuests3')}</span></li> | ||
| <li className="flex items-start">{/* ...existing code... */}<span>{t('tipsGuests4')}</span></li> | ||
| <li className="flex items-start">{/* ...existing code... */}<span>{t('tipsGuests5')}</span></li> |
There was a problem hiding this comment.
Comment placeholders like "...existing code..." are left in the rendered output. These should be replaced with the actual SVG icons, otherwise the Safety tips section will display broken markup instead of checkmark icons.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| <p className="mb-2"><strong>{t('email').split(':')[0]}:</strong> {t('email').split(':')[1]}</p> | ||
| <p className="mb-2"><strong>{t('address').split(':')[0]}:</strong> {t('address').split(':')[1]}</p> | ||
| <p><strong>{t('phone').split(':')[0]}:</strong> {t('phone').split(':')[1]}</p> |
There was a problem hiding this comment.
The code is attempting to split translation strings on ':' characters to extract label and value pairs (e.g., t('email').split(':')[0]). This is fragile and will break if the translation doesn't contain a colon, or contains multiple colons. Instead, create separate translation keys for labels and values (e.g., emailLabel and emailValue).
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| <div className="mt-4 pt-4 border-t border-neutral-200"> | ||
| <p className="text-neutral-600 italic"> | ||
| <strong>Host tip:</strong> This policy is good for attracting guests who may be hesitant to commit. It works well for last-minute bookings and locations with high competition. | ||
| <strong>{t('hostTipFlexible', { ns: 'Cancellation' }).split(':')[0]}:</strong> {t('hostTipFlexible')} |
There was a problem hiding this comment.
Similar issue with string splitting - t('hostTipFlexible').split(':')[0] assumes the translation contains a colon. If the translation is structured differently in different languages, this will break. Use separate translation keys for the label portion and the description portion.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| {t("signInToExisting", "Or sign in to your existing account")} {" "} | ||
| <Link | ||
| to="/login" | ||
| className="font-medium text-primary-600 hover:text-primary-500" | ||
| > | ||
| sign in to your existing account | ||
| {t("signInToExistingLink", "sign in to your existing account")} | ||
| </Link> |
There was a problem hiding this comment.
The translation implementation for the "Register" link is problematic. It provides default fallback text in the t() function calls, but for "signInToExisting" it includes the link text "sign in to your existing account" plus extra text. Then it adds the link component separately with another translation "signInToExistingLink". This creates redundant and confusing translation keys. Consolidate to use a single approach with Trans component for parts containing links.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| > | ||
| Privacy Policy | ||
| </Link> | ||
| {t("agreeTerms", "I agree to the Terms of Service and Privacy Policy")} |
There was a problem hiding this comment.
The Register page removes the actual links to Terms of Service and Privacy Policy and replaces them with just translated text. Users can no longer click through to read these important documents. This is a functional regression that breaks user experience and may have legal compliance implications.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| {t("profileInformation")} | ||
| </h2> | ||
|
|
||
| <form onSubmit={handleSubmitProfile}> | ||
| <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> | ||
| <div> | ||
| <label | ||
| htmlFor="firstName" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| First name | ||
| </label> | ||
| <input | ||
| type="text" | ||
| id="firstName" | ||
| name="firstName" | ||
| value={userData.firstName} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| /> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label | ||
| htmlFor="lastName" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| Last name | ||
| </label> | ||
| <input | ||
| type="text" | ||
| id="lastName" | ||
| name="lastName" | ||
| value={userData.lastName} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| /> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label | ||
| htmlFor="email" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| Email address | ||
| </label> | ||
| <input | ||
| type="email" | ||
| id="email" | ||
| name="email" | ||
| value={userData.email} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| disabled | ||
| /> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label | ||
| htmlFor="phone" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| Phone number | ||
| </label> | ||
| <input | ||
| type="tel" | ||
| id="phone" | ||
| name="phone" | ||
| value={userData.phone} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| /> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label | ||
| htmlFor="dateOfBirth" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| Date of birth | ||
| </label> | ||
| <input | ||
| type="date" | ||
| id="dateOfBirth" | ||
| name="dateOfBirth" | ||
| value={userData.dateOfBirth} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| /> | ||
| </div> | ||
| </div> | ||
|
|
||
| <h3 className="text-lg font-medium text-neutral-900 mt-8 mb-4"> | ||
| Address | ||
| </h3> | ||
|
|
||
| <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> | ||
| <div className="md:col-span-2"> | ||
| <label | ||
| htmlFor="street" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| Street address | ||
| </label> | ||
| <input | ||
| type="text" | ||
| id="street" | ||
| name="address.street" | ||
| value={userData.address.street} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| /> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label | ||
| htmlFor="city" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| City | ||
| </label> | ||
| <input | ||
| type="text" | ||
| id="city" | ||
| name="address.city" | ||
| value={userData.address.city} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| /> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label | ||
| htmlFor="state" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| State / Province | ||
| </label> | ||
| <input | ||
| type="text" | ||
| id="state" | ||
| name="address.state" | ||
| value={userData.address.state} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| /> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label | ||
| htmlFor="zipCode" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| ZIP / Postal code | ||
| </label> | ||
| <input | ||
| type="text" | ||
| id="zipCode" | ||
| name="address.zipCode" | ||
| value={userData.address.zipCode} | ||
| onChange={handleUserDataChange} | ||
| className="appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| /> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label | ||
| htmlFor="country" | ||
| className="block text-sm font-medium text-neutral-700 mb-1" | ||
| > | ||
| Country | ||
| </label> | ||
| <select | ||
| id="country" | ||
| name="address.country" | ||
| value={userData.address.country} | ||
| onChange={handleUserDataChange} | ||
| className="mt-1 block w-full py-2 px-3 border border-neutral-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm" | ||
| > | ||
| <option>United States</option> | ||
| <option>Canada</option> | ||
| <option>Mexico</option> | ||
| <option>United Kingdom</option> | ||
| </select> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="mt-8 flex justify-end"> | ||
| <button | ||
| type="submit" | ||
| className="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500" | ||
| > | ||
| Save changes | ||
| </button> | ||
| </div> | ||
| </form> | ||
| </div> | ||
| )} | ||
|
|
||
| {/* Payment Methods */} | ||
| {activeTab === "payment" && ( | ||
| <div className="p-6"> | ||
| <h2 className="text-xl font-semibold text-neutral-900 mb-6"> | ||
| Payment Methods | ||
| </h2> | ||
|
|
||
| {paymentMethods.length > 0 ? ( | ||
| <div className="space-y-4 mb-8"> | ||
| {paymentMethods.map((method) => ( | ||
| <div | ||
| key={method.id} | ||
| className={`border rounded-lg p-4 ${ | ||
| method.isDefault | ||
| ? "border-primary-500 bg-primary-50" | ||
| : "border-neutral-200" | ||
| }`} | ||
| > | ||
| <div className="flex items-center justify-between"> | ||
| <div className="flex items-center"> | ||
| {method.brand === "Visa" && ( | ||
| <svg | ||
| className="h-8 w-12 text-primary-500" | ||
| viewBox="0 0 48 32" | ||
| fill="currentColor" | ||
| > | ||
| <path d="M44 0H4C1.8 0 0 1.8 0 4v24c0 2.2 1.8 4 4 4h40c2.2 0 4-1.8 4-4V4c0-2.2-1.8-4-4-4zm0 28H4V4h40v24z" /> | ||
| <path d="M13 15.1l2.8-6.8h2L15.1 16h-2.1l-2.7-7.7h2l.7 7.8zm7.6 1.2c-1.7 0-3-1.3-3-3s1.3-3 3-3 3 1.3 3 3-1.3 3-3 3zm0-4.3c-.7 0-1.3.6-1.3 1.3s.6 1.3 1.3 1.3 1.3-.6 1.3-1.3-.6-1.3-1.3-1.3zm7 4.3c-1.7 0-3-1.3-3-3s1.3-3 3-3 3 1.3 3 3c0 1.6-1.4 3-3 3zm0-4.3c-.7 0-1.3.6-1.3 1.3s.6 1.3 1.3 1.3 1.3-.6 1.3-1.3-.6-1.3-1.3-1.3z" /> | ||
| </svg> | ||
| )} | ||
|
|
||
| {method.brand === "Mastercard" && ( | ||
| <svg | ||
| className="h-8 w-12 text-primary-500" | ||
| viewBox="0 0 48 32" | ||
| fill="currentColor" | ||
| > | ||
| <path | ||
| d="M4 0C1.8 0 0 1.8 0 4v24c0 2.2 1.8 4 4 4h40c2.2 0 4-1.8 4-4V4c0-2.2-1.8-4-4-4H4z" | ||
| fillOpacity=".2" | ||
| /> | ||
| <path d="M44 0H4C1.8 0 0 1.8 0 4v24c0 2.2 1.8 4 4 4h40c2.2 0 4-1.8 4-4V4c0-2.2-1.8-4-4-4zM44 28H4V4h40v24z" /> | ||
| <path | ||
| d="M24 23c3.9 0 7-3.1 7-7s-3.1-7-7-7-7 3.1-7 7 3.1 7 7 7z" | ||
| fillOpacity=".7" | ||
| /> | ||
| <path | ||
| d="M24 23c3.9 0 7-3.1 7-7s-3.1-7-7-7V23z" | ||
| fillOpacity=".5" | ||
| /> | ||
| </svg> | ||
| )} | ||
|
|
||
| <div className="ml-3"> | ||
| <div className="text-sm font-medium text-neutral-900"> | ||
| {method.brand} ending in {method.last4} | ||
| </div> | ||
| <div className="text-xs text-neutral-500"> | ||
| Expires {method.expMonth}/{method.expYear} | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="flex items-center"> | ||
| {method.isDefault ? ( | ||
| <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-primary-100 text-primary-800"> | ||
| Default | ||
| </span> | ||
| ) : ( | ||
| <button | ||
| onClick={() => | ||
| handleSetDefaultPaymentMethod(method.id) | ||
| } | ||
| className="text-sm text-primary-600 hover:text-primary-700 mr-4" | ||
| > | ||
| Set as default | ||
| </button> | ||
| )} | ||
|
|
||
| <button | ||
| onClick={() => | ||
| handleRemovePaymentMethod(method.id) | ||
| } | ||
| className="text-sm text-red-600 hover:text-red-700 ml-4" | ||
| > | ||
| Remove | ||
| </button> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| ) : ( | ||
| <div className="text-center py-8 border border-dashed border-neutral-300 rounded-md mb-8"> | ||
| <svg | ||
| className="mx-auto h-12 w-12 text-neutral-400" | ||
| fill="none" | ||
| viewBox="0 0 24 24" | ||
| stroke="currentColor" | ||
| > | ||
| <path | ||
| strokeLinecap="round" | ||
| strokeLinejoin="round" | ||
| strokeWidth="2" | ||
| d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" | ||
| /> | ||
| </svg> | ||
| <h3 className="mt-2 text-sm font-medium text-neutral-900"> | ||
| No payment methods | ||
| </h3> | ||
| <p className="mt-1 text-sm text-neutral-500"> | ||
| Add a payment method to easily book properties. | ||
| </p> | ||
| </div> | ||
| )} | ||
|
|
||
| <button className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"> | ||
| Add payment method | ||
| </button> | ||
| {/* Profile form and content here */} |
There was a problem hiding this comment.
The Account page has a massive deletion of actual implementation code (lines 398-720+ removed), leaving only a comment "Profile form and content here". This breaks the entire profile editing functionality. If this was intentional for refactoring, the new implementation is missing from this PR.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| "city-tours": "城市游览", | ||
| "city-toursDesc": "与本地导游一起探索", | ||
| "outdoor-adventures": "户外探险", | ||
| "outdoor-adventuresDesc": "与本地导游一起探索", | ||
| "local-cuisine": "当地美食", | ||
| "local-cuisineDesc": "与本地导游一起探索", | ||
| "heroTitle": "寻找<1>像家一样</1>的住宿", | ||
| "heroDescription": "发现全球独特的住房、公寓和体验——为舒适、风格和难忘的回忆精心挑选。", | ||
| "exploreStays": "探索住宿", | ||
| "becomeHost": "成为房东", | ||
|
|
||
| "inspirationTitle": "为您的下一个旅程寻找灵感", | ||
| "inspirationSubtitle": "探索热门目的地,享受完美度假租赁", | ||
|
|
||
| "newYork": "纽约", | ||
| "newYorkProperties": "120套房源", | ||
| "losAngeles": "洛杉矶", | ||
| "losAngelesProperties": "94套房源", | ||
| "miami": "迈阿密", | ||
| "miamiProperties": "85套房源", | ||
| "chicago": "芝加哥", | ||
| "chicagoProperties": "73套房源", | ||
|
|
||
| "stayAnywhereTitle": "随处可住", | ||
| "stayAnywhereSubtitle": "适合各种风格和预算的独特住宿", | ||
| "apartments": "公寓", | ||
| "apartmentsDesc": "都市舒适", | ||
| "houses": "房屋", | ||
| "housesDesc": "整套住宅", | ||
| "cabins": "小木屋", | ||
| "cabinsDesc": "质朴静谧", | ||
| "villas": "别墅", | ||
| "villasDesc": "奢华住宿", | ||
|
|
||
| "discoverExperiencesTitle": "发现体验", | ||
| "discoverExperiencesSubtitle": "寻找由本地专家主办的活动", | ||
| "cityTours": "城市游览", | ||
| "cityToursDesc": "与本地导游一起探索", | ||
| "outdoorAdventures": "户外探险", | ||
| "outdoorAdventuresDesc": "与本地导游一起探索", | ||
| "localCuisine": "当地美食", | ||
| "localCuisineDesc": "与本地导游一起探索", | ||
|
|
||
| "becomeAHostTitle": "成为房东", | ||
| "becomeAHostDesc": "分享您的空间,赚取额外收入,与来自世界各地的客人建立联系。", | ||
| "learnMore": "了解更多", | ||
| "city-tours": "城市游览", | ||
| "city-toursDesc": "与本地导游一起探索", | ||
| "outdoor-adventures": "户外探险", | ||
| "outdoor-adventuresDesc": "与本地导游一起探索", | ||
| "local-cuisine": "当地美食", | ||
| "local-cuisineDesc": "与本地导游一起探索" |
There was a problem hiding this comment.
The Home.json translation file has duplicate keys for city tours, outdoor adventures, and local cuisine (lines 2-7 and 48-53). This creates invalid JSON that will cause parsing issues or unpredictable behavior.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
name: "📦 fixing lanugage translation"
about: Submit changes for review
title: "PR: fixing lanugage translation"
labels: "SWoC26"
assignees: @"AnimeshRajwar"
📌 Linked Issue
Closes #55
🛠 Changes Made
-Created modular Safety.json translation files for all supported languages.
-Registered the Safety namespace in the i18n configuration for all languages.
-Refactored Safety.jsx to use translation keys for all user-facing text.
🧪 Testing
npm test)📸 UI Changes (if applicable)
📝 Documentation Updates
✅ Checklist
💡 Additional Notes (If any)