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

@malva-ui/i18n

v0.2.0

Published

Localisation for Malva UI — signal-based per-component i18n with ICU MessageFormat and 14 lazy-loaded language packs.

Readme

@malva-ui/i18n

Localisation for Malva UI — signal-based, per-component, with ICU MessageFormat and lazy-loaded language packs.

Every string a Malva UI component renders (pagination labels, dialog close buttons, empty-state copy, date-picker month names) comes from here. Nothing is hardcoded in the components.

Install

npm install @malva-ui/i18n

Installed automatically by ng add @malva-ui/core.

Quick start

Register one lazy-loaded language pack in your root providers:

import { provideMlvI18n } from '@malva-ui/i18n';

export const appConfig: ApplicationConfig = {
  providers: [provideMlvI18n(() => import('@malva-ui/i18n/en'))],
};

The pack is fetched during app initialisation, so it is a separate chunk — you ship one locale, not fourteen.

The loader may resolve to either shape of MlvLanguageModule: a module whose default export is the pack, or one that exposes it under a <locale>Language name — which is what the published locale entry points carry, since the package build flattens each one to a single named export. Importing a locale entry point directly, as above, therefore works unchanged; a pack you write yourself uses export default.

import { provideMlvI18n, type MlvLanguageModule } from '@malva-ui/i18n';

// Both are accepted.
provideMlvI18n(() => import('@malva-ui/i18n/en')); // export const enLanguage
provideMlvI18n(() => import('./my-own-pack')); // export default myPack

// `MlvLanguageModule` types a loader you hold yourself.
const loader: () => Promise<MlvLanguageModule> = () => import('@malva-ui/i18n/uk');

MlvI18nService.switchLanguage() takes the same two shapes, so runtime locale switching needs no wrapper either.

One module, one pack. default wins whenever it is there, and is used as-is. Without one, the module must expose exactly one <locale>Language — the loader throws rather than guessing:

// Fine — `default` is returned as-is, whatever your pack's keys are called.
provideMlvI18n(async () => ({ default: myPack }));

// Throws: two `<locale>Language` exports, and which one wins would be the order
// your barrel happens to declare them in.
provideMlvI18n(() => import('./locales')); // export * from '…/en'; export * from '…/de';

Re-export a single locale, or pick one explicitly — import('@malva-ui/i18n/en').then((pack) => ({ default: pack.enLanguage })).

Available locales

de · en · es · fr · id · it · ja · nl · pl · pt · ro · tr · uk · zh-Hans

provideMlvI18n(() => import('@malva-ui/i18n/uk'));

Translating your own strings

MlvTranslatePipe and MlvI18nService read the same message store, so application copy can share the component locale:

import { MlvTranslatePipe } from '@malva-ui/i18n';

@Component({ imports: [MlvTranslatePipe] })
export class MyComponent {}

Messages are ICU MessageFormat, so plurals and selects work as expected:

{count, plural, =0 {No results} one {# result} other {# results}}

Formatting locale

Plural categories, # number formatting and Malva UI's dates format in one locale, MLV_LOCALE — a Signal<string> holding the active pack's locale, falling back to Angular's LOCALE_ID while no pack is loaded or when the pack declares none. It moves with MlvI18nService.switchLanguage(), and it never reads the browser language, so a server render and its hydration agree.

Every shipped pack declares its locale (pt declares pt-PT). A pack you write yourself declares it in the optional locale field — a BCP 47 tag; without one, the pack formats in LOCALE_ID:

import type { MlvLanguage } from '@malva-ui/i18n';

export default {
  locale: 'de-CH',
  // …every component slice
} satisfies MlvLanguage;

MLV_LOCALE always reports a canonical tag: a malformed pack locale falls back to LOCALE_ID instead of making Intl throw. Read it to format your own values in the same locale:

import { MLV_LOCALE } from '@malva-ui/i18n';

private readonly _locale = inject(MLV_LOCALE);
protected readonly _price = computed(() =>
  new Intl.NumberFormat(this._locale(), { style: 'currency', currency: 'EUR' })
    .format(this.amount()),
);

Provide it yourself only to decouple formatting from the pack, and do it in the application providers — { provide: MLV_LOCALE, useValue: signal('de-CH').asReadonly() }.

Testing

@malva-ui/i18n/testing provides helpers for unit tests that render Malva UI components without booting a real language pack.

Peer dependencies

@angular/core, intl-messageformat (>=10).

Related packages

Versioning and support

Semver contract, what counts as public API, the deprecation window and the support window per major: VERSIONING.md (the repository is private while the library is pre-1.0, so the link needs repository access — ask us for the policy if it 404s for you).

License

MIT