@gringow/gringow-shadow
v0.2.0
Published
A HTML class for Gringow AI-powered translation tool
Maintainers
Readme
@gringow/gringow-shadow
Lightweight Web Component layer for Gringow translations. Provides the <g-gringow> custom element, translation store, and language change events for vanilla JavaScript projects. This is the foundation layer used by @gringow/gringow-react.
Features
- 🎯 Custom Element -
<g-gringow>for declarative translations - 🗂️ Translation Store - Singleton cache manager with language awareness
- 📡 Language Events - Type-safe language change broadcasting
- 🪶 Zero Dependencies - Pure Web Components API
- ⚡ Framework Agnostic - Works with vanilla JS, React, Vue, etc.
- 🔄 Smart Caching - Memoized cache fetching and lookup
Installation
# Using pnpm
pnpm add @gringow/gringow-shadow
# Using npm
npm install @gringow/gringow-shadow
# Using yarn
yarn add @gringow/gringow-shadowQuick Start
Vanilla HTML Setup
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="gringow-cache-url" content="/gringow/gringow.json">
</head>
<body>
<g-gringow data-cache-id="grw_abc123" data-flatten="Hello world"></g-gringow>
<button id="btn-pt">Português</button>
<button id="btn-fr">Français</button>
<script type="module">
import { GringowComponent, GringowStore, LanguageChangeEvent } from '@gringow/gringow-shadow'
// Configure store
GringowStore.cacheUrl = '/gringow/gringow.json'
GringowStore.language = 'en-US'
await GringowStore.fetchCache()
// Register custom element
GringowComponent.defaults = { store: GringowStore }
customElements.define(GringowComponent.GRINGOW_ELEMENT_NAME, GringowComponent)
// Handle language changes
document.getElementById('btn-pt').onclick = () => {
dispatchEvent(LanguageChangeEvent.create('pt-BR'))
}
document.getElementById('btn-fr').onclick = () => {
dispatchEvent(LanguageChangeEvent.create('fr-CA'))
}
// Listen to language changes
addEventListener(LanguageChangeEvent.EVENT_NAME, (event) => {
console.log('Language changed to:', event.detail.lang)
})
</script>
</body>
</html>Component API
<g-gringow> Custom Element
Declarative translation component that reads from the cache and updates on language changes.
Attributes
data-cache-id(required) - Cache ID fromgringow.json(e.g.,grw_abc123)data-flatten(required) - Original flattened string used as fallbackdata-replacements(optional) - JSON array for interpolation (e.g.,'["Alice", 5]')
Example with Replacements
<!-- Cache entry: "Hello {0}, you have {1} messages" -->
<g-gringow
data-cache-id="grw_msg456"
data-flatten="Hello {name}, you have {count} messages"
data-replacements='["Alice", 5]'>
</g-gringow>
<!-- Renders: "Hello Alice, you have 5 messages" -->GringowStore (Singleton)
Central cache manager for fetching and accessing translations.
Properties
// Cache file URL (auto-detects from <meta> or <html data-gringow-cache-url>)
GringowStore.cacheUrl: string | null
// Active language (defaults to document.documentElement.lang)
GringowStore.language: string | null
// Cached translations object
GringowStore.cache: GringowCache | nullMethods
// Fetch and memoize cache from cacheUrl
await GringowStore.fetchCache(): Promise<void>
// Get translated string for active language
GringowStore.getCacheItem(cacheId: string): string | null
// Manual cache setter
GringowStore.setCache(cache: GringowCache): voidConfiguration Priority
The store resolves cacheUrl in this order:
GringowStore.cacheUrl(programmatic)<meta name="gringow-cache-url" content="/path/to/cache.json"><html data-gringow-cache-url="/path/to/cache.json">
LanguageChangeEvent
Custom event for broadcasting language changes across components.
Usage
// Dispatch language change
dispatchEvent(LanguageChangeEvent.create('pt-BR'))
// Listen for changes
addEventListener(LanguageChangeEvent.EVENT_NAME, (event) => {
console.log('New language:', event.detail.lang)
// event.detail.lang === 'pt-BR'
})Constants
LanguageChangeEvent.EVENT_NAME-'gringow:language-change'LanguageChangeEvent.create(lang: string)- Factory method for events
Advanced Examples
Dynamic Content with Interpolation
<script type="module">
import { GringowComponent, GringowStore } from '@gringow/gringow-shadow'
GringowStore.cacheUrl = '/gringow/gringow.json'
GringowStore.language = 'en-US'
await GringowStore.fetchCache()
GringowComponent.defaults = { store: GringowStore }
customElements.define('g-gringow', GringowComponent)
// Dynamically create element with replacements
const element = document.createElement('g-gringow')
element.setAttribute('data-cache-id', 'grw_welcome')
element.setAttribute('data-flatten', 'Welcome back, {name}!')
element.setAttribute('data-replacements', JSON.stringify(['Alice']))
document.body.appendChild(element)
</script>Multiple Language Switcher
<nav>
<button data-lang="en-US">English</button>
<button data-lang="pt-BR">Português</button>
<button data-lang="fr-CA">Français</button>
<button data-lang="es-ES">Español</button>
</nav>
<main>
<g-gringow data-cache-id="grw_title" data-flatten="Welcome"></g-gringow>
<g-gringow data-cache-id="grw_desc" data-flatten="Choose your language"></g-gringow>
</main>
<script type="module">
import { GringowComponent, GringowStore, LanguageChangeEvent } from '@gringow/gringow-shadow'
// Setup
GringowStore.cacheUrl = '/gringow/gringow.json'
GringowStore.language = document.documentElement.lang || 'en-US'
await GringowStore.fetchCache()
GringowComponent.defaults = { store: GringowStore }
customElements.define('g-gringow', GringowComponent)
// Wire language buttons
document.querySelectorAll('[data-lang]').forEach(btn => {
btn.onclick = () => {
const lang = btn.dataset.lang
document.documentElement.lang = lang
dispatchEvent(LanguageChangeEvent.create(lang))
}
})
</script>Framework Integration (Vue/Svelte/etc)
// utils/gringow.ts
import { GringowComponent, GringowStore, LanguageChangeEvent } from '@gringow/gringow-shadow'
export async function initGringow(cacheUrl: string, initialLang: string) {
GringowStore.cacheUrl = cacheUrl
GringowStore.language = initialLang
await GringowStore.fetchCache()
GringowComponent.defaults = { store: GringowStore }
if (!customElements.get('g-gringow')) {
customElements.define('g-gringow', GringowComponent)
}
}
export function changeLanguage(lang: string) {
dispatchEvent(LanguageChangeEvent.create(lang))
}Module Exports
The package provides granular exports for tree-shaking:
// Main export (all components)
import { GringowComponent, GringowStore, LanguageChangeEvent } from '@gringow/gringow-shadow'
// Individual exports
import { GringowComponent } from '@gringow/gringow-shadow/component'
import { GringowStore } from '@gringow/gringow-shadow/store'
import { LanguageChangeEvent } from '@gringow/gringow-shadow/event'Development
# Install dependencies
pnpm install
# Build the package
pnpm run build
# Watch mode for development
pnpm run watchBrowser Compatibility
Built on Web Components standards:
- Custom Elements v1
- Shadow DOM v1
- ES2020+ modules
Supported browsers: Chrome 54+, Firefox 63+, Safari 10.1+, Edge 79+
Related Packages
- @gringow/gringow - Core translation library
- @gringow/gringow-react - React integration (built on this package)
- @gringow/gringow-vite - Vite plugin
- @gringow/cli - CLI tool
- @gringow/gringow-nextjs - Next.js plugin (experimental)
Resources
License
MIT © Renato Gaspar
Questions? Open an issue on GitHub
