mrkeyoor.com_
Wed 23 Sept 02:51 UTC
npmUtilsupdated 22 Sept 2026

@intlify/shared review

@intlify/shared 11.4.10 is the utility layer used inside Vue I18n and other Intlify packages. Its root export includes value guards, simple `{token}` substitution, display conversion, source-code frames, cache-key generation, HTML escaping, translation-markup sanitization, an object copier, and a synchronous typed emitter. Version 11.4.9 changed `deepCopy()` so arrays are copied recursively instead of retaining references to the source; 11.4.10 republishes the package with the Vue I18n release that fixes devtools group IDs for AST keys. This is published internal infrastructure with almost no package-level API documentation, not a general localization API.

Verdict

Our @intlify/shared 11.4.8 install took 1.3 seconds, used 1 MB, and returned 0 audit findings; current 11.4.10 remains a small fit for code that must match Vue I18n internals. Most applications should leave it transitive because Node 22, sparse direct-use docs, and monorepo-coupled releases outweigh the convenience of its mixed utility bag.

We installed it

Lab card: what happened when we installed @intlify/sharedScreenshot of @intlify/shared documentation
Install✓ · 1.3s1 package on disk · 1 MB
ImportESM import works · require() works · CommonJS package with exports map
Browser2.4 KBgzipped (4.8 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @intlify/shared install cleanly?

Yes. In a fresh container with an empty cache, npm install @intlify/shared finished in 1 seconds, leaving 1 package and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does @intlify/shared add to a browser bundle?

2.4 KB gzipped (4.8 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does @intlify/shared work with both ESM and CommonJS?

Yes. Both import '@intlify/shared' and require('@intlify/shared') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does @intlify/shared include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@intlify/shared or @vue/shared: which should you use?

@vue/shared: Use it when Vue-internal utility parity matters and the needed helper comes from the source project Intlify credits. Our @intlify/shared 11.4.8 install took 1.3 seconds, used 1 MB, and returned 0 audit findings; current 11.4.10 remains a small fit for code that must match Vue I18n internals.

When should you not use @intlify/shared?

Application code only needs ordinary type guards or object helpers. @vue/shared or a focused package has a clearer audience than Intlify's internal support module.

API stability3/5The package publishes one root entry with TypeScript declarations and condition-specific builds, and many guard and formatting names have persisted through Vue I18n 11. Direct consumers still rely on an internal support contract. Version 11.4.9 changed `deepCopy()` array identity, and 11.4.10 arrived with a core-base devtools fix rather than a shared-specific release. Behavior may move to serve monorepo callers without a dedicated migration guide.
Docs2/5The package README says it is the shared utility module for Intlify, identifies the Vue and mitt code origins, and gives the MIT license. It does not list exports, show a single call, define the Node 22 floor, explain environment-specific builds, or describe behavior for `deepCopy()`, `format()`, `sanitizeTranslatedHtml()`, and `createEmitter()`. The generated declarations and tagged source are the usable references for direct consumers.
Maintenance5/5Version 11.4.10 was published on August 25, 2026, the same day GitHub records the latest repository push. Version 11.4.9 had shipped two days earlier with a shared-package array-copy fix. The unarchived Vue I18n repository has 2,712 stars and 90 open issues and pull requests. Releases and source changes are current, although package-specific change history must be reconstructed from monorepo releases.
Ecosystem3/5npm counted 4,100,172 downloads from August 18 through August 24, 2026. That reach comes mainly from Vue I18n and related Intlify packages that install this module transitively. It has no direct-use plugin ecosystem or standalone manual. Compatibility is strongest inside the same major and minor Intlify family; application developers can find better-supported public surfaces for emitters, sanitization, or generic object utilities.

Use it if

  • An Intlify extension must behave exactly like the Vue I18n 11 implementation it sits beside.
  • A debugging tool needs the same code-frame, display-string, or devtools group-ID helpers as the monorepo.
  • Translation processing depends on Intlify's specific cache-key or markup-sanitization behavior.
  • You have read the 11.4.10 declarations and can keep this direct dependency aligned with other `@intlify` packages.
Skip it if

Setup reality

We installed @intlify/shared 11.4.8 in a fresh Node 22 Bookworm sandbox in 1.3 seconds. It left one package and 1 MB on disk, while the package itself was 116 KB unpacked. npm audit found 0 known vulnerabilities. The measured version has 0 direct and 0 peer dependencies, bundled TypeScript declarations, and an MIT license. Its CommonJS package has an exports map; both require() and ESM import worked.

The registry now serves 11.4.10, released on August 25, 2026. Current metadata still requires Node 22 or newer and has no dependencies. The exports map selects ESM, CommonJS, browser, production, and development builds from the package root. Import from @intlify/shared and let the runtime choose; the exposed dist/* path exists for tooling, but pinning an application to a generated filename couples it to packaging details. No credentials, config, or compilation step is needed.

The public surface is broader than the README, which only calls the module Intlify's shared utility package and credits code forked from Vue and mitt. Read the declarations before direct use. createEmitter() is synchronous and has no once() helper. format() is token replacement, friendlyJSONstringify() escapes three characters after JSON serialization, and toDisplayString() can throw on circular arrays or plain objects because it calls JSON.stringify().

Version 11.4.9 fixed deepCopy() so nested arrays receive new arrays rather than sharing the source reference; it still mutates an existing destination and skips __proto__. sanitizeTranslatedHtml() handles quoted and unquoted attributes, event-handler names, JavaScript URLs, and style url() values, yet it remains string rewriting rather than an HTML parser. Our browser build measured 4.8 KB minified and 2.4 KB gzipped for an import of the package, small enough for Intlify internals but unnecessary when an app needs only one familiar guard.

Patterns

Replace named message tokens format-named-token

import { format } from '@intlify/shared'

const text = format('Hello {name}, {count} items remain', {
  name: 'Ada',
  count: 3
})

`format()` recognizes alphanumeric names only. Missing keys turn into empty strings, and no locale grammar or plural selection runs.

Replace numeric message tokens format-positional-token

import { format } from '@intlify/shared'

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

Numeric placeholders index the remaining arguments. Use Vue I18n itself when the sentence needs locale-aware choices.

Match Intlify's format cache identity make-format-cache-key

import { generateFormatCacheKey } from '@intlify/shared'

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

The output is serialized from fixed locale, key, and source properties. It is not designed as a security token or hash.

Escape Intlify's three JSON trouble characters serialize-friendly-json

import { friendlyJSONstringify } from '@intlify/shared'

const json = friendlyJSONstringify({ text: "it's line
two" })

The helper escapes U+2028, U+2029, and apostrophes after `JSON.stringify()`. It does not make arbitrary JSON safe for every HTML context.

Use the package's runtime guards narrow-value-types

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()` accepts any object with callable `then` and `catch` properties; it does not require a native Promise instance.

Render a value for debug output display-debug-value

import { toDisplayString } from '@intlify/shared'

console.log(toDisplayString(null))
console.log(toDisplayString({ count: 2 }))
console.log(toDisplayString(['en', 'fr']))

Arrays and ordinary objects use two-space JSON. Circular structures throw from `JSON.stringify()`.

Point to a source-string error build-code-frame

import { generateCodeFrame } from '@intlify/shared'

const source = 'first line\nhello {name\nlast line'
const start = source.indexOf('{name')
console.error(generateCodeFrame(source, start, start + 5))

Offsets are JavaScript string positions. The frame includes up to 2 surrounding lines on either side.

Send a typed synchronous event emit-typed-event

import { createEmitter } from '@intlify/shared'

type Events = { saved: { id: string }; failed: Error }
const emitter = createEmitter<Events>()
const onSaved = (value?: Events['saved']) => console.log(value?.id)

emitter.on('saved', onSaved)
emitter.emit('saved', { id: '42' })
emitter.off('saved', onSaved)

Handlers run immediately. Keep the same function reference for `off()`, and expect thrown listener errors to escape `emit()`.

Observe every emitter event listen-all-events

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

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

Wildcard listeners run after listeners for the named event and receive the event name before the payload.

Escape a value used as HTML text escape-html-text

import { escapeHtml } from '@intlify/shared'

const safe = escapeHtml(userText)
container.innerHTML = `<p>${safe}</p>`

The helper also escapes slash and equals. Assigning `textContent` is simpler when markup is not required.

Neutralize dangerous translation attributes sanitize-translation-markup

import { sanitizeTranslatedHtml } from '@intlify/shared'

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

The function rewrites risky attributes and URLs. It does not remove arbitrary elements, so it cannot replace an HTML parser-based sanitizer for untrusted markup.

Copy messages into an existing object copy-message-tree

import { deepCopy } from '@intlify/shared'

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

`deepCopy()` mutates the destination and skips `__proto__`. Since 11.4.9, nested arrays receive new arrays instead of retaining source references.

Alternatives

PackageRegistryPick it when
@vue/sharednpmUse it when Vue-internal utility parity matters and the needed helper comes from the source project Intlify credits.
lodash-esnpmUse it for documented collection and object utilities that are maintained for direct application use.
mittnpmUse it when the only requirement is the tiny emitter model on which Intlify's emitter is based.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.