Skip to content

Conversation

@octavio-vercetti
Copy link

@octavio-vercetti octavio-vercetti commented Nov 7, 2025

Problem

When a developer changes the key property in a .content.ts file (e.g., from 'landing-page' to 'new-landing'), Intlayer's file watcher rebuilds the new dictionary but leaves the old dictionary files in place. This causes:

  • Runtime error: Dictionary {old-key} not found
  • TypeScript errors: Key not in registry
  • Orphaned files in .intlayer/ folder

Root Cause

handleContentDeclarationFileChange only processes the current file's content without checking if the same file previously exported a dictionary with a different key.

Solution

Incremental Fix (@intlayer/chokidar)

When a file changes:

  1. Compare new dictionary keys with existing dictionaries from same file path
  2. Detect key changes by matching filePath property
  3. Delete old dictionary files (unmerged, merged, types)
  4. Rebuild entry points and module augmentation

Cold-Start Fix (vite-intlayer)

Add optional cleanOnStartup config:

intlayer({
  cleanOnStartup: true // Default: false
})

When enabled, wipes .intlayer/ folder on dev server start to guarantee fresh build from source files.

Testing

Manually tested scenarios:

  1. Change key in .content.ts during dev → old files cleaned automatically
  2. Change key while server off, then restart with cleanOnStartup: true → clean rebuild
  3. Multiple key changes in sequence → no orphaned files

Breaking Changes

None. Both features are opt-in or automatic cleanup of invalid state.

- Detect when content file key changes and remove old dictionary files
- Delete unmerged, merged, and type files for changed keys
- Force rebuild of entry points and module augmentation
- Add cleanOnStartup option to vite-intlayer plugin (opt-in)

Fixes issue where changing a dictionary key in .content.ts files
left orphaned dictionary files, causing "Dictionary not found" errors
and TypeScript type mismatches.
Copy link
Owner

@aymericzip aymericzip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @octavio-vercetti, sorry I missed this!

Great job! I was actually going to work on fixing this annoying behavior, and your approach is great, but I had another idea in mind for the implementation

First, I don’t want this kind of “global option” on the intlayer() Vite plugin. This should instead be defined globally in the intlayer.config.ts file to avoid inconsistencies with next-intlayer, react-scripts-intlayer, etc.

Then, regarding the detection of changes in .content files, I was thinking of checking the last time each file was saved. If any file was modified after the last build, then we trigger a rebuild.

This means the check should be done in the prepareIntlayer function. Let me know if you’d be interested in implementing it, otherwise I’ll take care of it in the next few days.

Steps:

  1. Add your cleanOnStartup config field under config.build

    • packages/@intlayer/types/src/config.ts
    • packages/@intlayer/config/src/configFile/buildConfigurationFields.ts
  2. Update forceRun: xxxx to trigger the rebuild

    • packages/@intlayer/chokidar/src/prepareIntlayer.ts

We can move:

const files: string[] = await listDictionaries(configuration);

outside of the runOnce function, and then use fs.stat to detect whether one of these files was modified more recently.

@aymericzip
Copy link
Owner

I implemented the change, closing this PR, but thanks anyway!

068f600

@aymericzip aymericzip closed this Nov 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants