PHPackages                             xoshbin/filament-translatable-select - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Search &amp; Filtering](/categories/search)
4. /
5. xoshbin/filament-translatable-select

ActiveLibrary[Search &amp; Filtering](/categories/search)

xoshbin/filament-translatable-select
====================================

A Filament Select component with built-in translatable search functionality for Laravel applications using Spatie Laravel Translatable

v1.0.0(4mo ago)0634↓78.6%[2 PRs](https://github.com/Xoshbin/filament-translatable-select/pulls)MITPHPPHP ^8.2CI passing

Since Sep 15Pushed 2mo agoCompare

[ Source](https://github.com/Xoshbin/filament-translatable-select)[ Packagist](https://packagist.org/packages/xoshbin/filament-translatable-select)[ Docs](https://github.com/xoshbin/filament-translatable-select)[ GitHub Sponsors](https://github.com/Xoshbin)[ RSS](/packages/xoshbin-filament-translatable-select/feed)WikiDiscussions main Synced 3d ago

READMEChangelog (1)Dependencies (16)Versions (8)Used By (0)

Filament TranslatableSelect
===========================

[](#filament-translatableselect)

[![Latest Version on Packagist](https://camo.githubusercontent.com/4495f8b3e602e0b00946d9548124fddc7f8e3e6149b8aa105a5815d0b44d8b3f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f786f736862696e2f7472616e736c617461626c652d73656c6563742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/xoshbin/translatable-select)[![GitHub Tests Action Status](https://camo.githubusercontent.com/1a4aabcf44f549159d3da04a12c260e75f9adcc18613ba09cfc6b035d98f6762/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f786f736862696e2f7472616e736c617461626c652d73656c6563742f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/xoshbin/translatable-select/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/5bb2a3a3eaf55fa44871480b58ec02ea7e99bb3f9bf80b8f6e71bfedd1df86c9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f786f736862696e2f7472616e736c617461626c652d73656c6563742f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/xoshbin/translatable-select/actions?query=workflow%3A%22Fix+PHP+code+styling%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/277348c27b7b9b2e5c9827fd43f1fb2a195dee68600bc11097d4bf2344a3daab/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f786f736862696e2f7472616e736c617461626c652d73656c6563742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/xoshbin/translatable-select)

A powerful Filament v4 Select component that **fully extends** Filament's native Select while adding **cross-locale search functionality** for **Spatie Laravel Translatable** models. Search across all locales simultaneously, regardless of the current application locale, while maintaining 100% compatibility with all native Filament Select features.

🚀 Key Features
--------------

[](#-key-features)

- **🔍 Cross-Locale Search**: Search across all locales simultaneously, regardless of current app locale
- **🎯 Full Filament Compatibility**: Inherits ALL native Select features (relationships, multi-select, preloading, etc.)
- **⚡ Performance Optimized**: Efficient JSON column queries with N+1 prevention
- **🔧 Highly Configurable**: Custom search fields, locales, query modifiers, and more
- **🧪 Thoroughly Tested**: 52 tests covering unit, feature, and integration scenarios
- **🏗️ Clean Architecture**: Separation of concerns with dedicated services
- **📦 Zero Breaking Changes**: Drop-in replacement for standard Filament Select
- **🌐 Database Agnostic**: Optimized for MySQL, PostgreSQL, and SQLite
- **🔤 Case-Insensitive Search**: Automatic case-insensitive search across all database engines
- **🏢 Multi-Tenancy Ready**: Seamless integration with Laravel Filament's tenancy system

📋 Requirements
--------------

[](#-requirements)

- **PHP**: ^8.1
- **Laravel**: ^10.0|^11.0
- **Filament**: ^4.0 (v4 only - clean, modern implementation)
- **Spatie Laravel Translatable**: ^6.0

📦 Installation
--------------

[](#-installation)

Install the package via Composer:

```
composer require xoshbin/translatable-select
```

### Publish Configuration (Optional)

[](#publish-configuration-optional)

You can publish the configuration file to customize default settings:

```
php artisan vendor:publish --tag="translatable-select-config"
```

This will publish the configuration file to `config/translatable-select.php` where you can customize:

- Default search behavior and limits
- Locale resolution strategies
- Performance optimization settings
- Database-specific configurations

🎯 Core Concept: Full Filament Select Compatibility + Cross-Locale Search
------------------------------------------------------------------------

[](#-core-concept-full-filament-select-compatibility--cross-locale-search)

`TranslatableSelect` is a **complete extension** of Filament's native Select component. It inherits ALL standard functionality while adding powerful cross-locale search capabilities.

### **What Makes It Special:**

[](#what-makes-it-special)

✅ **100% Filament Select Compatibility**: All native features work exactly as expected ✅ **Cross-Locale Search**: Search across all locales simultaneously ✅ **Relationship Support**: Full support for Eloquent relationships ✅ **Multi-Select**: Native multiple selection support ✅ **Preloading**: Efficient option preloading ✅ **Query Modification**: Custom query constraints and filters

### **Two Usage Patterns:**

[](#two-usage-patterns)

#### **1. Direct Model Usage (forModel)**

[](#1-direct-model-usage-formodel)

```
// For direct model selection with cross-locale search
TranslatableSelect::forModel('currency_id', Currency::class, 'name')
    ->label('Currency')
    ->searchableFields(['name', 'code'])
    ->required()
```

#### **2. Relationship Usage (relationship)**

[](#2-relationship-usage-relationship)

```
// For Eloquent relationships with cross-locale search
TranslatableSelect::make('category_id')
    ->relationship('category', 'name')
    ->searchableFields(['name', 'description'])
    ->multiple()
    ->preload()
```

### **Key Advantages:**

[](#key-advantages)

- **Drop-in Replacement**: Replace any `Select::make()` with `TranslatableSelect::make()`
- **Enhanced Search**: Automatically searches across all locales
- **Performance Optimized**: Efficient JSON column queries
- **Highly Configurable**: Extensive customization options

🔧 Basic Usage
-------------

[](#-basic-usage)

### Quick Start Examples

[](#quick-start-examples)

#### **Simple Model Selection**

[](#simple-model-selection)

```
use Xoshbin\TranslatableSelect\Components\TranslatableSelect;

// Basic usage - searches across all locales automatically
TranslatableSelect::forModel('currency_id', Currency::class, 'name')
    ->label('Currency')
    ->required()
```

#### **Relationship Selection**

[](#relationship-selection)

```
// Works with Eloquent relationships
TranslatableSelect::make('category_id')
    ->relationship('category', 'name')
    ->label('Category')
    ->multiple()
    ->preload()
```

#### **Advanced Configuration**

[](#advanced-configuration)

```
// Full feature example
TranslatableSelect::forModel('product_id', Product::class, 'name')
    ->label('Product')
    ->searchableFields(['name', 'description'])
    ->searchLocales(['en', 'ar', 'ku'])
    ->modifyQueryUsing(fn($query) => $query->where('active', true))
    ->multiple()
    ->preload()
    ->required()
```

⚙️ Configuration Options
------------------------

[](#️-configuration-options)

### Search Configuration

[](#search-configuration)

#### **Custom Search Fields**

[](#custom-search-fields)

```
TranslatableSelect::forModel('product_id', Product::class, 'name')
    ->searchableFields(['name', 'description', 'sku'])  // Search multiple fields
```

#### **Limit Search Locales**

[](#limit-search-locales)

```
TranslatableSelect::forModel('category_id', Category::class, 'name')
    ->searchLocales(['en', 'ar'])  // Only search in specific locales
```

#### **Fallback Locale**

[](#fallback-locale)

```
TranslatableSelect::forModel('tag_id', Tag::class, 'name')
    ->fallbackLocale('en')  // Fallback when translation missing
```

### Query Customization

[](#query-customization)

#### **Query Modification**

[](#query-modification)

```
TranslatableSelect::forModel('user_id', User::class, 'name')
    ->modifyQueryUsing(fn($query) => $query->where('active', true))
```

#### **Relationship Constraints**

[](#relationship-constraints)

```
TranslatableSelect::make('category_id')
    ->relationship('category', 'name')
    ->modifyQueryUsing(fn($query) => $query->where('parent_id', null))
```

### Performance Options

[](#performance-options)

#### **Preloading**

[](#preloading)

```
TranslatableSelect::forModel('currency_id', Currency::class, 'name')
    ->preload()  // Load all options immediately
```

#### **Search Debounce**

[](#search-debounce)

```
TranslatableSelect::forModel('product_id', Product::class, 'name')
    ->searchDebounce(300)  // Delay search by 300ms
```

🔄 Migration from Standard Filament Select
-----------------------------------------

[](#-migration-from-standard-filament-select)

### Simple Drop-in Replacement

[](#simple-drop-in-replacement)

TranslatableSelect is designed as a complete drop-in replacement for Filament's native Select component:

```
// Before: Standard Filament Select
Select::make('category_id')
    ->relationship('category', 'name')
    ->searchable()
    ->preload()

// After: TranslatableSelect with cross-locale search
TranslatableSelect::make('category_id')
    ->relationship('category', 'name')
    ->searchableFields(['name']) // Now searches across all locales!
    ->preload()
```

### Enhanced Features

[](#enhanced-features)

Add powerful search capabilities to existing selects:

```
// Standard select with limited search
Select::make('product_id')
    ->relationship('product', 'name')
    ->searchable()

// Enhanced with cross-locale search and multiple fields
TranslatableSelect::make('product_id')
    ->relationship('product', 'name')
    ->searchableFields(['name', 'sku', 'description']) // Search multiple fields
    ->searchLocales(['en', 'ar', 'ku']) // Across multiple locales
    ->searchDebounce(300) // Performance optimization
```

### Migration Checklist

[](#migration-checklist)

1. **Replace Import Statement**:

    ```
    // Old
    use Filament\Forms\Components\Select;

    // New
    use Xoshbin\TranslatableSelect\Components\TranslatableSelect;
    ```
2. **Update Component Usage**:

    ```
    // Old
    Select::make('field_name')

    // New
    TranslatableSelect::make('field_name')
    ```
3. **Add Search Configuration**:

    ```
    // Add these methods for enhanced functionality
    ->searchableFields(['name', 'code'])
    ->searchLocales(['en', 'ar', 'ku']) // Optional: specify locales
    ```
4. **Review Query Modifiers** (Important for Multi-Tenant Apps):

    ```
    // Remove manual tenant filtering - let Filament handle it
    // Old (problematic)
    ->modifyQueryUsing(fn($query) => $query->where('company_id', $tenant->id))

    // New (correct)
    ->modifyQueryUsing(fn($query) => $query->where('active', true))
    ```

🏗️ Model Setup
--------------

[](#️-model-setup)

### Basic Model Configuration

[](#basic-model-configuration)

Your translatable models should use the `HasTranslations` trait from Spatie Laravel Translatable:

```
use Spatie\Translatable\HasTranslations;

class Currency extends Model
{
    use HasTranslations;

    public array $translatable = ['name'];

    protected $fillable = ['code', 'name', 'symbol'];
}
```

### Example Models

[](#example-models)

#### **Category Model**

[](#category-model)

```
use Spatie\Translatable\HasTranslations;

class Category extends Model
{
    use HasTranslations;

    public array $translatable = ['name', 'description'];

    protected $fillable = ['name', 'description', 'active'];

    protected $casts = [
        'active' => 'boolean',
    ];
}
```

#### **Product Model with Relationships**

[](#product-model-with-relationships)

```
use Spatie\Translatable\HasTranslations;

class Product extends Model
{
    use HasTranslations;

    public array $translatable = ['name', 'description'];

    protected $fillable = ['name', 'description', 'sku', 'category_id'];

    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }
}
```

🔧 Configuration File
--------------------

[](#-configuration-file)

The package comes with a comprehensive configuration file. Here are the key settings:

```
return [
    /*
    |--------------------------------------------------------------------------
    | Default Search Behavior
    |--------------------------------------------------------------------------
    */
    'default_search_limit' => 50,
    'default_search_fields' => ['name'],
    'enable_cross_locale_search' => true,

    /*
    |--------------------------------------------------------------------------
    | Locale Configuration
    |--------------------------------------------------------------------------
    */
    'locale_resolution' => [
        'strategy' => 'auto', // 'auto', 'config', 'manual'
        'fallback_locale' => 'en',
        'available_locales' => ['en', 'ar', 'ku'],
    ],

    /*
    |--------------------------------------------------------------------------
    | Performance Settings
    |--------------------------------------------------------------------------
    */
    'performance' => [
        'enable_query_caching' => true,
        'cache_duration' => 300, // 5 minutes
        'max_search_results' => 100,
    ],

    /*
    |--------------------------------------------------------------------------
    | Database Optimization
    |--------------------------------------------------------------------------
    */
    'database' => [
        'case_insensitive_search' => true,
        'json_extraction_patterns' => [
            'mysql' => 'LOWER(JSON_UNQUOTE(JSON_EXTRACT(`{field}`, "$.{locale}"))) LIKE LOWER(?)',
            'pgsql' => 'LOWER(({field}->>\'{locale}\')) ILIKE ?',
            'sqlite' => 'LOWER(json_extract(`{field}`, "$.{locale}")) LIKE LOWER(?)',
        ],
    ],
];
```

🏢 Multi-Tenancy Considerations
------------------------------

[](#-multi-tenancy-considerations)

### Overview

[](#overview)

TranslatableSelect seamlessly integrates with Laravel Filament's tenancy system. The component automatically respects tenant scoping when used in tenant-aware resources, but there are important considerations to ensure optimal performance and avoid conflicts.

### ⚠️ Important: Avoid Duplicate Company/Tenant Filtering

[](#️-important-avoid-duplicate-companytenant-filtering)

**❌ INCORRECT - Causes Search Conflicts:**

```
// DON'T DO THIS - Manual tenant filtering conflicts with Filament's automatic tenancy
TranslatableSelect::forModel('account_id', Account::class, 'name')
    ->modifyQueryUsing(fn($query) => $query->where('company_id', Filament::getTenant()->id))
    ->searchableFields(['name', 'code'])
```

**✅ CORRECT - Let Filament Handle Tenancy:**

```
// DO THIS - Filament automatically applies tenant scoping
TranslatableSelect::forModel('account_id', Account::class, 'name')
    ->searchableFields(['name', 'code'])
    ->modifyQueryUsing(fn($query) => $query->where('active', true)) // Only add business logic filters
```

### Best Practices for Multi-Tenant Applications

[](#best-practices-for-multi-tenant-applications)

#### **1. Trust Filament's Automatic Tenancy**

[](#1-trust-filaments-automatic-tenancy)

```
// Filament automatically adds tenant scoping - no manual filtering needed
TranslatableSelect::make('category_id')
    ->relationship('category', 'name')
    ->searchableFields(['name', 'description'])
    ->modifyQueryUsing(fn($query) => $query->where('active', true)) // Business logic only
```

#### **2. Use Query Modifiers for Business Logic Only**

[](#2-use-query-modifiers-for-business-logic-only)

```
// Focus on business rules, not tenant filtering
TranslatableSelect::forModel('product_id', Product::class, 'name')
    ->searchableFields(['name', 'sku'])
    ->modifyQueryUsing(function($query) {
        return $query->where('active', true)
                    ->where('stock_quantity', '>', 0)
                    ->orderBy('name');
    })
```

#### **3. Relationship-Based Tenant Scoping**

[](#3-relationship-based-tenant-scoping)

```
// For complex tenant relationships
TranslatableSelect::make('supplier_id')
    ->relationship('supplier', 'name')
    ->searchableFields(['name', 'company_name'])
    ->modifyQueryUsing(fn($query) => $query->where('approved', true))
```

### Multi-Tenant Model Setup

[](#multi-tenant-model-setup)

Ensure your models are properly configured for tenancy:

```
use Spatie\Translatable\HasTranslations;
use Illuminate\Database\Eloquent\Model;

class Account extends Model
{
    use HasTranslations;

    public array $translatable = ['name'];

    protected $fillable = ['name', 'code', 'type', 'company_id'];

    // Filament will automatically scope by company_id when using tenancy
    public function company()
    {
        return $this->belongsTo(Company::class);
    }
}
```

🎨 Advanced Examples
-------------------

[](#-advanced-examples)

### E-commerce Product Selection

[](#e-commerce-product-selection)

```
TranslatableSelect::forModel('product_id', Product::class, 'name')
    ->label('Product')
    ->searchableFields(['name', 'description', 'sku'])
    ->searchLocales(['en', 'ar', 'ku'])
    ->modifyQueryUsing(fn($query) => $query->where('active', true)->with('category'))
    ->getOptionLabelUsing(fn($record) => "{$record->name} ({$record->sku})")
    ->multiple()
    ->preload()
    ->required()
```

### Multi-Tenant Category Selection (Correct Way)

[](#multi-tenant-category-selection-correct-way)

```
TranslatableSelect::make('category_id')
    ->relationship('category', 'name')
    ->searchableFields(['name', 'description'])
    ->modifyQueryUsing(fn($query) => $query->where('active', true)) // No manual tenant filtering!
    ->preload()
    ->required()
```

### Tag Selection with Custom Styling

[](#tag-selection-with-custom-styling)

```
TranslatableSelect::forModel('tags', Tag::class, 'name')
    ->label('Tags')
    ->searchableFields(['name'])
    ->searchDebounce(300)
    ->multiple()
    ->preload()
    ->getOptionLabelUsing(fn($record) => "🏷️ {$record->name}")
    ->placeholder('Select tags...')
```

### Real-World Usage Examples

[](#real-world-usage-examples)

#### **Accounting System - Account Selection**

[](#accounting-system---account-selection)

```
// Income accounts for product configuration
TranslatableSelect::forModel('income_account_id', Account::class, 'name')
    ->label('Income Account')
    ->searchableFields(['name', 'code'])
    ->modifyQueryUsing(fn($query) => $query->whereIn('type', [
        AccountType::Income,
        AccountType::OtherIncome
    ]))
    ->getOptionLabelUsing(fn($record) => "{$record->code} - {$record->name}")
    ->required()

// Expense accounts for product configuration
TranslatableSelect::forModel('expense_account_id', Account::class, 'name')
    ->label('Expense Account')
    ->searchableFields(['name', 'code'])
    ->modifyQueryUsing(fn($query) => $query->whereIn('type', [
        AccountType::Expense,
        AccountType::CostOfGoodsSold
    ]))
    ->getOptionLabelUsing(fn($record) => "{$record->code} - {$record->name}")
    ->required()
```

#### **Inventory Management - Product Selection**

[](#inventory-management---product-selection)

```
TranslatableSelect::make('product_id')
    ->relationship('product', 'name')
    ->searchableFields(['name', 'sku', 'description'])
    ->modifyQueryUsing(fn($query) => $query->where('active', true))
    ->getOptionLabelUsing(fn($record) => "{$record->sku} - {$record->name}")
    ->preload()
    ->required()
```

#### **CRM System - Customer Selection**

[](#crm-system---customer-selection)

```
TranslatableSelect::forModel('customer_id', Customer::class, 'name')
    ->label('Customer')
    ->searchableFields(['name', 'company_name', 'email'])
    ->modifyQueryUsing(fn($query) => $query->where('active', true))
    ->getOptionLabelUsing(fn($record) => $record->company_name
        ? "{$record->name} ({$record->company_name})"
        : $record->name)
    ->searchDebounce(300)
    ->required()
```

🔍 How It Works
--------------

[](#-how-it-works)

### Architecture Overview

[](#architecture-overview)

The package consists of three main components:

1. **TranslatableSelect Component**: Extends Filament's Select with cross-locale search
2. **LocaleResolver Service**: Handles locale detection and management
3. **TranslatableSearchService**: Manages cross-locale search logic

### Cross-Locale Search Process

[](#cross-locale-search-process)

1. **Locale Detection**: Automatically detects available locales from:

    - Laravel application configuration (`config/app.php`)
    - Model's translatable configuration
    - Manual configuration via `searchLocales()`
2. **Field Analysis**: Identifies translatable fields from model's `$translatable` array
3. **Query Construction**: Builds efficient database queries using JSON extraction:

    ```
    -- Example MySQL query for searching "tech" across locales (case-insensitive)
    SELECT * FROM categories
    WHERE LOWER(JSON_UNQUOTE(JSON_EXTRACT(`name`, "$.en"))) LIKE LOWER('%tech%')
       OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(`name`, "$.ar"))) LIKE LOWER('%tech%')
       OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(`name`, "$.ku"))) LIKE LOWER('%tech%')
    LIMIT 50
    ```
4. **Result Processing**: Formats results using current locale with fallback support

### Case-Insensitive Search

[](#case-insensitive-search)

The component automatically performs case-insensitive searches across all supported database engines:

- **MySQL**: Uses `LOWER()` functions for both JSON fields and search terms
- **PostgreSQL**: Uses `ILIKE` operator for case-insensitive pattern matching
- **SQLite**: Uses `LOWER()` functions similar to MySQL

This means searching for "product", "Product", or "PRODUCT" will all return the same results.

### Performance Optimizations

[](#performance-optimizations)

- **Efficient JSON Queries**: Database-specific optimized JSON extraction
- **Query Limits**: Configurable result limits prevent performance issues
- **N+1 Prevention**: Eager loading for relationships
- **Search Debouncing**: Configurable search delays
- **Preloading Support**: Load options immediately when needed

🐛 Troubleshooting
-----------------

[](#-troubleshooting)

### Common Issues

[](#common-issues)

**1. Component not found**

```
# Clear cache and rediscover packages
php artisan config:clear
php artisan package:discover
```

**2. "No options match your search" despite valid data**

This is often caused by conflicting query modifiers in multi-tenant applications:

```
// ❌ PROBLEM: Manual tenant filtering conflicts with Filament's automatic tenancy
TranslatableSelect::forModel('account_id', Account::class, 'name')
    ->modifyQueryUsing(fn($query) => $query->where('company_id', $tenant->id)) // Causes conflicts!

// ✅ SOLUTION: Remove manual tenant filtering, let Filament handle it
TranslatableSelect::forModel('account_id', Account::class, 'name')
    ->searchableFields(['name', 'code'])
    ->modifyQueryUsing(fn($query) => $query->where('active', true)) // Business logic only
```

**3. Case sensitivity issues**

The component automatically handles case-insensitive search, but if you're experiencing issues:

```
// Ensure you're not overriding the search behavior
TranslatableSelect::forModel('product_id', Product::class, 'name')
    ->searchableFields(['name']) // Let the component handle case sensitivity
```

**4. No search results**

```
// Ensure your model has the HasTranslations trait
use Spatie\Translatable\HasTranslations;

class YourModel extends Model
{
    use HasTranslations;

    public array $translatable = ['name'];
}
```

**5. Search not working across locales**

```
// Check if translatable fields are properly configured
TranslatableSelect::forModel('model_id', YourModel::class, 'name')
    ->searchableFields(['name']) // Explicitly set searchable fields
    ->searchLocales(['en', 'ar', 'ku']) // Specify locales if needed
```

**6. Performance issues**

```
// Optimize with search limits and debouncing
TranslatableSelect::forModel('product_id', Product::class, 'name')
    ->searchDebounce(300)  // Add 300ms delay
    ->modifyQueryUsing(fn($query) => $query->limit(25))
```

**7. Relationship search not working**

```
// Ensure the relationship method exists and is properly defined
TranslatableSelect::make('category_id')
    ->relationship('category', 'name') // 'category' method must exist on the model
    ->searchableFields(['name'])
```

### Debug Helpers

[](#debug-helpers)

```
// Check available locales
$localeResolver = app(\Xoshbin\TranslatableSelect\Services\LocaleResolver::class);
dd($localeResolver->getAvailableLocales());

// Test search service directly
$searchService = app(\Xoshbin\TranslatableSelect\Services\TranslatableSearchService::class);
dd($searchService->getFilamentSearchResults(
    Account::class,
    'product', // Search term
    ['name', 'code'], // Search fields
    ['en', 'ar', 'ku'], // Search locales
    null, // Query modifier
    50 // Limit
));

// Check current locale
dd(app()->getLocale());

// Test model translatable configuration
dd(Account::make()->getTranslatableAttributes());

// Check if tenancy is affecting queries (in tenant-aware resources)
dd(Filament::getTenant()?->getKey());
```

### Debugging Search Issues

[](#debugging-search-issues)

If search is not working, enable query logging to see what's happening:

```
// Add this to your resource or form to debug queries
use Illuminate\Support\Facades\DB;

// Enable query logging
DB::enableQueryLog();

// Perform your search...

// Check the queries
dd(DB::getQueryLog());
```

### Common Query Conflicts

[](#common-query-conflicts)

**Problem**: Duplicate tenant filtering

```
-- This query shows duplicate company_id conditions
SELECT * FROM accounts
WHERE company_id = 1 -- Filament's automatic tenancy
  AND company_id = 1 -- Your manual filtering (duplicate!)
  AND (LOWER(JSON_UNQUOTE(JSON_EXTRACT(`name`, "$.en"))) LIKE LOWER('%product%'))
```

**Solution**: Remove manual tenant filtering

```
// Let Filament handle tenancy automatically
TranslatableSelect::forModel('account_id', Account::class, 'name')
    ->searchableFields(['name', 'code'])
    // No manual company_id filtering needed!
```

🧪 Testing
---------

[](#-testing)

The package includes a comprehensive test suite with 52 tests covering:

- **Unit Tests**: LocaleResolver and TranslatableSearchService
- **Feature Tests**: TranslatableSelect component functionality
- **Integration Tests**: Filament compatibility and real-world usage

```
# Run all tests
composer test

# Run tests with coverage
./vendor/bin/pest --coverage

# Run specific test types
./vendor/bin/pest tests/Unit
./vendor/bin/pest tests/Feature
./vendor/bin/pest tests/Integration
```

🚀 What's New in v2.0
--------------------

[](#-whats-new-in-v20)

This is a **complete rewrite** of the package with:

- ✅ **Filament v4 Only**: Clean, modern implementation
- ✅ **Full Select Compatibility**: Inherits ALL native Filament Select features
- ✅ **Enhanced Performance**: Optimized queries and N+1 prevention
- ✅ **Comprehensive Tests**: 52 tests with full coverage
- ✅ **Clean Architecture**: Separation of concerns with dedicated services
- ✅ **Zero Breaking Changes**: Drop-in replacement for standard Select
- ✅ **Case-Insensitive Search**: Automatic case-insensitive search across all database engines
- ✅ **Multi-Tenancy Integration**: Seamless compatibility with Filament's tenancy system
- ✅ **Improved Error Handling**: Better debugging and troubleshooting capabilities

### Recent Improvements (Latest Release)

[](#recent-improvements-latest-release)

#### 🔧 **Fixed Search Functionality Issues**

[](#-fixed-search-functionality-issues)

- **Case Sensitivity**: Resolved case-sensitive search problems where "product" wouldn't match "Product Sales"
- **Multi-Tenancy Conflicts**: Fixed conflicts between manual tenant filtering and Filament's automatic tenancy system
- **Query Optimization**: Improved database query generation for better performance

#### 🏢 **Enhanced Multi-Tenancy Support**

[](#-enhanced-multi-tenancy-support)

- **Automatic Tenant Scoping**: Works seamlessly with Filament's tenant-aware resources
- **Conflict Prevention**: Prevents duplicate company/tenant filtering that caused search failures
- **Best Practices Documentation**: Comprehensive guide for multi-tenant applications

#### 🔍 **Improved Search Capabilities**

[](#-improved-search-capabilities)

- **Cross-Locale Search**: Search "sales" and find both "Product Sales" and "Sales Discounts &amp; Returns"
- **Case-Insensitive**: Search "product" and match "Product Sales" regardless of case
- **Database Agnostic**: Optimized queries for MySQL, PostgreSQL, and SQLite

📝 Changelog
-----------

[](#-changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

🤝 Contributing
--------------

[](#-contributing)

Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.

🔒 Security Vulnerabilities
--------------------------

[](#-security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

👥 Credits
---------

[](#-credits)

- [Khoshbin](https://github.com/Xoshbin)
- [All Contributors](../../contributors)

📄 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance82

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 84.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

122d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/88844b024c613b0dff2f4355a3ce9938287ec682d1f27964fbee51857b3bd4ff?d=identicon)[khoshbin](/maintainers/khoshbin)

---

Top Contributors

[![Xoshbin](https://avatars.githubusercontent.com/u/1606070?v=4)](https://github.com/Xoshbin "Xoshbin (27 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (4 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

spatiesearchlaraveltranslatableselectfilamentmulti-localecross-locale

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/xoshbin-filament-translatable-select/health.svg)

```
[![Health](https://phpackages.com/badges/xoshbin-filament-translatable-select/health.svg)](https://phpackages.com/packages/xoshbin-filament-translatable-select)
```

###  Alternatives

[spatie/laravel-permission

Permission handling for Laravel 12 and up

12.9k102.4M1.4k](/packages/spatie-laravel-permission)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[spatie/laravel-health

Monitor the health of a Laravel application

87512.0M167](/packages/spatie-laravel-health)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.6k](/packages/rawilk-profile-filament-plugin)[finity-labs/fin-mail

A powerful email template manager and composer for Filament with dynamic token replacement, template versioning, and inline email sending.

284.5k1](/packages/finity-labs-fin-mail)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.0k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
