@gringow/gringow-react
v0.2.0
Published
React bindings for Gringow AI-powered translation tool
Downloads
281
Readme
@gringow/gringow-react
React bindings for Gringow AI-powered translations. Provides declarative template string translations with runtime language switching and smart caching. Built on @gringow/gringow-shadow Web Components.
Features
- ⚛️ React 19+ Support - Uses modern React features and hooks
- 🏷️ Template Literal Syntax - Translate with `g`Hello ${name}``
- 🔄 Runtime Language Switching - Change languages without reload
- 💾 Smart Caching - Automatic cache lookup and fallback
- 🌐 SSR Compatible - Server-side rendering support
- 🎯 Type-Safe - Full TypeScript definitions included
Installation
# Using pnpm
pnpm add @gringow/gringow @gringow/gringow-react
# Using npm
npm install @gringow/gringow @gringow/gringow-react
# Using yarn
yarn add @gringow/gringow @gringow/gringow-reactRequirements
- React 19+
- A Gringow cache file (generated by @gringow/cli or @gringow/gringow-vite)
Quick Start
1. Initialize Gringow (Client-Side)
// app-bootstrap.tsx (client-only)
import '@gringow/gringow-react/browser'
import { GringowStore } from '@gringow/gringow-react/store'
// Configure store
GringowStore.language = 'en-US'
GringowStore.cacheUrl = '/gringow/gringow.json'
// Fetch cache once
await GringowStore.fetchCache()2. Use Translations in Components
// Welcome.tsx
import { g } from '@gringow/gringow-react'
export function Welcome({ name }: { name: string }) {
return (
<div>
<h1>{g`Hello ${name}, welcome back!`}</h1>
<p>{g`You have new messages`}</p>
</div>
)
}3. Add Language Switcher
// LanguageSwitcher.tsx
import { changeLanguage } from '@gringow/gringow-react'
export function LanguageSwitcher() {
return (
<div>
<button onClick={() => changeLanguage('en-US')}>English</button>
<button onClick={() => changeLanguage('pt-BR')}>Português</button>
<button onClick={() => changeLanguage('fr-CA')}>Français</button>
</div>
)
}Usage Examples
Basic Translation
import { g } from '@gringow/gringow-react'
function Greeting() {
return <h1>{g`Welcome to Gringow`}</h1>
}Dynamic Content
import { g } from '@gringow/gringow-react'
function UserProfile({ user }: { user: { name: string; role: string } }) {
return (
<div>
{g`Hello ${user.name}!`}
{g`Your role: ${user.role}`}
</div>
)
}Full Application Example
// main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import '@gringow/gringow-react/browser'
import { GringowStore } from '@gringow/gringow-react/store'
import App from './App'
// Bootstrap Gringow
async function init() {
GringowStore.cacheUrl = '/gringow/gringow.json'
GringowStore.language = document.documentElement.lang || 'en-US'
await GringowStore.fetchCache()
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
}
init()// App.tsx
import { g, changeLanguage } from '@gringow/gringow-react'
export default function App() {
const [user] = React.useState({ name: 'Alice', unread: 5 })
return (
<div>
<nav>
<button onClick={() => changeLanguage('en-US')}>EN</button>
<button onClick={() => changeLanguage('pt-BR')}>PT</button>
<button onClick={() => changeLanguage('es-ES')}>ES</button>
</nav>
<main>
<h1>{g`Welcome ${user.name}!`}</h1>
<p>{g`You have ${user.unread} unread messages`}</p>
<button>{g`Mark all as read`}</button>
</main>
</div>
)
}With Vite
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { GringowVitePlugin } from '@gringow/gringow-vite'
export default defineConfig({
plugins: [
react(),
GringowVitePlugin()
]
})API Reference
g Template Tag
Main translation function using tagged template literals.
function g(strings: TemplateStringsArray, ...values: unknown[]): ReactNodeExample:
{g`Hello ${name}!`}
{g`You have ${count} messages`}The g helper:
- Flattens the template string
- Creates a cache ID via content hashing
- Returns a
<g-gringow>custom element - Falls back to original string if cache unavailable
GringowStore
Singleton store for managing translation cache and language state.
Properties
// Active language (defaults to document.documentElement.lang)
GringowStore.language: string | null
// Cache file URL
GringowStore.cacheUrl: string | null
// Loaded cache object
GringowStore.cache: GringowCache | nullMethods
// Fetch and cache translations
await GringowStore.fetchCache(): Promise<void>
// Get translation for specific cache ID
GringowStore.getCacheItem(cacheId: string): string | null
// Manually set cache
GringowStore.setCache(cache: GringowCache): voidConfiguration Fallbacks
cacheUrl resolution order:
GringowStore.cacheUrl(programmatic)<meta name="gringow-cache-url" content="/path"><html data-gringow-cache-url="/path">
changeLanguage()
Convenience function for language switching.
function changeLanguage(lang: string): voidExample:
<button onClick={() => changeLanguage('pt-BR')}>Português</button>Dispatches a global LanguageChangeEvent that updates all mounted components.
LanguageChangeEvent
Custom event for language changes.
class LanguageChangeEvent extends CustomEvent<{ lang: string }>
// Constants
LanguageChangeEvent.EVENT_NAME: 'gringow:language-change'
// Factory method
LanguageChangeEvent.create(lang: string): LanguageChangeEventManual usage:
window.dispatchEvent(LanguageChangeEvent.create('fr-CA'))
// Listen for changes
window.addEventListener(LanguageChangeEvent.EVENT_NAME, (event) => {
console.log('Language changed to:', event.detail.lang)
})Development scripts
pnpm run build # Compile TypeScript to dist/
pnpm run watch # Rebuild on changes during local developmentLicense
MIT © Renato Gaspar
How It Works
- Template Literal -
gtag flattens strings and generates cache IDs - Custom Element - Returns
<g-gringow>Web Component (from shadow package) - Cache Lookup - Component queries
GringowStorefor translations - Fallback - Shows original text if cache unavailable or SSR
- Reactivity - Updates automatically on
LanguageChangeEvent
SSR Support
The package handles server-side rendering gracefully:
// Server renders original text
{g`Hello ${name}`} // Outputs: "Hello Alice"
// Client hydrates and replaces with translation
{g`Hello ${name}`} // Outputs: "Olá Alice" (if pt-BR)The <g-gringow> element only translates on the client after cache loads.
Module Exports
// Main export
import { g, changeLanguage, LanguageChangeEvent } from '@gringow/gringow-react'
// Store export
import { GringowStore } from '@gringow/gringow-react/store'
// Browser initialization (import once)
import '@gringow/gringow-react/browser'Development
# Install dependencies
pnpm install
# Build the package
pnpm run build
# Watch mode
pnpm run watchBest Practices
- Import browser module once - Do it in your app's entry point
- Fetch cache early - Call
GringowStore.fetchCache()before rendering - Use Vite plugin - Automatically extracts translations during build
- Keep fallbacks - Original strings serve as loading state
- Cache versioning - Bust cache when translations update
Related Packages
- @gringow/gringow - Core translation library
- @gringow/gringow-shadow - Web Component layer (this package depends on it)
- @gringow/gringow-vite - Vite plugin for build-time extraction
- @gringow/cli - CLI for translation management
- @gringow/gringow-nextjs - Next.js plugin (experimental)
Resources
License
MIT © Renato Gaspar
Need Help? Open an issue on GitHub
