Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Underscore Translatable Laravel Package

esign/laravel-underscore-translatable

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Pros:
    • Simple & Lightweight: Follows a straightforward underscore-based approach (e.g., title_en, title_nl) for translations, avoiding complex JSON-based storage (unlike Spatie’s json approach).
    • Eloquent Integration: Seamlessly integrates with Laravel’s Eloquent ORM, requiring minimal model-level changes.
    • Database Agnostic: Works with any database supporting standard column naming conventions.
    • Inspired by Spatie: Leverages a battle-tested pattern (though with a different storage mechanism), reducing conceptual risk.
  • Cons:
    • Schema Bloat: Adds N columns per translatable field (e.g., title_en, title_es), which may increase database size and complexity for high-cardinality locales.
    • No Fallback Mechanism: Unlike Spatie’s package, this lacks built-in fallback logic (e.g., default locale) out of the box.
    • Limited Query Flexibility: Translatable fields cannot be easily queried directly (e.g., WHERE title_en = 'foo'), requiring workarounds.

Integration Feasibility

  • Laravel Compatibility:
    • Works with Laravel 10+ (based on last release date: 2026-04-26). Verify compatibility with your Laravel version (e.g., 11.x may require adjustments).
    • Assumes standard Eloquent model structure; no framework-level hooks or service providers are required.
  • Database Requirements:
    • Supports MySQL, PostgreSQL, SQLite, etc., but requires manual schema adjustments for existing tables (e.g., adding _en, _nl suffixes to columns).
    • No migrations are provided; TPM must define them or use a migration generator.
  • Testing Overhead:
    • Low for basic use cases, but edge cases (e.g., dynamic locale switching, partial updates) may need custom tests.

Technical Risk

  • Medium Risk:
    • Schema Migration: Risk of breaking existing queries if translatable fields are added to production tables without safeguards (e.g., backups, rollback plans).
    • Performance: High-cardinality locales (e.g., 20+ languages) could degrade write performance due to increased column count.
    • Locale Management: No built-in locale validation or management (e.g., enforcing ISO 639-1 codes). Custom logic may be needed.
  • Mitigation:
    • Use feature flags or database views to isolate changes during migration.
    • Limit translatable fields to critical attributes (e.g., avoid translating created_at).
    • Pair with a locale management package (e.g., laravel-localization) if needed.

Key Questions

  1. Locale Strategy:
    • How will locales be determined (e.g., user session, URL parameter, header)? Does the package support dynamic locale switching?
  2. Fallback Behavior:
    • What happens if a translation is missing for a locale? Will you implement a fallback (e.g., default to en)?
  3. Querying Translations:
    • How will you handle queries filtering by translated content (e.g., search)? Will you use raw SQL or a scope?
  4. Testing:
    • Are there existing tests for edge cases (e.g., concurrent updates, partial saves)?
  5. Alternatives:
    • Why not use Spatie’s package? Does this package offer a critical advantage (e.g., simpler schema, better performance)?
  6. Future-Proofing:
    • How will you handle adding/removing locales post-launch? Will schema migrations be automated?

Integration Approach

Stack Fit

  • Ideal For:
    • Projects with static, known locales (e.g., 3–5 languages) and simple translation needs (e.g., product names, descriptions).
    • Teams prioritizing database simplicity over query flexibility.
    • Applications where translations are not query-heavy (e.g., CMS content, marketing pages).
  • Less Ideal For:
    • Highly multilingual apps (e.g., 10+ locales) due to schema bloat.
    • Systems requiring complex translation queries (e.g., full-text search across locales).
    • Projects using polymorphic translations or hierarchical data.

Migration Path

  1. Assessment Phase:
    • Audit existing models to identify translatable fields.
    • Define supported locales (e.g., ['en', 'nl', 'fr']).
  2. Schema Migration:
    • Add underscore-suffixed columns to target tables (e.g., title_en, title_nl).
    • Example migration:
      Schema::table('posts', function (Blueprint $table) {
          $table->string('title_en')->nullable()->after('title');
          $table->string('title_nl')->nullable()->after('title_en');
      });
      
    • For large tables, consider a zero-downtime migration (e.g., add columns, backfill data, then enable the trait).
  3. Model Integration:
    • Apply the UnderscoreTranslatable trait and define $translatable.
    • Example:
      class Post extends Model {
          use UnderscoreTranslatable;
          public $translatable = ['title', 'description'];
      }
      
  4. Data Backfill:
    • Write a script to populate existing data into translatable columns (e.g., copy title to title_en).
    • Example:
      Post::query()->each(function ($post) {
          $post->setTranslations(['en' => ['title' => $post->title]]);
          $post->save();
      });
      
  5. Testing:
    • Validate CRUD operations with translations.
    • Test edge cases (e.g., saving partial translations, locale-specific validation).

Compatibility

  • Laravel Versions:
    • Confirmed compatibility with Laravel 10+. Test with your version (e.g., 11.x may need adjustments).
  • Database Drivers:
    • Works with MySQL, PostgreSQL, SQLite. Test with your primary database.
  • Dependencies:
    • No hard dependencies beyond Laravel core. Verify no conflicts with other packages (e.g., Spatie’s translatable).
  • Caching:
    • Translations are stored in the database; no caching layer is provided. Consider caching translated attributes if performance is critical.

Sequencing

  1. Phase 1 (MVP):
    • Implement for non-critical models (e.g., blog posts, static pages).
    • Use a single locale (e.g., en) to validate the pattern.
  2. Phase 2 (Scaling):
    • Add additional locales (e.g., nl, fr).
    • Implement fallback logic (e.g., default to en if nl is missing).
  3. Phase 3 (Optimization):
    • Add scopes for querying translations (e.g., Post::whereTranslation('title', 'en', 'foo')).
    • Explore caching strategies for translated attributes.

Operational Impact

Maintenance

  • Pros:
    • Simple Maintenance: No complex JSON parsing or serialization. Translations are stored as plain columns.
    • Database-Level Backups: Easier to back up/restore compared to JSON-based solutions.
    • Tooling Support: Standard SQL tools (e.g., ALTER TABLE, EXPLAIN) work out of the box.
  • Cons:
    • Schema Changes: Adding/removing locales requires database migrations.
    • No Built-in Validation: Must manually validate locale codes (e.g., prevent title_xx).
    • Partial Updates: Saving only one locale at a time requires careful handling to avoid overwriting other locales.

Support

  • Pros:
    • Debugging: Errors are easier to trace (e.g., Column 'title_en' not found).
    • Community: Inspired by Spatie’s package; similar issues may have existing solutions.
  • Cons:
    • Limited Documentation: README is concise; may need to document custom logic (e.g., fallback behavior).
    • No Official Support: MIT license implies community-driven support. Plan for internal documentation or paid support if critical.
    • Edge Cases: Support for dynamic locales or runtime locale switching may require custom code.

Scaling

  • Performance:
    • Reads: Fast for single-locale access (e.g., SELECT title_en FROM posts).
    • Writes: Slower for multi-locale updates (e.g., updating 5 columns vs. 1). Consider batching updates.
    • Database Size: Grows linearly with locales × translatable fields. Monitor table bloat.
  • Horizontal Scaling:
    • No inherent limitations, but ensure your database can handle the increased column count.
    • Consider read replicas if queries become heavy.
  • Caching:
    • Cache translated attributes at the application level (e.g., Redis) to reduce database load:
      public function getTitleAttribute($value) {
          $locale = app()->getLocale();
          return cache()->remember("post.{$this->id}.title.{$locale}", now()->addHours(1), function () {
              return $this->{"title_{$locale
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle