Skip to content

Extension silently fails to activate when locale folder contains non-locale subdirectories (e.g. namespace directories)Β #1372

@gkn1234

Description

@gkn1234

Scenario

I'm working on a Nuxt 4 project using @nuxtjs/i18n 10.1.0. My translations are organized by namespace β€” each feature area has its own subdirectory under i18n/locales/:

i18n/locales/
β”œβ”€β”€ en.json              ← global keys
β”œβ”€β”€ zh.json
β”œβ”€β”€ home/
β”‚   β”œβ”€β”€ en.json          ← $t('home.gallery.collection')
β”‚   └── zh.json
β”œβ”€β”€ workspace/
β”‚   β”œβ”€β”€ en.json          ← $t('workspace.export.title')
β”‚   └── zh.json
β”œβ”€β”€ assets/
β”œβ”€β”€ config/
β”œβ”€β”€ dialog/
β”œβ”€β”€ error/
β”œβ”€β”€ generate/
β”œβ”€β”€ guide/
β”œβ”€β”€ ...                  ← ~20 namespace directories in total

My .vscode/settings.json:

"i18n-ally.localesPaths": ["i18n/locales"],
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{namespace?}/?{locale}.json",
"i18n-ally.keystyle": "nested"

Problem

After installing i18n Ally v2.13.1, the extension appears activated (icon shows in Activity Bar), but:

  • Sidebar shows 0 keys in use
  • No inline translation annotations in .vue files
  • Output panel stops at πŸš€ Initializing loader "..." with no further output β€” no error, no warning

The extension fails completely silently.

Investigation

  1. Checked Output panel (i18n Ally) β€” log stops abruptly after πŸš€ Initializing loader, missing expected subsequent lines like πŸ“‚ Directory structure:, πŸ“‚ Loading locales under, βœ… Loading finished

  2. Opened Developer Tools (Cmd+Shift+P β†’ Developer: Toggle Developer Tools) β†’ Console shows:

    Activating extension 'lokalise.i18n-ally' failed: Invalid language tag: home.
    
  3. Traced through the source code β€” the crash occurs in LocaleLoader.guessDirStructure():

    const positives = dirnames
      .map(d => Config.tagSystem.lookup(d))

    Config.tagSystem.lookup() calls Intl.getCanonicalLocales() internally. When it encounters a directory named home (which is not a valid BCP47 language tag), Intl.getCanonicalLocales('home') throws RangeError: Invalid language tag: home.

    This exception is not caught anywhere in the call chain (guessDirStructure β†’ init β†’ initLoader β†’ update β†’ updateRootPath), causing the entire extension activation to fail.

Root cause

Same as #701 (reported Dec 2021, still open). The guessDirStructure() method assumes all subdirectory names under localesPaths are either valid locale codes or will be handled gracefully. In reality, namespace-based directory structures (which is a common pattern and even documented in the i18n Ally wiki) produce directory names like home, assets, dialog that are not valid BCP47 tags.

Suggested fix

Wrap the lookup call in a try-catch so invalid tags are treated as non-locale directories (which is the correct behavior for the "guess" logic):

const positives = dirnames
  .map((d) => {
    try {
      return Config.tagSystem.lookup(d)
    } catch {
      return undefined
    }
  })

Workaround

Explicitly set "i18n-ally.dirStructure": "file" to skip guessDirStructure() entirely.

Environment

  • i18n Ally: v2.13.1
  • VS Code: latest
  • OS: macOS (Darwin 25.2.0)
  • Framework: @nuxtjs/i18n 10.1.0 (Nuxt 4 / Vue 3)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions