auto-load extension i18n catalogs; add the missing tab-title ones

Five builtins (tickets, decisions, git, pql, problems) declared a
localized tab title but shipped no catalog and weren't in the hand-kept
preload list, so each logged "namespace not registered" on boot.
ExtensionManager now loads the i18n namespace of every localized
TabContribution when its extension activates — no manual list edit for a
new tab — and the five missing en_US catalogs are added.

T-155.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-23 16:49:56 +02:00
co-authored by Claude Opus 4.7
parent e5fa6302d3
commit 2fd911d01d
11 changed files with 91 additions and 1 deletions
@@ -105,6 +105,48 @@ void main() {
);
});
test('activating an extension auto-loads its localized tab namespace (T-155)', () async {
final local = await KernelFixture.create(
i18nCatalogs: {
'ext.localized': {
const Locale('en', 'US'): {
'tab.title': {'translation': 'Localized'},
},
},
},
preloadNamespaces: const [], // loadable, but not preloaded at boot
);
addTearDown(local.dispose);
// Not registered yet → string() falls back to the placeholder.
expect(
local.services.i18n.string('tab.title', namespace: 'ext.localized', placeholder: 'fallback'),
'fallback',
);
local.services.extensions.register(_Ext(
id: 'ext.localized',
contributions: [
TabContribution(
id: 'ext.localized.view',
slot: Slots.workspace,
title: 'Fallback',
titleKey: 'tab.title',
i18nNamespace: 'ext.localized',
build: (_) => const SizedBox.shrink(),
),
],
));
await local.services.extensions.activateAll();
// Activation auto-loaded the catalog → resolves, no "namespace not
// registered" warning.
expect(
local.services.i18n.string('tab.title', namespace: 'ext.localized', placeholder: 'fallback'),
'Localized',
);
});
test('deactivate removes contributions from the registry', () async {
f.services.extensions.register(_Ext(
id: 'ephemeral',