上岸的鱼

心中有光,便可使整个世界升起太阳

本文包含中文与英文两个版本。
This post includes both Chinese and English versions.


中文版

思考的起点

最近和朋友聊到一个很有意思的演进观点:

“以前 AI 是学习个人,后来是增强个人,现在是取代个人;现在已经开始学习团队、增强团队,后续是取代团队。”

这个说法很直观,也很有冲击力。但如果顺着系统与分工的底层逻辑去推演,现实往往不会沿着这种“简单粗暴的清空人类”的路线走。

比起“取代”,更贴切的词其实是“解构与重组”。


一、被取代的是“技能任务”,而不是“责任主体”

回看第一阶段,AI 确实在快速接管画图、写基础代码、提炼摘要这些“任务(Tasks)”。但这并不等于把一个完整的“人(Roles)”抹去了。

相反,它造就的是“超级个体”。过去需要 3 到 5 个人才能攒起来的小项目,现在一个掌握工具链的人就能跑通闭环。

AI 替代的是执行过程中的摩擦阻力,但定义问题、承担后果、拍板决策的动作,依然牢牢锚定在具体的人身上。


二、当 AI 开始学习团队:它取代的是“沟通摩擦”

现在大家开始讨论多智能体(Multi-Agent),讨论让 AI 学习组织流程(SOP)。那 AI 真的会取代团队吗?

要看你怎么定义团队:

  • 如果团队是指“流程中转站”:那些每天靠开会同步进度、跨部门传话、写汇报 PPT 的冗余中间层,确实会被彻底压缩。
  • 如果团队是指“核心决策与信任共同体”:它不会消失,而是会极度微型化

未来的组织形态可能不再是 100 人的金字塔,而是 3 到 5 个核心人类指挥官,调度着一整套动态生成的智能体集群。


三、终局:什么才是无法被计算的?

当智力执行与协同的边际成本无限趋近于零时,人类真正的壁垒反而会回归到最原始、最朴素的地方:

  1. 责任背书(Accountability):AI 无法坐牢,无法破产,无法替商业失败承担法律与道德后果。最终签发授权的永远是人。
  2. 价值定义(Problem Formulation):AI 擅长求解和优化,但它不会凭空产生渴望。“什么值得做”、“什么是美”,只有人类自己知道。
  3. 真实信任(Human Connection):算法生成的关怀和对话成本极低,但也因此变得廉价。基于真实血肉的声誉、博弈与信任,反而是最硬的通货。

结语

AI 没有把团队消灭,它只是把过去困在低效协同里的组织结构打碎了。

未来的胜出者,要么成为能够清晰拆解目标、编排智能体网络的“超级指挥官”;要么深耕现实世界,成为“高信任与强责任的连接者”。


English Version

The Starting Point

A thought-provoking perspective came up in a recent conversation:

“AI began by learning from individuals, evolved to augment individuals, and is now replacing individuals. Now it has started learning from teams and augmenting teams—will it ultimately replace teams?”

It is an intuitive and striking narrative. However, when analyzed through the lens of organizational dynamics and systemic division of labor, reality rarely follows a straightforward path of “total human obsolescence.”

Rather than “replacement,” a more precise description is “deconstruction and restructuring.”


1. Replacing “Tasks”, Not “Accountable Roles”

Looking at individual productivity, AI is rapidly taking over structured tasks—drafting code, generating illustrations, and summarizing documents. Yet, automating tasks is fundamentally different from erasing the human role entirely.

Instead, this shift is giving rise to the “Solopreneur” and “Super Individual.” A project that once required a team of five can now be shipped by a single person leveraging an AI toolchain.

AI eliminates execution friction, but problem formulation, decision-making, and bearing consequences remain inextricably tied to humans.


2. When AI Learns Teamwork: Eliminating Coordination Friction

With the rise of Multi-Agent Systems and workflow automations, the conversation shifts to whether AI will replace entire human teams.

