@gringow/gringow-react 0.0.8 → 0.2.0
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 +310 -44
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,90 +1,278 @@
|
|
|
1
1
|
# @gringow/gringow-react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@gringow/gringow-react)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
6
|
+
React bindings for Gringow AI-powered translations. Provides declarative template string translations with runtime language switching and smart caching. Built on [@gringow/gringow-shadow](https://www.npmjs.com/package/@gringow/gringow-shadow) Web Components.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- ⚛️ **React 19+ Support** - Uses modern React features and hooks
|
|
11
|
+
- 🏷️ **Template Literal Syntax** - Translate with \`g\`Hello ${name}\`\`
|
|
12
|
+
- 🔄 **Runtime Language Switching** - Change languages without reload
|
|
13
|
+
- 💾 **Smart Caching** - Automatic cache lookup and fallback
|
|
14
|
+
- 🌐 **SSR Compatible** - Server-side rendering support
|
|
15
|
+
- 🎯 **Type-Safe** - Full TypeScript definitions included
|
|
10
16
|
|
|
11
17
|
## Installation
|
|
18
|
+
|
|
12
19
|
```bash
|
|
20
|
+
# Using pnpm
|
|
13
21
|
pnpm add @gringow/gringow @gringow/gringow-react
|
|
14
|
-
|
|
15
|
-
#
|
|
22
|
+
|
|
23
|
+
# Using npm
|
|
24
|
+
npm install @gringow/gringow @gringow/gringow-react
|
|
25
|
+
|
|
26
|
+
# Using yarn
|
|
27
|
+
yarn add @gringow/gringow @gringow/gringow-react
|
|
16
28
|
```
|
|
17
29
|
|
|
18
|
-
###
|
|
19
|
-
|
|
20
|
-
-
|
|
30
|
+
### Requirements
|
|
31
|
+
|
|
32
|
+
- **React 19+**
|
|
33
|
+
- **A Gringow cache file** (generated by [@gringow/cli](https://www.npmjs.com/package/@gringow/gringow-cli) or [@gringow/gringow-vite](https://www.npmjs.com/package/@gringow/gringow-vite))
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
21
36
|
|
|
22
|
-
|
|
23
|
-
Register the custom element once on the client, configure the store, and then render translated strings with the `g`
|
|
24
|
-
helper.
|
|
37
|
+
### 1. Initialize Gringow (Client-Side)
|
|
25
38
|
|
|
26
39
|
```tsx
|
|
27
|
-
// app-bootstrap.
|
|
40
|
+
// app-bootstrap.tsx (client-only)
|
|
28
41
|
import '@gringow/gringow-react/browser'
|
|
29
42
|
import { GringowStore } from '@gringow/gringow-react/store'
|
|
30
43
|
|
|
44
|
+
// Configure store
|
|
31
45
|
GringowStore.language = 'en-US'
|
|
32
46
|
GringowStore.cacheUrl = '/gringow/gringow.json'
|
|
47
|
+
|
|
48
|
+
// Fetch cache once
|
|
33
49
|
await GringowStore.fetchCache()
|
|
34
50
|
```
|
|
35
51
|
|
|
52
|
+
### 2. Use Translations in Components
|
|
53
|
+
|
|
36
54
|
```tsx
|
|
37
55
|
// Welcome.tsx
|
|
38
56
|
import { g } from '@gringow/gringow-react'
|
|
39
57
|
|
|
40
58
|
export function Welcome({ name }: { name: string }) {
|
|
41
|
-
return
|
|
59
|
+
return (
|
|
60
|
+
<div>
|
|
61
|
+
<h1>{g`Hello ${name}, welcome back!`}</h1>
|
|
62
|
+
<p>{g`You have new messages`}</p>
|
|
63
|
+
</div>
|
|
64
|
+
)
|
|
42
65
|
}
|
|
43
66
|
```
|
|
44
67
|
|
|
45
|
-
|
|
68
|
+
### 3. Add Language Switcher
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
// LanguageSwitcher.tsx
|
|
72
|
+
import { changeLanguage } from '@gringow/gringow-react'
|
|
73
|
+
|
|
74
|
+
export function LanguageSwitcher() {
|
|
75
|
+
return (
|
|
76
|
+
<div>
|
|
77
|
+
<button onClick={() => changeLanguage('en-US')}>English</button>
|
|
78
|
+
<button onClick={() => changeLanguage('pt-BR')}>Português</button>
|
|
79
|
+
<button onClick={() => changeLanguage('fr-CA')}>Français</button>
|
|
80
|
+
</div>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
```
|
|
46
84
|
|
|
47
|
-
|
|
48
|
-
> application (typically in your client bootstrap).
|
|
85
|
+
## Usage Examples
|
|
49
86
|
|
|
50
|
-
|
|
51
|
-
The store can be fed from a static file or from a hosted endpoint. When not set programmatically, `cacheUrl` falls back
|
|
52
|
-
to `<meta name="gringow-cache-url">` or `data-gringow-cache-url` on `<html>`, and `language` defaults to
|
|
53
|
-
`document.documentElement.lang`.
|
|
87
|
+
### Basic Translation
|
|
54
88
|
|
|
55
89
|
```tsx
|
|
56
|
-
import {
|
|
90
|
+
import { g } from '@gringow/gringow-react'
|
|
57
91
|
|
|
58
|
-
|
|
59
|
-
|
|
92
|
+
function Greeting() {
|
|
93
|
+
return <h1>{g`Welcome to Gringow`}</h1>
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Dynamic Content
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { g } from '@gringow/gringow-react'
|
|
60
101
|
|
|
61
|
-
|
|
62
|
-
|
|
102
|
+
function UserProfile({ user }: { user: { name: string; role: string } }) {
|
|
103
|
+
return (
|
|
104
|
+
<div>
|
|
105
|
+
{g`Hello ${user.name}!`}
|
|
106
|
+
{g`Your role: ${user.role}`}
|
|
107
|
+
</div>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
63
110
|
```
|
|
64
111
|
|
|
65
|
-
|
|
112
|
+
### Full Application Example
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
// main.tsx
|
|
116
|
+
import React from 'react'
|
|
117
|
+
import ReactDOM from 'react-dom/client'
|
|
118
|
+
import '@gringow/gringow-react/browser'
|
|
119
|
+
import { GringowStore } from '@gringow/gringow-react/store'
|
|
120
|
+
import App from './App'
|
|
121
|
+
|
|
122
|
+
// Bootstrap Gringow
|
|
123
|
+
async function init() {
|
|
124
|
+
GringowStore.cacheUrl = '/gringow/gringow.json'
|
|
125
|
+
GringowStore.language = document.documentElement.lang || 'en-US'
|
|
126
|
+
await GringowStore.fetchCache()
|
|
66
127
|
|
|
67
|
-
|
|
68
|
-
|
|
128
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
129
|
+
<React.StrictMode>
|
|
130
|
+
<App />
|
|
131
|
+
</React.StrictMode>
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
init()
|
|
136
|
+
```
|
|
69
137
|
|
|
70
138
|
```tsx
|
|
71
|
-
|
|
139
|
+
// App.tsx
|
|
140
|
+
import { g, changeLanguage } from '@gringow/gringow-react'
|
|
141
|
+
|
|
142
|
+
export default function App() {
|
|
143
|
+
const [user] = React.useState({ name: 'Alice', unread: 5 })
|
|
72
144
|
|
|
73
|
-
|
|
74
|
-
|
|
145
|
+
return (
|
|
146
|
+
<div>
|
|
147
|
+
<nav>
|
|
148
|
+
<button onClick={() => changeLanguage('en-US')}>EN</button>
|
|
149
|
+
<button onClick={() => changeLanguage('pt-BR')}>PT</button>
|
|
150
|
+
<button onClick={() => changeLanguage('es-ES')}>ES</button>
|
|
151
|
+
</nav>
|
|
152
|
+
|
|
153
|
+
<main>
|
|
154
|
+
<h1>{g`Welcome ${user.name}!`}</h1>
|
|
155
|
+
<p>{g`You have ${user.unread} unread messages`}</p>
|
|
156
|
+
<button>{g`Mark all as read`}</button>
|
|
157
|
+
</main>
|
|
158
|
+
</div>
|
|
159
|
+
)
|
|
75
160
|
}
|
|
76
161
|
```
|
|
77
162
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
163
|
+
### With Vite
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
// vite.config.ts
|
|
167
|
+
import { defineConfig } from 'vite'
|
|
168
|
+
import react from '@vitejs/plugin-react'
|
|
169
|
+
import { GringowVitePlugin } from '@gringow/gringow-vite'
|
|
170
|
+
|
|
171
|
+
export default defineConfig({
|
|
172
|
+
plugins: [
|
|
173
|
+
react(),
|
|
174
|
+
GringowVitePlugin()
|
|
175
|
+
]
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## API Reference
|
|
180
|
+
|
|
181
|
+
### `g` Template Tag
|
|
182
|
+
|
|
183
|
+
Main translation function using tagged template literals.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
function g(strings: TemplateStringsArray, ...values: unknown[]): ReactNode
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Example:**
|
|
190
|
+
```tsx
|
|
191
|
+
{g`Hello ${name}!`}
|
|
192
|
+
{g`You have ${count} messages`}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The `g` helper:
|
|
196
|
+
1. Flattens the template string
|
|
197
|
+
2. Creates a cache ID via content hashing
|
|
198
|
+
3. Returns a `<g-gringow>` custom element
|
|
199
|
+
4. Falls back to original string if cache unavailable
|
|
200
|
+
|
|
201
|
+
### GringowStore
|
|
202
|
+
|
|
203
|
+
Singleton store for managing translation cache and language state.
|
|
204
|
+
|
|
205
|
+
#### Properties
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
// Active language (defaults to document.documentElement.lang)
|
|
209
|
+
GringowStore.language: string | null
|
|
210
|
+
|
|
211
|
+
// Cache file URL
|
|
212
|
+
GringowStore.cacheUrl: string | null
|
|
213
|
+
|
|
214
|
+
// Loaded cache object
|
|
215
|
+
GringowStore.cache: GringowCache | null
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### Methods
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
// Fetch and cache translations
|
|
222
|
+
await GringowStore.fetchCache(): Promise<void>
|
|
223
|
+
|
|
224
|
+
// Get translation for specific cache ID
|
|
225
|
+
GringowStore.getCacheItem(cacheId: string): string | null
|
|
226
|
+
|
|
227
|
+
// Manually set cache
|
|
228
|
+
GringowStore.setCache(cache: GringowCache): void
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### Configuration Fallbacks
|
|
232
|
+
|
|
233
|
+
`cacheUrl` resolution order:
|
|
234
|
+
1. `GringowStore.cacheUrl` (programmatic)
|
|
235
|
+
2. `<meta name="gringow-cache-url" content="/path">`
|
|
236
|
+
3. `<html data-gringow-cache-url="/path">`
|
|
237
|
+
|
|
238
|
+
### changeLanguage()
|
|
239
|
+
|
|
240
|
+
Convenience function for language switching.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
function changeLanguage(lang: string): void
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Example:**
|
|
247
|
+
```tsx
|
|
248
|
+
<button onClick={() => changeLanguage('pt-BR')}>Português</button>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Dispatches a global `LanguageChangeEvent` that updates all mounted components.
|
|
252
|
+
|
|
253
|
+
### LanguageChangeEvent
|
|
254
|
+
|
|
255
|
+
Custom event for language changes.
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
class LanguageChangeEvent extends CustomEvent<{ lang: string }>
|
|
259
|
+
|
|
260
|
+
// Constants
|
|
261
|
+
LanguageChangeEvent.EVENT_NAME: 'gringow:language-change'
|
|
262
|
+
|
|
263
|
+
// Factory method
|
|
264
|
+
LanguageChangeEvent.create(lang: string): LanguageChangeEvent
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Manual usage:**
|
|
268
|
+
```tsx
|
|
269
|
+
window.dispatchEvent(LanguageChangeEvent.create('fr-CA'))
|
|
270
|
+
|
|
271
|
+
// Listen for changes
|
|
272
|
+
window.addEventListener(LanguageChangeEvent.EVENT_NAME, (event) => {
|
|
273
|
+
console.log('Language changed to:', event.detail.lang)
|
|
274
|
+
})
|
|
275
|
+
```
|
|
88
276
|
|
|
89
277
|
## Development scripts
|
|
90
278
|
```bash
|
|
@@ -94,3 +282,81 @@ pnpm run watch # Rebuild on changes during local development
|
|
|
94
282
|
|
|
95
283
|
## License
|
|
96
284
|
MIT © Renato Gaspar
|
|
285
|
+
|
|
286
|
+
## How It Works
|
|
287
|
+
|
|
288
|
+
1. **Template Literal** - `g` tag flattens strings and generates cache IDs
|
|
289
|
+
2. **Custom Element** - Returns `<g-gringow>` Web Component (from shadow package)
|
|
290
|
+
3. **Cache Lookup** - Component queries `GringowStore` for translations
|
|
291
|
+
4. **Fallback** - Shows original text if cache unavailable or SSR
|
|
292
|
+
5. **Reactivity** - Updates automatically on `LanguageChangeEvent`
|
|
293
|
+
|
|
294
|
+
## SSR Support
|
|
295
|
+
|
|
296
|
+
The package handles server-side rendering gracefully:
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
// Server renders original text
|
|
300
|
+
{g`Hello ${name}`} // Outputs: "Hello Alice"
|
|
301
|
+
|
|
302
|
+
// Client hydrates and replaces with translation
|
|
303
|
+
{g`Hello ${name}`} // Outputs: "Olá Alice" (if pt-BR)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
The `<g-gringow>` element only translates on the client after cache loads.
|
|
307
|
+
|
|
308
|
+
## Module Exports
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
// Main export
|
|
312
|
+
import { g, changeLanguage, LanguageChangeEvent } from '@gringow/gringow-react'
|
|
313
|
+
|
|
314
|
+
// Store export
|
|
315
|
+
import { GringowStore } from '@gringow/gringow-react/store'
|
|
316
|
+
|
|
317
|
+
// Browser initialization (import once)
|
|
318
|
+
import '@gringow/gringow-react/browser'
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Development
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
# Install dependencies
|
|
325
|
+
pnpm install
|
|
326
|
+
|
|
327
|
+
# Build the package
|
|
328
|
+
pnpm run build
|
|
329
|
+
|
|
330
|
+
# Watch mode
|
|
331
|
+
pnpm run watch
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Best Practices
|
|
335
|
+
|
|
336
|
+
1. **Import browser module once** - Do it in your app's entry point
|
|
337
|
+
2. **Fetch cache early** - Call `GringowStore.fetchCache()` before rendering
|
|
338
|
+
3. **Use Vite plugin** - Automatically extracts translations during build
|
|
339
|
+
4. **Keep fallbacks** - Original strings serve as loading state
|
|
340
|
+
5. **Cache versioning** - Bust cache when translations update
|
|
341
|
+
|
|
342
|
+
## Related Packages
|
|
343
|
+
|
|
344
|
+
- **[@gringow/gringow](https://www.npmjs.com/package/@gringow/gringow)** - Core translation library
|
|
345
|
+
- **[@gringow/gringow-shadow](https://www.npmjs.com/package/@gringow/gringow-shadow)** - Web Component layer (this package depends on it)
|
|
346
|
+
- **[@gringow/gringow-vite](https://www.npmjs.com/package/@gringow/gringow-vite)** - Vite plugin for build-time extraction
|
|
347
|
+
- **[@gringow/cli](https://www.npmjs.com/package/@gringow/gringow-cli)** - CLI for translation management
|
|
348
|
+
- **[@gringow/gringow-nextjs](https://www.npmjs.com/package/@gringow/gringow-nextjs)** - Next.js plugin (experimental)
|
|
349
|
+
|
|
350
|
+
## Resources
|
|
351
|
+
|
|
352
|
+
- [Documentation](https://gringow.dev)
|
|
353
|
+
- [GitHub Repository](https://github.com/rntgspr/gringow)
|
|
354
|
+
- [Example: React + Vite](https://github.com/rntgspr/gringow/tree/main/example-gringow-vite)
|
|
355
|
+
|
|
356
|
+
## License
|
|
357
|
+
|
|
358
|
+
MIT © [Renato Gaspar](https://github.com/rntgspr)
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
**Need Help?** Open an issue on [GitHub](https://github.com/rntgspr/gringow/issues)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gringow/gringow-react",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "React bindings for Gringow AI-powered translation tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@types/react": "^19.2.7",
|
|
36
36
|
"react": "19.1.0",
|
|
37
37
|
"react-dom": "19.1.0",
|
|
38
|
-
"@gringow/gringow": "0.
|
|
39
|
-
"@gringow/gringow-shadow": "0.0
|
|
38
|
+
"@gringow/gringow": "0.2.0",
|
|
39
|
+
"@gringow/gringow-shadow": "0.2.0"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "rm -rf ./dist/* ./tsconfig.tsbuildinfo && tsup",
|