syriable/localizator

AI-powered Laravel package for automatic translation scanning and generation

Installs: 10

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/syriable/localizator

v1.4.0 2025-08-29 19:01 UTC

This package is auto-updated.

Last update: 2025-12-29 19:56:49 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

An advanced Laravel package for automatic translation scanning and AI-powered translation generation. Built for Laravel 12+ with modern PHP standards and FilamentPHP 4 compatibility.

๐Ÿš€ Features

  • ๐Ÿ” Comprehensive Scanning: Automatically scan PHP, Blade, Vue.js, and JavaScript files for translation functions
  • ๐Ÿšซ Smart Comment Detection: Automatically skip translation keys in comments (/* {{ __('key') }} */)
  • ๐Ÿงน Remove Missing Keys: Clean up unused translation keys from language files with --remove-missing
  • ๐Ÿค– AI-Powered Translations: Generate translations using OpenAI, Claude, Google Translate, or Azure Translator
  • ๐Ÿ“ Multiple Formats: Support for both JSON and PHP array translation files
  • โš™๏ธ Highly Configurable: Extensive configuration options for customizing behavior
  • ๐Ÿงช Production Ready: Built with PSR standards, PHPStan level 8, and comprehensive testing
  • ๐Ÿ”ง Developer Friendly: Interactive CLI commands with progress indicators and validation
  • ๐Ÿ’พ Safe Operations: Automatic backups and dry-run capabilities

๐Ÿ“‹ Requirements

  • PHP 8.3 or higher
  • Laravel 12.0 or higher
  • Composer

๐Ÿ“ฆ Installation

Install the package via Composer:

composer require syriable/localizator

Publish the configuration file:

php artisan vendor:publish --tag="localizator-config"

This will publish the configuration file to config/localizator.php.

โš™๏ธ Configuration

The package comes with extensive configuration options. Here are the key settings:

// config/localizator.php
return [
    // Translation file type: 'default' (PHP) or 'json'
    'localize' => env('LOCALIZATOR_TYPE', 'default'),
    
    // Source language for AI translations
    'source_language' => env('LOCALIZATOR_SOURCE_LANG', 'en'),
    
    // Use nested array structure for dot notation keys
    'nested' => true,
    
    // Directories to scan for translation functions
    'dirs' => [
        app_path(),
        resource_path('views'),
        resource_path('js'),
        resource_path('vue'),
        base_path('routes'),
    ],
    
    // File patterns to include
    'patterns' => [
        '*.php',
        '*.blade.php',
        '*.vue',
        '*.js',
        '*.ts',
    ],
    
    // Translation functions to look for
    'functions' => [
        '__',
        'trans',
        'trans_choice',
        '@lang',
        '@choice',
        'Lang::get',
        'Lang::choice',
        '$t',  // Vue i18n
        '$tc', // Vue i18n choice
    ],
    
    // AI translation settings
    'ai' => [
        'provider' => env('LOCALIZATOR_AI_PROVIDER', 'openai'),
        'openai' => [
            'api_key' => env('OPENAI_API_KEY'),
            'model' => env('OPENAI_MODEL', 'gpt-3.5-turbo'),
        ],
        'claude' => [
            'api_key' => env('ANTHROPIC_API_KEY'),
            'model' => env('CLAUDE_MODEL', 'claude-3-sonnet-20240229'),
        ],
        // ... more AI provider configurations
    ],
];

Environment Variables

Add these to your .env file:

# Basic Configuration
LOCALIZATOR_TYPE=default
LOCALIZATOR_SOURCE_LANG=en

# AI Provider (choose one)
LOCALIZATOR_AI_PROVIDER=openai

# OpenAI Configuration
OPENAI_API_KEY=your-openai-api-key
OPENAI_MODEL=gpt-3.5-turbo

# Or Claude Configuration
ANTHROPIC_API_KEY=your-anthropic-api-key
CLAUDE_MODEL=claude-3-sonnet-20240229

# Or Google Translate Configuration
GOOGLE_TRANSLATE_API_KEY=your-google-api-key
GOOGLE_CLOUD_PROJECT_ID=your-project-id

# Or Azure Translator Configuration
AZURE_TRANSLATOR_KEY=your-azure-key
AZURE_TRANSLATOR_REGION=your-region
AZURE_TRANSLATOR_ENDPOINT=your-endpoint

