04 | 中英文双语的工程实现
本文目录 第 4 篇中英文双语的工程实现 1. 整体设计 2. CJK 字体自动检测2.1 问题2.2 检测方法2.3 字体切换 统一绘制入口 3. 分段缩放 —— 中文为什么需要更大字号3.1 原理3.2 CJKScale 实现 4. 字形码点采集 —— 为什么会显示 ??4.1 问题复现4.2 修复 5. 语言切换与持久化️ 6. 中文全链路修复一览 下篇预告 系列目录系列第 4 篇· 一款游戏只有英文在国内平台发布是不完整的。本文记录加入简体中文支持的工程实践。上一篇222 个 Bug 修复教会我的事 第 4 篇中英文双语的工程实现 1. 整体设计C 语言做 i18n 没有标准做法。最朴素的方案枚举 二维数组。#defineLANG_EN0#defineLANG_ZH1typedefenum{STR_BEGINNER,STR_INTERMEDIATE,STR_EXPERT,STR_TITLE,STR_SUBTITLE,STR_STATISTICS,STR_SETTINGS_HELP,// ... ≈ 100 个 IDSTR_COUNT}StringId;staticconstchar*I18N[LANG_COUNT][STR_COUNT]{[LANG_EN]{[STR_BEGINNER]Beginner,[STR_TITLE]MINESWEEPER,},[LANG_ZH]{[STR_BEGINNER]u8初级,[STR_TITLE]u8扫雷,}};#defineS(id)I18N[currentLang][id]使用DrawT(gameFont,S(STR_STATISTICS),pos,48,2,WHITE);// 英文 → STATISTICS 中文 → 统计数据方案优点缺点✅枚举数组本方案零依赖 · 编译期检查加语言需改源码❌ GNU gettext外部 .po 文件Windows 兼容差❌ JSON/YAML外部编辑友好需引入解析器 100 条字符串 × 2 种语言枚举数组是最实用的选择。 2. CJK 字体自动检测2.1 问题Raylib 的DrawTextEx一次只能用一种字体。英文用font2.ttf漂亮中文需要font4.ttf含 CJK 字符。如果全用 CJK 字体英文字形靠 fallback 渲染风格不统一全用英文字体中文显示为方块。2.2 检测方法CJK 统一码区U4E00–U9FFF全落在 UTF-8 三字节编码范围0xE0开头。检测只需staticboolHasCJK(constchar*text){constunsignedchar*p(constunsignedchar*)text;while(*p){if((*p0xF0)0xE0)returntrue;// 三字节 CJK// 根据 UTF-8 编码前进}returnfalse;}不需要查码点表。O(N) 且 N 30字符串长度帧率影响可忽略。2.3 字体切换 统一绘制入口staticFontPickFont(constchar*text){if(HasCJK(text)cjkFont.texture.id!GetFontDefault().texture.id)returncjkFont;returntitleFont;}staticvoidDrawT(Font dummy,constchar*text,Vector2 pos,floatfontSize,floatspacing,Color tint){(void)dummy;// 兼容旧签名floatfsIsCJKFont(text)?CJKScale(fontSize):fontSize;DrawTextEx(PickFont(text),text,pos,fs,spacing,tint);}️英文 vs 中文渲染对比 3. 分段缩放 —— 中文为什么需要更大字号3.1 原理英文字母 e2 画 中文汉字 赢17 画16×16 像素里2 画和 17 画的辨识度完全不同。3.2 CJKScale 实现staticfloatCJKScale(floatfontSize){if(fontSize14)returnfontSize*1.45f;// 14→≈20pxif(fontSize18)returnfontSize*1.40f;// 16→≈22pxif(fontSize24)returnfontSize*1.35f;// 22→≈30pxif(fontSize36)returnfontSize*1.25f;// 32→≈40pxreturnfontSize*1.20f;// 大字号微调}用途原字号英文 ≈CJK 缩放后提升菜单最佳时间14px小20px✅ 可读设置标签16px一般22px✅ 清楚按钮文字22px正常30px✅ 舒服标题52px大62px✅ 几乎无感⚠️注意MeasureT测量函数也必须使用CJKScale否则居中公式用未缩放尺寸文字画偏了。 4. 字形码点采集 —— 为什么会显示??4.1 问题复现Bug 现象与修复修复前 [ English ] [ ?? ] ← 简体中文 显示为 ?? 修复后 [ English ] [简体中文] ← 正常显示根因与修复过程见 Bug #5 章节。Raylib 的LoadFontEx需要指定要加载哪些 Unicode 码点cjkFontLoadFontEx(font4.ttf,192,codepoints,cpCount);// 不指定的字符 → 纹理里没有 → 渲染为 ?BuildCJKCodepoints最初只扫描I18N[LANG_ZH]翻译表。但设置页的语言按钮文字是硬编码的constchar*langNames[]{English,u8简体中文};// ❌ 不在翻译表简 · 体 · 文 三个字从未出现在翻译表中 → 码点集没有 → 字形缺失 →??。4.2 修复staticintBuildCJKCodepoints(int*codepoints,intmaxCount){// ASCII 总是包含for(inti32;i126;i)codepoints[count]i;// 额外硬编码字符串staticconstchar*extra[]{u8简体中文,NULL};for(intpass0;pass2;pass){constchar**src(pass0)?I18N[LANG_ZH]:extra;// 扫描 UTF-8 序列提取码点去重}returncount;}教训BuildCJKCodepoints必须覆盖所有可能显示在屏幕上的 CJK 字符包括不是从翻译表取的字符串。 5. 语言切换与持久化// 设置页点击切换if(点击简体中文){currentLangLANG_ZH;SaveSettings();}// 启动时恢复intsavedLangLoadSettings();if(savedLangLANG_EN||savedLangLANG_ZH)currentLangsavedLang;语言选择通过settings.dat持久化带版本号 校验和关闭游戏再打开也不会丢失。️ 6. 中文全链路修复一览问题根因修复??乱码字形码点未包含硬编码字符串补扫 extraStringsFix #217小字看不清CJK 缩放仅 1.1x分段缩放 1.20-1.45xFix #216字体边缘锯齿加载尺寸 144px提升至192pxFix #218全屏中文模糊画布 1280×720 被放大canvasMult 高分辨率 RTFix #221文字与面板重叠缩放后布局参数没同步面板增高、间距加大Fix #219-220️问题 → 根因 → 修复全链路问题中文显示 ??根因字形码点未覆盖问题小字看不清根因CJK 缩放仅 1.1x问题字体边缘锯齿根因加载尺寸 144px问题全屏中文模糊根因画布 1280x720 被放大问题文字溢出面板根因缩放后布局没同步Fix #217补扫硬编码字符串Fix #216分段缩放 1.20-1.45xFix #218加载尺寸 144→192pxFix #221canvasMult 高分辨率 RTFix #219-220面板增高、间距加大 下篇预告第 5 篇持久化、撤销、提示那些非核心功能二进制存档格式与校验和、有限状态撤销栈、Hint 安全格算法、Smiley Face 4 状态设计。真正区分能跑和好用的 80%。 系列目录#标题状态1项目概览与扫雷核心算法✅ 已发布2Raylib 渲染架构✅ 已发布3222 个 Bug 修复教会我的事✅ 已发布4中英文双语的工程实现← 本文✅ 已发布5持久化、撤销、提示非核心功能 待发布6200 个单元测试C 项目也能 TDD 待发布7960×640 → 1280×720全局缩放重构实录 待发布如果你觉得有帮助点赞 收藏 关注三连支持作者继续写下去

