darvis / livewire-inline-translation
Inline translation editing for Livewire applications with database storage
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/darvis/livewire-inline-translation
Requires
- php: ^8.2
- illuminate/support: ^11.0|^12.0
- livewire/livewire: ^3.0|^4.0
Requires (Dev)
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
README
Inline translation editing for Livewire applications with database storage. This package allows authorized users (e.g., staff) to edit translations directly on the website without accessing the CMS.
✨ Features
- ✅ Inline Editing - Edit translations directly on your website
- ✅ HTML Editor - Optional ContentEditable WYSIWYG editor for rich text content
- ✅ Database Storage - Custom translations stored in database with fallback to Laravel language files
- ✅ Flexible Authorization - Configurable guard system (staff, web, custom)
- ✅ Modern UI - Alpine.js modal with Tailwind inline styles
- ✅ Framework Agnostic - No Flux dependencies, works with any Livewire setup
- ✅ No External Dependencies - Built-in ContentEditable editor, no CDN required
- ✅ Auto-Discovery - Automatic Livewire component registration
- ✅ Well Tested - Comprehensive Pest test suite
- ✅ Fully Documented - Extensive documentation for developers
📋 Requirements
- PHP: 8.2 or higher
- Laravel: 11.x or 12.x
- Livewire: 3.x or 4.x
- Alpine.js: Any version (for modal functionality)
📚 Documentation
- Installation Guide - Step-by-step installation instructions
- Usage Guide - Learn how to use the package
- Configuration - All configuration options
- How It Works - Understanding the internals
- API Reference - Complete API documentation
- Contributing - How to contribute to this package
🚀 Quick Start
Installation
1. Install via Composer
composer require darvis/livewire-inline-translation
2. Publish and Run Migrations
php artisan vendor:publish --tag=inline-translation-migrations php artisan migrate
3. Publish Config (Optional)
php artisan vendor:publish --tag=inline-translation-config
This will create config/inline-translation.php where you can configure:
- Authentication guard (default:
staff) - Modal container ID
4. Publish Views (Optional)
If you want to customize the view:
php artisan vendor:publish --tag=inline-translation-views
5. Add Modal Container to Layout
Add this container to your layout file (e.g., resources/views/components/layouts/website.blade.php):
<!DOCTYPE html> <html> <head> <!-- Your head content --> @livewireStyles </head> <body> <!-- Your body content --> {{ $slot }} <!-- Add this container for inline translation modals --> <div id="inline-translation-modals"></div> @livewireScripts </body> </html>
Usage
Basic Usage
Use the component in your Blade templates:
<livewire:inline-translation translationKey="website.welcome" />
Translation Key Format
The translation key should follow the format: {group}.{key}
group: The language file name (e.g.,website,messages)key: The translation key within that file
Examples:
website.welcome→lang/en/website.php→['welcome' => '...']messages.hello→lang/en/messages.php→['hello' => '...']
How It Works
- For Visitors: Shows the translated text normally
- For Authorized Users:
- Shows text with blue dashed underline
- Click to open edit modal
- Edit and save translation
- Changes are stored in database
- No page reload needed
Translation Priority
- Database - Custom translations from
translationstable (highest priority) - Language Files - Laravel's default
lang/{locale}/{file}.phpfiles (fallback)
This means you can override any Laravel translation by editing it inline, and the original files remain untouched.
Configuration
Change Authentication Guard
In config/inline-translation.php:
return [ 'guard' => 'web', // Change from 'staff' to 'web' or any other guard ];
Or via environment variable:
INLINE_TRANSLATION_GUARD=web
Customize Modal Container
In config/inline-translation.php:
return [ 'modal_container_id' => 'my-custom-container', ];
Then update your layout:
<div id="my-custom-container"></div>
Database Structure
The package creates a translations table:
| Column | Type | Description |
|---|---|---|
| id | bigint | Primary key |
| locale | string(10) | Language code (e.g., 'en', 'nl') |
| group | string(100) | File name (e.g., 'website', 'messages') |
| key | string(255) | Translation key |
| value | text | Translation value |
| created_at | timestamp | Created timestamp |
| updated_at | timestamp | Updated timestamp |
Unique constraint on: locale, group, key
Examples
Example 1: Welcome Message
Language file lang/en/website.php:
return [ 'welcome' => 'Welcome to our website!', ];
Blade template:
<h1><livewire:inline-translation translationKey="website.welcome" /></h1>
Example 2: Multiple Translations
<div> <h1><livewire:inline-translation translationKey="website.title" /></h1> <p><livewire:inline-translation translationKey="website.description" /></p> <button><livewire:inline-translation translationKey="website.cta_button" /></button> </div>
Example 3: With HTML Content
The component supports HTML in translations:
<div> <livewire:inline-translation translationKey="website.rich_content" /> </div>
Language file:
return [ 'rich_content' => 'This is <strong>bold</strong> and <em>italic</em> text.', ];
Important Notes
Do NOT Use Inside Links or Buttons
❌ Wrong:
<a href="/contact"> <livewire:inline-translation translationKey="website.contact" /> </a>
✅ Correct:
<a href="/contact">{{ __('website.contact') }}</a>
The component generates a clickable span for authorized users, which conflicts with parent clickable elements.
Alpine.js Required
The modal uses Alpine.js x-teleport directive. Make sure Alpine.js is loaded in your layout:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
Troubleshooting
Modal Not Showing
- Check if
#inline-translation-modalscontainer exists in your layout - Verify Alpine.js is loaded
- Check browser console for JavaScript errors
Translations Not Saving
- Verify database migration ran successfully
- Check if user is authenticated with correct guard
- Verify translation key format is correct (
group.key)
Authorization Not Working
- Check
config/inline-translation.phpguard setting - Verify user is logged in with correct guard
- Clear config cache:
php artisan config:clear
🧪 Testing
The package includes a comprehensive test suite using Pest:
# Run all tests composer test # Run with coverage composer test-coverage # Run specific test file vendor/bin/pest tests/Unit/TranslationModelTest.php
🤝 Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Development Setup
# Clone the repository git clone https://github.com/darvis/livewire-inline-translation.git cd livewire-inline-translation # Install dependencies composer install # Run tests composer test
📝 Changelog
Please see CHANGELOG.md for recent changes.
🔒 Security
If you discover any security-related issues, please email info@arvid.nl instead of using the issue tracker.
📄 License
The MIT License (MIT). Please see License File for more information.
👨💻 Author
Arvid de Jong
- Email: info@arvid.nl
- GitHub: @darvis
🙏 Credits
⭐ Support
If you find this package helpful, please consider giving it a star on GitHub!