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

@intlify/core-base review

@intlify/core-base 11.4.10 is the framework-independent engine used beneath Vue I18n. It creates a mutable localization context and exports low-level functions for translation, plural choice, locale fallback, number formatting, and date formatting. It does not install into Vue, make locale state reactive, fetch catalogs, or supply components. Direct consumers must wire a message compiler, nested-key resolver, and fallback strategy. The current release stops devtools grouping from throwing when a message key is an AST, while 11.4.9 fixed stale locale-chain caches after fallback changes. Our measured full import of 11.4.8 was 38.4 KB minified and 13.6 KB gzipped.

Verdict

Our @intlify/core-base 11.4.8 install took 3.1 seconds, used 2 MB across 5 packages, and produced a 13.6 KB gzipped browser bundle with no audit findings. Install the current 11.4.10 release when you are building an Intlify-compatible adapter; application teams should usually choose `vue-i18n` or a higher-level framework-neutral package.

We installed it

Lab card: what happened when we installed @intlify/core-baseScreenshot of @intlify/core-base documentation
Install✓ · 3.1s5 packages on disk · 2 MB
ImportESM import works · require() works · CommonJS package with exports map
Browser13.6 KBgzipped (38.4 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/core-base install cleanly?

Yes. In a fresh container with an empty cache, npm install @intlify/core-base finished in 3 seconds, leaving 5 packages and 2 MB on disk. npm audit reported no known vulnerabilities.

How much does @intlify/core-base add to a browser bundle?

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

Does @intlify/core-base work with both ESM and CommonJS?

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

Does @intlify/core-base include TypeScript types?

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

@intlify/core-base or @formatjs/intl: which should you use?

@formatjs/intl: Choose it for a framework-neutral formatter tied to ICU messages and FormatJS extraction tooling. Our @intlify/core-base 11.4.8 install took 3.1 seconds, used 2 MB across 5 packages, and produced a 13.6 KB gzipped browser bundle with no audit findings.

When should you not use @intlify/core-base?

This is an ordinary Vue application. vue-i18n adds reactivity, useI18n, components, app installation, and documented catalog workflows around this engine.

API stability3/5`createCoreContext`, `translate`, `number`, `datetime`, `compile`, and the resolver and fallback helpers form a recognizable base API, with detailed TypeScript overloads. Direct users also touch caches, mutable context fields, global registration hooks, error codes, and devtools plumbing. Two consecutive patches changed fallback-cache behavior and AST handling. Because this foundation ships in lockstep with Vue I18n, parent-project changes can reach consumers who bypass its public adapter.
Docs1/5The package README only identifies @intlify/core-base as the core base module. It contains no setup path showing the compiler, resolver, or fallbacker needed for familiar behavior. Exported declarations explain many types, and repository tests reveal valid call combinations, but users must read implementation code to discover bare-context defaults, global registration effects, and runtime warnings. The main Vue I18n site is useful for the product above this layer, not a direct-user manual for this package.
Maintenance5/5The current 11.4.10 package and GitHub release shipped on August 25, 2026, and the repository was pushed again that day. Version 11.4.9 arrived 2 days earlier with 2 core-base fallback fixes; 11.4.10 followed with the AST-key devtools fix. GitHub shows an unarchived monorepo with 90 open issues and pull requests. Exact-version Intlify dependencies and rapid targeted patches make the active release line easy to identify.
Ecosystem3/5npm counted 3,569,765 downloads in the week ending August 24, 2026, while GitHub reports 2,712 stars for the Vue I18n monorepo. Much of that package traffic is transitive through Vue I18n rather than evidence of direct adoption. The engine connects cleanly to Intlify's compiler, shared utilities, devtools types, and precompiled resources. Outside that family, i18next and FormatJS have more direct tutorials, loaders, and adapters for application teams.

Use it if

  • You are writing an i18n adapter for another framework and need translation behavior compatible with the Intlify family.
  • Your runtime needs direct control of message compilation, nested key resolution, missing-key hooks, and regional fallback chains.
  • Locale-aware text, numbers, and dates are required without importing Vue itself.
  • Your build already emits Intlify message functions or AST resources and needs the matching execution layer.
Skip it if

Setup reality

We installed @intlify/core-base 11.4.8 in 3.1 seconds in a fresh Node 22 Bookworm sandbox on August 22, 2026. That measured install left 5 packages and 2 MB on disk. The package was 632 KB unpacked, declared 3 direct dependencies and no peers, and npm audit found 0 known vulnerabilities. It included TypeScript declarations. CommonJS require() and ESM import both worked through the exports map, and our browser build measured 38.4 KB minified and 13.6 KB gzipped.

The current registry release is 11.4.10, so those install numbers describe 11.4.8 rather than a fresh measurement of the two later patches. All three exact-version dependencies belong to Intlify. Node 22 or newer is required. There are no credentials or native compilation steps. The configuration cost is in code: pass compile, resolveValue, and fallbackWithLocaleChain if you want compiled strings, nested paths, and the regional chain behavior associated with Vue I18n.

A core context is mutable and non-reactive. Updating ctx.locale or ctx.messages will not notify UI code, load a file, save a preference, or update the document language. Global registration functions change defaults for later contexts across the process, which can leak between tests or tenants. Explicit per-context options are easier to isolate. Create one context per request when locale and catalogs differ across concurrent server work.

Runtime string compilation spends work during translation; precompiled functions or AST messages require a matching build pipeline. Number and date output comes from the host's Intl data. escapeParameter defaults to false, and an HTML warning does not sanitize returned markup. Version 11.4.9 matters for live fallback changes because it invalidates the locale-chain cache and corrects simple fallback maps. Version 11.4.10 then prevents AST message keys from breaking devtools group IDs.

Patterns

Create a context with compiler and fallback behavior create-core-context

import {
  compile,
  createCoreContext,
  fallbackWithLocaleChain,
  resolveValue,
} from '@intlify/core-base'

const ctx = createCoreContext({
  locale: 'en-US',
  fallbackLocale: 'en',
  messages: {
    'en-US': { greeting: 'Hello, {name}!' },
    en: { greeting: 'Hello, {name}!' },
  },
  messageCompiler: compile,
  messageResolver: resolveValue,
  localeFallbacker: fallbackWithLocaleChain,
})

A context without these 3 helpers cannot compile string messages and falls back to flat-key lookup plus the simple locale routine.

Insert a named value into a message interpolate-name

import { translate } from '@intlify/core-base'

const text = translate(ctx, 'greeting', { name: 'Ada' })
console.log(text)

The string is compiled because `ctx` was created with `messageCompiler: compile`. A bare context does not turn `{name}` into a placeholder.

Fill positional placeholders interpolate-list

const ctx = createCoreContext({
  locale: 'en',
  messages: { en: { status: '{0} of {1} complete' } },
  messageCompiler: compile,
  messageResolver: resolveValue,
  localeFallbacker: fallbackWithLocaleChain,
})

console.log(translate(ctx, 'status', [3, 10]))

List placeholders start at 0. Named placeholders are usually clearer to translators when the order can change between languages.

Select a plural branch from a count choose-plural-form

const ctx = createCoreContext({
  locale: 'en',
  messages: { en: { apples: 'no apples | one apple | {count} apples' } },
  messageCompiler: compile,
  messageResolver: resolveValue,
  localeFallbacker: fallbackWithLocaleChain,
})

console.log(translate(ctx, 'apples', 0))
console.log(translate(ctx, 'apples', 1))
console.log(translate(ctx, 'apples', 12))

The numeric choice also provides `count` and `n`. Locale selection uses `Intl.PluralRules` unless the context supplies a custom rule.

Look up a nested catalog path resolve-nested-message

import { resolveValue } from '@intlify/core-base'

const messages = {
  checkout: { payment: { failed: 'Payment failed' } },
}

console.log(resolveValue(messages, 'checkout.payment.failed'))
console.log(resolveValue(messages, 'checkout.payment.missing'))

`resolveValue` traverses object paths and array indexes, returning null for a miss. The default `resolveWithKeyValue` treats this dotted key as one flat property.

Inspect fallback order for a regional locale build-locale-chain

import { fallbackWithLocaleChain } from '@intlify/core-base'

const ctx = createCoreContext({
  locale: 'de-CH',
  fallbackLocale: {
    'de-CH': ['fr', 'it'],
    default: ['en'],
  },
  localeFallbacker: fallbackWithLocaleChain,
})

console.log(fallbackWithLocaleChain(ctx, ctx.fallbackLocale, 'de-CH'))

The locale-chain routine understands decision maps and implicit regional parents. A trailing `!` on the starting locale suppresses parent fallback.

Report and replace a missing message replace-missing-key

const ctx = createCoreContext({
  locale: 'en',
  messages: { en: {} },
  missing(_ctx, locale, key, type) {
    reportMissing({ locale, key, type })
    return `[${key}]`
  },
  messageCompiler: compile,
  messageResolver: resolveValue,
  localeFallbacker: fallbackWithLocaleChain,
})

console.log(translate(ctx, 'account.title'))

The missing hook runs inside translation and may return replacement text. Keep its reporting path fast because rendering can call it repeatedly.

Escape values inserted into a translation escape-parameters

const ctx = createCoreContext({
  locale: 'en',
  messages: { en: { hello: 'Hello, {name}!' } },
  escapeParameter: true,
  messageCompiler: compile,
  messageResolver: resolveValue,
  localeFallbacker: fallbackWithLocaleChain,
})

console.log(translate(ctx, 'hello', {
  name: '<img src=x onerror=alert(1)>',
}))

`escapeParameter` is false unless enabled. Escaped placeholders do not make arbitrary HTML stored in a catalog safe to inject into a page.

Trim each translated string after resolution post-process-result

const ctx = createCoreContext({
  locale: 'en',
  messages: { en: { padded: '  ready  ' } },
  postTranslation(value, key) {
    auditTranslation(key)
    return typeof value === 'string' ? value.trim() : value
  },
  messageCompiler: compile,
  messageResolver: resolveValue,
  localeFallbacker: fallbackWithLocaleChain,
})

console.log(translate(ctx, 'padded'))

`postTranslation` runs on every successful result. Slow I/O here adds latency to every call and can multiply during one render.

Format money with named number rules format-currency

import { number } from '@intlify/core-base'

const ctx = createCoreContext({
  locale: 'en-US',
  numberFormats: {
    'en-US': { money: { style: 'currency', currency: 'USD' } },
    'ja-JP': { money: { style: 'currency', currency: 'JPY' } },
  },
  localeFallbacker: fallbackWithLocaleChain,
})

console.log(number(ctx, 10100, 'money'))
console.log(number(ctx, 10100, 'money', 'ja-JP'))

Formatting support and exact output come from `Intl.NumberFormat` in the running JavaScript engine. `part: true` returns parts instead of a final string.

Render a date in an explicit time zone format-date

import { datetime } from '@intlify/core-base'

const ctx = createCoreContext({
  locale: 'en-US',
  datetimeFormats: {
    'en-US': { short: { year: 'numeric', month: 'short', day: 'numeric' } },
  },
  localeFallbacker: fallbackWithLocaleChain,
})

console.log(datetime(ctx, new Date('2026-08-08T12:00:00Z'), {
  key: 'short',
  timeZone: 'UTC',
}))

Without `timeZone`, the host machine decides the zone and may render a different calendar date. Invalid dates warn and return an empty string.

Replace locale and catalog on one context change-locale

ctx.locale = 'ja-JP'
ctx.messages['ja-JP'] = {
  greeting: 'こんにちは、{name}さん',
}

const text = translate(ctx, 'greeting', { name: 'Ada' })
console.log(text)

These assignments mutate plain context state. They do not notify a component tree, download messages, save the choice, or alter `<html lang>`.

Alternatives

PackageRegistryPick it when
@formatjs/intlnpmChoose it for a framework-neutral formatter tied to ICU messages and FormatJS extraction tooling.
intl-messageformatnpmChoose it when compiling and formatting individual ICU messages is enough and no catalog context is needed.
@messageformat/corenpmChoose it for ICU-style compilation with explicit runtime and build-time paths.
i18nextnpmChoose it for a documented general-purpose i18n system with loaders, plugins, and framework adapters.

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.