anylang-dev 0.1.0 → 0.1.1

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.
package/README.md CHANGED
@@ -11,7 +11,7 @@ It works in JSX and TSX when the text is wrapped in a JavaScript expression:
11
11
 
12
12
  ```tsx
13
13
  export function Hero() {
14
- const $tr = useAnyLang(language);
14
+ const $tr = useTr();
15
15
 
16
16
  return (
17
17
  <section>
@@ -32,22 +32,18 @@ By default, `anylang` scans `.js`, `.jsx`, `.ts`, `.tsx`, `.vue`, and `.html` fi
32
32
  `anylang` does not require a built-in selector. Build any selector UI you want and pass the selected locale to `setLanguage`.
33
33
 
34
34
  ```tsx
35
- const [language, setSelectedLanguage] = useState<LanguageCode>("en");
36
- const $tr = useAnyLang(language);
37
-
38
- function handleLanguageChange(nextLanguage: LanguageCode) {
39
- setLanguage(nextLanguage);
40
- setSelectedLanguage(nextLanguage);
41
- }
35
+ const { language, languages, setLanguage } = useLanguage();
42
36
 
43
37
  return (
44
38
  <select
45
39
  value={language}
46
- onChange={(event) => handleLanguageChange(event.target.value as LanguageCode)}
40
+ onChange={(event) => setLanguage(event.target.value as LanguageCode)}
47
41
  >
48
- <option value="en">English</option>
49
- <option value="hi">हिन्दी</option>
50
- <option value="ja">日本語</option>
42
+ {languages.map((language) => (
43
+ <option key={language.code} value={language.code}>
44
+ {language.nativeLabel}
45
+ </option>
46
+ ))}
51
47
  </select>
52
48
  );
53
49
  ```
@@ -221,11 +217,51 @@ Import the generated runtime file in your app:
221
217
 
222
218
  ```tsx
223
219
  import {
224
- languages,
225
- setLanguage,
226
- useAnyLang,
220
+ AnyLangProvider,
221
+ useLanguage,
222
+ useTr,
227
223
  type LanguageCode
228
224
  } from "./anylang.generated";
229
225
  ```
230
226
 
231
227
  You do not manually import `en.json`, `hi.json`, `ja.json`, etc. The generated file does that for you based on `sourceLocale` and `targetLocales`.
228
+
229
+ Wrap your app once:
230
+
231
+ ```tsx
232
+ root.render(
233
+ <AnyLangProvider>
234
+ <App />
235
+ </AnyLangProvider>
236
+ );
237
+ ```
238
+
239
+ Then use translations in any component:
240
+
241
+ ```tsx
242
+ function Hero() {
243
+ const $tr = useTr();
244
+ return <h1>{$tr("hero.title", "Translate your website with anylang")}</h1>;
245
+ }
246
+ ```
247
+
248
+ And build any selector with `useLanguage`:
249
+
250
+ ```tsx
251
+ function LanguageSelector() {
252
+ const { language, languages, setLanguage } = useLanguage();
253
+
254
+ return (
255
+ <select
256
+ value={language}
257
+ onChange={(event) => setLanguage(event.target.value as LanguageCode)}
258
+ >
259
+ {languages.map((language) => (
260
+ <option key={language.code} value={language.code}>
261
+ {language.nativeLabel}
262
+ </option>
263
+ ))}
264
+ </select>
265
+ );
266
+ }
267
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anylang-dev",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Bring-your-own-key website translation JSON generator.",
5
5
  "type": "module",
6
6
  "files": [
package/src/pipeline.js CHANGED
@@ -159,7 +159,7 @@ function generatedRuntimeSource({ importFrom, localeImports, sourceLocale }) {
159
159
  .join(",\n");
160
160
 
161
161
  return `/* This file is generated by anylang. Do not edit by hand. */
162
- import { useCallback } from 'react'
162
+ import { createContext, createElement, useCallback, useContext, useMemo, useState, type ReactNode } from 'react'
163
163
  import { $tr as translate, configureAnyLang, setAnyLangLocale } from '${importFrom}'
164
164
  ${imports}
165
165
 
@@ -185,6 +185,54 @@ export function useAnyLang(locale: LanguageCode) {
185
185
  export function setLanguage(locale: LanguageCode) {
186
186
  setAnyLangLocale(locale)
187
187
  }
188
+
189
+ type AnyLangContextValue = {
190
+ language: LanguageCode
191
+ languages: typeof languages
192
+ setLanguage: (locale: LanguageCode) => void
193
+ $tr: (key: string, source?: string) => string
194
+ }
195
+
196
+ const AnyLangContext = createContext<AnyLangContextValue | null>(null)
197
+
198
+ export function AnyLangProvider({
199
+ children,
200
+ defaultLanguage = '${sourceLocale}' as LanguageCode,
201
+ }: {
202
+ children: ReactNode
203
+ defaultLanguage?: LanguageCode
204
+ }) {
205
+ const [language, setSelectedLanguage] = useState<LanguageCode>(defaultLanguage)
206
+ const $tr = useAnyLang(language)
207
+
208
+ const value = useMemo(() => ({
209
+ language,
210
+ languages,
211
+ setLanguage(nextLanguage: LanguageCode) {
212
+ setAnyLangLocale(nextLanguage)
213
+ setSelectedLanguage(nextLanguage)
214
+ },
215
+ $tr,
216
+ }), [language, $tr])
217
+
218
+ return createElement(AnyLangContext.Provider, { value }, children)
219
+ }
220
+
221
+ export function useLanguage() {
222
+ const context = useContext(AnyLangContext)
223
+ if (!context) throw new Error('useLanguage must be used inside AnyLangProvider')
224
+ return {
225
+ language: context.language,
226
+ languages: context.languages,
227
+ setLanguage: context.setLanguage,
228
+ }
229
+ }
230
+
231
+ export function useTr() {
232
+ const context = useContext(AnyLangContext)
233
+ if (!context) throw new Error('useTr must be used inside AnyLangProvider')
234
+ return context.$tr
235
+ }
188
236
  `;
189
237
  }
190
238