๐Ÿ› ๏ธ Usage

Automatic Generation (Recommended)

Generate all translation files automatically without any interactive prompts:

# Generate for default locales (configured in config/localizator.php)
php artisan localizator:generate

# Generate for specific locales
php artisan localizator:generate en es fr de

# Silent mode (no output except errors)
php artisan localizator:generate --silent

# With AI auto-translation
php artisan localizator:generate es fr --auto-translate

# Generate JSON files instead of PHP
php artisan localizator:generate en --format=json

# Force overwrite without backup
php artisan localizator:generate en --force

Interactive Scanning

Scan your application with interactive prompts and review options:

php artisan localizator:scan en es fr de

Advanced Options

The scan command supports various options for different use cases:

# Dry run - see what would be done without making changes
php artisan localizator:scan en --dry-run

# Remove missing translation keys (clean up unused keys)
php artisan localizator:scan en --remove-missing

# Sort translation keys alphabetically
php artisan localizator:scan en --sort

# Enable AI-powered auto-translation
php artisan localizator:scan es fr --auto-translate

# Auto-translate with review process
php artisan localizator:scan es --auto-translate --review

# Specify AI provider and source language
php artisan localizator:scan es --auto-translate --provider=claude --source-lang=en

# Custom batch size for AI translations
php artisan localizator:scan es --auto-translate --batch-size=25

# Generate JSON files instead of PHP
php artisan localizator:scan en --format=json

# Create backups of existing files
php artisan localizator:scan en --backup

# Verbose output for debugging
php artisan localizator:scan en -v

Command Comparison

Feature localizator:generate localizator:scan
Interaction Fully automatic, zero prompts Interactive with prompts and choices
Locale Selection Uses config defaults or arguments Prompts for locale selection if not specified
AI Review Auto-accepts all translations Optional review process for AI translations
Best for CI/CD, automated workflows Manual control, reviewing translations
Speed Fast, no waiting for input Slower due to interactive prompts
Silent Mode Yes (--silent flag) No
Configuration Uses locales from config Always prompts if no arguments

Recommendation: Use localizator:generate for most cases, especially in automated environments. Use localizator:scan when you need to review and approve translations manually.

Interactive Mode

When you run the command without specifying locales, it will prompt you to select from supported languages:

php artisan localizator:scan

๐Ÿ” What Gets Scanned

The package automatically detects and extracts translation keys from:

Comment Detection & Skipping

NEW in v1.4.0: The package now automatically skips translation keys found in comments, preventing disabled or temporary keys from being added to your language files.

Supported Comment Types:

// C-style comments
/* {{ __('disabled.key') }} */

// Single-line comments  
// {{ __('commented.key') }}

// Blade comments
{{-- {{ __('blade.disabled.key') }} --}}

// HTML comments
<!-- {{ __('html.commented.key') }} -->

// Multiline comments
/*
 * {{ __('multiline.disabled.key1') }}
 * {{ __('multiline.disabled.key2') }}
 */

Why This Matters:

  • โœ… Prevents cluttering language files with temporary/disabled keys
  • โœ… Keeps your translations clean and organized
  • โœ… Allows developers to comment out translations without affecting builds
  • โœ… Works automatically - no configuration needed

File Types Scanned

PHP Files

__('auth.login.title')           // โ†’ resources/lang/en/auth.php: ['login' => ['title' => '...']]
trans('validation.email.required') // โ†’ resources/lang/en/validation.php: ['email' => ['required' => '...']]
trans_choice('messages.items', $count)
Lang::get('dashboard.widgets.summary')
Lang::choice('items.count', 5)

Blade Templates

@lang('app.title')
@choice('messages.items', $itemCount)
{{ __('buttons.submit') }}
{{ trans('labels.name') }}

Vue.js Components

<template>
  <h1>{{ $t('dashboard.title') }}</h1>
  <p>{{ $tc('users.count', userCount) }}</p>
</template>

<script>
this.$t('notifications.success')
this.$tc('items.found', itemsFound)
</script>

JavaScript Files

$t('messages.welcome')
$tc('items.selected', selectedCount)

๐Ÿ—๏ธ Intelligent Nested Structure

The package automatically organizes translation files based on dot notation keys, following Laravel's best practices:

How It Works