The answer depends on how a team is defined:

  • The “Relay Layer”: Middle layers that exist purely for status updates, cross-department handoffs, and alignment meetings will be drastically compressed.
  • The “Core Decision & Trust Unit”: Far from disappearing, teams will become hyper-compact.

Future organizations will likely shift from 100-person pyramids to micro-squads of 3 to 5 human leaders orchestrating an elastic swarm of autonomous agents.


3. The Endgame: What Remains Uncomputable?

As the marginal cost of intellectual execution and workflow coordination drops toward zero, human competitive moats will return to three foundational pillars:

  1. Accountability: AI cannot go to prison, go bankrupt, or assume legal and ethical liability for failures. Final sign-offs and risk absorption must come from humans.
  2. Value Formulation: AI excels at optimization and problem-solving, but lacks intrinsic desire. Defining what is worth solving and what constitutes value remains a human prerogative.
  3. Authentic Trust: Algorithmically generated interactions are cheap to produce, which diminishes their relational weight. Real-world reputation, skin-in-the-game commitment, and interpersonal trust become the scarcest assets.

Closing Thoughts

AI is not eradicating human teams; it is dismantling the bureaucratic friction that has long plagued organizational collaboration.

The future belongs to two profiles: the “Super Conductors” who can deconstruct complex goals and orchestrate agent networks, and the “Trust Connectors” who anchor their value in real-world accountability and high-stakes relationships.

本文包含中文与英文两个版本。
This post includes both Chinese and English versions.


中文版

思考的起点

最近在重新审视自己的职业轨迹。我在游戏行业做了十多年,近期带了个小团队开发一款消除类游戏,但不可避免地面临着产品品质与商业变现的困境。与此同时,一个利用 AI 为传统商贸公司搭建自动化流的机会摆在面前。两相对比,引发了我对技术演进下,个人能力边界与商业选择底层逻辑的思考。

一、能力的让渡与直觉的溢价

当我们谈论 AI 的全面渗透时,最直观的感受是:大家似乎越来越不愿意“思考”了。很多问题下意识地就直接抛给 AI 去处理。

这其实是一个必然的过程。就像计算器的普及让心算能力变得不再重要一样,AI 正在大批量接管人类的常规逻辑运算和繁琐执行工作。当我们把这些能力让渡给机器后,什么才是人类不可替代的壁垒?我的答案是:对未来的直觉、同理心、以及在复杂模糊环境下的决断力。当执行的边际成本无限趋近于零,真正稀缺的,是提出正确问题的人。

二、确定性与红海的博弈

在选择继续做游戏还是转向 B 端自动化时,本质上是在做一场关于“确定性”的博弈。

游戏行业是一个极其典型的红海市场,竞争极度饱和,成功往往带有极强的幸存者偏差。你付出 100% 的努力,未必能换回 10% 的商业成功。而在传统商贸等实体行业引入 AI 自动化,则是利用“确定”的技术,去解决企业“确定”的痛点(降本增效)。面对时代的技术红利,与其在一个胜率极低的市场里死磕概率,不如拿着降维的工具,去传统行业里攫取确定性的价值回报。

三、终局:一人公司与 Agent 蜂群

这引出了我对未来工作形态的最终构想:一个人带领一群 Agent(智能体)或 AI 工具去完成整个业务闭环。

这就是高度进阶的“超级个体”或“一人公司”模式。在这个架构下,个人的角色发生了根本性的跃迁——从一个系统中的执行节点,变成了整个系统的“指挥官”。你不需要去管理充满摩擦力的人类团队,而是通过调度底层的 AI 工作流,一个人就能覆盖从系统架构、代码开发到业务运营的全流程。

结语

AI 终究只是个人能力的放大器。学会去剥离那些会被轻易替代的“计算”属性,做那个掌控 Agent 蜂群、制定规则并把握方向的人。


English Version

