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 🙏

© 2024 – Pkg Stats / Ryan Hefner

simstate-i18n

v2.2.0

Published

A Strongly-typed react i18n library based on simstate

Downloads

12

Readme

simstate-i18n

NPM types Build Status

simstate-i18n is a strongly-typed React i18n library based on simstate.

Features

  • Use text id in a strongly-typed manner
  • Support nested text id
  • Support placeholders on text definition
  • Support async language loading for code splitting
  • Hot change languages without page reloading
  • Hot change texts without restarting the application

Install

npm install --save simstate-i18n

Example

My blog ddadaal.me is created with simstate-i18n.

Try changing the language by the LanguageSelector.

Usage

This library requires setting up necessary files and folders before using the components and store.

Setup

Check out the example folder for recommended file structure.

.
├── App.tsx
└── i18n
    ├── cn.ts
    ├── en.ts
    └── index.ts
  1. Create a folder i18n (or anything you want) on your src folder
  2. Create a file ({language}.ts, for example cn.ts, en.ts) under i18n folder for each language to support with the following content:
    • Every such file defines a language object for one language
    • Language object contains the basic information (id, strings, names etc.) and the mappings from id to text
    • Every language objects should have exactly identical structure.
// src/i18n/en.ts
// example: example/i18n/{en,cn}.ts

export default {
  // The id of the language. Any unique string is acceptable.
  id: "en",

  // The name of the language
  name: "English",

  // The definitions of id and text template.
  // Use "{}" as the placeholder for dynamically set text or React component.
  definitions: {
    navbar: {
      home: "Home",
      about: "About",
    },
    content: "Current time: {}. Thanks for using simstate-i18n."
  }
}
  1. Create a index.ts under the i18n folder with the following content:
// src/i18n/index.ts
// example: example/i18n/index.ts

// Imports
import cn from "./cn";
import { createI18nContext, I18nStoreDef, I18nStore } from "simstate-i18n";
import { useStore } from "simstate";

// Load English dynamically to support code splitting
const en = () => import("./en").then((x) => x.default);

// The actual Language type,
// might be useful when the Language object is extended and the extra properties are needed
export type Language = typeof cn;

// Create the I18nContext with cn as the default language.
export const i18nContext = createI18nContext(cn, { en });

// Destruct and export the members for easier usage
// Recommendation: rename the idAccessor to lang for shorter typing
export const { getLanguage, idAccessor: lang } = i18nContext;

// This function is shortcut to use I18nStore,
// and also specify the exact types of Language objects,
// which helps avoid type casting.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function useI18nStore() {
  return useStore(I18nStore) as I18nStoreDef<Language["definitions"], Language>;
}
  1. Create and inject a new global simstate store with the i18nContext instance.
// example: example/App.tsx

import { i18nContext } from "./i18n";
import { createI18nStore } from "simstate-i18n";
import { StoreProvider } from "simstate";

const Root = () => {
  // Create global i18nStore instance.
  const [i18nStore] = useState(() => createI18nStore(i18nContext));
  return (
    <StoreProvider stores={[i18nStore]}>
      <App />
    </StoreProvider>
  )
}

Usage

When the configurations are completed and the global I18nStore is injected, it is possible to use the provided components and store.

Localized/LocalizedString component

<LocalizedString /> or <Localized /> component are used in place of raw texts to provide i18n capabilities to anywhere a React component can be. It shows the text of the specified id of the current language.

All LocalizedString components will be updated when the current language is changed.

Example:

// import the idAccessor (renamed to lang) from i18n folder
// which is used to access the id of a text strongly-typedly.
import { lang } from "./i18n";
import { LocalizedString } from "simstate-i18n";

// Set the id of text as accessing properties of the lang object
// If the text has placeholders {},
// set the replacements prop with the replacement elements
// that will be inserted into the placeholders in order.
<LocalizedString id={lang.content} replacements={[Date.now()]} />

// The same as above but name is shorter
<Localized id={lang.content} replacements={[Date.now()]} />

useLocalized hook

This hook is used to suffice more advanced usage.

The following example behaves the same as the LocalizedString example above, and will also be updated when the current language is updated.

Example:

import { lang } from "./i18n";
import { useLocalized } from "simstate-i18n";

const Component = () => {
  const content = useLocalized(lang.content, [Date.now()]);
  return content;
}

I18nStore store

The I18nStore instance of current provider scope can be acquired with useStore function provided by simstate, which can be used to control the current language as well as getting some information.

Example:

import { I18nStore } from "simstate-i18n";
import { useStore } from "simstate";

const ControlPanel = () => {
  const i18nStore = useStore(I18nStore);

  return (
    <div>
      <p>
        Current language: {i18nStore.currentLanguage.name}
      </p>
      {
        i18nStore.switchingToId && `Switching to ${i18nStore.switchingToId}`
      }
      <ul>
        {allLanguages.map((lang) => (
          <li key={lang.id}>
            <a onClick={() => i18nStore.changeLanguage(lang.id)}>
              {lang.name}
            </a>
          </li>
        ))}
      </ul>
    </div>
  )
}

Related

simstate: A Strongly-typed React State Management Tool Favoring React Hooks and TypeScript.

Strongly Typed i18n with TypeScript (English): This article of mine talks about the problems of using raw string as the text ids, and also introduces a proxy-based text id generation method which is now replaced with another method (src/i18nContext.ts) which should have better performance.

License

MIT © ddadaal