anylang-dev 0.1.0 → 0.1.2
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 +55 -20
- package/package.json +1 -1
- package/src/config.js +1 -1
- package/src/pipeline.js +50 -2
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 =
|
|
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
|
|
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) =>
|
|
40
|
+
onChange={(event) => setLanguage(event.target.value as LanguageCode)}
|
|
47
41
|
>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
```
|
|
@@ -90,7 +86,7 @@ anylang translate
|
|
|
90
86
|
"exclude": ["node_modules", ".git", "dist", "build", ".next"],
|
|
91
87
|
"outDir": "locales",
|
|
92
88
|
"runtime": {
|
|
93
|
-
"output": "
|
|
89
|
+
"output": "anylang.ts",
|
|
94
90
|
"importFrom": "anylang-dev/runtime"
|
|
95
91
|
},
|
|
96
92
|
"functionName": "$tr",
|
|
@@ -155,8 +151,7 @@ locales/
|
|
|
155
151
|
en.json
|
|
156
152
|
hi.json
|
|
157
153
|
anylang.lock.json
|
|
158
|
-
|
|
159
|
-
anylang.generated.ts
|
|
154
|
+
anylang.ts
|
|
160
155
|
```
|
|
161
156
|
|
|
162
157
|
The lock file stores SHA-256 fingerprints so unchanged strings are skipped on later runs.
|
|
@@ -176,7 +171,7 @@ anylang scan
|
|
|
176
171
|
```
|
|
177
172
|
|
|
178
173
|
This writes keyed source entries to `locales/en.json` and creates placeholder entries in each target locale.
|
|
179
|
-
It also generates `
|
|
174
|
+
It also generates `anylang.ts`, which imports all locale JSON files and exports runtime helpers.
|
|
180
175
|
|
|
181
176
|
3. Translate with Gemini:
|
|
182
177
|
|
|
@@ -221,11 +216,51 @@ Import the generated runtime file in your app:
|
|
|
221
216
|
|
|
222
217
|
```tsx
|
|
223
218
|
import {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
219
|
+
AnyLangProvider,
|
|
220
|
+
useLanguage,
|
|
221
|
+
useTr,
|
|
227
222
|
type LanguageCode
|
|
228
|
-
} from "./anylang
|
|
223
|
+
} from "./anylang";
|
|
229
224
|
```
|
|
230
225
|
|
|
231
226
|
You do not manually import `en.json`, `hi.json`, `ja.json`, etc. The generated file does that for you based on `sourceLocale` and `targetLocales`.
|
|
227
|
+
|
|
228
|
+
Wrap your app once:
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
root.render(
|
|
232
|
+
<AnyLangProvider>
|
|
233
|
+
<App />
|
|
234
|
+
</AnyLangProvider>
|
|
235
|
+
);
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Then use translations in any component:
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
function Hero() {
|
|
242
|
+
const $tr = useTr();
|
|
243
|
+
return <h1>{$tr("hero.title", "Translate your website with anylang")}</h1>;
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
And build any selector with `useLanguage`:
|
|
248
|
+
|
|
249
|
+
```tsx
|
|
250
|
+
function LanguageSelector() {
|
|
251
|
+
const { language, languages, setLanguage } = useLanguage();
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<select
|
|
255
|
+
value={language}
|
|
256
|
+
onChange={(event) => setLanguage(event.target.value as LanguageCode)}
|
|
257
|
+
>
|
|
258
|
+
{languages.map((language) => (
|
|
259
|
+
<option key={language.code} value={language.code}>
|
|
260
|
+
{language.nativeLabel}
|
|
261
|
+
</option>
|
|
262
|
+
))}
|
|
263
|
+
</select>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
```
|
package/package.json
CHANGED
package/src/config.js
CHANGED
package/src/pipeline.js
CHANGED
|
@@ -131,7 +131,7 @@ function normalizeTargetEntry(entry) {
|
|
|
131
131
|
async function writeGeneratedRuntime(config) {
|
|
132
132
|
if (config.runtime === false) return;
|
|
133
133
|
|
|
134
|
-
const output = path.resolve(config.runtime?.output || "
|
|
134
|
+
const output = path.resolve(config.runtime?.output || "anylang.ts");
|
|
135
135
|
const outDir = path.resolve(config.outDir);
|
|
136
136
|
const locales = [config.sourceLocale, ...config.targetLocales.filter((locale) => locale !== config.sourceLocale)];
|
|
137
137
|
const importFrom = config.runtime?.importFrom || "anylang-dev/runtime";
|
|
@@ -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
|
|