mrkeyoor.com_
Sat 08 Aug 21:00 UTC
npmUtilsupdated 08 Aug 2026

@intlify/shared

@intlify/shared is the internal utility layer published by the Vue I18n and Intlify project. It contains small type guards, placeholder formatting, display conversion, source code frames, cache-key helpers, a typed event emitter, warning helpers, HTML escaping and translation sanitization, and an object-copy routine. It has no Vue peer dependency and can be imported on its own, but its README describes it as shared infrastructure for Intlify rather than a standalone application utility toolkit.

Verdict

Keep @intlify/shared as a transitive dependency unless you are extending Intlify itself or need byte-for-byte behavioral parity with Vue I18n. Its helpers work, but the Node 22 floor and monorepo-internal support posture make focused public packages safer for application code.

API stability3/5The utility names are small and familiar, and v11.4.8 publishes declarations plus explicit root and dist exports. The package is nevertheless tied to the Vue I18n release train rather than an independent public API promise; the repository's main branch already carries 12.0.0-alpha.4 metadata, and behavior such as translation sanitization can expand for project-internal needs.
Docs2/5The package README states its purpose, fork provenance, authors, and MIT licensing, but it contains no list of exports, signatures, examples, compatibility table, or behavioral warnings. Correct use requires reading generated declarations and tagged source files, particularly for deepCopy and sanitizeTranslatedHtml, whose names imply broader behavior than their implementations provide.
Maintenance5/5Version 11.4.8 was published on July 26, 2026, and the vue-i18n repository was pushed on August 3, 2026. The monorepo is not archived, v11 is explicitly marked stable and maintained after an accidental deprecation notice, and active v12 alpha metadata shows continuing work rather than a frozen transitive package.
Ecosystem3/5The package recorded 4,047,463 downloads last week and inherits reach from Vue I18n, whose repository has 2,703 stars. That scale mostly reflects its role below vue-i18n and related tools, not a community of direct consumers; there are no documented plugins or application integrations built around the shared helpers themselves.

Use it if

  • You are building or debugging an Intlify package and need the exact helpers used by Vue I18n 11
  • You publish an adapter that already depends on the Intlify 11 package family and want consistent formatting, warning, or emitter behavior
  • You need to reproduce Vue I18n's message sanitization or cache-key behavior exactly rather than approximately
  • You have inspected the v11.4.8 exports and accept coupling your code to a monorepo support package
Skip it if

Setup reality

The install has no dependencies, peer dependencies, native compilation, credentials, or configuration file, but it is less frictionless than its size suggests. Version 11.4.8 declares Node >= 22, which package managers may enforce or warn about. It ships ESM, CommonJS, browser, production, development, and TypeScript declaration targets through an exports map; use the package root and let the resolver select a build rather than importing unpublished source paths. The dist/* subpath is exposed, but binding application code to a particular generated file makes upgrades more brittle. Most downloads are likely transitive through vue-i18n, so seeing the package in a lockfile is not a reason to add it to package.json. If you do import it directly, keep its major and minor line aligned with the rest of your @intlify packages because all are released from one monorepo. Several names are easy to overread: format only replaces simple alphanumeric {tokens}; sanitizeTranslatedHtml is targeted translation markup handling, not a general HTML parser; deepCopy writes into an existing object and does not independently clone arrays; createEmitter calls handlers synchronously and provides no once method or async error isolation. The package's own README lists provenance and licensing but no API examples, so the TypeScript declarations and exact tagged source are the practical reference. Test bundler output in production mode because the exports map selects different CommonJS files for production and development.

Patterns

Replace named placeholdersformat-named-placeholders

import { format } from '@intlify/shared';

const message = format('Hello {name}, you have {count} items', {
  name: 'Ada',
  count: 3,
});

Only alphanumeric tokens match. Missing keys become an empty string, and this helper does not implement ICU message syntax or locale-aware plural rules.

Replace positional placeholdersformat-positional-placeholders

import { format } from '@intlify/shared';

const message = format('{0} of {1}', 3, 10);

Positional indexes are looked up on the arguments array. Use vue-i18n message formatting when translation grammar, pluralization, or locale rules matter.

Create an Intlify format cache keycreate-cache-key

import { generateFormatCacheKey } from '@intlify/shared';

const key = generateFormatCacheKey(
  'en-US',
  'invoice.total',
  '{amount, number, currency}'
);

The function serializes fixed l, k, and s properties. It is meant to match Intlify's cache identity, not to create a cryptographic or collision-resistant key.

Escape line separators and apostrophes in JSONserialize-script-safe-json

import { friendlyJSONstringify } from '@intlify/shared';

const json = friendlyJSONstringify({ text: "it's line\u2028two" });

This wraps JSON.stringify and escapes U+2028, U+2029, and apostrophes. It is not a general HTML or JavaScript sanitizer.

Use the bundled type guardsnarrow-runtime-values

import { isArray, isDate, isPlainObject, isPromise } from '@intlify/shared';

if (isDate(value)) console.log(value.toISOString());
if (isArray(value)) console.log(value.length);
if (isPlainObject(value)) console.log(Object.keys(value));
if (isPromise(value)) await value;

isPromise checks for an object with then and catch functions; it recognizes promise-like values and does not require a native Promise instance.

Convert a value to display textrender-display-value

import { toDisplayString } from '@intlify/shared';

console.log(toDisplayString(null));       // ''
console.log(toDisplayString({ a: 1 }));   // pretty JSON
console.log(toDisplayString(['a', 'b'])); // pretty JSON

Plain objects and arrays use two-space JSON formatting. Circular data throws through JSON.stringify, and custom object toString methods are preserved.

Show a source error with nearby linesgenerate-source-frame

import { generateCodeFrame } from '@intlify/shared';

const source = 'first line
hello {name
last line';
const start = source.indexOf('{name');
console.error(generateCodeFrame(source, start, start + 5));

Offsets are JavaScript string indexes, not UTF-8 byte offsets. The helper displays a two-line range around the selected location.

Create a typed synchronous event emittercreate-typed-emitter

import { createEmitter } from '@intlify/shared';

type Events = { saved: { id: string }; failed: Error };
const emitter = createEmitter<Events>();

const onSaved = (payload?: Events['saved']) => console.log(payload?.id);
emitter.on('saved', onSaved);
emitter.emit('saved', { id: '42' });
emitter.off('saved', onSaved);

Handlers run synchronously. Keep the original function reference for off; the emitter has no once helper and does not catch handler exceptions.

Listen to every emitter eventobserve-all-events

const logEvent = (type, payload) => {
  console.log(type, payload);
};

emitter.on('*', logEvent);
emitter.emit('saved', { id: '42' });
emitter.off('*', logEvent);

Wildcard handlers receive event type first and payload second, after handlers registered for that specific event have run.

Escape a string for HTML text outputescape-untrusted-text

import { escapeHtml } from '@intlify/shared';

const safeText = escapeHtml(userSuppliedText);
container.innerHTML = `<p>${safeText}</p>`;

escapeHtml also escapes slash and equals characters. Prefer textContent when possible because it avoids constructing HTML at all.

Neutralize dangerous translation attributessanitize-translation-markup

import { sanitizeTranslatedHtml } from '@intlify/shared';

const html = sanitizeTranslatedHtml(
  '<a href="javascript:alert(1)" onclick="steal()">Help</a>'
);

This targets attribute values, event handlers, and javascript URLs. It does not parse and remove arbitrary elements, so do not use it as a full untrusted-HTML sanitizer.

Copy nested message properties into a destinationmerge-message-objects

import { deepCopy } from '@intlify/shared';

const target = { nav: { home: 'Home' } };
deepCopy({ nav: { account: 'Account' }, tags: ['new'] }, target);

deepCopy mutates target, skips __proto__, and merges nested objects. Arrays are assigned rather than recursively cloned, so source and destination can share an array reference.

Alternatives

PackageRegistryPick it when
@vue/sharednpmYou are already in Vue internals and want the upstream utility collection that this package says some helpers were forked from
lodash-esnpmApplication code needs documented, independently versioned collection and object utilities with per-function imports
mittnpmYou only need the tiny event emitter whose implementation Intlify credits as the basis for createEmitter