The Starting Point of Reflection

Recently, I found myself re-evaluating my career trajectory. After spending over a decade in the gaming industry, I am currently leading a small team developing a Match-3 game, inevitably grappling with the dual dilemmas of product quality and commercial viability. Meanwhile, an opportunity emerged to build automated workflows using AI for a traditional trading company. The contrast between these two paths sparked a deeper reflection on the boundaries of personal capability and the underlying logic of business choices in the face of technological evolution.

I. The Surrender of Capability and the Premium of Intuition

When discussing the pervasive penetration of AI, the most immediate observation is that people seem increasingly reluctant to “think.” There is a subconscious tendency to offload problems directly to AI.

This is, in fact, an inevitable progression. Just as the popularization of calculators rendered mental arithmetic less crucial, AI is taking over human routine logical processing and tedious execution at scale. Once we surrender these capabilities to machines, what remains as humanity’s irreplaceable moat? My answer is: intuition for the future, empathy, and the ability to make decisive judgments in complex, ambiguous environments. When the marginal cost of execution approaches zero, the truly scarce resource is the person who can ask the right questions.

II. The Gamble Between Certainty and the Red Ocean

The choice between continuing in game development and pivoting to B2B automation is fundamentally a gamble concerning “certainty.”

The gaming industry is a quintessential red ocean market—hyper-competitive and saturated, where success often carries a strong element of survivorship bias. You can invest 100% of your effort and not even see a 10% commercial return. In contrast, introducing AI automation into traditional sectors like commerce means using “certain” technology to solve an enterprise’s “certain” pain points (reducing costs and increasing efficiency). Faced with the technological dividends of our era, rather than obsessing over low-probability success in a cutthroat market, it is far more pragmatic to wield a multidimensional tool to secure definite value returns in traditional industries.

III. The Endgame: The One-Person Company and the Agent Swarm

This brings me to my ultimate vision for the future of work: one person leading a swarm of Agents or AI tools to complete an entire business loop.

This is the highly evolved model of the “Super Individual” or the “One-Person Company.” Within this architecture, the role of the individual undergoes a fundamental leap—from an execution node within a system to the “commander” of the entire system. Instead of managing a human team fraught with organizational friction, a single person can cover the entire process—from system architecture and code development to business operations—by simply orchestrating the underlying AI workflows.

Conclusion

Ultimately, AI is merely an amplifier of individual capability. We must learn to strip away the easily replaceable “computational” attributes of our work, and strive to be the one who commands the swarm of Agents, sets the rules, and steers the direction.

Aion (灵汐):补全自动化背后的“信任感”

中文版 | English

🚀 创造者说:为什么要“反抗”粗暴的清理逻辑?

在 macOS 上,“清理闲置应用”一直是个让人不安的概念。市面上大多数工具逻辑非常单一:它们只盯着计时器,只要你几分钟没点开某个窗口,应用就可能被强行关闭。这种不确定性会打断下载、同步或是在线会议,在无形中消耗用户的心理能量。

我写 Aion 的初衷,就是想让自动化学会**“听懂状态”**。

真正的“分寸感”:从体征感知到呼吸感

为了解决“误杀”,我为 Aion 建立了一套基于应用体征的感知逻辑。不再看交互时长,而看应用本身是否在“干活”:

  • 感知流量吞吐:只要应用还在持续读写数据,它就拥有最高优先级的保护权。
  • 留给系统的“呼吸感”:这是我最执着的一处设计。为了应对信号抖动,我给系统设置了一个 10 秒的缓冲期。即使应用信号暂时消失,Aion 也会因为这层“呼吸感”,选择再等一等,而不是瞬间拔掉插头。
  • 租约协议:针对长耗时的后台任务(比如本地 AI 代理),应用可以申请特定时长的租约,确保它在完成工作前不被中断。

让自动化不再是黑盒

