react-scoped-i18n 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +85 -69
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,112 +1,114 @@
1
1
  # react-scoped-i18n 🌐
2
2
 
3
- `react-scoped-i18n 🌐` is a **fully type-safe** i18n solution for **React**.
3
+ A React i18n library where **translations live next to the components that render them** - no keys, no JSON files, fully type-safe at compile time.
4
4
 
5
- It encourages writing translations right next to the components that use them.
5
+ Works with **React** and **React Native** (_vanilla & Expo_).
6
6
 
7
7
  ---
8
8
 
9
- ## Getting started:
9
+ ## The problem with key-based i18n
10
10
 
11
- ### [Installation & Usage](/docs/usage.md)
11
+ Every other i18n library makes you name things. You write a key in your component, then jump to a JSON file to write the actual string, then come back. Keys get stale. Typos go unnoticed until runtime. Your translation file becomes a graveyard of strings you're not sure are still used.
12
12
 
13
- ### [API](/docs/api.md)
13
+ `react-scoped-i18n` flips this: **translations are just code, written inline, where you need them.**
14
14
 
15
- ###### Note: You can use this with both React and React Native (+ Expo) projects. 🚀
15
+ ```tsx
16
+ const { t } = useI18n();
17
+
18
+ const name = `Oto`;
19
+
20
+ return <Heading>
21
+ {t({
22
+ en: `Welcome back, ${name}!`,
23
+ es: `¡Bienvenido de nuevo, ${name}!`,
24
+ })}
25
+ </Heading>;
26
+ ```
16
27
 
28
+ No keys. No files. `ctrl+f` on any rendered string takes you straight to the component.
17
29
 
18
30
  ---
19
31
 
20
- ## Why `react-scoped-i18n 🌐`?
32
+ ## Type safety that actually catches bugs
21
33
 
22
- ### Key features:
23
- - Very minimal setup with out-of-the-box number & date formatting
24
- - Fully type-safe:
25
- - - missing translations or unsupported languages are compile-time errors
26
- - - return types of `t()` are inferred from translation values
27
- - Utilize the widely supported [Internationalization API (Intl)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) for number, currency, date and time formatting
28
- - Usage is entirely in the runtime; no build-time transforms, no new syntax is required for string interpolation or dynamic translations generated at runtime, everything is plain JS/TS
34
+ Forget to add a translation for a language you support? **TypeScript error.** Reference an unsupported language? **TypeScript error.** At compile time, not in production.
29
35
 
30
- ### The focus is on dev experience:
31
- - Translations are colocated with the components that use them; looking up translations in the codebase always immediately leads to the relevant component code
32
- - No context switching between component code and translation files when developing UI
33
- - No tedious naming of translation keys, as they usually provide little value
34
- - Ditch restrictive translation file formats (JSON, YAML); use the full power of JS/TS
35
- - Runs within React's context system. No additional build steps, changes can be hot-reloaded, language switches reflected immediately
36
+ ```tsx
37
+ return <Heading>
38
+ {t({
39
+ en: `Welcome back, ${name}!`,
40
+ // TS Error: Property 'es' is missing - your app supports Spanish
41
+ })}
42
+ </Heading>;
43
+ ```
36
44
 
37
45
  ---
38
46
 
39
- ## What does it look like?
47
+ ## Getting started
40
48
 
41
- ##### Very Basic Example:
49
+ - **[Installation & Usage](/docs/usage.md)** - 30 second setup
50
+ - **[API Reference](/docs/api.md)** - full reference
42
51
 
43
- ```tsx
44
- import { useI18n } from "@/i18n";
45
- import { Heading, Button } from "@/components";
52
+ ---
46
53
 
47
- export const WelcomeMessage = () => {
48
- const { t, commons } = useI18n();
54
+ ## Key features
55
+
56
+ - **Colocated translations** - live in the component, not a separate file
57
+ - **Compile-time safety** - missing or unsupported languages are TypeScript errors
58
+ - **No build-time transforms** - no Babel plugins, no magic, lives in React runtime (React Context)
59
+ - **No custom syntax** - plain JS template literals, no `{count, plural, ...}` to memorise
60
+ - **Out-of-the-box formatting** - numbers, currencies, dates and times via the native [Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)
61
+ - **Hot-reload friendly** - language switches are reflected immediately
62
+ - **Minimal setup** - takes 30 seconds
63
+
64
+ ---
49
65
 
66
+ ## Examples
67
+
68
+ ### Interpolation
69
+
70
+ ```tsx
71
+ export const WelcomeMessage = () => {
72
+ const { t } = useI18n();
50
73
  const name = `John`;
51
74
 
52
75
  return (
53
- <>
54
- <Heading>
55
- {t({
56
- // all fully type-safe for all configured languages
57
- en: `Welcome to the website, ${name}!`,
58
- es: `¡Bienvenido al sitio web, ${name}!`,
59
- sl: `Dobrodošli na spletno stran, ${name}!`,
60
- })}
61
- </Heading>
62
- <Button>{
63
- // "commons" object is used for commonly used, shared translations
64
- t(commons.continue)
65
- }</Button>
66
- </>
76
+ <Heading>
77
+ {t({
78
+ en: `Welcome to the website, ${name}!`,
79
+ es: `¡Bienvenido al sitio web, ${name}!`,
80
+ sl: `Dobrodošli na spletno stran, ${name}!`,
81
+ })}
82
+ </Heading>
67
83
  );
68
84
  };
