martin6363/filament-ai-translator
Filament AI Translator brings AI-powered translation to Laravel Filament admin panels, helping you translate resource labels, forms, and content quickly. Streamline multilingual apps with automated translations and simple Filament integration.
This package wires Google Gemini into Filament so editors can translate translatable model content from one locale to another without leaving the admin panel. v1.0.0 is the initial release, so treat the docs as the source of truth for exact class names and config keys.
Minimal setup:
composer require the package, then publish its config:
php artisan vendor:publish --tag="<package>-config"
.env. Most packages in this space read a name like GEMINI_API_KEY (check config/<package>.php for the actual key it pulls).public function panel(Panel $panel): Panel
{
return $panel
->plugin(\Vendor\Package\YourPlugin::make());
}
spatie/laravel-translatable with a json column (e.g. name, description) plus public array $translatable = [...].Where to look first:
First use case: open a record that has source-locale content (e.g. en), trigger the translate action, pick one or more target locales, review the generated values in the form before saving. Do this manually on a single record before enabling any batch or auto-save behavior — it's the fastest way to confirm credentials, locale mapping, and which attributes are actually translatable.
Single-record translate with review. The safest day-to-day pattern is generate → review → save. Trigger translation on the edit page, let Gemini fill the target-locale fields, inspect them in the form, then persist. This keeps a human in the loop for terminology, brand names, and formatting.
Bulk translate from the table. If the package exposes a bulk action on the resource table, use it for backfilling a newly added locale. Select the records, choose the target locale, and let it process. Pair this with a queue (see below) so the request doesn't time out on large selections.
Locale-to-locale, not just English-to-target. Prefer translating from the locale that has the most complete, highest-quality copy (often the source language the content was authored in) rather than chaining en → de → fr. Chained translation compounds drift. Let the config define a canonical source locale.
Field-scoped translation. Limit translation to the fields that genuinely need it. Marketing copy, SEO meta, and product descriptions are obvious candidates; internal notes, slugs, and SKUs usually are not. Where the package allows selecting fields per action, scope them — smaller prompts mean cheaper, faster, more consistent output.
Queue long jobs. Wrap translation in a queued job or use the package's queue integration if it ships one. Gemini calls are network-bound; doing them synchronously inside a Filament action on a 50-record bulk operation will hit PHP max_execution_time and Filament's request timeout.
Cache and diff. Translation is a paid API call. Re-translating unchanged source content is pure waste. If the package offers a "translate only when source changed" toggle or hashing, enable it; otherwise guard your bulk actions with a where on a last_translated_at-style timestamp you maintain yourself.
Glossary / prompt tuning. If the package exposes a system prompt, glossary, or tone/locale-hint config, use it. Brand names, product categories, and formal-vs-informal address (Sie/du, usted/tú) are the usual failure points, and a short glossary is far cheaper than post-editing.
Validation after generation. Treat generated content as untrusted input: max length limits, required fields, and HTML sanitization for rich-text columns all still apply. Gemini can and will return content that overflows a varchar or introduces markup you don't render.
API key and quota failures fail quietly. The most common first-run problem is no visible effect or a generic error toast. Check storage/logs/laravel.log, verify the key has the Gemini API enabled for the right Google Cloud project, and confirm the model name in config matches one your key can access. Model IDs get deprecated/renamed by Google — a hardcoded default in config is a common breakage point.
Cost is easy to underestimate. Bulk actions over many records × many locales × many fields multiply fast. Start with a handful of records, watch usage in Google's console, and set a budget alert before running a full backfill.
Rate limits and 429s. Free/entry tiers have low per-minute quotas. On batch operations you'll see intermittent failures; add retry/backoff with RateLimited/retry() or process in chunks with a small delay. Don't interpret a partial failure as a package bug.
Rich text and HTML. Translating HTML can mangle tags or introduce unclosed markup. Where possible translate plain-text fields and handle rich text separately, or sanitize output through a purifier before saving.
Locale codes must match. en, en_US, en-US, and en-us all cause different bugs depending on whether the package maps them to Gemini's language names, Filament's getLocales(), or your DB JSON keys. Confirm one canonical set in config and stick to it — mismatches produce silently empty translations.
Empty source = empty target. Gemini will hallucinate if you send an empty or whitespace-only source string. Guard the action to skip empty fields rather than letting the model invent content.
Unsaved form state. If the translate action runs before the form is saved, it may read stale DB values instead of what's currently typed. Get the source text from the form state where the package allows it, otherwise save first, then translate.
Extension points to look for: the plugin class's ->using()/configuration methods, any publishable prompt or client class, and Filament action overrides. Since this is v1.0.0, pin the version in composer.json, publish the config rather than editing vendor files, and expect breaking changes in minor releases until the API stabilizes. File issues with your exact Filament version — v3 vs v4 differences are the most likely source of integration problems.
How can I help you explore Laravel packages today?