相关新闻

spring对junit的支持

spring对junit的支持

引入spring和junit4的依赖<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.4</version> </dependency> <!-- spring对junit支持的依赖&#xff0c;spring…

2026/7/1 9:48:32阅读更多 →
【AI】魔珐星云 SDK 实战测评:Cursor、Copilot、通义灵码如何走向具身交互成品

【AI】魔珐星云 SDK 实战测评:Cursor、Copilot、通义灵码如何走向具身交互成品

博主介绍&#xff1a;✌全网粉丝24W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

2026/7/1 9:48:32阅读更多 →
分布式消息队列对比分析

分布式消息队列对比分析

分布式消息队列对比分析 在当今高并发、高可用的分布式系统中&#xff0c;消息队列作为异步通信的核心组件&#xff0c;承担着解耦、削峰、异步处理等重要职责。随着技术的演进&#xff0c;市面上涌现了多种分布式消息队列解决方案&#xff0c;如Kafka、RabbitMQ、RocketMQ等。…

2026/7/1 9:48:32阅读更多 →
ICM-42688-P与PIC18F96J94在工业运动控制中的高精度应用

ICM-42688-P与PIC18F96J94在工业运动控制中的高精度应用

1. ICM-42688-P与PIC18F96J94的黄金组合解析在工业级运动传感与控制领域&#xff0c;ICM-42688-P六轴MEMS惯性测量单元(IMU)与PIC18F96J94微控制器的组合正在重塑设备感知能力的边界。这套方案的核心竞争力在于&#xff1a;ICM-42688-P提供4000dps陀螺仪量程和32g加速度计量程的…