Translation Key โ†’ Generated File Structure

  • auth.login.title โ†’ resources/lang/en/auth.php

    return [
        'login' => [
            'title' => 'Login Title'
        ]
    ];
  • validation.custom.email.required โ†’ resources/lang/en/validation.php

    return [
        'custom' => [
            'email' => [
                'required' => 'Email is required'
            ]
        ]
    ];

Key Benefits

โœ… Organized Structure: Files are automatically organized by context
โœ… Laravel Standard: Follows Laravel's recommended translation file structure
โœ… Deep Nesting: Supports unlimited nesting levels (auth.forms.login.validation.required)
โœ… Backward Compatible: Can be disabled with 'nested' => false
โœ… Merge Existing: Intelligently merges with existing translation files

๐Ÿงน Remove Missing Keys

NEW in v1.4.0: The --remove-missing option has been improved to properly clean up unused translation keys from your language files.

How It Works

When you delete translation keys from your source code, they remain in your language files. The --remove-missing flag solves this by:

  1. Scanning your codebase for currently used translation keys
  2. Comparing with existing translation files
  3. Removing keys that no longer exist in your source code
  4. Preserving all keys that are still in use

Usage Examples

# Remove unused keys from English translations
php artisan localizator:scan en --remove-missing

# Remove unused keys and create backups
php artisan localizator:scan en --remove-missing --backup

# See what would be removed without making changes
php artisan localizator:scan en --remove-missing --dry-run

# Remove unused keys from multiple locales
php artisan localizator:scan en es fr --remove-missing

Before & After Example

Before (your source code changed):

// You removed this from your Blade file:
// {{ __('auth.old_feature') }}

// But kept this:
{{ __('auth.login.title') }}

Translation file before cleanup:

// resources/lang/en/auth.php
return [
    'login' => ['title' => 'Login'],
    'old_feature' => 'This is no longer used',  // โ† Will be removed
];

After running --remove-missing:

// resources/lang/en/auth.php
return [
    'login' => ['title' => 'Login'],  // โ† Preserved
    // 'old_feature' removed automatically
];

Safety Features

  • โœ… Dry Run: Use --dry-run to preview changes before applying
  • โœ… Backups: Use --backup to create timestamped backups
  • โœ… Incremental: Only removes unused keys, preserves translations
  • โœ… Multi-format: Works with both PHP and JSON translation files

๐Ÿค– AI Translation Features

Supported AI Providers

  • OpenAI: GPT-3.5 Turbo, GPT-4, and other models
  • Anthropic Claude: Claude 3 Sonnet, Haiku, and Opus models
  • Google Translate: Google Cloud Translation API
  • Azure Translator: Microsoft Azure Translator Text API

Translation Context

Provide context to improve AI translations:

// config/localizator.php
'ai' => [
    'context' => [
        'domain' => 'e-commerce',      // Business domain
        'tone' => 'friendly',          // Communication tone
        'additional_context' => 'This is a Laravel application for online shopping',
    ],
],

Batch Processing

AI translations are processed in batches to optimize API usage:

'ai' => [
    'batch_size' => 50,          // Translations per batch
    'rate_limit' => 60,          // Requests per minute
],

Validation

Automatic validation ensures translation quality:

  • Placeholder preservation (:name, {count}, etc.)
  • Length validation
  • Key naming convention checks

๐Ÿ“ Output Formats

JSON Format

{
    "welcome.message": "Welcome to our application",
    "auth.failed": "These credentials do not match our records",
    "dashboard.title": "Dashboard"
}

PHP Array Format

Nested Structure (Default)

With 'nested' => true in configuration, translation keys use dot notation to create organized, nested file structures:

// For keys like 'auth.login.title', 'auth.login.button'
// File: resources/lang/en/auth.php
return [
    'login' => [
        'title' => 'Login',
        'button' => 'Sign In',
        'failed' => 'These credentials do not match our records.',
    ],
    'register' => [
        'title' => 'Create Account',
        'button' => 'Sign Up',
    ],
    'logout' => 'Sign Out', // Single-level key
];

// For keys like 'validation.custom.email.required'
// File: resources/lang/en/validation.php
return [
    'custom' => [
        'email' => [
            'required' => 'Email is required',
            'email' => 'Must be a valid email',
        ],
        'password' => [
            'min' => 'Password must be at least 8 characters',
        ],
    ],
    'attributes' => [
        'first_name' => 'First Name',
        'last_name' => 'Last Name',
    ],
];

