npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@contentstorage/react-intl-plugin

v1.0.0

Published

react-intl plugin for Contentstorage live editor translation tracking

Readme

Contentstorage React-Intl Plugin

Official react-intl plugin for Contentstorage live editor translation tracking.

Features

  • Live Editor Integration - Automatically detects and enables tracking when running in Contentstorage live editor
  • Translation Tracking - Maps translation values to their message IDs for click-to-edit functionality
  • Zero Production Overhead - Tracking only activates in live editor mode
  • TypeScript Support - Full type definitions included
  • Memory Management - Automatic cleanup of old entries to prevent memory leaks
  • Drop-in Replacement - Simply replace IntlProvider with ContentstorageIntlProvider

Installation

npm install @contentstorage/react-intl-plugin

Quick Start

Basic Usage

Replace react-intl's IntlProvider with ContentstorageIntlProvider:

import { ContentstorageIntlProvider } from '@contentstorage/react-intl-plugin';

function App() {
  const messages = {
    welcome: 'Welcome to our site',
    greeting: 'Hello {name}!',
  };

  return (
    <ContentstorageIntlProvider locale="en" messages={messages}>
      <YourApp />
    </ContentstorageIntlProvider>
  );
}

That's it! Live editor tracking is now enabled when in live editor mode.

How It Works

Live Editor Detection

The plugin automatically detects when your app is running in the Contentstorage live editor by checking:

  1. The app is running in an iframe (window.self !== window.top)
  2. The URL contains the query parameter ?contentstorage_live_editor=true

Both conditions must be true for tracking to activate.

Translation Tracking

When in live editor mode, the plugin maintains a global window.memoryMap that maps translation values to their message IDs:

window.memoryMap = new Map([
  ["Welcome to our site", {
    ids: Set(["welcome", "homepage.title"]),
    type: "text",
    metadata: {
      language: "en",
      trackedAt: 1704067200000
    }
  }],
  // ... more entries
]);

This allows the Contentstorage live editor to:

  1. Find which message IDs produced a given text
  2. Enable click-to-edit functionality
  3. Highlight translatable content on the page

Memory Management

The plugin automatically limits the size of window.memoryMap to prevent memory leaks:

  • Default limit: 10,000 entries
  • Oldest entries are removed first (based on trackedAt timestamp)
  • Configurable via maxMemoryMapSize option

Configuration Options

<ContentstorageIntlProvider
  locale="en"
  messages={messages}

  // Optional: Enable debug logging
  debug={false}

  // Optional: Maximum number of entries in memoryMap
  maxMemoryMapSize={10000}

  // Optional: Force live mode (useful for testing)
  forceLiveMode={false}

  // ... all other IntlProvider props
>
  <YourApp />
</ContentstorageIntlProvider>

Usage with React

With Hooks

import { useIntl, ContentstorageIntlProvider } from '@contentstorage/react-intl-plugin';

function MyComponent() {
  const intl = useIntl();

  return (
    <div>
      <h1>{intl.formatMessage({ id: 'welcome' })}</h1>
      <p>{intl.formatMessage({ id: 'greeting' }, { name: 'User' })}</p>
    </div>
  );
}

function App() {
  return (
    <ContentstorageIntlProvider locale="en" messages={messages}>
      <MyComponent />
    </ContentstorageIntlProvider>
  );
}

With Components

import { FormattedMessage, ContentstorageIntlProvider } from '@contentstorage/react-intl-plugin';

function MyComponent() {
  return (
    <div>
      <h1><FormattedMessage id="welcome" /></h1>
      <p><FormattedMessage id="greeting" values={{ name: 'User' }} /></p>
    </div>
  );
}

function App() {
  return (
    <ContentstorageIntlProvider locale="en" messages={messages}>
      <MyComponent />
    </ContentstorageIntlProvider>
  );
}

Usage with Next.js

App Router (Next.js 13+)

// app/providers.tsx
'use client';

import { ContentstorageIntlProvider } from '@contentstorage/react-intl-plugin';
import messages from './messages/en.json';

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <ContentstorageIntlProvider locale="en" messages={messages}>
      {children}
    </ContentstorageIntlProvider>
  );
}
// app/layout.tsx
import { Providers } from './providers';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Pages Router (Next.js 12 and below)

// pages/_app.tsx
import type { AppProps } from 'next/app';
import { ContentstorageIntlProvider } from '@contentstorage/react-intl-plugin';
import messages from '../messages/en.json';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <ContentstorageIntlProvider locale="en" messages={messages}>
      <Component {...pageProps} />
    </ContentstorageIntlProvider>
  );
}

Testing

Force Live Mode

For testing purposes, you can force live mode:

<ContentstorageIntlProvider
  locale="en"
  messages={messages}
  forceLiveMode={true} // Always enable tracking
>
  <YourApp />
</ContentstorageIntlProvider>

Debug Memory Map

import { debugMemoryMap } from '@contentstorage/react-intl-plugin';

// In browser console or your code
debugMemoryMap();

// Output:
// [Contentstorage] Memory map contents:
// Total entries: 156
// ┌─────────┬──────────────────────────────┬─────────────────────┐
// │ (index) │ value                        │ keys                │
// ├─────────┼──────────────────────────────┼─────────────────────┤
// │    0    │ 'Welcome to our site'        │ 'welcome'           │
// └─────────┴──────────────────────────────┴─────────────────────┘

Browser Support

  • Modern browsers (Chrome, Firefox, Safari, Edge)
  • ES2019+ features required
  • React 16.8+ (hooks support)

TypeScript

Full TypeScript support included with type definitions:

import type {
  ContentstorageIntlProviderProps,
  MemoryMap,
  MemoryMapEntry,
  ContentstorageWindow,
} from '@contentstorage/react-intl-plugin';

Performance

  • Zero overhead in production - Tracking only happens in live editor
  • Minimal overhead in editor - Simple Map operations, ~1ms per translation
  • Automatic cleanup - Old entries removed to prevent memory leaks
  • One-time tracking - Static messages tracked once on load

Troubleshooting

memoryMap is empty

Problem: window.memoryMap exists but has no entries.

Solutions:

  • Verify you're in an iframe: window.self !== window.top
  • Check URL has ?contentstorage_live_editor=true
  • Enable debug mode to see what's being tracked
  • Ensure messages are being passed to provider

Live editor can't find translations

Problem: Clicking on translated text doesn't work in live editor.

Solutions:

  • Verify translation values exactly match rendered text
  • Check that message IDs are being tracked (enable debug mode)
  • Ensure messages are passed to ContentstorageIntlProvider

TypeScript errors

Problem: TypeScript can't find type definitions.

Solutions:

  • Ensure @types/react is installed
  • Check tsconfig.json has "esModuleInterop": true
  • Try importing types explicitly: import type { ... }

Contributing

Contributions are welcome! Please see our Contributing Guide.

License

MIT License - see LICENSE file for details.

Support

  • Documentation: https://docs.contentstorage.app
  • Issues: https://github.com/contentstorage/react-intl-plugin/issues
  • Email: [email protected]