Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ddadaal/simstate-i18n
A strongly-typed React i18n library based on simstate that supports dynamic language changing and text id autocomplete
https://github.com/ddadaal/simstate-i18n
i18n react
Last synced: 23 days ago
JSON representation
A strongly-typed React i18n library based on simstate that supports dynamic language changing and text id autocomplete
- Host: GitHub
- URL: https://github.com/ddadaal/simstate-i18n
- Owner: ddadaal
- Created: 2020-07-16T03:09:32.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2021-06-06T01:44:10.000Z (over 3 years ago)
- Last Synced: 2024-04-25T15:21:44.429Z (7 months ago)
- Topics: i18n, react
- Language: TypeScript
- Homepage:
- Size: 1.14 MB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# simstate-i18n
[![NPM](https://img.shields.io/npm/v/simstate-i18n.svg)](https://www.npmjs.com/package/simstate-i18n)
[![types](https://img.shields.io/npm/types/simstate.svg?style=flat-square)](https://www.npmjs.com/package/simstate-i18n)
[![Build Status](https://travis-ci.com/ddadaal/simstate-i18n.svg?branch=master)](https://travis-ci.com/ddadaal/simstate-i18n)`simstate-i18n` is a strongly-typed React i18n library based on [simstate](https://github.com/ddadaal/simstate).
# DEPRECATED!
This library has been superceded by [`react-typed-i18n`](https://github.com/ddadaal/react-typed-i18n). The new library:
- has all features of this library!
- does not depend on `simstate`
- use `string` literals as id which are typechecked using `template literal types`Please give it a try!
# 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
```bash
npm install --save simstate-i18n
```# Example
My blog [ddadaal.me](https://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](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.```typescript
// src/i18n/en.ts
// example: example/i18n/{en,cn}.tsexport 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."
}
}
```3. Create a `index.ts` under the `i18n` folder with the following content:
```typescript
// 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;
}
```1. Create and inject a new global `simstate` store with the i18nContext instance.
```tsx
// example: example/App.tsximport { i18nContext } from "./i18n";
import { createI18nStore } from "simstate-i18n";
import { StoreProvider } from "simstate";const Root = () => {
// Create global i18nStore instance.
const [i18nStore] = useState(() => createI18nStore(i18nContext));
return (
)
}
```## 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
`` or `` 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:
```tsx
// 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.// The same as above but name is shorter
```
### 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:
```tsx
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:
```tsx
import { I18nStore } from "simstate-i18n";
import { useStore } from "simstate";const ControlPanel = () => {
const i18nStore = useStore(I18nStore);return (
Current language: {i18nStore.currentLanguage.name}
{
i18nStore.switchingToId && `Switching to ${i18nStore.switchingToId}`
}
{allLanguages.map((lang) => (
i18nStore.changeLanguage(lang.id)}>
{lang.name}
))}
)
}
```# Related
[`simstate`](https://github.com/ddadaal/simstate): A Strongly-typed React State Management Tool Favoring [React Hooks](https://reactjs.org/docs/hooks-intro.html) and [TypeScript](https://www.typescriptlang.org/).
[Strongly Typed i18n with TypeScript](https://ddadaal.me/articles/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)](src/i18nContext.ts) which should have better performance.
# License
MIT © [ddadaal](https://github.com/ddadaal)