🌐 Translation System
Build multilingual applications with OnigiriJS's powerful i18n module. Support for plural forms, date/number formatting, and automatic DOM translation.
🍙 Quick Start
1
Initialize Translation Module
Load the module and configure your default locale:
// Load translation module
<script src="onigiri-translation.js"></script>
// Initialize with configuration
Onigiri.i18n.init({
locale: 'en',
fallbackLocale: 'en',
autoDetect: true,
missingTranslationWarning: true
});
2
Add Translations
Register translations for multiple languages:
// Add translations for English
Onigiri.i18n.addTranslations('en', {
welcome: 'Welcome to OnigiriJS!',
user: {
profile: 'User Profile',
settings: 'Settings'
},
messages: {
one: 'You have {count} message',
other: 'You have {count} messages'
}
});
// Add translations for Spanish
Onigiri.i18n.addTranslations('es', {
welcome: '¡Bienvenido a OnigiriJS!',
user: {
profile: 'Perfil de Usuario',
settings: 'Configuración'
},
messages: {
one: 'Tienes {count} mensaje',
other: 'Tienes {count} mensajes'
}
});
3
Use Translations
Translate strings in your JavaScript code:
// Simple translation
const welcome = Onigiri.t('welcome');
// "Welcome to OnigiriJS!"
// Nested keys
const profile = Onigiri.t('user.profile');
// "User Profile"
// With parameters
const greeting = Onigiri.t('hello', { name: 'Alice' });
// "Hello, Alice!"
// Plural forms
const msgCount = Onigiri.tc('messages', 5);
// "You have 5 messages"
🎯 Core Features
Basic Translation
Use the t() method for simple string translation:
// Basic usage
Onigiri.t('key')
// With specific locale
Onigiri.t('key', null, 'es')
// With parameters
Onigiri.t('greeting', { name: 'Bob', time: 'morning' })
// Translation: "Good {time}, {name}!"
// Result: "Good morning, Bob!"
Nested Translations
Organize translations with nested objects:
Onigiri.i18n.addTranslations('en', {
nav: {
home: 'Home',
about: 'About Us',
contact: {
title: 'Contact',
email: 'Email Us',
phone: 'Call Us'
}
}
});
// Access nested translations
Onigiri.t('nav.home'); // "Home"
Onigiri.t('nav.contact.email'); // "Email Us"
Plural Forms
Handle pluralization with the tc() method:
// Define plural translations
Onigiri.i18n.addTranslations('en', {
items: {
one: '{count} item',
other: '{count} items'
},
apples: {
zero: 'No apples',
one: 'One apple',
other: '{count} apples'
}
});
// Use plural translation
Onigiri.tc('items', 1); // "1 item"
Onigiri.tc('items', 5); // "5 items"
Onigiri.tc('apples', 0); // "No apples"
Onigiri.tc('apples', 1); // "One apple"
Onigiri.tc('apples', 42); // "42 apples"
🍙 Language Support: OnigiriJS includes plural rules for English, Spanish, French, German, Russian, Polish, Arabic, Japanese, Chinese, Korean, and more!
Automatic DOM Translation
Translate HTML elements using data attributes:
<!-- HTML -->
<h1 data-i18n="welcome"></h1>
<p data-i18n="user.greeting"></p>
<button data-i18n="actions.save"></button>
<input type="text" data-i18n-placeholder="form.name" />
<img data-i18n-alt="logo.description" />
<script>
// Translate all elements
Onigiri.i18n.translatePage();
// Or translate specific elements
O('[data-i18n]').translate();
</script>
🌍 Locale Management
Setting the Locale
// Set current locale
Onigiri.i18n.setLocale('es');
// Get current locale
const locale = Onigiri.i18n.getLocale();
// "es"
// Get available locales
const locales = Onigiri.i18n.getLocales();
// ["en", "es", "fr", "de"]
Locale Change Events
React to locale changes automatically:
document.addEventListener('onigiri:locale:changed', function(e) {
console.log('Locale changed to:', e.detail.locale);
// Update UI
updateNavigationLabels();
refreshDateFormats();
});
// When you change locale, the event fires automatically
Onigiri.i18n.setLocale('fr');
// Page automatically translates!
Bulk Translation Loading
// Add multiple locales at once
Onigiri.i18n.addMessages({
en: {
title: 'My App',
logout: 'Log Out'
},
es: {
title: 'Mi Aplicación',
logout: 'Cerrar Sesión'
},
fr: {
title: 'Mon Application',
logout: 'Se Déconnecter'
}
});
📅 Date & Number Formatting
Date Formatting
Format dates according to locale conventions:
const date = new Date('2025-12-21');
// Short format
Onigiri.i18n.formatDate(date, 'short', 'en');
// "12/21/25"
// Medium format
Onigiri.i18n.formatDate(date, 'medium', 'en');
// "Dec 21, 2025"
// Long format
Onigiri.i18n.formatDate(date, 'long', 'es');
// "21 de diciembre de 2025"
// Full format
Onigiri.i18n.formatDate(date, 'full', 'fr');
// "dimanche 21 décembre 2025"
// Time only
Onigiri.i18n.formatDate(date, 'time');
// "12:00 AM"
// Date and time
Onigiri.i18n.formatDate(date, 'datetime');
// "Dec 21, 2025, 12:00 AM"
Number Formatting
// Basic number formatting
Onigiri.i18n.formatNumber(1234567.89, {}, 'en');
// "1,234,567.89" (US format)
Onigiri.i18n.formatNumber(1234567.89, {}, 'de');
// "1.234.567,89" (German format)
// Percentage
Onigiri.i18n.formatNumber(0.42, {
style: 'percent'
});
// "42%"
// With decimal places
Onigiri.i18n.formatNumber(42.5, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
// "42.50"
Currency Formatting
// Format currency
Onigiri.i18n.formatCurrency(1234.56, 'USD', 'en');
// "$1,234.56"
Onigiri.i18n.formatCurrency(1234.56, 'EUR', 'de');
// "1.234,56 €"
Onigiri.i18n.formatCurrency(1234.56, 'JPY', 'ja');
// "¥1,235"
Onigiri.i18n.formatCurrency(1234.56, 'GBP', 'en-GB');
// "£1,234.56"
🔧 Advanced Usage
Namespaced Translations
Organize translations by namespace/module:
// Add translations with namespace
Onigiri.i18n.addTranslations('en', {
save: 'Save',
cancel: 'Cancel',
delete: 'Delete'
}, 'admin');
Onigiri.i18n.addTranslations('en', {
save: 'Save Post',
publish: 'Publish'
}, 'blog');
// Access namespaced translations
Onigiri.t('admin.save'); // "Save"
Onigiri.t('blog.save'); // "Save Post"
Check Translation Existence
// Check if translation exists
if (Onigiri.i18n.has('user.profile')) {
const profile = Onigiri.t('user.profile');
}
// With specific locale
if (Onigiri.i18n.has('welcome', 'es')) {
const welcome = Onigiri.t('welcome', null, 'es');
}
Get All Translations
// Get all translations for current locale
const allTranslations = Onigiri.i18n.getTranslations();
// Get translations for specific locale
const spanishTranslations = Onigiri.i18n.getTranslations('es');
🎨 Real-World Example
<!-- HTML -->
<div id="app">
<nav>
<h1 data-i18n="app.title"></h1>
<select id="language-selector">
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
</nav>
<main>
<h2 data-i18n="dashboard.welcome"></h2>
<p id="message-count"></p>
<p id="last-login"></p>
<button data-i18n="actions.refresh"></button>
</main>
</div>
<script>
// Initialize translations
Onigiri.i18n.init({ locale: 'en' });
// Add English translations
Onigiri.i18n.addTranslations('en', {
app: { title: 'My Dashboard' },
dashboard: {
welcome: 'Welcome back!',
lastLogin: 'Last login: {date}'
},
messages: {
one: 'You have {count} new message',
other: 'You have {count} new messages'
},
actions: { refresh: 'Refresh' }
});
// Add Spanish translations
Onigiri.i18n.addTranslations('es', {
app: { title: 'Mi Panel' },
dashboard: {
welcome: '¡Bienvenido de nuevo!',
lastLogin: 'Último acceso: {date}'
},
messages: {
one: 'Tienes {count} mensaje nuevo',
other: 'Tienes {count} mensajes nuevos'
},
actions: { refresh: 'Actualizar' }
});
// Create dashboard component
const dashboard = new Onigiri.prototype.Component({
data: {
messageCount: 5,
lastLogin: new Date('2025-12-21T10:30:00')
},
methods: {
updateUI() {
// Update message count with plural
const msgText = Onigiri.tc('messages', this.messageCount, {
count: this.messageCount
});
O('#message-count').text(msgText);
// Update last login with formatted date
const loginDate = Onigiri.i18n.formatDate(
this.lastLogin,
'datetime'
);
const loginText = Onigiri.t('dashboard.lastLogin', {
date: loginDate
});
O('#last-login').text(loginText);
}
},
mounted() {
// Initial translation
Onigiri.i18n.translatePage();
this.updateUI();
// Language selector
O('#language-selector').on('change', (e) => {
Onigiri.i18n.setLocale(e.target.value);
});
// Auto-update on locale change
document.addEventListener('onigiri:locale:changed', () => {
this.updateUI();
});
}
});
dashboard.mount('#app');
</script>
⚙️ Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
locale |
String | 'en' | Default locale |
fallbackLocale |
String | 'en' | Fallback when translation not found |
autoDetect |
Boolean | true | Auto-detect locale from browser |
storageKey |
String | 'onigiri_locale' | Storage key for locale preference |
missingTranslationWarning |
Boolean | true | Warn about missing translations |
🍙 Pro Tip: Load translations asynchronously from JSON files to keep your main bundle small! Use
Onigiri.ajax to fetch translation files on demand.
🔗 Integration Examples
Loading Translations from JSON
// Load translations from external files
async function loadTranslations(locale) {
try {
const response = await fetch(`/locales/${locale}.json`);
const translations = await response.json();
Onigiri.i18n.addTranslations(locale, translations);
return true;
} catch (error) {
console.error('Failed to load translations:', error);
return false;
}
}
// Initialize and load
Onigiri.i18n.init({ locale: 'en' });
await loadTranslations('en');
await loadTranslations('es');
Onigiri.i18n.translatePage();
HumHub Integration
// Create multilingual HumHub module
Onigiri.humhub('myModule', {
data: {
items: []
},
created() {
// Load HumHub translations
if (typeof humhub !== 'undefined') {
const locale = humhub.config.get('language');
Onigiri.i18n.setLocale(locale);
}
},
mounted() {
Onigiri.i18n.translatePage();
this.loadItems();
},
methods: {
loadItems() {
// Use translated strings
const loading = Onigiri.t('module.loading');
console.log(loading);
}
}
});
✅ Development Roadmap
Track the progress of OnigiriJS modules. Tasks are marked complete by the development team.
OnigiriJS Module Roadmap
Implementation progress of planned modules
6 / 21 completed (29%)
onigiri-state
Shared global & scoped state management
onigiri-directives
Declarative DOM bindings (o-show, o-model, etc.)
onigiri-resource
REST-style data models over AJAX
onigiri-observe
Intersection & Mutation observer helpers
onigiri-humhub-ui
Standard HumHub UI abstractions (modal, notify, confirm)
onigiri-lifecycle
Component lifecycle hooks
onigiri-guard
Debounce, throttle, single-run guards
onigiri-scroll
Scroll save/restore & helpers (PJAX-friendly)
onigiri-permission
Client-side permission awareness
onigiri-portal
DOM teleport / overlay mounting
onigiri-router
Micro router (non-SPA, PJAX-first)
onigiri-sanitize
HTML & input sanitization
onigiri-shortcut
Keyboard shortcut manager
onigiri-queue
Sequential async task runner
onigiri-gesture
Touch & swipe helpers
onigiri-devtools
Debugging & inspection helpers
onigiri-plugin
Plugin registration system
onigiri-time
Relative time & timezone utilities
onigiri-emojis
Emoji Picker and Manager
onigiri-tasks
Task Management
onigiri-polls
Polls creation and management
Note: Task completion is managed by the OnigiriJS development team.