| 1 | import { pickText } from "@/lib/i18n/dictionaries"; |
| 2 | import { MERCH_TARGET_PRICE } from "@/lib/merch/catalog"; |
| 3 | |
| 4 | /** Merch copy uses the site's shared en/zh content bridge; other locales fall back to English. */ |
| 5 | const text = { |
| 6 | title: { en: "Open source, worn out loud.", zh: "把开源精神,穿在身上。" }, |
| 7 | description: { en: "For the people building with Codewhale. Everyday solids, an ocean-wave mascot hoodie and one ombré option; a soft mascot companion in development; expressive art for your desk and a contributor edition at cost.", zh: "给和 Codewhale 一起创造的人。日常纯色、海浪吉祥物卫衣,还有一款渐变;正在筹备的毛绒吉祥物、热闹的桌面图案,以及按成本提供的贡献者款。" }, |
| 8 | launchTitle: { en: "Everyday staples. Mascot favorites.", zh: "日常基础款,也有吉祥物。" }, |
| 9 | launchBody: { en: "Eight apparel styles, led by everyday staples and the blue wave-and-stars mascot hoodie. The seated plush doll joins the planned collection, with its prototype next. Tide stays the single ombré option.", zh: "八款服饰,日常基础款搭配蓝色海浪与星星的吉祥物卫衣。坐姿毛绒娃娃也加入计划中的系列,下一步先做实物样品。海潮款仍是唯一的渐变设计。" }, |
| 10 | launchAlt: { en: "Six Codewhale apparel concepts in two color choices each: solid Signature and Classic cotton tees, Whale Bro cotton tees, solid Signature polos, solid Everyday fleece hoodies, and Tide ombré jersey tees.", zh: "六款 Codewhale 服饰概念,每款两种配色:纯色日常款与经典款棉 T 恤、鲸鱼兄弟棉 T 恤、纯色 Polo 衫、纯色抓绒卫衣,以及海潮渐变 T 恤。" }, |
| 11 | launchPriceNote: { en: "Fabric and print samples come first. Each garment will have its own price and destination shipping quote.", zh: "先确认面料与印花样品,再分别确定每款服饰的售价和目的地运费。" }, |
| 12 | lineupTitle: { en: "The first-drop shortlist.", zh: "首批款式候选。" }, |
| 13 | lineupBody: { en: "Six solid styles, the Ocean Wave mascot hoodie with a White alternative, and one ombré tee. Two proposed options per style: sixteen combinations before sizes. The doll is a separate planned product, with a prototype before orders.", zh: "六款纯色、海浪吉祥物卫衣(另有白色款),以及一款渐变 T 恤。每款提出两种选择,共十六种组合,再分别选择尺码。娃娃作为单独筹备的产品,先完成实物样品,再开放订购。" }, |
| 14 | mascotTitle: { en: "Ocean waves. Our blue-haired mascot.", zh: "海浪与星星,蓝发吉祥物。" }, |
| 15 | mascotBody: { en: "The cobalt hoodie with flowing pale-blue waves and stars leads the mascot edition. Keep the original saluting character, 誓死效忠 Codewhale badge and codewhale.net. A White hoodie and solid mascot tees complete the choices.", zh: "钴蓝衣身、浅蓝海浪与星星,是吉祥物系列的主打卫衣。保留原来的敬礼角色、「誓死效忠 Codewhale」徽章与 codewhale.net。另有白色卫衣与纯色吉祥物 T 恤。" }, |
| 16 | mascotAlt: { en: "Original Codewhale mascot hoodie concepts: White and cobalt-blue Ocean Wave hoodies, with pale-blue waves and stars on the blue option and the centered saluting character badge on both.", zh: "原来的 Codewhale 吉祥物卫衣概念:白色与钴蓝海浪款。蓝色款印有浅蓝海浪与星星,两款正中都保留敬礼角色徽章。" }, |
| 17 | mascotLink: { en: "Meet the mascot edition", zh: "看看吉祥物款" }, |
| 18 | mascotTee: { en: "Mascot Tee", zh: "吉祥物 T 恤" }, |
| 19 | mascotHoodie: { en: "Ocean Wave Mascot Hoodie", zh: "海浪吉祥物卫衣" }, |
| 20 | mascotLayout: { en: "One centered character badge, 誓死效忠 Codewhale and website", zh: "一个正中的角色徽章,搭配誓死效忠 Codewhale 与网址" }, |
| 21 | mascotTeeColors: { en: "White / cobalt", zh: "白色 / 钴蓝" }, |
| 22 | mascotHoodieColors: { en: "Ocean Wave / White", zh: "蓝色海浪 / 白色" }, |
| 23 | mascotHoodieLayout: { en: "Flowing waves and stars around the centered mascot badge; plain White alternative", zh: "海浪与星星围绕正中的吉祥物徽章,另有纯白款" }, |
| 24 | mascotCotton: { en: "Cotton tee; colorful badge print to be sampled", zh: "棉 T 恤,彩色徽章印花待样品确认" }, |
| 25 | mascotLightweight: { en: "Lightweight stretch-polyester scuba; all-over print", zh: "轻薄聚酯弹力空气层面料,全幅印花" }, |
| 26 | colorLabel: { en: "Color options · concepts", zh: "候选配色 · 概念" }, |
| 27 | whaleBroTee: { en: "Whale Bro Tee", zh: "鲸鱼兄弟 T 恤" }, |
| 28 | tideTee: { en: "Tide Ombré Tee", zh: "海潮渐变 T 恤" }, |
| 29 | whaleBroLayout: { en: "Compact whale, 鲸鱼兄弟, Codewhale and website", zh: "简洁小鲸、鲸鱼兄弟、Codewhale 与网址" }, |
| 30 | tideLayout: { en: "Small left-chest signature on the single gradient design", zh: "唯一渐变款,搭配左胸小标志" }, |
| 31 | ombreDirection: { en: "Stretch-polyester jersey for the budget gradient option", zh: "聚酯弹力针织面料,用作平价渐变款" }, |
| 32 | signatureColors: { en: "White / navy", zh: "白色 / 深蓝" }, |
| 33 | classicColors: { en: "Ivory / cobalt", zh: "象牙白 / 钴蓝" }, |
| 34 | whaleBroColors: { en: "White / ice blue", zh: "白色 / 冰蓝" }, |
| 35 | poloColors: { en: "Navy / ivory", zh: "深蓝 / 象牙白" }, |
| 36 | hoodieColors: { en: "Charcoal / navy", zh: "炭灰 / 深蓝" }, |
| 37 | tideColors: { en: "Lagoon / Daybreak", zh: "浅海 / 晨光" }, |
| 38 | styleLabel: { en: "Style", zh: "款式" }, |
| 39 | printLabel: { en: "Print layout", zh: "印花位置" }, |
| 40 | fabricLabel: { en: "Fabric direction · samples pending", zh: "面料方向 · 待样品确认" }, |
| 41 | signatureTee: { en: "Signature Tee", zh: "日常款 T 恤" }, |
| 42 | classicTee: { en: "Classic Tee", zh: "经典款 T 恤" }, |
| 43 | tidePolo: { en: "Signature Polo", zh: "日常款 Polo 衫" }, |
| 44 | signatureHoodie: { en: "Everyday Hoodie", zh: "日常抓绒卫衣" }, |
| 45 | classicHoodie: { en: "Classic Hoodie", zh: "经典款卫衣" }, |
| 46 | signatureLayout: { en: "Small left-chest whale, name and website", zh: "左胸小鲸、名字与网址" }, |
| 47 | classicLayout: { en: "Centered whale, name and website", zh: "正中小鲸、名字与网址" }, |
| 48 | poloLayout: { en: "Small left-chest signature, clear of the buttons", zh: "左胸小标志,避开纽扣" }, |
| 49 | cottonDirection: { en: "Solid cotton tee with a simple flat print", zh: "纯色棉 T 恤,搭配简洁单色印花" }, |
| 50 | poloDirection: { en: "Solid stretch-polyester polo with a small flat print", zh: "纯色聚酯弹力 Polo 衫,搭配小印花" }, |
| 51 | hoodieDirection: { en: "Heavier polyester fleece; solid body and a small flat print", zh: "较厚聚酯抓绒,纯色衣身搭配小印花" }, |
| 52 | paletteNote: { en: "Everyday solids, one blue wave-and-stars hoodie, and one Tide gradient tee. Only Tide uses Lagoon (aqua → navy) or Daybreak (ivory → cobalt). Colors are concepts; exact fabric, variants and print need samples.", zh: "日常纯色、一款蓝色海浪星星卫衣,以及一款海潮渐变 T 恤。只有海潮款采用浅海配色(浅水蓝 → 深蓝)或晨光配色(象牙白 → 钴蓝)。配色为概念,具体面料、款式和印花需用实物样品确认。" }, |
| 53 | fitLink: { en: "Compare garment measurements", zh: "对比成衣尺寸" }, |
| 54 | launchLink: { en: "Explore the full lineup", zh: "看看完整系列" }, |
| 55 | archiveTitle: { en: "More layouts and earlier studies", zh: "其他版式与之前的设计" }, |
| 56 | archiveBody: { en: "These print studies remain useful references. The White cotton tee price review below belongs to the earlier configured garment; it does not price every color or the polo, hoodie and ombré tee.", zh: "这些印花版式保留作参考。下方白色棉 T 恤的价格确认属于之前配置的服饰方案,不代表所有配色、Polo 衫、卫衣或渐变 T 恤的价格。" }, |
| 57 | preparing: { en: "Preparing the first drop. Samples before sales.", zh: "首批周边筹备中,先确认实物样品,再开售。" }, |
| 58 | merch: { en: "Merch", zh: "周边" }, |
| 59 | browse: { en: "Explore the tees", zh: "看看 T 恤" }, |
| 60 | heroTitle: { en: "Codewhale Signature", zh: "Codewhale 日常款" }, |
| 61 | heroBody: { en: "A little whale beside the name. Small on the chest, easy to wear every day.", zh: "名字旁边,一只小鲸。胸前小小的图案,日常穿着刚刚好。" }, |
| 62 | heroAlt: { en: "Six everyday Codewhale shirt concepts: Signature, Wordmark, Classic, Field, Ocean line and use codewhale., with different colors and print placements.", zh: "六款日常 Codewhale T 恤概念:日常款、字标款、经典款、前后印款、海平线款和 use codewhale.,展示不同颜色与印花位置。" }, |
| 63 | collection: { en: "Codewhale, every day.", zh: "日常穿 Codewhale。" }, |
| 64 | collectionBody: { en: "Small chest prints, clean wordmarks and the classic whale. Start with Signature or Classic; the other layouts give you more ways to wear Codewhale.", zh: "胸前小图案、简洁字标,还有经典的小鲸。先看看日常款和经典款,再选一种你喜欢的 Codewhale 穿法。" }, |
| 65 | colorNote: { en: "Color studies above; ordering begins with reviewed white-tee prints. Field has two print placements and needs a separate quote.", zh: "上图为配色探索;订购先从确认过的白色 T 恤印花开始。前后印款有两个印花位置,需要单独报价。" }, |
| 66 | classicTitle: { en: "Codewhale Classic", zh: "Codewhale 经典款" }, |
| 67 | classicBody: { en: "The whale and the name, centered. A familiar Codewhale tee for a meetup or an ordinary Tuesday.", zh: "小鲸和名字,放在正中间。去聚会,或普通的一天,都可以穿 Codewhale。" }, |
| 68 | wordmarkTitle: { en: "Codewhale Wordmark", zh: "Codewhale 字标款" }, |
| 69 | wordmarkBody: { en: "Just Codewhale and the website. Clean type, no extra story.", zh: "只印 Codewhale 和网址。简洁的字,不必多说。" }, |
| 70 | oceanTitle: { en: "Ocean line", zh: "海平线款" }, |
| 71 | oceanBody: { en: "A small whale, the name, one quiet line. Plenty of space around it.", zh: "一只小鲸,一个名字,一条安静的线。四周,留一点空白。" }, |
| 72 | pocketTitle: { en: "use codewhale. · small chest print", zh: "use codewhale. · 胸前小印花" }, |
| 73 | pocketBody: { en: "The invitation, kept small. Whale, words and website on the left chest.", zh: "把邀请,印得小一点。小鲸、文字和网址,都在左胸。" }, |
| 74 | community: { en: "A little more personality.", zh: "再添一点个性。" }, |
| 75 | communityBody: { en: "Whale Bro, a build-time joke, or a larger use codewhale. print. The same simple apparel direction.", zh: "鲸鱼兄弟、编译时的笑话,或更大的 use codewhale. 印花。依然是简洁的日常服饰。" }, |
| 76 | whaleBroTitle: { en: "Whale Bro", zh: "鲸鱼兄弟" }, |
| 77 | whaleBroBody: { en: "The community nickname, with a small whale and Codewhale signature.", zh: "社区里的昵称,配一只小鲸和 Codewhale 的署名。" }, |
| 78 | select: { en: "Review this tee", zh: "查看这款 T 恤" }, |
| 79 | selected: { en: "Selected design", zh: "已选图案" }, |
| 80 | targetPrice: { en: "Target tee price: ¥{cny} in mainland China · US${usd} elsewhere", zh: "T 恤目标售价:中国大陆 ¥{cny} · 其他地区 US${usd}" }, |
| 81 | priceNote: { en: "Shipping is separate. Final pricing depends on the approved print; delivery and tax notes are reviewed before payment.", zh: "运费单独显示。最终价格以确认的印刷方案为准,付款前会说明配送与税费情况。" }, |
| 82 | designNote: { en: "Artwork previews are concepts. Print details, fit and availability need a production proof.", zh: "图案预览为设计概念,印刷细节、版型与供货需要生产样品确认。" }, |
| 83 | compilingTitle: { en: "Compiling…", zh: "编译中……" }, |
| 84 | compilingBody: { en: "Quiet type for the time between builds.", zh: "把编译的等待,留给一行安静的文字。" }, |
| 85 | useTitle: { en: "use codewhale.", zh: "use codewhale." }, |
| 86 | useBody: { en: "The whale mark and a straightforward invitation. One color, a few words.", zh: "鲸鱼标记,加上一句直接的邀请。一种颜色,几句简单的话。" }, |
| 87 | contributorTitle: { en: "Built together. Offered at cost.", zh: "一起构建,按成本提供。" }, |
| 88 | contributorBody: { en: "Pick a phrase in one of Codewhale's languages. Add a GitHub username, user ID or contribution link; it stays off the print. Production, processing and postage are shown before payment.", zh: "用 Codewhale 的一种语言,选一句想穿在身上的话。填写 GitHub 用户名、用户 ID 或贡献链接,这些信息不会印在衣服上。付款前,制作、支付和运费都会列明。" }, |
| 89 | contributorLink: { en: "Choose your contributor tee", zh: "选择贡献者 T 恤" }, |
| 90 | contributorFlowNote: { en: "Choose your print text and review the local draft first. Delivery details are sent only when you request a delivery price.", zh: "先选择印字并查看本地草稿。仅在请求配送价格时发送配送信息。" }, |
| 91 | contributorArtNote: { en: "Simple print text in Codewhale's languages. The contributor page previews your selected phrase.", zh: "用 Codewhale 的语言,印上简单的文字。贡献者页面会预览你选择的短语。" }, |
| 92 | seasonal: { en: "A moment on tour.", zh: "巡游中的一刻。" }, |
| 93 | seasonalBody: { en: "The China Tour design sits beside the everyday collection. Seasonal artwork is being reviewed; ordering is not open for this edition.", zh: "中国巡游图案与日常系列并肩。季节限定设计仍在确认,这一款暂未开放订购。" }, |
| 94 | deskTitle: { en: "Detailed art for the desk.", zh: "复杂的故事,留给桌面。" }, |
| 95 | deskBody: { en: "Stage Dive, cache jokes and developer characters, with room for color and detail. Mousepads, deskmats and stickers need print, texture and durability samples before pricing or orders.", zh: "舞台跃动、缓存笑话与开发者角色,让色彩与细节展开。鼠标垫、桌垫与贴纸先确认印刷、手感与耐用度,再定价和开放订购。" }, |
| 96 | stageTitle: { en: "Open source. Open mic.", zh: "开源,也开麦。" }, |
| 97 | stageBody: { en: "Concert energy for a deskmat or sticker. The detailed Stage Dive artwork is being adapted for the desk.", zh: "把开源演出的热闹,放到桌垫和贴纸上。舞台跃动的复杂图案,正在改为桌面周边。" }, |
| 98 | stageAlt: { en: "Codewhale desk gear concepts with Stage Dive concert artwork, ocean currents and developer stickers.", zh: "Codewhale 桌面周边概念:舞台演出图案、海流和开发者贴纸。" }, |
| 99 | cacheTitle: { en: "Cache me if you can.", zh: "Cache me if you can." }, |
| 100 | cacheAlt: { en: "Flat mousepad artwork with a whale, ocean currents and Cache me if you can lettering.", zh: "鼠标垫平面图案:鲸鱼、海流与 Cache me if you can 字样。" }, |
| 101 | deskmat: { en: "Deskmat", zh: "桌垫" }, |
| 102 | mousepad: { en: "Mousepad", zh: "鼠标垫" }, |
| 103 | stickers: { en: "Stickers", zh: "贴纸" }, |
| 104 | deskAlt: { en: "Detailed Codewhale mousepad, deskmat and sticker artwork concepts.", zh: "Codewhale 鼠标垫、桌垫与贴纸的复杂图案设计概念。" }, |
| 105 | later: { en: "Still in the sketchbook.", zh: "还在画册里。" }, |
| 106 | laterBody: { en: "Little things to take with you. These accessory concepts are still being explored.", zh: "能随身带走的小物。这些配件图案仍在探索中。" }, |
| 107 | concept: { en: "Concept · not for sale", zh: "设计概念 · 暂不售卖" }, |
| 108 | plushTitle: { en: "A Codewhale companion for your desk.", zh: "桌边的 Codewhale 毛绒伙伴。" }, |
| 109 | plushBody: { en: "A 20cm seated doll with an embroidered face, layered navy-to-aqua hair, soft whale clip and tail, and a navy-and-white outfit. Part of the planned collection; a physical prototype comes before preorders.", zh: "20 厘米坐姿娃娃,刺绣面孔、深蓝到浅水蓝的层叠头发、柔软的鲸鱼发夹与尾巴,搭配蓝白服装。它已加入计划中的系列,先做实物样品,再开放预订。" }, |
| 110 | plushStatus: { en: "In development · prototype planned", zh: "筹备中 · 实物打样计划" }, |
| 111 | plushAlt: { en: "Codewhale 20cm seated plush doll concept in front, three-quarter and back views: embroidered blue eyes, layered navy-to-aqua hair, whale clip and tail, and navy-and-white outfit.", zh: "Codewhale 20 厘米坐姿毛绒娃娃概念,展示正面、侧面与背面:蓝色刺绣眼睛、深蓝至浅水蓝的层叠头发、鲸鱼发夹与尾巴,以及蓝白服装。" }, |
| 112 | plushLink: { en: "Meet the plush doll", zh: "看看毛绒娃娃" }, |
| 113 | accessoriesTitle: { en: "Little companions", zh: "随身小伙伴" }, |
| 114 | hoodieTitle: { en: "The same little whale. A simple hoodie.", zh: "还是那只小鲸,换一件简单的卫衣。" }, |
| 115 | hoodieBody: { en: "A small whale mark and quiet type on a plain hoodie. Fabric, fit and print are sampled before ordering opens.", zh: "纯色卫衣上,印一只小鲸和简单的字。先用实物样品确认面料、版型与印刷,再开放订购。" }, |
| 116 | deliveryTitle: { en: "Your tee, your destination.", zh: "你的 T 恤,寄到你的目的地。" }, |
| 117 | deliveryBody: { en: "Choose a country and enter the delivery address. Review the approved destination shipping rate, total and tax note before continuing to payment.", zh: "选择国家或地区并填写配送地址。前往付款前,先查看经确认的目的地运费、合计与税费说明。" }, |
| 118 | destination: { en: "Delivery country or region", zh: "配送国家或地区" }, |
| 119 | size: { en: "Size", zh: "尺码" }, |
| 120 | white: { en: "White cotton tee · one item", zh: "白色纯棉 T 恤 · 一件" }, |
| 121 | name: { en: "Recipient name", zh: "收件人姓名" }, |
| 122 | line1: { en: "Street address", zh: "街道地址" }, |
| 123 | line2: { en: "Apartment, building or unit (optional)", zh: "楼栋、单元、房间号(选填)" }, |
| 124 | city: { en: "City", zh: "城市" }, |
| 125 | region: { en: "State, province or region", zh: "州、省或地区" }, |
| 126 | postalCode: { en: "Postal code", zh: "邮政编码" }, |
| 127 | phone: { en: "Delivery phone number", zh: "配送联系电话" }, |
| 128 | addressNote: { en: "This address is used for delivery checks and fulfillment. Changing it requires a new price review.", zh: "此地址用于配送确认与履约。修改地址后需重新确认价格。" }, |
| 129 | reviewDelivery: { en: "Review delivery price", zh: "确认配送价格" }, |
| 130 | reviewing: { en: "Reviewing delivery…", zh: "正在确认配送……" }, |
| 131 | notReady: { en: "Samples before sales. Ordering is not open for this design yet; no payment will be taken.", zh: "先确认样品,再开售。此图案尚未开放订购,不会收取付款。" }, |
| 132 | checking: { en: "Checking ordering availability…", zh: "正在确认是否可订购……" }, |
| 133 | statusError: { en: "Ordering availability could not be checked. Please try again later.", zh: "暂时无法确认是否可订购,请稍后重试。" }, |
| 134 | quoteError: { en: "We couldn't review delivery for this address. Check the details and try again.", zh: "无法确认此地址的配送价格,请检查信息后重试。" }, |
| 135 | routeUnavailable: { en: "This design and destination still need a print and delivery review.", zh: "此图案与目的地仍需完成印刷及配送确认。" }, |
| 136 | tryLater: { en: "Please wait a minute, then try again.", zh: "请稍等一分钟后重试。" }, |
| 137 | checkoutError: { en: "Payment could not be opened. Your order has not been placed. Try again or review delivery again.", zh: "无法打开付款页面,订单尚未提交。请重试或重新确认配送价格。" }, |
| 138 | expired: { en: "This price review has expired. Please review delivery again before payment.", zh: "此次价格确认已过期,付款前请重新确认配送价格。" }, |
| 139 | merchandise: { en: "Printed tee", zh: "印花 T 恤" }, |
| 140 | shipping: { en: "Destination shipping rate", zh: "目的地运费" }, |
| 141 | processing: { en: "Payment processing", zh: "支付手续费" }, |
| 142 | total: { en: "Total before any charges noted below", zh: "合计(下方另有说明的费用除外)" }, |
| 143 | quoteTitle: { en: "Review before you pay.", zh: "付款前,确认一下。" }, |
| 144 | payment: { en: "Continue to secure payment", zh: "前往安全付款" }, |
| 145 | opening: { en: "Opening payment…", zh: "正在打开付款……" }, |
| 146 | returnToMerch: { en: "Back to the collection", zh: "返回周边系列" }, |
| 147 | } as const; |
| 148 | |
| 149 | export type StorefrontCopy = Record<keyof typeof text, string>; |
| 150 | export function getStorefrontCopy(locale: string): StorefrontCopy { |
| 151 | const copy = Object.fromEntries(Object.entries(text).map(([key, value]) => [key, pickText(value, locale)])) as StorefrontCopy; |
| 152 | const number = new Intl.NumberFormat(locale, { maximumFractionDigits: 2 }); |
| 153 | copy.targetPrice = copy.targetPrice.replace("{cny}", number.format(MERCH_TARGET_PRICE.cny / 100)).replace("{usd}", number.format(MERCH_TARGET_PRICE.usd / 100)); |
| 154 | return copy; |
| 155 | } |
| 156 | |
| 157 | export function countryLabel(code: string, fallback: string, locale: string): string { |
| 158 | try { return new Intl.DisplayNames([locale], { type: "region" }).of(code) ?? fallback; } |
| 159 | catch { return fallback; } |
| 160 | } |
| 161 |