通过“活动记录”,Aion 终于能把它的判断路径摊开来系统化地陈述。它不再是一个黑盒,而是一个你可以查账的辅助系统。这种可解释性,才是一个工具应当具备的“分寸感”。它在应用真闲置时替你收拾,在应用做正事时保持克制,而在你追问“刚才为什么这样做”时,给出精准的答案。


项目官网: aion.7caifei.com


[EN] 🚀 Maker’s Note: Reclaiming Trust in Automation

On macOS, blunt “Idle Timers” often break background workflows. Most tools kill a process simply because you haven’t clicked its window.

Vital Signs vs. Idle Timers

I built Aion to track an application’s vital signs instead of just time. Key features include:

  • Data Throughput Monitoring: Direct tracking of network/disk I/O to ensure background tasks stay alive.
  • Hysteresis Logic: To handle signal instability, Aion implements a 10-second hysteresis buffer. If a vital signal drops, the protection remains active for 10 seconds to filter out momentary flickers, ensuring deterministic uptime.
  • Application Leases: For AI Agents or long-running scripts, Aion supports a lease-based protocol that prevents interruption during critical phases.

Automation Without the Black Box

The foundation of trust is interpretability. Through the Activity Log, Aion explains its decisions in real-time. This transparency transforms Aion from a blunt automation tool into a reliable, auditing system that respects your Mac’s true state.


Project: aion.7caifei.com

Aether:离开键盘鼠标,开启 Mac 的无接触交互

中文版 | English

🚀 创造者说:寻找键盘鼠标之外的自由度

写 Aether 的念头,产生于一个很随性的瞬间:当我想更自由地坐着、站着,或者干脆离那堆沉重的物理外设远一点时,我不希望丧失对 Mac 的掌控权。

借助你戴着的耳机,Aether 想做的是一种**“无接触交互”**:让你离开键盘鼠标,依然能通过语音和头部姿态掌控全局。

Aether 的三层能力架构

在 Aether 的设计里,它是分层级帮你接管系统的:

  1. 语音输入:提供按住说话、唤醒词及免提模式。它不仅仅是听写,更是为了让你在回消息、重命名或编辑短文本时,文字能直接精准地落入你正在操作的那个输入框里。
  2. 语音控制:将语音指令转化为点击、双击、撤销、滚动等系统动作。它的价值在于“分流”,把那些频繁把你拉回触控板的小干扰交给声音去处理。
  3. 头控指针:利用耳机的轴向数据映射光标位置。配合我的校准算法,它给了你一个“看哪儿指哪儿”的自然出口,并有效缓解了硬件本身不可避免的传感器漂移。

确定性的意图仲裁

语音交互最大的痛点,就是分不清你是在“正常的说话”还是在“严肃的下令”。

我在底层设计了一套基于证据的仲裁机制。它不再盲目猜测,而是通过分析你当前的控制模式、指令前缀以及识别的置信度,判定每一声语音的真实意图。这种工程上的确定性,确保了你在想执行“滚动”或“点击”时,系统能给出连贯、可预测的反馈。


项目官网: aether.7caifei.com


[EN] 🚀 Maker’s Note: Reclaiming Freedom Without Peripheral Constraints

Aether was born from the desire for physical freedom—the ability to control your Mac while leaning back or standing away from the desk.

The Three Layers of Aether

  1. Voice Input: Supporting Push to Talk, Wake Word, and Hands-free modes for “direct-to-field” text entry.
  2. Voice Actions: Translating speech into deterministic commands like click, scroll, and drag, offloading micro-interactions.
  3. Head Pointer: Mapping earbud motion to the cursor with calibration logic to mitigate hardware sensor drift.

Evidence-Based Intent Arbitration

The core friction in voice UI is resolving the conflict between “speaking” and “commanding.” Aether implements an Evidence-Based Utterance Arbitrator that routes voice data based on specific patterns:

  • State Logic: Analyzes the current control mode and evidence stability (Stable/Live typing).
  • Confidence Scoring: Only executes commands when high-confidence intent matches a known router decision.

This deterministic approach ensures that your voice intent is captured and routed correctly, providing a reliable interaction layer that adapts to you, not the other way around.


Project: aether.7caifei.com

本文包含中文与英文两个版本。
This post includes both Chinese and English versions.

中文版

现象

这次遇到的问题是:Antigravity 聊天框里消息可以发出去,但一直没有回复

最开始最显眼的报错是:

1
2
3
4
5
[Error] Server initialization failed.
Message: Pending response rejected since connection got disposed

[Error] antigravity client: couldn't create connection to server.
Error: connect ECONNREFUSED 127.0.0.1:60557

另外还有一条容易让人分心的错误:

1
Error generating commit message: [unknown] core.repositoryformatversion does not support extension: worktreeconfig

但排查到最后,这两类信息都不是根因。

先排掉假线索

第一条假线索是 worktreeconfig
它确实会影响 Git 相关能力,比如自动生成 commit message,但它和聊天框“不回复”不是一条链路。

第二条假线索是 ECONNREFUSED
继续追日志后会发现,language server 后面其实已经成功拉起:

1
2
3
4
LS lspClient started successfully
Language server started
loadCodeAssist
fetchAvailableModels

所以端口拒绝连接更像是启动阶段的一次短暂失败,而不是最后把聊天功能彻底卡死的根因。

真正的问题在 renderer

真正关键的报错出现在 renderer 日志里:

1
[createInstance] ... depends on UNKNOWN service agentSessions

同时还能看到类似提示:

1
command 'workbench.action.chat.newChat' not found

这说明问题已经不只是 language server,而是聊天工作台本身依赖的会话服务没有被正常注册
也就是说,输入框虽然还在,但聊天的前端主链路已经坏了。

为什么重装当前版本没用

我后面做了一个关键对比:不仅看本机 /Applications/Antigravity.app,还去下载并比对了当时官方 releases 提供的当前版本安装包。

结论是:

  1. 本机当前版本和官方当前版本是一致的。
  2. 所以不是“这台机器装坏了”。
  3. 至少在这次命中的链路里,当时的当前官方包本身就有问题

也正因为如此,单纯删掉再重装最新版没有意义。

为什么没有直接热补丁 App 包

排查过程中,我一度已经定位到工作台主包里可疑的注册缺失点,也做过本地补丁尝试。

但在 macOS 上很快就会撞到系统安全策略:

1
2
Security policy would not allow process
The file is adhoc signed or signed by an unknown certificate chain

意思很直接:

  1. 技术上能改。
  2. 但改完的包不适合长期稳定运行。
  3. 因为只要动了已签名 App 的资源,后面就会遇到签名链、AMFI 或系统策略的问题。

所以“直接热补丁现有安装包”不是一个稳妥方案。

最后可用的修法

最后真正可用的修法不是继续硬修当前版本,而是:

  1. 换成一份官方签名的旧版 Antigravity 1.20.6
  2. 把 language server 路径一起切到这份旧版自带的二进制。
  3. 关闭自动更新,避免它再次跳回坏版本。

关键配置在:

1
$HOME/Library/Application Support/Antigravity/User/settings.json

核心字段如下:

1
2
3
4
5
{
"codeiumDev.languageServerBinaryPath": "$HOME/Applications/Antigravity 1.20.6.app/Contents/Resources/app/extensions/antigravity/bin/language_server_macos_arm",
"antigravity.persistentLanguageServer": false,
"update.mode": "none"
}

其中:

  • codeiumDev.languageServerBinaryPath:强制指向旧版 1.20.6 自带的 language server。
  • antigravity.persistentLanguageServer: false:避免继续黏住旧的异常状态。
  • update.mode: none:防止自动更新把运行链路再次切回坏版本。

这条路更稳的原因在于:它仍然使用的是官方签名包,没有继续破坏应用完整性。

这次排查最值得记住的几点

  1. 不要被第一条报错带偏。
  2. 要先区分“噪音错误”和“致命错误”。
  3. 不要默认“重装最新版”一定有用。
  4. 在 macOS 上,热补丁已签名 App 通常不是长期修法。
  5. 如果问题确实出在某个发布版本里,官方签名旧版 + 锁版本 往往比自行魔改更现实。

结语

这次问题最难的地方,不是没有日志,而是日志太多,而且有不少误导项

表面看像 language server,像 Git,像本地缓存,最后真正影响聊天恢复的,却是工作台聊天链路和版本选择。

最后真正把它拉回正常的,不是继续修当前安装,而是:

回退到官方签名的 1.20.6,切换 language server 路径,并锁住更新。


English Version

Symptom

The problem looked simple at first: messages could be sent in Antigravity chat, but no reply ever came back.

The first errors that stood out were:

1
2
3
4
5
[Error] Server initialization failed.
Message: Pending response rejected since connection got disposed

[Error] antigravity client: couldn't create connection to server.
Error: connect ECONNREFUSED 127.0.0.1:60557

There was also another distracting error:

1
Error generating commit message: [unknown] core.repositoryformatversion does not support extension: worktreeconfig

In the end, neither of them turned out to be the real root cause.

Removing the false leads first

The worktreeconfig error was the first false lead.
It can affect Git-related features such as commit message generation, but it is not on the same path as “chat sends but never replies”.

The second false lead was ECONNREFUSED.
Once I kept reading the logs, it became clear that the language server was eventually starting successfully:

1
2
3
4
LS lspClient started successfully
Language server started
loadCodeAssist
fetchAvailableModels

So the refused localhost port looked more like a startup race or transient failure, not the final blocker.

The real failure was in the renderer

The truly important error showed up in the renderer log:

1
[createInstance] ... depends on UNKNOWN service agentSessions

There was also a related message like:

1
command 'workbench.action.chat.newChat' not found

That changes the diagnosis completely.
At that point, the issue is no longer just the language server. It means the chat workbench itself is missing a required session service registration.

In other words, the input box may still be visible, but the front-end chat pipeline is already broken.

Why reinstalling the current version did not help

I compared not only the local /Applications/Antigravity.app, but also the then-current official installer downloaded from the official releases feed.

The result was:

  1. The local current version matched the official current version.
  2. So this was not simply “a corrupted install on this Mac”.
  3. On the code path I hit during this debugging session, the current official build itself appeared to be problematic.

That is why deleting and reinstalling the latest version did not meaningfully help.

Why I did not hot-patch the app bundle

At one point I had already narrowed the issue down to a suspicious missing registration in the workbench bundle and even tried building a local patch.

On macOS, that quickly runs into system policy:

1
2
Security policy would not allow process
The file is adhoc signed or signed by an unknown certificate chain

That means:

  1. You can patch it technically.
  2. But the patched app is not a good long-term runtime target.
  3. Once you modify resources inside a signed app, you start fighting code signing, AMFI, and system policy.

So “hot-patching the installed app” is not a reliable long-term fix.

The fix that actually worked

The working solution was not to keep patching the broken current version, but to:

  1. Switch to an officially signed older build, Antigravity 1.20.6.
  2. Repoint the language server path to the binary shipped inside that build.
  3. Disable auto-update so it would not jump back to the broken version.

The key configuration lives in:

1
$HOME/Library/Application Support/Antigravity/User/settings.json

The important fields were:

1
2
3
4
5
{
"codeiumDev.languageServerBinaryPath": "$HOME/Applications/Antigravity 1.20.6.app/Contents/Resources/app/extensions/antigravity/bin/language_server_macos_arm",
"antigravity.persistentLanguageServer": false,
"update.mode": "none"
}