Flat Structure (Legacy)

With 'nested' => false, keys remain flat within files:

// File: resources/lang/en/auth.php
return [
    'login.title' => 'Login',
    'login.button' => 'Sign In',
    'register.title' => 'Create Account',
];

๐Ÿงช Testing

Run the package tests:

composer test

Run static analysis:

composer analyse

Fix code style:

composer format

Run all quality checks:

composer test && composer analyse && composer format

๐Ÿ“ˆ Performance

The package is optimized for large codebases:

  • Efficient File Scanning: Uses Symfony Finder for fast directory traversal
  • Regex Optimization: Compiled patterns for translation function detection
  • Memory Management: Processes files in chunks to handle large projects
  • Caching: Optional caching of scan results to speed up subsequent runs

๐Ÿ›ก๏ธ Security

  • Validates all translation keys against configurable patterns
  • Sanitizes file paths and prevents directory traversal
  • Respects Laravel's security practices for file operations
  • API keys are stored securely in environment variables

๐Ÿ”ง Advanced Configuration

Custom Translation Functions

Add your own translation function patterns:

'functions' => [
    '__',
    'trans',
    'myCustomTransFunction',  // Your custom function
    'MyClass::translate',     // Static method
],

File Exclusion

Exclude specific files or directories:

'exclude' => [
    'vendor',
    'node_modules',
    'storage',
    'specific-file.php',
    'temp-directory',
],

Custom Output Settings

Customize the generated files:

'output' => [
    'indent' => 2,              // Spaces for indentation
    'line_length' => 80,        // Maximum line length
    'comments' => true,         // Include generation comments
    'backup' => true,           // Create backups
],

๐Ÿšจ Troubleshooting

Common Issues

1. No translation keys found

  • Check that your functions configuration includes all translation methods used in your codebase
  • Verify that the dirs and patterns settings cover your file locations
  • Ensure keys aren't all commented out (v1.4.0+ automatically skips commented keys)
  • Use --dry-run -v to see detailed scanning information

2. AI translation failures

  • Verify your API keys are correctly set in .env
  • Check your API quotas and rate limits
  • Use smaller batch sizes if encountering timeout errors

3. --remove-missing not working

  • Ensure the command completed successfully (exit code 0)
  • Check that translation keys were actually removed from your source code
  • Use --dry-run to see what keys would be removed before running
  • Verify you're scanning the correct directories with --dry-run -v

4. Permission errors

  • Ensure Laravel has write permissions to the resources/lang directory
  • Check file ownership and permissions

Debug Mode

Enable verbose output for debugging:

php artisan localizator:scan en -v

Log Analysis

Check Laravel logs for detailed error information:

tail -f storage/logs/laravel.log

๐Ÿค Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Development Setup

  1. Clone the repository
  2. Install dependencies: composer install
  3. Run tests: composer test
  4. Run static analysis: composer analyse
  5. Fix code style: composer format

๐Ÿ“„ Changelog

Please see CHANGELOG.md for more information on what has changed recently.

๐Ÿ”’ Security

If you discover any security-related issues, please email security@syriable.com instead of using the issue tracker.

๐Ÿ“ License

The MIT License (MIT). Please see License File for more information.

๐Ÿ™ Credits

๐Ÿ”— Related Packages

๐Ÿ’ก Tips & Best Practices

1. Organize Translation Keys

Use dot notation for hierarchical organization:

__('dashboard.widgets.sales.title')
__('forms.validation.required')
__('emails.welcome.subject')

2. Use Placeholders

Keep translations flexible with placeholders:

__('welcome.greeting', ['name' => $user->name])
__('items.count', ['count' => $itemCount])

3. Review AI Translations

Always review AI-generated translations for:

  • Cultural appropriateness
  • Context accuracy
  • Technical terminology
  • Brand consistency

4. Version Control

Include translation files in version control but consider:

  • Using separate branches for translation updates
  • Implementing review processes for translation changes
  • Automated testing for translation completeness

5. Performance Optimization

For large applications:

  • Use JSON format for better performance
  • Enable caching in production
  • Consider splitting translations into smaller, feature-specific files

Made with โค๏ธ by Syriable