nomadweb/frontend/src/lib/toolCopy.ts
eric bdf0516197 Fix dating match gate and expand seed data for usable demos.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-04 06:18:25 -05:00

99 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Locale } from "@/lib/i18n";
import { TOOL_LINKS, type ToolLink } from "@/lib/tools";
type ToolCopy = Record<string, { title: string; desc: string }>;
/** English titles/descriptions for the toolkit catalog (ZH lives on TOOL_LINKS). */
const EN: ToolCopy = {
trip: { title: "Trip planner", desc: "Multi-city routes and budget totals" },
spin: { title: "Destiny wheel", desc: "Randomize your next stop" },
matcher: { title: "Smart matcher", desc: "Quiz-based destination picks" },
season: { title: "Best months", desc: "Avoid rain and peak season" },
weekend: { title: "Weekend ideas", desc: "City activities by energy level" },
"rainy-day": { title: "Rainy-day plan", desc: "Indoor ideas when it pours" },
"day-plan": { title: "Remote day planner", desc: "Block work into a timeline" },
daylight: { title: "Daylight work window", desc: "Sunrise, sunset & deep work" },
calculator: { title: "Cost calculator", desc: "Estimate by housing tier" },
"cost-compare": { title: "Home vs nomad cost", desc: "Compare hometown vs travel costs" },
savings: { title: "Launch fund goal", desc: "Track savings progress" },
runway: { title: "Nomad runway", desc: "How many months can savings last" },
"first-month": { title: "First-month landing cost", desc: "Rent, deposit, SIM in one calc" },
expenses: { title: "Expense ledger", desc: "Categorize and sum spending" },
"bill-split": { title: "Bill split", desc: "Per-person + tip in seconds" },
"invoice-fx": { title: "Invoice FX", desc: "Net after fees and FX" },
tipping: { title: "Tipping cheat sheet", desc: "Local tipping norms" },
laundry: { title: "Laundry day budget", desc: "Estimate by kilo" },
flight: { title: "Flight estimate", desc: "Rough round-trip fare" },
currency: { title: "Currency converter", desc: "Multi-currency convert" },
"tax-days": { title: "Tax-day counter", desc: "Track the 183-day rule" },
timezone: { title: "Timezone board", desc: "Work-hour overlap" },
meetings: { title: "Meeting golden hours", desc: "Align shared meeting windows" },
jetlag: { title: "Jetlag recovery", desc: "Recovery tips after flights" },
sleep: { title: "Sleep cycles", desc: "Back-calculate bedtime" },
wifi: { title: "Wi‑Fi grade", desc: "Is speed enough for remote work" },
workspot: { title: "Workspot cost", desc: "Month pass vs café value" },
"data-budget": { title: "Data budget", desc: "Monthly data and plan tips" },
focus: { title: "Focus timer", desc: "Pomodoro deep work" },
mood: { title: "Mood check-in", desc: "One-minute travel mood log" },
hydration: { title: "Hydration tracker", desc: "Daily water goals by climate" },
coworking: { title: "Coworking", desc: "Popular co-working spaces" },
cafes: { title: "Cafés", desc: "Laptop-friendly coffee shops" },
visa: { title: "Visa guide", desc: "Policy and smart matching" },
"visa-stay": { title: "Stay countdown", desc: "Visa days remaining" },
housing: { title: "Housing guide", desc: "Coliving / apartment options" },
"coliving-qa": { title: "Viewing questions", desc: "Must-ask coliving checklist" },
"deposit-return": { title: "Deposit return checklist", desc: "Checkout without surprises" },
sim: { title: "Connectivity", desc: "SIM / eSIM recommendations" },
plugs: { title: "Power plugs", desc: "Voltage and plug types" },
packing: { title: "Packing list", desc: "Pre-departure checklist" },
"bag-weight": { title: "Bag weight", desc: "Estimate vs airline limits" },
arrival: { title: "Arrival checklist", desc: "First week on the ground" },
"airport-transfer": { title: "Airport transfer", desc: "Cheap / fast / easy ranking" },
phrases: { title: "Survival phrases", desc: "Copy common phrases" },
notes: { title: "City notes", desc: "Private local notes" },
insurance: { title: "Insurance guide", desc: "Compare travel health cover" },
emergency: { title: "Emergency contacts", desc: "First aid and consulates" },
atm: { title: "ATM pitfalls", desc: "Cash and FX tips" },
"food-water": { title: "Food & water", desc: "Stomach and drinking water tips" },
"scam-alerts": { title: "Local scam alerts", desc: "Common tricks at a glance" },
};
const CAT_EN: Record<string, string> = {
all: "🌏 All",
plan: "🗺️ Plan",
money: "💰 Money",
work: "💻 Work",
life: "🌴 Life",
safety: "🛡️ Safety",
};
const CAT_ZH: Record<string, string> = {
all: "🌏 全部",
plan: "🗺️ 规划",
money: "💰 金钱",
work: "💻 工作",
life: "🌴 生活",
safety: "🛡️ 安全",
};
export function localizedToolLinks(locale: Locale): ToolLink[] {
if (locale !== "en") return TOOL_LINKS;
return TOOL_LINKS.map((tool) => {
const copy = EN[tool.id];
if (!copy) return tool;
return { ...tool, title: copy.title, desc: copy.desc };
});
}
export function localizedToolCategories(locale: Locale) {
const labels = locale === "en" ? CAT_EN : CAT_ZH;
return (["all", "plan", "money", "work", "life", "safety"] as const).map((key) => ({
key,
label: labels[key],
}));
}
export function localizedTool(id: string, locale: Locale): ToolLink | undefined {
return localizedToolLinks(locale).find((t) => t.id === id);
}