{"_id":"@contentstorage/vue-i18n-plugin","_rev":"3-aafe72fade8c4f25defb1729c4ac15a3","name":"@contentstorage/vue-i18n-plugin","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.2":{"name":"@contentstorage/vue-i18n-plugin","version":"1.0.2","keywords":["vue-i18n","vue","vue3","contentstorage","translation","live-editor","i18n","internationalization"],"author":{"name":"Kaido Hussar","email":"kaido@contentstorage.app"},"license":"MIT","_id":"@contentstorage/vue-i18n-plugin@1.0.2","maintainers":[{"name":"kaidohussar","email":"kaidohus@gmail.com"}],"homepage":"https://github.com/contentstorage/vue-i18n-plugin#readme","bugs":{"url":"https://github.com/contentstorage/vue-i18n-plugin/issues"},"dist":{"shasum":"527030cb2e04d0d5957c02abb56792add37fe10a","tarball":"https://registry.npmjs.org/@contentstorage/vue-i18n-plugin/-/vue-i18n-plugin-1.0.2.tgz","fileCount":18,"integrity":"sha512-cK8ZYjX7E+c5Zlv1vAaVj1LkU1PJywhsbsxIXdhCEaldcRuMDoXK3jlqtXZLI5GeeRgKgXFrbl+axc7m7UC1Iw==","signatures":[{"sig":"MEUCIQDOCtDOspiIpz969gbq+rFnckGWi/cTC4KpDoffMUxCzAIgGMPORTEJEeE9fFLy6VMfZBo6Xej2CQbIJvl5g6+cn8M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":199867},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"addeb53dd999e2a54e48ab6a0791ba76e7b6236d","scripts":{"dev":"rollup -c -w","test":"jest","build":"rollup -c","format":"prettier --write \"src/**/*.ts\"","release":"npx release-it","type-check":"tsc --noEmit","format:check":"prettier --check \"src/**/*.ts\"","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaidohussar","email":"kaidohus@gmail.com"},"repository":{"url":"git+https://github.com/contentstorage/vue-i18n-plugin.git","type":"git"},"_npmVersion":"10.9.3","description":"Vue-i18n plugin for Contentstorage live editor translation tracking","directories":{},"_nodeVersion":"22.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","jest":"^29.7.0","tslib":"^2.6.2","rollup":"^4.9.4","ts-jest":"^29.1.1","prettier":"^3.7.4","vue-i18n":"^9.9.0","release-it":"^19.0.5","typescript":"^5.3.3","@types/jest":"^29.5.11","@types/node":"^20.10.6","@vue/test-utils":"^2.4.3","jest-environment-jsdom":"^29.7.0","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-typescript":"^11.1.6","@rollup/plugin-node-resolve":"^15.2.3","@release-it/conventional-changelog":"^10.0.1"},"peerDependencies":{"vue":">=3.0.0","vue-i18n":">=9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/vue-i18n-plugin_1.0.2_1765779718619_0.2504187675005627","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@contentstorage/vue-i18n-plugin","version":"1.0.3","keywords":["vue-i18n","vue","vue3","contentstorage","translation","live-editor","i18n","internationalization"],"author":{"name":"Kaido Hussar","email":"kaido@contentstorage.app"},"license":"MIT","_id":"@contentstorage/vue-i18n-plugin@1.0.3","maintainers":[{"name":"kaidohussar","email":"kaidohus@gmail.com"}],"homepage":"https://github.com/contentstorage/vue-i18n-plugin#readme","bugs":{"url":"https://github.com/contentstorage/vue-i18n-plugin/issues"},"dist":{"shasum":"2ea06651aa90b978bf6b3fc0b129a97affc49a0a","tarball":"https://registry.npmjs.org/@contentstorage/vue-i18n-plugin/-/vue-i18n-plugin-1.0.3.tgz","fileCount":18,"integrity":"sha512-Zp2+3iHh0kVmbzNRJnh7VQ5rYLlzCBv6etmSdLOXOFed04L2cUrapdmxMyQmM27zydK5jJ64xFdhrs6zdNcUjw==","signatures":[{"sig":"MEQCIEUgInRcE2LIrBHUnhhf6T5xax1xMdW5b5y0m7KrBwZXAiBeRRh/ypGIiwShHXu386dsh0mF5bx5YXOycWW8/BhUxQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":208230},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"bfe6540ce2e8cc750387bd9dac3ec7fb2c3159c2","scripts":{"dev":"rollup -c -w","test":"jest","build":"rollup -c","format":"prettier --write \"src/**/*.ts\"","release":"npx release-it","type-check":"tsc --noEmit","format:check":"prettier --check \"src/**/*.ts\"","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaidohussar","email":"kaidohus@gmail.com"},"repository":{"url":"git+https://github.com/contentstorage/vue-i18n-plugin.git","type":"git"},"_npmVersion":"10.9.3","description":"Vue-i18n plugin for Contentstorage live editor translation tracking","directories":{},"_nodeVersion":"22.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","jest":"^29.7.0","tslib":"^2.6.2","rollup":"^4.9.4","ts-jest":"^29.1.1","prettier":"^3.7.4","vue-i18n":"^9.9.0","release-it":"^19.0.5","typescript":"^5.3.3","@types/jest":"^29.5.11","@types/node":"^20.10.6","@vue/test-utils":"^2.4.3","jest-environment-jsdom":"^29.7.0","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-typescript":"^11.1.6","@rollup/plugin-node-resolve":"^15.2.3","@release-it/conventional-changelog":"^10.0.1"},"peerDependencies":{"vue":">=3.0.0","vue-i18n":">=9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/vue-i18n-plugin_1.0.3_1766768228777_0.0549983847441291","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@contentstorage/vue-i18n-plugin","version":"1.0.4","description":"Vue-i18n plugin for Contentstorage live editor translation tracking","author":{"name":"Kaido Hussar","email":"kaido@contentstorage.app"},"main":"dist/index.js","module":"dist/index.esm.js","types":"dist/index.d.ts","scripts":{"build":"rollup -c","dev":"rollup -c -w","test":"jest","type-check":"tsc --noEmit","format":"prettier --write \"src/**/*.ts\"","format:check":"prettier --check \"src/**/*.ts\"","prepublishOnly":"npm run build","release":"npx release-it"},"keywords":["vue-i18n","vue","vue3","contentstorage","translation","live-editor","i18n","internationalization"],"license":"MIT","peerDependencies":{"vue":">=3.0.0","vue-i18n":">=9.0.0"},"devDependencies":{"@release-it/conventional-changelog":"^10.0.1","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-typescript":"^11.1.6","@types/jest":"^29.5.11","@types/node":"^20.10.6","@vue/test-utils":"^2.4.3","jest":"^29.7.0","jest-environment-jsdom":"^29.7.0","prettier":"^3.7.4","release-it":"^19.0.5","rollup":"^4.9.4","ts-jest":"^29.1.1","tslib":"^2.6.2","typescript":"^5.3.3","vue":"^3.4.0","vue-i18n":"^9.9.0"},"repository":{"type":"git","url":"git+https://github.com/contentstorage/vue-i18n-plugin.git"},"publishConfig":{"access":"public"},"_id":"@contentstorage/vue-i18n-plugin@1.0.4","gitHead":"e65375f07a793eca627a5834127305261318b97a","bugs":{"url":"https://github.com/contentstorage/vue-i18n-plugin/issues"},"homepage":"https://github.com/contentstorage/vue-i18n-plugin#readme","_nodeVersion":"22.18.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-k53gMd/wBtnkiiN639LvGID7EjpRJHQjM15YW7MjNWMkiJ+RgNgOY+aGDv2s83lWRqtG+biNgXJM8wNJEopN9w==","shasum":"c188e452ea535efdda34d3fc4a2c90f45a13da26","tarball":"https://registry.npmjs.org/@contentstorage/vue-i18n-plugin/-/vue-i18n-plugin-1.0.4.tgz","fileCount":18,"unpackedSize":208648,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGsTvL0hZL/9cPIvhNJgNGIZSHMVMiSlR2VHXrovIYLEAiB/F3dVp+h9kPiEGYCrjqUEGF1qkcxdeFa4Y7Mb67TzdA=="}]},"_npmUser":{"name":"kaidohussar","email":"kaidohus@gmail.com"},"directories":{},"maintainers":[{"name":"kaidohussar","email":"kaidohus@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vue-i18n-plugin_1.0.4_1766778054898_0.44254671528178435"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-15T06:21:58.525Z","modified":"2025-12-26T19:40:56.438Z","1.0.2":"2025-12-15T06:21:58.763Z","1.0.3":"2025-12-26T16:57:08.913Z","1.0.4":"2025-12-26T19:40:56.214Z"},"bugs":{"url":"https://github.com/contentstorage/vue-i18n-plugin/issues"},"author":{"name":"Kaido Hussar","email":"kaido@contentstorage.app"},"license":"MIT","homepage":"https://github.com/contentstorage/vue-i18n-plugin#readme","keywords":["vue-i18n","vue","vue3","contentstorage","translation","live-editor","i18n","internationalization"],"repository":{"type":"git","url":"git+https://github.com/contentstorage/vue-i18n-plugin.git"},"description":"Vue-i18n plugin for Contentstorage live editor translation tracking","maintainers":[{"name":"kaidohussar","email":"kaidohus@gmail.com"}],"readme":"# Contentstorage vue-i18n Plugin\n\nOfficial vue-i18n plugin for [Contentstorage](https://contentstorage.app) live editor translation tracking.\n\n## Features\n\n- **Live Editor Integration** - Automatically detects and enables tracking when running in Contentstorage live editor\n- **Translation Tracking** - Maps translation values to their keys for click-to-edit functionality\n- **Zero Production Overhead** - Tracking only activates in live editor mode\n- **TypeScript Support** - Full type definitions included\n- **Memory Management** - Automatic cleanup of old entries to prevent memory leaks\n- **CDN Loading** - Optional support for loading translations from CDN\n- **Flexible Integration** - Works with both new and existing vue-i18n instances\n\n## Installation\n\n```bash\nnpm install @contentstorage/vue-i18n-plugin\n```\n\n## Quick Start\n\n### Basic Usage\n\n```typescript\nimport { createApp } from 'vue';\nimport { createContentstorageI18n } from '@contentstorage/vue-i18n-plugin';\nimport App from './App.vue';\n\nconst i18n = createContentstorageI18n({\n  // ContentStorage options\n  contentKey: 'your-content-key-here', // Get this from Contentstorage dashboard\n  debug: false,\n\n  // vue-i18n options\n  locale: 'en',\n  fallbackLocale: 'en',\n  messages: {\n    en: {\n      welcome: 'Welcome to our site',\n      greeting: 'Hello {name}!',\n    },\n    es: {\n      welcome: 'Bienvenido a nuestro sitio',\n      greeting: 'Hola {name}!',\n    },\n  },\n});\n\nconst app = createApp(App);\napp.use(i18n);\napp.mount('#app');\n\n// Use translations as normal with useI18n() or $t()\n// Live editor tracking is automatically enabled when in live editor mode!\n```\n\n### With CDN Loading\n\nLoad translations dynamically from ContentStorage CDN:\n\n```typescript\nimport { createContentstorageI18n } from '@contentstorage/vue-i18n-plugin';\n\nconst i18n = createContentstorageI18n({\n  contentKey: 'your-content-key',\n  enableCdnLoading: true,\n  preloadLanguages: ['en', 'es'], // Preload these languages on init\n  locale: 'en',\n});\n\napp.use(i18n);\n\n// Load additional languages on demand\nawait i18n.contentStorage.loadLanguage('fr');\n```\n\n### Attaching to Existing Instance\n\nIf you already have a vue-i18n instance:\n\n```typescript\nimport { createI18n } from 'vue-i18n';\nimport { attachContentstorageTracker } from '@contentstorage/vue-i18n-plugin';\n\nconst i18n = createI18n({\n  legacy: false, // Required for tracking support\n  locale: 'en',\n  messages: {\n    en: { welcome: 'Welcome' },\n  },\n});\n\n// Attach ContentStorage tracking\nconst tracker = attachContentstorageTracker(i18n, {\n  contentKey: 'your-key',\n  debug: true,\n});\n\n// Check if in live mode\nif (tracker.inLiveMode) {\n  console.log('Live editor mode active');\n}\n```\n\n## Configuration Options\n\n```typescript\ninterface ContentstorageVueI18nOptions {\n  /**\n   * Your Contentstorage content key (required for CDN loading)\n   */\n  contentKey?: string;\n\n  /**\n   * Enable debug logging\n   * @default false\n   */\n  debug?: boolean;\n\n  /**\n   * Maximum number of entries in memoryMap\n   * @default 10000\n   */\n  maxMemoryMapSize?: number;\n\n  /**\n   * Custom path for loading translations\n   * @example '{{lng}}.json'\n   * @example (lng) => `https://my-cdn.com/${lng}.json`\n   */\n  loadPath?: string | ((language: string) => string);\n\n  /**\n   * Custom fetch implementation\n   */\n  request?: (url: string, options: RequestInit) => Promise<any>;\n\n  /**\n   * Query parameter name for live editor detection\n   * @default 'contentstorage_live_editor'\n   */\n  liveEditorParam?: string;\n\n  /**\n   * Force live mode (useful for testing)\n   * @default false\n   */\n  forceLiveMode?: boolean;\n\n  /**\n   * Custom URL for the live editor script\n   * @default 'https://cdn.contentstorage.app/live-editor.js?contentstorage-live-editor=true'\n   */\n  customLiveEditorScriptUrl?: string;\n\n  /**\n   * Languages to preload from CDN on initialization\n   */\n  preloadLanguages?: string[];\n\n  /**\n   * Enable automatic translation loading from CDN\n   * @default false\n   */\n  enableCdnLoading?: boolean;\n}\n```\n\n### Manual Translation Tracking\n\nWhen loading translations from custom sources:\n\n```typescript\nconst i18n = createContentstorageI18n({\n  forceLiveMode: true,\n  locale: 'en',\n});\n\n// Load translations from your own source\nconst customTranslations = await fetchMyTranslations('de');\n\n// Set them in vue-i18n\ni18n.global.setLocaleMessage('de', customTranslations);\n\n// Track them for live editor\ni18n.contentStorage.trackMessages(customTranslations, 'de');\n```\n\n### Enable Debug Mode\n\n```typescript\nconst i18n = createContentstorageI18n({\n  contentKey: 'your-key',\n  debug: true,\n  locale: 'en',\n  messages: { en: { welcome: 'Welcome' } },\n});\n\n// Console output:\n// [ContentStorage] Live editor mode enabled\n// [ContentStorage] Tracker attached to vue-i18n instance\n// [ContentStorage] Tracked 1 initial translations for en\n```\n\n## How It Works\n\n### Live Editor Detection\n\nThe plugin automatically detects when your app is running in the Contentstorage live editor by checking:\n\n1. The app is running in an iframe (`window.self !== window.top`)\n2. The URL contains the query parameter `?contentstorage_live_editor=true`\n\nBoth conditions must be true for tracking to activate.\n\n### Translation Tracking\n\nWhen in live editor mode, the plugin:\n\n1. Sets up a `postTranslation` handler in vue-i18n\n2. Intercepts each translation call\n3. Retrieves the template (with `{placeholders}`) from the message store\n4. Tracks it in the global `window.memoryMap`\n\n```typescript\nwindow.memoryMap = new Map([\n  [\"Welcome to our site\", {\n    ids: Set([\"welcome\"]),\n    type: \"text\",\n    metadata: {\n      language: \"en\",\n      trackedAt: 1704067200000\n    }\n  }],\n  [\"Hello {name}!\", {\n    ids: Set([\"greeting\"]),\n    type: \"text\",\n    metadata: {\n      language: \"en\",\n      trackedAt: 1704067200001\n    }\n  }],\n]);\n```\n\nThis allows the Contentstorage live editor to:\n1. Find which translation keys produced a given text\n2. Enable click-to-edit functionality\n3. Highlight translatable content on the page\n\n### Memory Management\n\nThe plugin automatically limits the size of `window.memoryMap` to prevent memory leaks:\n\n- Default limit: 10,000 entries\n- Oldest entries are removed first (based on `trackedAt` timestamp)\n- Configurable via `maxMemoryMapSize` option\n\n## Usage with Vue 3 Composition API\n\n```typescript\n// main.ts\nimport { createApp } from 'vue';\nimport { createContentstorageI18n } from '@contentstorage/vue-i18n-plugin';\nimport App from './App.vue';\n\nconst i18n = createContentstorageI18n({\n  contentKey: 'your-key',\n  locale: 'en',\n  messages: {\n    en: { welcome: 'Welcome', greeting: 'Hello {name}!' },\n  },\n});\n\ncreateApp(App).use(i18n).mount('#app');\n```\n\n```vue\n<!-- Component.vue -->\n<script setup lang=\"ts\">\nimport { useI18n } from 'vue-i18n';\n\nconst { t } = useI18n();\n</script>\n\n<template>\n  <h1>{{ t('welcome') }}</h1>\n  <p>{{ t('greeting', { name: 'John' }) }}</p>\n</template>\n```\n\n## Testing\n\n### Force Live Mode\n\nFor testing purposes, you can force live mode:\n\n```typescript\nconst i18n = createContentstorageI18n({\n  forceLiveMode: true, // Always enable tracking\n  locale: 'en',\n  messages: { en: { test: 'Test' } },\n});\n```\n\n### Debug Memory Map\n\n```typescript\nimport { debugMemoryMap } from '@contentstorage/vue-i18n-plugin';\n\n// In browser console or your code\ndebugMemoryMap();\n\n// Output:\n// [ContentStorage] Memory map contents:\n// Total entries: 42\n// ┌─────────┬──────────────────────────────┬─────────────────────┐\n// │ (index) │ value                        │ keys                │\n// │ language                                                     │\n// ├─────────┼──────────────────────────────┼─────────────────────┤\n// │    0    │ 'Welcome to our site'        │ 'welcome'           │\n// │ 'en'                                                         │\n// └─────────┴──────────────────────────────┴─────────────────────┘\n```\n\n## Browser Support\n\n- Modern browsers (Chrome, Firefox, Safari, Edge)\n- Vue 3.0+\n- vue-i18n 9.0+\n\n## TypeScript\n\nFull TypeScript support included:\n\n```typescript\nimport type {\n  ContentstorageVueI18nOptions,\n  CreateContentstorageI18nOptions,\n  MemoryMap,\n  MemoryMapEntry,\n  ContentstorageWindow,\n} from '@contentstorage/vue-i18n-plugin';\n```\n\n## Performance\n\n- **Zero overhead in production** - Tracking only happens in live editor mode\n- **Minimal overhead in editor** - Simple Map operations, ~1ms per translation\n- **Automatic cleanup** - Old entries removed to prevent memory leaks\n- **Efficient template lookup** - Templates retrieved from vue-i18n's message store\n\n## Troubleshooting\n\n### memoryMap is empty\n\n**Problem**: `window.memoryMap` exists but has no entries.\n\n**Solutions**:\n- Verify you're in an iframe: `window.self !== window.top`\n- Check URL has `?contentstorage_live_editor=true`\n- Enable debug mode to see what's being tracked\n- Ensure vue-i18n is using composition mode (`legacy: false`)\n\n### Live editor can't find translations\n\n**Problem**: Clicking on translated text doesn't work in live editor.\n\n**Solutions**:\n- Verify translation values match rendered text\n- Check that tracking happens before DOM renders\n- Enable debug mode and check console logs\n\n### TypeScript errors\n\n**Problem**: TypeScript can't find type definitions.\n\n**Solutions**:\n- Ensure vue-i18n types are installed\n- Check `tsconfig.json` has `\"esModuleInterop\": true`\n\n### CORS errors\n\n**Problem**: Cannot load translations from CDN.\n\n**Solutions**:\n- Verify your contentKey is correct\n- Check CDN URL in network tab\n- Use custom `request` function to debug\n\n## API Reference\n\n### createContentstorageI18n(options)\n\nCreates a vue-i18n instance with ContentStorage integration.\n\n**Returns**: `ContentstorageI18n` - Extended I18n instance with `contentStorage` utilities\n\n### attachContentstorageTracker(i18n, options)\n\nAttaches tracking to an existing vue-i18n instance.\n\n**Returns**: `ContentstorageTracker` - The tracker instance\n\n### ContentstorageI18n.contentStorage\n\n- `loadLanguage(language: string): Promise<void>` - Load translations from CDN\n- `trackMessages(messages: object, language: string): void` - Manually track translations\n- `isLiveMode: boolean` - Whether live editor mode is active\n- `tracker: ContentstorageTracker` - The underlying tracker\n- `loader: ContentstorageLoader | null` - The CDN loader (if enabled)\n\n### Utility Exports\n\n- `debugMemoryMap()` - Log memory map contents\n- `loadLiveEditorScript()` - Manually load the live editor script\n- `setCurrentLanguageCode(code)` - Set active language\n- `getCurrentLanguageCode()` - Get active language\n- `detectLiveEditorMode()` - Check if in live editor\n- `getMemoryMap()` - Get the memory map directly\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Support\n\n- Documentation: https://docs.contentstorage.app\n- Issues: https://github.com/contentstorage/vue-i18n-plugin/issues\n- Email: support@contentstorage.app\n","readmeFilename":"README.md"}