Why this is safer:

  • It keeps using an officially signed build.
  • It avoids breaking the integrity of the installed app bundle.
  • It pins the runtime to a version that still behaves normally.

The most useful lessons from this debugging session

  1. Do not let the first visible error dictate the whole investigation.
  2. Separate noisy errors from fatal ones.
  3. Do not assume reinstalling the latest build will always help.
  4. On macOS, patching a signed app is rarely the best long-term answer.
  5. If a release itself is the problem, an officially signed older version plus update pinning is often much more practical.

Closing note

The hardest part of this issue was not the lack of logs.
It was the opposite: there were too many logs, and several of them were misleading.

At first glance it looked like a language server problem, or a Git problem, or a cache problem.
In the end, the real issue was the chat workbench path itself and the version being used.

What finally brought the app back to a usable state was:

rolling back to the officially signed 1.20.6 build, repointing the language server path, and locking updates.

UE5 插件开发:C++ Tooltip 本地化失效的避坑指南

在进行 UE 插件开发时,我们通常会为 UPROPERTY 编写注释,期望这些注释能作为 Tooltip 在编辑器中显示,并支持多语言本地化。但在实际操作中,经常会遇到翻译失效的问题。

问题现象

当你完成了以下步骤:

  1. 代码注释: 编写了 /** My Tooltip with \n Newline */
  2. 文本收集: 成功 Gather 到了对应的 SourceString。
  3. 完成翻译: 在 PO 文件中填好了对应的中文并编译为 LocRes。

却发现编辑器里悬停显示的依然是旧的英文,甚至当你删除了代码中的注释,编辑器里依然顽固地显示着之前的旧文本。

这种情况通常不是缓存的问题,而是掉进了 UE 本地化中最隐蔽的陷阱:UHT 元数据持久化 (Metadata Persistence)


原因分析

UE 的 Tooltip 并非在运行时直接读取代码注释,其真实流程如下:

  1. 编译期 (UHT): Unreal Header Tool 解析 .h 文件。它读取注释并将其转换为一个字符串常量,作为 MetaData 烧录进生成的 .gen.cpp 文件中,最终编译进二进制。
  2. 运行期 (Editor): 编辑器通过反射系统 (FProperty::GetToolTipText) 获取这个硬编码在二进制里的 SourceString
  3. 查字典: 编辑器拿着这个 SourceString 去 LocRes 里寻找匹配的翻译。

核心症结:SourceString 的不确定性

UHT 在处理注释时非常不透明:

  • 它可能会将 /** A \n B */ 解析为 "A\nB",也可能解析为 "A B"
  • 解析结果受操作系统换行符(CRLF/LF)和缩进的影响。

导致失效的典型场景:

  1. 最初写的注释生成的 Key A 被烧录进了二进制。
  2. 你发现翻译不对,修改了注释,UHT 生成了 Key B。
  3. 由于增量编译或构建缓存的原因,二进制文件没有彻底更新,或者 UHT 认为该 .h 无需重新处理。
  4. 结果是:LocRes 里存的是 Key B 的翻译,但二进制里残留的依然是 Key A。 由于 SourceString 不匹配,翻译永远无法生效。

解决方案:显式元数据 (Explicit Meta)

与其去猜测 UHT 会如何解析注释,不如直接接管这个过程。

最佳实践:对于必须本地化的编辑器属性,不要依赖注释,直接使用显式元数据。

修改方式

1
2
3
4
5
6
7
8
9
10
11
// ❌ 依赖注释(不推荐)
/**
* The Enhanced Input Action.
* Triggers the attack.
*/
UPROPERTY(EditAnywhere)
UInputAction* InputAction;

// ✅ 显式覆盖(推荐)
UPROPERTY(EditAnywhere, meta=(ToolTip="The Enhanced Input Action. Triggers the attack."))
UInputAction* InputAction;