69
85
  ```
70
86
 
71
- <details>
72
- <summary>
73
- Number Formatting Basic Example:
74
- </summary>
87
+ ### Number & currency formatting
75
88
 
76
89
  ```tsx
77
- import { useI18n } from "@/i18n";
78
- import { Text } from "@/components";
79
-
80
90
  export const PriceTag = () => {
81
91
  const { t, format } = useI18n();
82
92
 
83
93
  const price = 19.99;
84
94
 
85
- const currency = `USD`;
86
-
87
95
  return (
88
96
  <Text>
89
97
  {t({
90
- en: `The price is ${format.currency(price, currency)}.`,
91
- es: `El precio es ${format.currency(price, currency)}.`,
92
- sl: `Cena je ${format.currency(price, currency)}.`,
98
+ en: `The price is ${format.currency(price, "USD")}.`,
99
+ es: `El precio es ${format.currency(price, "USD")}.`,
100
+ sl: `Cena je ${format.currency(price, "USD")}.`,
93
101
  })}
94
102
  </Text>
95
103
  );
96
104
  };
97
105
  ```
98
- </details>
99
106
 
107
+ ### Pluralization
100
108
 
101
- <details>
102
- <summary>
103
- Pluralization Basic Example:
104
- </summary>
109
+ Full ICU category support (`one`, `two`, `many`, etc.), including a `negative` shorthand and the ability to target specific numbers.
105
110
 
106
111
  ```tsx
107
- import { useI18n } from "@/i18n";
108
- import { Text } from "@/components";
109
-
110
112
  export const Apples = () => {
111
113
  const { tPlural } = useI18n();
112
114
 
@@ -119,7 +121,7 @@ export const Apples = () => {
119
121
  negative: `You are in apple debt...`,
120
122
  one: `You have one apple.`,
121
123
  many: `You have ${count} apples.`,
122
- 42: `You have the perfect number of apples!`, // ‼️ you can target specific numbers
124
+ 42: `You have the perfect number of apples!`,
123
125
  },
124
126
  es: {
125
127
  one: `Tienes una manzana.`,
@@ -127,21 +129,35 @@ export const Apples = () => {
127
129
  },
128
130
  sl: {
129
131
  one: `Imaš eno jabolko.`,
130
- two: `Imaš dve jabolki.`, // ‼️ handling dual form in Slovenian that English and Spanish don't have
132
+ two: `Imaš dve jabolki.`, // handling the Slovenian dual form
131
133
  many: `Imaš ${count} jabolk.`,
132
- }
134
+ },
133
135
  })}
134
136
  </Text>
135
- )
137
+ );
136
138
  };
137
139
  ```
138
- </details>
139
140
 
140
- ----
141
+ ### Shared / common translations
142
+
143
+ ```tsx
144
+ const { t, commons } = useI18n();
145
+
146
+ return <Button>{t(commons.continue)}</Button>;
147
+ ```
148
+
149
+ ---
150
+
151
+ ## Who this is for
152
+
153
+ `react-scoped-i18n` is built for **small teams and indie developers** who:
141
154
 
142
- `react-scoped-i18n 🌐` shines most when devs are the ones adding translations into the app, and when the number of supported languages is small-to-medium sized.
155
+ - Write and maintain their own translations (or work directly with translators in code)
156
+ - Support a small-to-medium number of languages
157
+ - Want TypeScript to enforce correctness, not just assist with autocomplete
158
+ - Prefer reading code over managing JSON files
143
159
 
144
- You can find more in-depth examples in the [Installation & Usage](/docs/usage.md) and the API definitions in [API](/docs/api.md)
160
+ If your workflow involves external translation platforms like Crowdin or Lokalise (or third party translators touching files directly), this approach is likely not for you.
145
161
 
146
162
  ---
147
163
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-scoped-i18n",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "A scoped internationalization (i18n) library for React applications",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",