2026/7/1 11:09:09阅读更多 →
还在为字幕制作烦恼?Subtitle Edit 免费开源字幕编辑神器帮你轻松搞定

还在为字幕制作烦恼?Subtitle Edit 免费开源字幕编辑神器帮你轻松搞定

还在为字幕制作烦恼&#xff1f;Subtitle Edit 免费开源字幕编辑神器帮你轻松搞定 【免费下载链接】subtitleedit the subtitle editor :) 项目地址: https://gitcode.com/gh_mirrors/su/subtitleedit 你是否遇到过这样的困扰&#xff1f;辛辛苦苦录制的视频&#xff0c…

2026/7/1 11:09:09阅读更多 →
终极指南:Wand-Enhancer开源工具深度解锁WeMod完整功能

终极指南:Wand-Enhancer开源工具深度解锁WeMod完整功能

终极指南&#xff1a;Wand-Enhancer开源工具深度解锁WeMod完整功能 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer Wand-Enhancer是一个专业的开源增强工…

2026/7/1 11:09:09阅读更多 →
jvm~jvm配置与系统配置的关系

jvm~jvm配置与系统配置的关系

keycloak是运行在jboss上面&#xff0c;并且部署到了容器里&#xff0c;在k8s上面进行编排&#xff0c;现在遇到gc在某个时刻垃圾回收速度变慢&#xff0c;CPU接近100%&#xff0c;容器导致存活探针失败&#xff0c;容器最后重启二 问题分析与解决方案这是一个典型的 JVM GC 问…

2026/7/1 11:09:09阅读更多 →
MPC5643L/SPC56EL评估板硬件设计解析:电源、时钟与调试接口配置实战

MPC5643L/SPC56EL评估板硬件设计解析:电源、时钟与调试接口配置实战

1. 项目概述与核心价值在嵌入式系统开发&#xff0c;尤其是汽车电子和工业控制这类对可靠性要求极高的领域&#xff0c;直接在产品板上进行软件调试和硬件验证风险极高。一块设计精良的微控制器评估板&#xff0c;就如同一个功能完备的“实验田”&#xff0c;它能为开发者提供一…

2026/7/1 11:09:09阅读更多 →
【Gartner认证级评估】:ChatGPT企业版 vs Microsoft Copilot for Business vs Anthropic Enterprise——总拥有成本(TCO)深度比对

【Gartner认证级评估】:ChatGPT企业版 vs Microsoft Copilot for Business vs Anthropic Enterprise——总拥有成本(TCO)深度比对

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ChatGPT企业版价格结构全景解析 ChatGPT企业版&#xff08;ChatGPT Enterprise&#xff09;并非按用户数或 API 调用量简单计费&#xff0c;而是采用基于组织规模、功能需求与服务等级的定制化定价模型…

2026/7/1 11:04:09阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月&#xff0c;Boris Cherny 公开宣布自己卸载了 IDE。一时间&#xff0c;Vibe Coding 成了全行业最热的话题。6个月后&#xff0c;当我们回过头来拉一份真实账本&#xff0c;发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/1 4:42:14阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言&#xff1a;审计结束三个月了&#xff0c;审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间&#xff0c;内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中&#xff0c;审计…

2026/7/1 5:19:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/1 0:01:44阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/1 0:01:44阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/1 0:01:44阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/1 0:01:44阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/1 0:01:44阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/1 0:01:44阅读更多 →