fix(plugins): reject locale ids Intl cannot parse (#12533)

* fix(plugins): reject locale ids Intl cannot parse

`pluginLocaleIdSchema` checks the shape of a locale id but not its grammar,
and the shape check is looser than BCP 47 in one direction: `en-US-US`
(duplicate region) and `en-aaa` (a subtag that is neither region nor script)
both match it. A pack declaring one installs, loads, and translates every
string — and then `Intl.DateTimeFormat` throws inside `getIntlLocale()`, which
swallows the error and falls back to English. Nothing is logged, so the pack
author sees a working pack with English dates and no way to tell why.

Delegate the grammar to `Intl.getCanonicalLocales` in a `.refine`, so the tag
is rejected at install where the author can still act on it. The bundled
`pt-BR` pack and every other well-formed tag are unaffected.

* Condense this branch's comments to one line

AGENTS.md asks for one-line comments that say why, and main's comment
cleanup (#33249) applied that across the repository. This brings the
comments this branch adds in line with it. No code changes.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
Evgenii
2026-10-27 16:22:09 -07:00
committed by GitHub
co-authored by OrcaWin
parent 7a834988dc
commit 6c469aea6d
2 changed files with 23 additions and 0 deletions
@@ -120,6 +120,9 @@ describe('content-pack manifest contributions', () => {
it.each([
['language pack', { languagePacks: [{ locale: 'en_US', path: 'locale.json' }] }],
// Shape-legal but ill-formed: the regex alone let these load with dates falling back to English.
['duplicate region', { languagePacks: [{ locale: 'en-US-US', path: 'locale.json' }] }],
['unknown subtag', { languagePacks: [{ locale: 'en-aaa', path: 'locale.json' }] }],
['language pack path', { languagePacks: [{ locale: 'pt-BR', path: '../outside.json' }] }],
['VM recipe', { vmRecipes: [{ path: '\\\\server\\recipe.json' }] }],
['agent profile', { agents: [{ path: 'agents/../profile.json' }] }]
@@ -127,6 +130,14 @@ describe('content-pack manifest contributions', () => {
expect(parsePluginManifest(manifest(contributes)).ok).toBe(false)
})
it.each(['ru', 'pt-BR', 'zh-Hans-CN', 'en-US'])('accepts the well-formed locale %s', (locale) => {
expect(
parsePluginManifest(manifest({ languagePacks: [{ locale, path: 'locale.json' }] }))
).toMatchObject({
ok: true
})
})
it('rejects duplicate ids, locales, paths, and bindings', () => {
const parsed = pluginManifestSchema.safeParse(
manifest({
@@ -7,12 +7,24 @@ export const PLUGIN_KEYBINDING_LIMIT = 256
export const PLUGIN_VM_RECIPE_LIMIT = 64
export const PLUGIN_AGENT_PROFILE_LIMIT = 64
/** True when Intl can parse the tag's grammar, not just its shape. */
function isWellFormedLocaleId(value: string): boolean {
try {
Intl.getCanonicalLocales(value)
return true
} catch {
return false
}
}
// Locale IDs become filenames/i18next keys; a bounded BCP 47 subset excludes path syntax.
// Intl rejects shape-valid, ill-formed tags (`en-US-US`) at install, not silently when formatting.
export const pluginLocaleIdSchema = z
.string()
.min(2)
.max(35)
.regex(/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/, 'must be a portable locale identifier')
.refine(isWellFormedLocaleId, 'must be a well-formed locale identifier')
export const pluginLanguagePackContributionSchema = z
.object({