What a reader sees
The dialog that runs a step opens with its title translated and everything inside it in English:
對齊 <- braid.label, localized
Cross-link sources and validate the graph globally <- braid.summary, not
Mode * <- inputs[].label, not
Build + Validate <- option label, not
Adds the relationships that only ... <- option description, not
Scope <- inputs[].label, not
Bounded context to focus on, ... <- inputs[].description, not
Whole Graph <- inputs[].placeholder, not
執行 <- the app's own string, localized
Why
SkillManifest.braid.label is localizedText, so a step has a name in both languages. Nothing else a skill declares does:
braid.summary
SkillInputBaseShape.label
SkillInputBaseShape.description
SkillInputBaseShape.placeholder
SkillInputStaticOption.label
SkillInputStaticOption.description
All are z.string(). There is no place to put a translation, so an author who wanted one could not write it.
This was easy to miss while the strings were barely visible. The option descriptions in particular only reached a native <option>'s title, which meant hovering a closed dropdown to read them. Now that they are shown under the field, the gap is in plain sight.
The change
Give those six fields the localizedText shape the label already has, then fill in the translations across the six shipped skills.
localizedText accepts a plain string as well, so existing frontmatter keeps parsing and a skill that offers one language stays valid. That matters for skills outside this repo.
Why it is not folded into #96
It touches the schema and every skill in the repo, and it is unrelated to what that branch is about. Reviewing it beside a block protocol would serve neither.
Also worth deciding
Whether a plugin's skills should be able to declare a language this deployment does not read, and what a surface shows when it cannot find one. localize already falls back, so this is a question about what the fallback should say rather than about whether it exists.
What a reader sees
The dialog that runs a step opens with its title translated and everything inside it in English:
Why
SkillManifest.braid.labelislocalizedText, so a step has a name in both languages. Nothing else a skill declares does:braid.summarySkillInputBaseShape.labelSkillInputBaseShape.descriptionSkillInputBaseShape.placeholderSkillInputStaticOption.labelSkillInputStaticOption.descriptionAll are
z.string(). There is no place to put a translation, so an author who wanted one could not write it.This was easy to miss while the strings were barely visible. The option descriptions in particular only reached a native
<option>'stitle, which meant hovering a closed dropdown to read them. Now that they are shown under the field, the gap is in plain sight.The change
Give those six fields the
localizedTextshape the label already has, then fill in the translations across the six shipped skills.localizedTextaccepts a plain string as well, so existing frontmatter keeps parsing and a skill that offers one language stays valid. That matters for skills outside this repo.Why it is not folded into #96
It touches the schema and every skill in the repo, and it is unrelated to what that branch is about. Reviewing it beside a block protocol would serve neither.
Also worth deciding
Whether a plugin's skills should be able to declare a language this deployment does not read, and what a surface shows when it cannot find one.
localizealready falls back, so this is a question about what the fallback should say rather than about whether it exists.