为什么这样做有效?

  1. 跳过不确定解析: meta=(ToolTip="...") 是直接赋值。UHT 不会对其进行任何“智能化”处理,你写什么,二进制里就是什么。
  2. 跨平台一致性: 无论什么操作系统或 IDE,这个字符串在二进制层面上是绝对一致的。
  3. 强制 UHT 更新: 修改 meta 会明确告知 UHT 文件已变更,从而确保重新编译并刷新二进制中的元数据。

结语

如果你遇到了“代码改了、翻译更新了,但编辑器死活不认”的本地化难题,请尝试以下操作:

  1. 放弃依赖注释: 在对应的 UPROPERTY 中添加 meta=(ToolTip="你的文本")
  2. 手动强制更新: 如果可能,清理并重新编译项目,确保二进制中的 SourceString 被刷新。
  3. 重新收集文本: 运行一次新的 Gather Text 流程。

这通常是解决 UE Tooltip 本地化顽疾最稳妥、最高效的方法。

MacMessageBackup:iMessage 和通话记录备份到 Gmail

把 macOS 上的短信和通话记录备份到 Gmail,支持日历同步。原生 SwiftUI 界面,菜单栏常驻。


为什么做这个

iMessage 数据只存在本地 ~/Library/Messages/chat.db,换电脑或者重装系统就没了。

之前用过 SMS Backup+ 备份安卓短信到 Gmail,体验很好 —— 邮件搜索功能用来找历史记录非常方便。macOS 上没找到类似的工具,就自己写了一个。

功能

iMessage & 短信 → Gmail
通话记录 → Gmail(保留时长、类型等元数据)
通话记录 → 日历同步(方便在日历里回看)
断点续传 - 记录进度,中断后继续
菜单栏常驻 - 实时显示进度如 “52/460”

效果

备份后在 Gmail 里长这样:

  • 每条短信/通话是一封邮件
  • 自动加 Label 分类(如 SMS 或Call Log`)
  • 保留原始时间戳,按日期排序

技术实现

数据读取

直接读 SQLite 数据库:

1
2
短信:~/Library/Messages/chat.db
通话:~/Library/Application Support/CallHistoryDB/CallHistory.storedata

需要 Full Disk Access 权限,应用首次启动会引导授权。

上传到 Gmail

用 Python 的 imaplib 做批量 IMAP APPEND。

为什么用 Python 而不是纯 Swift?

  • Swift 的 IMAP 库不太成熟
  • Python 复用连接,批量上传很快(每秒几百条)
  • macOS 自带 Python 3,不需要额外依赖

流程:

1
Swift 读取数据库 → 生成 .eml 文件 → Python 批量 IMAP APPEND → Gmail

密码安全

Gmail 应用专用密码存在 macOS Keychain 里,不走任何中间服务器。

安装使用

系统要求:macOS 13.0+

步骤

① 下载或编译 app
② 首次运行右键"打开"(绕过 Gatekeeper)
③ 授权 Full Disk Access
④ 填入 Gmail 和应用专用密码
⑤ 点 Backup

生成应用专用密码

Google 账户 → 安全性 → 两步验证 → 应用专用密码

不要用主密码。

代码结构

1
2
3
4
5
6
7
8
9
10
11
12
MacMessageBackup/
├── App/ # 入口
├── Models/ # Message, CallRecord, BackupConfig
├── Services/
│ ├── IMAPService.swift # Gmail 上传核心(运行时生成 Python 脚本)
│ ├── MessageDatabaseService.swift
│ ├── CallHistoryService.swift
│ └── LocalCalendarService.swift
└── Views/
├── ContentView.swift
├── MenuBarView.swift
└── SettingsView.swift

已知限制

  • 只读备份,不能从 Gmail 还原回手机(iOS 系统限制)
  • 需要 Full Disk Access 权限
  • 没有 Apple 开发者签名,首次运行要手动信任

🔗 项目地址:GitHub - MacMessageBackup

MIT License

0%