https://github.com/fnx-software/filament-astrotomic
Manage multilingual content in Filament v4+ with astrotomic/laravel-translatable, supercharged with a reactive Locale Switcher, sortable/searchable Columns, and a translatable Select component.
https://github.com/fnx-software/filament-astrotomic
astrotomic filament filament-plugin filament4 filamentphp laravel laravel-translatable localization multilingual translations
Last synced: 5 months ago
JSON representation
Manage multilingual content in Filament v4+ with astrotomic/laravel-translatable, supercharged with a reactive Locale Switcher, sortable/searchable Columns, and a translatable Select component.
- Host: GitHub
- URL: https://github.com/fnx-software/filament-astrotomic
- Owner: fnx-software
- License: mit
- Created: 2025-09-29T06:14:23.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2026-01-15T08:51:16.000Z (5 months ago)
- Last Synced: 2026-01-16T01:42:23.022Z (5 months ago)
- Topics: astrotomic, filament, filament-plugin, filament4, filamentphp, laravel, laravel-translatable, localization, multilingual, translations
- Language: PHP
- Homepage:
- Size: 429 KB
- Stars: 0
- Watchers: 0
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE.md
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
# Filament Astrotomic Translations
[](https://packagist.org/packages/fnx-software/filament-astrotomic)
This package is an extension for **Filament v4+** and [laravel-translatable](https://docs.astrotomic.info/laravel-translatable) to easily manage multilingual content in your admin panel.
This is an enhanced fork of [doriiaan/filament-astrotomic](https://github.com/Doriiaan/filament-astrotomic) and the original [cactus-galaxy/filament-astrotomic](https://github.com/CactusGalaxy/FilamentAstrotomic), updated for Filament 4 and introducing powerful new features like a reactive `LocaleSwitcher` and dedicated components for displaying translated content.

## Installation
You can install the package via Composer:
```bash
composer require fnx-software/filament-astrotomic
```
Publish the configuration for `astrotomic/laravel-translatable`:
```bash
php artisan vendor:publish --tag="translatable"
```
Configure the locales your app should use in `config/translatable.php`:
```php
// config/translatable.php
'locales' => [
'en',
'es',
'fr',
],
```
## Setup
### Adding the Plugin to a Panel
Register the plugin in your Panel Provider:
```php
// app/Providers/Filament/AdminPanelProvider.php
use Fnxsoftware\FilamentAstrotomic\FilamentAstrotomicPlugin;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->plugins([
FilamentAstrotomicPlugin::make(),
]);
}
```
### Customizing the Main Locale (Optional)
By default, the main locale is taken from your `config/translatable.php` file. You can override this dynamically when registering the plugin.
**Set a static main locale:**
```php
FilamentAstrotomicPlugin::make()
->mainLocale('ar')
```
**Set a dynamic main locale (e.g., from database settings):**
```php
use App\Models\Setting;
FilamentAstrotomicPlugin::make()
->mainLocale(fn () => Setting::where('key', 'default_locale')->first()?->value ?? 'en')
```
### Customizing the Available Locales (Optional)
By default, the available locales are loaded from your `config/translatable.php` file.
You can override the locale list when registering the plugin, which is useful when your locales are stored in the database (e.g., per-tenant settings).
**Set a static locales list:**
```php
FilamentAstrotomicPlugin::make()
->locales(['ar', 'en', 'fr'])
```
## Basic Usage
### 1. Preparing Your Model
Make your Eloquent model translatable as described in the [laravel-translatable documentation](https://docs.astrotomic.info/laravel-translatable/installation#models).
```php
// app/Models/Post.php
use Illuminate\Database\Eloquent\Model;
use Astrotomic\Translatable\Contracts\Translatable as TranslatableContract;
use Astrotomic\Translatable\Translatable;
class Post extends Model implements TranslatableContract
{
use Translatable;
public array $translatedAttributes = ['title', 'content'];
protected $fillable = ['author_id'];
}
```
### 2. Preparing Your Resource
Apply the `ResourceTranslatable` trait to your Filament resource class:
```php
// app/Filament/Resources/PostResource.php
use Fnxsoftware\FilamentAstrotomic\Resources\Concerns\ResourceTranslatable;
use Filament\Resources\Resource;
class PostResource extends Resource
{
use ResourceTranslatable;
// ...
}
```
### 3. Making Resource Pages Translatable
You must also apply the corresponding translatable trait to each of your resource's pages.
**List Page:**
```php
// app/Filament/Resources/PostResource/Pages/ListPosts.php
use Fnxsoftware\FilamentAstrotomic\Resources\Pages\ListTranslatable;
use Filament\Resources\Pages\ListRecords;
class ListPosts extends ListRecords
{
use ListTranslatable;
// ...
}
```
**Create Page:**
```php
// app/Filament/Resources/PostResource/Pages/CreatePost.php
use Fnxsoftware\FilamentAstrotomic\Resources\Pages\CreateTranslatable;
use Filament\Resources\Pages\CreateRecord;
class CreatePost extends CreateRecord
{
use CreateTranslatable;
// ...
}
```
**Edit Page:**
```php
// app/Filament/Resources/PostResource/Pages/EditPost.php
use Fnxsoftware\FilamentAstrotomic\Resources\Pages\EditTranslatable;
use Filament\Resources\Pages\EditRecord;
class EditPost extends EditRecord
{
use EditTranslatable;
// ...
}
```
**View Page:**
```php
// app/Filament/Resources/PostResource/Pages/ViewPost.php
use Fnxsoftware\FilamentAstrotomic\Resources\Pages\ViewTranslatable;
use Filament\Resources\Pages\ViewRecord;
class ViewPost extends ViewRecord
{
use ViewTranslatable;
// ...
}
```
## Form Components
### `TranslatableTabs` for Localized Fields
To manage translations for your model's attributes, use the `TranslatableTabs` component. It automatically creates a tab for each locale.
```php
use Fnxsoftware\FilamentAstrotomic\Schemas\Components\TranslatableTabs;
use Fnxsoftware\FilamentAstrotomic\TranslatableTab;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\RichEditor;
use Filament\Forms\Form;
public static function form(Form $form): Form
{
return $form->schema([
TranslatableTabs::make()
->localeTabSchema(fn (TranslatableTab $tab) => [
TextInput::make($tab->makeName('title'))
->required($tab->isMainLocale()), // Required only for the main language
RichEditor::make($tab->makeName('content')),
])
]);
}
```

#### Customizing Field Labels
To make it clearer which language a field belongs to, you can use the `makePrefixLabel()` and `makeSuffixLabel()` methods on the `TranslatableTab` object to automatically add the locale name to your field labels.
```php
use Fnxsoftware\FilamentAstrotomic\Schemas\Components\TranslatableTabs;
use Fnxsoftware\FilamentAstrotomic\TranslatableTab;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
TranslatableTabs::make()
->localeTabSchema(fn (TranslatableTab $tab) => [
TextInput::make($tab->makeName('title'))
// Renders label as "Title (English)"
->label($tab->makePrefixLabel('Title')),
Textarea::make($tab->makeName('description'))
// Renders label as "(English) Description"
->label($tab->makeSuffixLabel('Description')),
])
```
#### Custom Locales Per `TranslatableTabs` Instance
By default, `TranslatableTabs` will use the locales configured for the plugin (or the `translatable.locales` config).
If you need to override the locales for a specific form (or even for a single set of fields), you may pass a custom list directly to the component:
```php
use Fnxsoftware\FilamentAstrotomic\Schemas\Components\TranslatableTabs;
use Fnxsoftware\FilamentAstrotomic\TranslatableTab;
use Filament\Forms\Components\TextInput;
TranslatableTabs::make()
->customLocales(['ar', 'en', 'fr', 'pt'])
->localeTabSchema(fn (TranslatableTab $tab) => [
TextInput::make($tab->makeName('label'))
->required($tab->isMainLocale()),
])
```
### `TranslatableSelect` for Relationships
The standard `Select::relationship()` component does not work with `astrotomic/laravel-translatable`. This package provides a `TranslatableSelect` component to correctly load, search, and display options from a translatable `BelongsTo` relationship.
```php
use Fnxsoftware\FilamentAstrotomic\Forms\Components\TranslatableSelect;
use Filament\Forms\Form;
public static function form(Form $form): Form
{
return $form->schema([
// ... other fields
TranslatableSelect::make('country_id')
->translatableRelationship('country', 'name')
->searchable()
->preload()
->label('Country')
->required(),
]);
}
```
This will correctly display the country names in the current locale, and the search functionality will also work on the translated names.
## Displaying Translated Content Reactively
This package provides a seamless way to view translated content on your List and View pages using a `LocaleSwitcher` action that works with dedicated table columns and infolist entries.
### 1. Add the `LocaleSwitcher` Action
Add the `LocaleSwitcher` to the header actions of your List and View pages.
```php
// In your List page (e.g., ListPosts.php)
use Fnxsoftware\FilamentAstrotomic\Actions\LocaleSwitcher;
use Filament\Actions\CreateAction;
protected function getHeaderActions(): array
{
return [
CreateAction::make(),
LocaleSwitcher::make(), // Add this
];
}
```

### 2. Use `TranslatableColumn` in Tables
The `TranslatableColumn` automatically displays the translation for the selected locale and provides out-of-the-box search and sort functionality.
```php
// In your Table definition
use Fnxsoftware\FilamentAstrotomic\Tables\Columns\TranslatableColumn;
use Filament\Tables\Table;
public static function table(Table $table): Table
{
return $table
->columns([
TranslatableColumn::make('title')
->searchable()
->sortable(),
// ... other columns
]);
}
```
### 3. Use `TranslatableEntry` in Infolists
Similarly, use `TranslatableEntry` in your infolists to display translated content that reacts to the `LocaleSwitcher`.
```php
// In your Infolist definition
use Fnxsoftware\FilamentAstrotomic\Infolists\Components\TranslatableEntry;
use Filament\Infolists\Infolist;
public static function infolist(Infolist $infolist): Infolist
{
return $infolist
->schema([
TranslatableEntry::make('title'),
TranslatableEntry::make('content'),
// ... other entries
]);
}
```
## 🚀 Single Locale Optimization & Customization
### Automatic Grid View
When your application or a specific tenant only has **one locale** active, `TranslatableTabs` will automatically switch its layout to a standard **Grid**.
This removes the unnecessary tab bar, rendering the fields directly. This provides a cleaner UI for single-language contexts without requiring code changes.
### Forcing Tabs Layout
If you prefer to always show the language tabs (even when only one locale is available), you can force the layout using one of two methods:
#### 1. Global Configuration
Force tabs globally for all `TranslatableTabs` components in your `AdminPanelProvider`:
```php
use Fnxsoftware\FilamentAstrotomic\FilamentAstrotomicPlugin;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->plugin(
FilamentAstrotomicPlugin::make()
->force() // Always show tabs
);
}
```
#### 2. Per-Component Configuration
Force tabs on a specific component:
```php
use Fnxsoftware\FilamentAstrotomic\Schemas\Components\TranslatableTabs;
TranslatableTabs::make('translations')
->force() // Always show tabs for this specific component
->localeTabSchema(fn (TranslatableTab $tab) => [
// ...
])
```
---
### Custom Locales for Switcher
You can now define specific locales for the `LocaleSwitcher` action, overriding the global or tenant configurations. This is useful if specific resources or pages only support a subset of languages.
```php
use Fnxsoftware\FilamentAstrotomic\Actions\LocaleSwitcher;
// Pass a list of locale codes (labels generated automatically)
LocaleSwitcher::make()
->locales(['en', 'fr']);
// Or pass custom labels
LocaleSwitcher::make()
->locales([
'en' => 'English (US)',
'fr' => 'Français (France)',
]);
```
## Advanced Usage
### Custom Locales Per-Resource
Override the `getTranslatableLocales()` method in your resource to specify a different set of locales than the global configuration.
```php
public static function getTranslatableLocales(): array
{
return ['en', 'fr'];
}
```
### Modal Forms
To use translatable fields inside modal actions (like an `EditAction` on a table row), you must correctly mutate the data.
```php
use App\Models\Post;
use Filament\Tables\Actions\EditAction;
->actions([
EditAction::make()->mutateRecordDataUsing(function (Post $record, array $data) {
return static::mutateTranslatableData($record, $data);
}),
])
```
### Nested Relationship Support
Both `TranslatableColumn` and `TranslatableEntry` fully support displaying, searching, and sorting translated attributes on nested relationships using dot notation.
**`TranslatableColumn` with a relationship:**
The column will display the country's name, and the search and sort functionality will correctly filter and order the `governorates` table based on the name of the related country.
```php
// In your GovernorateResource table
TranslatableColumn::make('country.name')
->label('Country')
->searchable()
->sortable(),
```
**`TranslatableEntry` with a relationship:**
The entry will display the translated name of the related country on the governorate's view page.
```php
// In your GovernorateResource infolist
TranslatableEntry::make('country.name')
->label('Country'),
```
## Testing
```bash
composer test
```
## Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
## Contributing
Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.
## Credits
- **Original Author:** [Oleksandr Moik (cactus-galaxy)](https://github.com/oleksandr-moik)
- **Filament v4 Fork:** [Alary Dorian (Doriiaan)](https://github.com/Doriiaan)
- **Current Maintainer:** [Fnx-Software](https://github.com/fnx-software)
- [All Contributors](../../contributors)
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.