lindemannrock / craft-translation-manager
Comprehensive translation management system for Craft CMS with Formie integration
Installs: 20
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:craft-plugin
pkg:composer/lindemannrock/craft-translation-manager
Requires
- php: ^8.2
- craftcms/cms: ^5.0.0
- lindemannrock/craft-logging-library: ^5.0
Requires (Dev)
- craftcms/phpstan: dev-main
- dev-main
- 5.3.1
- 5.3.0
- 5.2.0
- 5.1.0
- 5.0.9
- 5.0.8
- 5.0.7
- 5.0.6
- 5.0.5
- 5.0.4
- 5.0.3
- 5.0.2
- 5.0.1
- 5.0.0
- 1.21.9
- 1.21.8
- 1.21.7
- 1.21.6
- 1.21.5
- 1.21.4
- 1.21.3
- 1.21.2
- 1.21.1
- 1.21.0
- 1.20.0
- 1.19.8
- 1.19.7
- 1.19.6
- 1.19.5
- 1.19.4
- 1.19.3
- 1.19.2
- 1.19.1
- 1.19.0
- 1.18.0
- 1.17.0
- 1.16.0
- 1.15.4
- 1.15.3
- 1.15.2
- 1.15.1
- 1.15.0
- 1.14.5
- 1.14.4
- 1.14.3
- 1.14.2
- 1.14.1
- 1.14.0
- 1.13.0
- 1.12.6
- 1.12.5
- 1.12.4
- 1.12.3
- 1.12.2
- 1.12.1
- 1.12.0
- 1.11.0
- 1.10.0
- 1.9.0
- 1.8.0
- 1.7.1
- 1.7.0
- 1.6.0
- 1.5.0
- 1.4.2
- 1.4.1
- 1.4.0
- 1.3.5
- 1.3.4
- 1.3.3
- 1.3.2
This package is auto-updated.
Last update: 2025-11-11 07:38:23 UTC
README
A comprehensive translation management system for Craft CMS 5 with Formie integration, advanced filtering, and enterprise-grade security.
Why Translation Manager?
Translation Manager was created to solve critical gaps in Craft CMS multi-language workflows.
The Primary Problem: Managing site translations shouldn't require static language files and redeployments for every text change. Traditional approaches meant:
- Editing PHP language files manually for every translation update
- Redeploying the entire site for simple text changes
- No centralized interface to manage all site translations
- Difficult to track what needs translation vs what's already translated
The Formie Problem: Our first major integration tackled Formie forms, which had complex translation management challenges:
- Duplicating entire forms for each language (maintenance nightmare)
- Manual translation files (formie.php) for each language - difficult to track and manage
- No centralized workflow for managing all field properties and content
- Keeping translations in sync when forms change
Our Solution: Translation Manager provides a unified Control Panel interface to manage both site translations (through custom categories) and all Formie form elements. Changes are instantly available without touching code files or redeploying.
Features
- Multi-Site Translation Support:
- Site-aware translation management for any language combination
- Site selector in breadcrumbs like native Craft elements
- Dynamic text direction (RTL/LTR) based on site language
- Per-site translation files generation
- Locale Variant Support: Full support for regional language variants (en-US, en-GB, en-CA, etc.)
- Automatic source language detection based on primary site configuration (uses the base language of your primary site)
- Unified Translation Management: Manage all translations in one place with an intuitive interface
- Smart Deduplication: Each unique text is stored only once, regardless of how many forms use it
- Comprehensive Formie Support:
- Automatic capture of ALL field types including options, subfields, and special properties
- Support for Radio, Dropdown, Checkboxes, Address, Name, Date, Table, Repeater, and more
- Respects Formie's configured plugin name
- Site Translations: Custom translation category for site content with namespace protection
- Advanced Filtering: Filter by type (Forms/Site), status (Pending/Translated/Not Used), and search
- Bulk Operations: Save all changes at once, bulk delete unused translations
- Smart Usage Detection:
- Automatically identifies unused translations when forms/fields are deleted
- Reactivates translations when text is reused in new forms
- Updates context to reflect current usage location
- Advanced Maintenance Tools:
- Template scanner to identify unused translations automatically
- Granular cleanup options (All/Site/Forms unused translations)
- One-click cleanup with backup protection
- Import/Export Functionality:
- CSV export with current filters and Type column
- CSV import with preview and malicious content detection
- PHP translation file generation for production use
- Protection against CSV injection attacks
- Import history tracking with backup links
- Dedicated Logging: All operations logged to
storage/logs/translation-manager.log - Security Hardened: XSS protection, CSRF validation, symlink attack prevention, restricted secure paths, and more
- Advanced Backup System:
- Manual and automatic backups (daily/weekly/monthly)
- Asset Volume Storage: Store backups in any Craft asset volume (local or cloud)
- Cloud Storage Support: S3, Servd, Wasabi, and other cloud providers
- Auto-backup before dangerous operations
- Organized backup folders by type (scheduled, imports, maintenance, manual)
- Configurable retention with manual backup exemption
- Restore functionality with pre-restore backup
- Download backups as ZIP files from any storage location
- Loading indicators and progress feedback for slow operations
- Automatic recovery if queue is cleared
- RTL Support: Full support for Arabic text editing with proper RTL display
- Keyboard Shortcuts: Ctrl/Cmd+S to save all changes
- Debug Tools: Built-in search debugger for troubleshooting
- Twig Code Filtering: Automatically excludes text containing Twig syntax
Requirements
- Craft CMS 5.0 or greater
- PHP 8.2 or greater
- Logging Library 5.0 or greater (installed automatically as dependency)
- Formie 3.0 or greater (optional, for form translations)
Installation
Via Composer
cd /path/to/project
composer require lindemannrock/craft-translation-manager
./craft plugin/install translation-manager
Using DDEV
cd /path/to/project
ddev composer require lindemannrock/craft-translation-manager
ddev craft plugin/install translation-manager
Via Control Panel
In the Control Panel, go to Settings → Plugins and click "Install" for Translation Manager.
Multi-Site Translation Support
Translation Manager supports multi-site setups with any language combination. The system automatically creates translations for all configured sites when new text is discovered.
How Multi-Site Works
- Translation Key: The universal identifier (can be any language: English, Arabic, German, etc.)
- Site-Specific Translations: Each site has its own translation of the same key
- Site Switcher: Native Craft site selector in breadcrumbs
- Dynamic Interface: Text direction (RTL/LTR) adapts to site language
- Per-Site Export: Generates separate translation files for each site language (e.g.,
en-US/lindemannrock.php,ar/formie.php)
Example Multi-Site Workflow
{# Template uses same translation key #} {{ 'Welcome'|t('lindemannrock') }}
Database Storage:
- English Site:
translationKey="Welcome"→translation="Welcome" - Arabic Site:
translationKey="Welcome"→translation="مرحباً" - French Site:
translationKey="Welcome"→translation="Bienvenue"
Generated Files:
translations/en-US/lindemannrock.php(English site)translations/ar/lindemannrock.php(Arabic site)translations/en-US/formie.php(English Formie forms)translations/ar/formie.php(Arabic Formie forms)
Site Switcher
The Control Panel includes a native Craft site switcher in the breadcrumbs:
- 🌍 En ▼ > Translation Manager > Translations
- Switch between sites to manage different language translations
- All filters and search terms are preserved when switching sites
Configuration
Config File
Create a config/translation-manager.php file to override default settings:
cp vendor/lindemannrock/craft-translation-manager/src/config.php config/translation-manager.php
<?php return [ 'translationCategory' => 'messages', 'autoExport' => true, 'backupEnabled' => true, 'logLevel' => 'error', // Options: 'debug', 'info', 'warning', 'error' // 'backupVolumeUid' => 'abc123-your-volume-uid', // Optional: Set backup volume // Multi-environment support 'production' => [ 'autoExport' => true, 'backupSchedule' => 'daily', 'logLevel' => 'warning', // More logging in production ], ];
See Configuration Documentation for all available options.
Control Panel Settings
Navigate to Settings → Translation Manager in the Control Panel to configure:
General Settings
- Translation Category: The category used for site translations (e.g.,
lindemannrock)- Cannot use reserved categories:
site,app,yii,craft - Must start with a letter and contain only letters and numbers
- Cannot use reserved categories:
- Enable Formie Integration: Capture translations from Formie forms
- Enable Site Translations: Capture translations using your configured category
- Auto Save: Enable/disable automatic saving with configurable delay (1-10 seconds)
- Enable Translation Suggestions: Show translation suggestions based on similar existing translations
File Generation Settings
- Auto Generate: Automatically generate translation files when saved
- Generation Path: Where PHP translation files are generated
- Must use safe aliases:
@root,@storage,@config, or@webroot - Protected against directory traversal attacks
- Must use safe aliases:
Manual Operations (Main Menu)
- Generate (
Translation Manager → Generate): Manually generate PHP translation files by type (All/Site/Forms) - Import/Export (
Translation Manager → Import/Export):- CSV Import with preview and malicious content detection
- CSV Export with filtering support
- Import History tracking with user, date, and results
- Batching support for large imports (50 translations per batch)
- Cloudflare-compatible to avoid false positive blocks
Interface Settings
- Items Per Page: Number of translations per page (10-500)
- Show Context: Display translation context in interface and exports
Site Translation Settings
When "Enable Site Translations" is enabled, the following settings become available:
-
Site Translation Category (Required): The category to use for site translations (e.g., 'lindemannrock' for
|t('lindemannrock'))- Must be used consistently in your templates
- Avoid using 'site' as it may conflict with Craft's internal translations
- Only captures translations using this specific category
-
Site Translations Skip Patterns: Text patterns to skip when capturing site translations
- One pattern per line
- Only applies to site translations, not Formie fields
- Useful for excluding common terms like "ID", "Title", "Status"
- Translations are only captured from frontend requests, never from the Control Panel
- Use "Apply Skip Patterns to Existing Translations" button to remove existing translations that match patterns
Backup Settings (Settings → Backup)
- Enable Backups: Turn on backup functionality
- Backup Before Import: Automatically backup before CSV imports
- Backup Schedule: Manual, Daily, Weekly, or Monthly automatic backups
- Retention Period: Days to keep automatic backups (manual backups never auto-delete)
- Backup Storage Volume: Select an asset volume for storing backups
- Choose from existing asset volumes (local or cloud-based like S3, Servd, etc.)
- Backups are stored in a
translation-manager/backupssubdirectory within the selected volume - Supports both local volumes and remote cloud storage with automatic fallback
- Falls back to custom backup path if no volume is selected
- Custom Backup Path: Manual path configuration (only used when no volume is selected)
- Default:
@storage/translation-manager/backups
- Default:
Backup Operations (Translation Manager → Backups)
- Create Backup: Manually create backups at any time
- Restore Backup: Restore from any previous backup (creates safety backup first)
- Download Backup: Download backups as ZIP files from any storage location
- Delete Backup: Remove backups (manual backups must be deleted manually)
- Backup History: View all backups with date, reason, creator, translation count, and size
Backups are automatically organized into:
/scheduled/- Daily/weekly/monthly automated backups/imports/- Backups before CSV imports/maintenance/- Backups before cleanup/clear operations/manual/- User-initiated backups (never auto-deleted)/other/- Backups before restore operations and miscellaneous activities
Maintenance (Translation Manager → Maintenance)
- Clean Up Unused Translations: Remove translations by type (All/Site/Forms)
- Template Scanner: Scan all templates to identify unused translations
- Danger Zone: Clear all translations by type with confirmation
- Auto-backup before clearing (if backups enabled)
- Automatically deletes corresponding translation files
Usage
Site Translations
Use your configured translation category in templates:
{{ 'Welcome to our site'|t('lindemannrock') }}
{{ 'Contact Us'|t('lindemannrock') }}
{{ 'All Rights Reserved.'|t('lindemannrock') }}
Managing Translations
- Navigate to Translation Manager → Translations in the Control Panel
- Use the filter dropdown to filter by:
- Status: All, Pending, Translated, Unused
- Type: All Types, Forms, Site (when both integrations enabled)
- Search for specific translations (searches both English and Arabic)
- Edit Arabic translations inline with RTL support
- Save changes:
- Click "Save All Changes" button
- Or use Ctrl/Cmd+S keyboard shortcut
- Auto-save triggers after configured delay (if enabled)
- Generate and Import/Export translations:
- Translation Manager → Generate: Generate PHP translation files manually
- Translation Manager → Import/Export: Import CSV with preview, export current filtered view as CSV
Status Indicators
- Pending (Orange): Translation needs Arabic text
- Translated (Teal): Translation has Arabic text
- Unused (Gray): Text no longer exists in any active form
Maintenance
The plugin includes a dedicated maintenance section to manage unused translations:
- Navigate to Translation Manager → Maintenance
- Select the type of cleanup to perform (All/Site/Forms unused translations)
- Click Clean Up to remove unused translations
- Use Rescan Templates to identify unused translations
- Translation files are automatically regenerated after cleanup
Formie Integration
Formie translations are captured automatically when:
- Creating or editing forms
- Adding or modifying fields
- Changing field labels, instructions, placeholders, or error messages
- Modifying button text
- Adding/changing dropdown, radio, or checkbox options
- Configuring subfield labels (Address, Name, Date fields)
- Setting up table columns, repeater buttons, or heading text
Supported Field Types
Standard Fields: SingleLineText, MultiLineText, Email, Number, Phone, Password, etc.
- Label, placeholder, instructions, error message
Options Fields: Dropdown, Radio, Checkboxes, Categories, Entries, Products, Tags, Users
- All option labels are captured
Complex Fields:
- Address: All enabled subfield labels and placeholders (Address 1/2/3, City, State, ZIP, Country)
- Name: Prefix, First Name, Middle Name, Last Name labels and placeholders
- Date: Day, Month, Year, Hour, Minute, Second, AM/PM labels and placeholders
- Table: Column headers and "Add Row" button text
- Repeater: Add/Remove button labels
- Agree: Description text, checked/unchecked values
- Recipients: Recipient option labels
- Heading: Heading text content
- Group: Recursively captures all nested field translations
Smart Deduplication
The system prevents duplicate translations:
- If "First Name" appears in multiple forms/fields, it's stored only once
- When text moves between forms, the context updates automatically
- Translations marked as "not used" are reactivated when the text is used again
Translation contexts follow the pattern:
- Field labels:
formie.{formHandle}.{fieldHandle}.label - Field options:
formie.{formHandle}.{fieldHandle}.option.{value} - Subfield labels:
formie.{formHandle}.{fieldHandle}.{subfield}.label - Button text:
formie.{formHandle}.button.{type}
Note: The plugin automatically detects and uses Formie's configured plugin name (e.g., "Forms" instead of "Formie") throughout the interface. This is configured in Formie's settings or via config/formie.php.
CSV Export
The CSV export includes:
- English Text
- Arabic Translation
- Type (Forms/Site)
- Context (if enabled in settings)
- Status
Exports respect current filters and are protected against CSV injection.
CSV Import
The plugin provides a secure built-in CSV import feature with preview:
- Access Import: Navigate to Translation Manager → Import/Export
- Upload CSV: Select your CSV file (max 5MB)
- Preview Changes: Review what will be imported, updated, or skipped
- Confirm Import: Import with automatic backup (if enabled)
- View History: Check import history with results and backup links
CSV Format Requirements:
- UTF-8 encoding for proper Arabic text support
- Headers in first row
- Comma, semicolon, tab, or pipe delimiter (auto-detected)
- Double quotes for text containing delimiters
Required Columns (flexible naming):
- English Text (or English, Source, Original)
- Arabic Translation (or Arabic, Translation, Translated) - optional
- Context (or Category, Type) - optional, defaults to 'site'
- Status - optional: pending/translated/unused
Example CSV:
English Text,Arabic Translation,Status,Context
"Welcome to our website","مرحباً بكم في موقعنا","translated","site"
"Contact Us","اتصل بنا","translated","site"
"Submit","إرسال","translated","formie.contactForm"
Security Features:
- File type validation (CSV/TXT only)
- File size limit (5MB)
- MIME type verification
- Client-side malicious content detection (XSS, SQL injection, PHP code)
- JavaScript-based scanning to avoid Cloudflare blocks
- No server-side pattern matching that could trigger WAF rules
- Input sanitization (HTML stripped)
- Length validation (5000 chars max)
- Permission checks
- CSRF protection
- Automatic backup before import (configurable)
- Detailed error reporting (first 10 errors shown)
Import Behavior:
- Updates existing translations with matching English text and context
- Creates new translations for unmatched entries
- Skips empty rows
- Preserves 'unused' status unless explicitly changed
- Triggers automatic file export if enabled
- Shows detailed results with counts
- Processes large imports in batches (50 per batch) to prevent timeouts
- Compatible with Servd's temporary filesystem for file uploads
PHP File Export
Translation files are exported to:
translations/
├── en/
│ ├── lindemannrock.php (your configured category)
│ └── formie.php
└── ar/
├── lindemannrock.php
└── formie.php
Files use atomic write operations for safety.
Permissions
The plugin provides granular permissions:
- View translations - Access the translations interface
- Edit translations - Modify and save translations
- Delete translations - Delete unused translations
- Export translations - Export to CSV or PHP files
- Manage plugin settings - Access settings and danger zone
Console Commands
Translation Commands
# Capture existing Formie fields php craft translation-manager/translations/capture-formie # Export all translations to PHP files php craft translation-manager/translations/export-all # Export Formie translations only php craft translation-manager/translations/export-formie # Export site translations only php craft translation-manager/translations/export-site # Import existing Formie translation files php craft translation-manager/translations/import-formie
Maintenance Commands
# Scan templates to identify unused translations php craft translation-manager/maintenance/scan-templates # Preview what would be marked unused (no changes) php craft translation-manager/maintenance/preview-scan # Clean unused translations by type php craft translation-manager/maintenance/clean-by-type --type=all # All unused php craft translation-manager/maintenance/clean-by-type --type=site # Site only php craft translation-manager/maintenance/clean-by-type --type=formie # Forms only # Clean all unused translations (legacy command) php craft translation-manager/maintenance/clean-unused
Backup Commands
# Create manual backup php craft translation-manager/backup/create [reason] # Run scheduled backup (for cron) php craft translation-manager/backup/scheduled # List all backups php craft translation-manager/backup/list # Clean old backups based on retention php craft translation-manager/backup/clean
Logging
Translation Manager uses the LindemannRock Logging Library for centralized logging.
Log Levels
- Error: Critical errors only
- Warning: Errors and warnings
- Info: General information
- Debug: Detailed debugging (includes performance metrics, requires devMode)
Configuration
// config/translation-manager.php return [ 'logLevel' => 'info', // error, warning, info, or debug ];
Note: Debug level requires Craft's devMode to be enabled. If set to debug with devMode disabled, it automatically falls back to info level.
Log Files
- Location:
storage/logs/translation-manager-YYYY-MM-DD.log - Retention: 30 days (automatic cleanup via Logging Library)
- Format: Structured JSON logs with context data
- Web Interface: View and filter logs in CP at Translation Manager → Logs
What's Logged
- Error: File generation failures, database errors, permission denials, backup failures
- Warning: Missing translations, failed operations, slow operations (>1s)
- Info: Translation saves, imports/exports, file generation, backup operations, cleanup actions
- Debug: Performance timing, detailed import/export steps, template scanning, queue operations
Log Management
Access logs through the Control Panel:
- Navigate to Translation Manager → Logs
- Filter by date, level, or search terms
- Download log files for external analysis
- View file sizes and entry counts
- Auto-cleanup after 30 days (configurable via Logging Library)
Requires: lindemannrock/logginglibrary plugin (installed automatically as dependency)
See docs/LOGGING.md for detailed logging documentation.
Security
Built-in Security Features
The Translation Manager plugin includes comprehensive security measures:
- XSS Protection: All template output properly escaped
- CSRF Protection: All forms validate CSRF tokens
- Symlink Attack Prevention: Real path resolution (
realpath()) prevents symlink traversal - Path Restriction: Export paths limited to secure aliases (@root, @storage, @translations)
- Backup Security: Backup paths restricted to non-web-accessible locations (@root, @storage)
- CSV Injection Protection: Special characters prefixed in exports
- Input Validation:
- Length limits (5000 chars) on translations
- Translation categories: letters, numbers, hyphens, underscores only
- Numeric ranges (items per page: 10-500)
- Safe attribute assignment
- SQL Injection Protection: Parameterized queries throughout
- Atomic File Operations: Temp files with proper locking
- Permission-based Access Control: Granular permissions for all operations
- Anonymous Access Prevention: All actions require authentication
- Security Event Logging: Comprehensive audit trail with user tracking
Security Best Practices
For Administrators
-
Permission Management
- Grant only necessary permissions to user groups
- Regularly audit user permissions
- Use separate accounts for different roles
- Enable two-factor authentication for admin accounts
-
Export Security
- Configure export paths to secure directories
- Limit export permissions to trusted users
- Regularly clean up old export files
- Monitor export logs for unusual activity
-
System Maintenance
- Keep Craft CMS and all plugins updated
- Review security logs regularly
- Monitor for failed permission attempts
- Backup translation data regularly
For Developers
-
Template Usage
- Always use the proper translation filter syntax
- Never output translation data without escaping
- Avoid inline JavaScript with translation data
- Use data attributes for dynamic content
-
Custom Integrations
- Validate all input when using the plugin's services
- Use Craft's permission system for access control
- Log security-relevant operations
- Follow Craft's security best practices
Reporting Security Issues
For security vulnerabilities, please see our Security Policy.
DO NOT create public GitHub issues for security vulnerabilities.
Troubleshooting
Search Not Finding Translations
- Check the Type filter is set to "All Types" (not just Forms or Site)
- Check the Status filter is set to "All"
- Try searching for partial text instead of the full phrase
- Use the debug search tool:
/cms/translation-manager/maintenance/debug-search-page - Common issues: leading/trailing spaces, text marked as "unused", text contains Twig syntax
Scheduled Backups Not Running
- Ensure backups are enabled and schedule is not "Manual"
- Check queue status:
craft queue/info - For production, ensure queue runner is active
- The plugin automatically recovers from queue failures on each page load
Translations Not Being Captured
- Formie: Save the form after adding fields, or run
craft translation-manager/translations/capture-formie - Site: Use correct category
{{ 'Text'|t('lindemannrock') }}and visit the frontend page - Locale Variants: If using locale-specific languages (en-US, en-GB, fr-CA, etc.):
- Translation files are automatically exported to the correct locale folder (e.g.,
/translations/en-US/lindemannrock.php) - The plugin automatically detects the source language from your primary site (the site with
primary: true) - Each locale variant can have its own unique translations
- Important: Changing your primary site's language may affect existing translations
- Clear Craft's cache after changing site language settings
- Translation files are automatically exported to the correct locale folder (e.g.,
- Text with Twig syntax ({{, {%, {#) is automatically excluded
Import Blocked by Security
- Use UTF-8 encoding with proper headers
- Avoid special characters that trigger WAF
- The plugin uses client-side validation to avoid Cloudflare blocks
- For large files, split into smaller batches
Settings Cannot Be Saved
- This is normal in production - settings are stored in database, not project config
- If error persists, run migrations:
craft migrate/all
Documentation
- Configuration Guide - Complete settings reference and multi-environment setup
- Backup System - Backup types, scheduling, and restoration
- Logging - Log configuration and security event monitoring
- Troubleshooting - Common issues and solutions
Support
- Issues: GitHub Issues
- Email: support@lindemannrock.com
License
This plugin is licensed under the MIT License. See LICENSE for details.
Developed by LindemannRock