Well, the only reason I can think of this happening is because something must have called MWNamespace::getCanonicalNamespaces before your extension initialized, thus causing the cache it has to be filled without the extension's namespaces. Maybe try calling MWNamespace::getCanonicalNamespaces( true ) to force regeneration?
Good call. This is part of the story. Part of what I had been doing in the wgExtensionFunctions hook was:
1) $wgCentralBannerDispatcher = "{$wgScript}/{$wgContLang->specialPage( 'BannerRandom' )}"; --> Eventually makes a call to Language->getNamespaces() which then caches the localized namespace names
2) Add custom namespaces.
If I reverse the order it works. However -- because I've already created the initial cache in Language -- and because this local cache does not get invalidated when getCanonicalNamespaces(true) gets called -- anything further down the initialization chain is stuffed.
To fix this I moved the (1) type calls to a ResourceLoaderGetConfigVars hook where they're actually needed. But -- I'm wondering if this is actually a bug in the Language object? Shouldn't it regenerate it's cache when getCanonicalNamespaces changes? (There is a hook that it calls, CanonicalNamespaces, that could potentially support this mechanism.)
~Matt Walker