Skip to content
Closed
2 changes: 1 addition & 1 deletion apps/web/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const config = withMyBundleAnalyzer(
],
i18n: {
defaultLocale: "en",
locales: ["en", "de", "id"],
locales: ["en", "de", "id", "zh-CN"],
},
}),
),
Expand Down
Binary file added apps/web/src/assets/chinese-flag.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/web/src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default {
"settings.english": "Englisch",
"settings.german": "Deutsch",
"settings.indonesian": "Indonesisch",
"settings.chinese": "中文",

// locationsettings page translations
"locationsettings.add new location": "Füge einen Ort hinzu",
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default {
"settings.english": "English",
"settings.german": "German",
"settings.indonesian": "Indonesian",
"settings.chinese": "中文",

// locationsettings page translations
"locationsettings.add new location": "Add new location",
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/locales/id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default {
"settings.english": "Inggris",
"settings.german": "Jerman",
"settings.indonesian": "Indonesia",
"settings.chinese": "中文",

// locationsettings page translations
"locationsettings.add new location": "Tambah lokasi baru",
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/locales/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export const {
en: () => import("./en"),
de: () => import("./de"),
id: () => import("./id"),
"zh-CN": () => import("./zh-CN"),
});
188 changes: 188 additions & 0 deletions apps/web/src/locales/zh-CN.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
export default {
// 404 page translations
"404.title": "404 - 页面未找到",

// common translations
"common.title": "Weather.io",
"common.location": "中文",

"common.start button": "查找您的位置",
"common.share button": "分享",
"common.menu home": "主页",
"common.menu locations": "地点",
"common.menu settings": "设置",
"common.menu contact": "联系我们",
"common.footer legal": "法律声明",
"common.footer contributors": "贡献者",

"common.search page title": "搜索 - Weather.io",

"common.miles per hour": "英里每小时",
"common.kilometers per hour": "千米每小时",
"common.knots": "节",
"common.meters per second": "米每秒",
"common.beaufort": "风级",
"common.hectopascals": "百帕",

"common.share text": "查看此页面: ",

"common.title 404 page": "404: 页面未找到",
"common.title offline page": "您已离线",

// settings page translations
"settings.temperature units": "温度单位",
"settings.wind speed units": "风速单位",
"settings.language": "语言",

"settings.english": "English",
"settings.german": "Deutsch",
"settings.indonesian": "Bahasa Indonesia",
"settings.chinese": "中文",

// locationsettings page translations
"locationsettings.add new location": "添加新位置",
"locationsettings.add new location button": "添加新位置",
"locationsettings.search input placeholder": "搜索城市",

"locationsettings.at least one city toast": "至少需要一个城市!",
"locationsettings.switched to city toast": "切换到城市!",
"locationsettings.added city toast": "添加城市!",
"locationsettings.city not found toast": "城市未找到!",
"locationsettings.try again toast": "请再试一次!",

"locationsettings.my location button": "设定我的位置",

// offline page translations
"offline.title": "您已离线",
"offline.message": "请检查您的网络连接",

// search page translations
"search.search input placeholder": "搜索城市",
"search.continue button": "下一步 -->",

"search.my location button": "设定我的位置",

// legal page translations
"legal.main text":"本网站的内容已经过仔细审核和制作。然而,我们无法保证所提供信息的准确性、完整性和时效性。我们不对因使用本网站而造成的任何损害或损失承担责任。链接页面的运营者对其内容负有完全责任。对于外部内容,我们明确排除任何责任。",
"legal.germany": "Germany",
"legal.information disclaimer": "根据《德国电信和信息服务法》第5条的规定",

// home page translations
"home.today": "今天",
"home.9 day forecast": "未来9天预报",
"home.precipitation": "降水",
"home.feels like": "体感温度",
"home.visibility": "能见度",
"home.wind pressure": "风速 & 气压",
"home.air quality": "空气质量",
"home.pressure": "气压",
"home.speed": "风速",
"home.moon phase": "月相",

"home.early morning": "凌晨",
"home.morning": "上午",
"home.noon": "中午",
"home.afternoon": "下午",
"home.night": "晚上",

"home.feels like phrase extremely warm": "今天天气非常炎热!",
"home.feels like phrase very warm": "今天太阳也似乎想降温了!",
"home.feels like phrase warm": "连冰淇淋都觉得太热了!",
"home.feels like phrase slightly more warm": "今天真是个暖洋洋的日子!",
"home.feels like phrase slightly warm": "是去野餐的好天气!",
"home.feels like phrase neutral":
"温度刚刚好,既不热也不冷。",
"home.feels like phrase slightly cold": "可能需要穿件薄外套。",
"home.feels like phrase slightly more cold": "今天是个寒冷的日子!",
"home.feels like phrase cold":
"企鹅们都因为寒冷去喝热巧克力了!",
"home.feels like phrase very cold":
"今天的寒冷天气连雪人都冻得发抖!",
"home.feels like phrase extremely cold":
"冷得连北极熊都懒得出门了!",

"home.air quality text very poor": "非常差",
"home.air quality text poor": "差",
"home.air quality text fair": "一般",
"home.air quality text moderate": "适中",
"home.air quality text good": "好",
"home.air quality text excellent": "优秀",

"home.sunset": "日落",
"home.sunrise": "日出",

"home.moonset": "月落",
"home.moonrise": "月升",

"home.weather state stormy": "暴风雨",
"home.weather state snowy": "雪天",
"home.weather state rainy": "雨天",
"home.weather state very cloudy": "多云",
"home.weather state cloudy": "阴天",

"home.weather state windy": "有风",
"home.weather state sunny": "晴天",

"home.this hour": "此时",
"home.early hour time ending": "上午",
"home.late hour time ending": "下午",

"home.9 day forecast card content":
"未来9天的天气预报。<br /> <span class=\"font-semibold\">温度</span> 为每日的平均温度,分别代表白天和夜晚的温度。",

Comment on lines +130 to +132
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using template interpolation instead of HTML in translations.

HTML markup embedded in translations can be fragile and harder to maintain. Consider using template interpolation:

- "home.9 day forecast card content": "未来9天的天气预报。<br /> <span class=\"font-semibold\">温度</span> 为每日的平均温度,分别代表白天和夜晚的温度。",
+ "home.9 day forecast card content": {
+   text: "未来9天的天气预报。{break}温度为每日的平均温度,分别代表白天和夜晚的温度。",
+   bold: ["温度"]
+ }

This approach:

  1. Separates content from presentation
  2. Reduces risk of HTML-related bugs
  3. Makes translations easier to maintain

Also applies to: 141-142, 182-183

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way of coding is not seen in other locales.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NicoCanada You're absolutely right. I apologize for my earlier suggestion. After checking all locale files, I can see that HTML markup is consistently used across all translations. Your implementation matches the established pattern in the codebase, so we should keep it as is.

🔗 Analysis chain
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the "home.9 day forecast card content" translation across all locale files
ast-grep --pattern 'export default {
  $$$
  "home.9 day forecast card content": $VALUE,
  $$$
}'

Length of output: 99


Script:

#!/bin/bash
# Search for the forecast card content translation in locale files
rg -A 1 -B 1 "home\.9 day forecast card content" apps/web/src/locales/

Length of output: 1167


✏️ Learnings added
Learnt from: NicoCanada
PR: The-Creative-Programming-Group/Weather-App#311
File: apps/web/src/locales/zh-CN.ts:130-132
Timestamp: 2025-01-30T23:04:08.252Z
Learning: In the Weather App project, translations in locale files use direct HTML markup (like <br /> and <span>) rather than template interpolation, as established by the existing implementation in en.ts, de.ts, and id.ts files.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

"home.precipitation card title": "当前降水",

"home.feels like card content":
"这个温度参数考虑了人类对天气的感知。",

"home.visibility card title": "当前能见度",

"home.wind pressure card title": "当前风力与气压",
"home.wind pressure card content":
"<b>海平面气压。</b> <br /> 在海平面,气压是由上方空气的重量所施加的力,平均值约为1013.25 hPa。",

"home.not available": "不可用",

"home.moon phase card title": "当前月相",
"home.moon phase card content":
"月相是从地球上看到的月球被阳光直接照射部分的形状。",

"home.moon phase new moon": "新月",
"home.moon phase waxing crescent": "蛾眉月",
"home.moon phase first quarter": "上弦月",
"home.moon phase waxing gibbous": "盈凸月",
"home.moon phase full moon": "满月",
"home.moon phase waning gibbous": "亏凸月",
"home.moon phase last quarter": "下弦月",
"home.moon phase waning crescent": "残月",

"home.more information": "更多信息",
"home.less information": "更少信息",

"home.sun hours": "日照时数",

"home.from": "来自",

// contact page translations
"contact.send button": "发送",
"contact.sent button": "已发送",
"contact.first name": "名字",
"contact.last name": "姓氏",
"contact.email": "邮箱",
"contact.message": "留言",

"contact.sent toast": "消息已发送!",
"contact.sending email loading toast": "正在发送邮件...",

"contact.invalid email": "无效的邮箱地址",
"contact.at least 2 characters": "此字段必须包含至少2个字符",
"contact.at least 10 characters": "此字段必须包含至少10个字符",

// contributors page translations
"contributors.made with love text":
'由以下人员<span class="text-4xl" style="color: rgb(239 68 68)">♥\uFE0F</span> 精心制作: ',
"contributors.founder": "创始人",
"contributors.engineer": "工程师",
"contributors.designer": "设计师",
"contributors.translator": "翻译员",
} as const;
22 changes: 21 additions & 1 deletion apps/web/src/pages/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { TemperatureUnitType, WindSpeedUnitType } from "~/states";
import germanFlag from "~/assets/german-flag.png";
import indonesianFlag from "~/assets/indonesian-flag.png";
import usaFlag from "~/assets/usa-flag.png";
import chineseFlag from "~/assets/chinese-flag.png";
import Layout from "~/components/Layout";
import {
getLocaleProps,
Expand Down Expand Up @@ -188,7 +189,7 @@ const Settings = observer(() => {
>
<Image
src={indonesianFlag}
alt="Flag of the Netherladns"
alt="Flag of the Republic of Indonesia"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LMAO, good spot

width={20}
height={20}
/>
Expand All @@ -199,6 +200,25 @@ const Settings = observer(() => {
<RxCheck width={20} height={20} className="h-9 w-9" />
)}
</button>
<button
className={`${normalButtonClass} ${
locale === "zh-CN" ? "border-2" : ""
}`}
onClick={() => changeLocale("zh-CN")}
>
<Image
src={chineseFlag}
alt="Flag of PRC"
width={20}
height={20}
/>
<p className={`${styles.buttontext} ml-2`}>
{translationSettings("chinese")}
</p>
{locale === "zh-CN" && (
<RxCheck width={20} height={20} className="h-9 w-9" />
)}
</button>
</div>
</div>
</Layout>
Expand Down
Loading