<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Omar Alalwi</title>
    <description>The latest articles on DEV Community by Omar Alalwi (@omar_alalwi).</description>
    <link>https://dev.to/omar_alalwi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2504227%2Fb068b705-053c-4833-8559-9641835cf378.jpg</url>
      <title>DEV Community: Omar Alalwi</title>
      <link>https://dev.to/omar_alalwi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omar_alalwi"/>
    <language>en</language>
    <item>
      <title>Simplifying Multilingual Models in Laravel with Lexi Translate</title>
      <dc:creator>Omar Alalwi</dc:creator>
      <pubDate>Sat, 30 Nov 2024 15:38:04 +0000</pubDate>
      <link>https://dev.to/omar_alalwi/simplifying-multilingual-models-in-laravel-with-lexi-translate-g4</link>
      <guid>https://dev.to/omar_alalwi/simplifying-multilingual-models-in-laravel-with-lexi-translate-g4</guid>
      <description>&lt;p&gt;&lt;strong&gt;Simplifying Multilingual Models in Laravel with Lexi Translate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Managing multilingual content in Laravel applications can often become cumbersome, especially when dealing with complex models and performance concerns. Enter &lt;strong&gt;Lexi Translate&lt;/strong&gt; – a lightweight and powerful package designed to simplify managing translations for multilingual Eloquent models.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore the features, setup, and usage of Lexi Translate, showcasing how it can help developers efficiently handle translations with caching, morph relationships, and more.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;What is Lexi Translate?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lexi Translate is a Laravel package that brings elegance and simplicity to managing translations for Eloquent models. It uses dynamic morph relationships to link translations, leverages caching for performance, and integrates seamlessly with Laravel's ORM.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Installing and Setting Up Lexi Translate&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To get started, install Lexi Translate via Composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require omaralalwi/lexi-translate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Publish the Configuration File&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Run the following command to publish the configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lexi-translate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Migration for the Translations Table&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Create the required database tables for translations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Getting Started with Lexi Translate&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Defining LexiTranslatable Models&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To use the package, include the &lt;code&gt;LexiTranslatable&lt;/code&gt; trait in your Eloquent models and define translatable attributes in the &lt;code&gt;$translatableFields&lt;/code&gt; array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\Model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Omaralalwi\LexiTranslate\Traits\LexiTranslatable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;LexiTranslatable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$translatableFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Updating or Creating Translations&lt;/strong&gt;
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Bulk Translations
&lt;/h5&gt;

&lt;p&gt;You can use the &lt;code&gt;setTranslations&lt;/code&gt; method to add or update multiple translations at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setTranslations&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'ar'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'العنوان باللغة العربية'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'الوصف باللغة العربية'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'en'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'English Title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Description in English'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Single Translation
&lt;/h5&gt;

&lt;p&gt;Alternatively, use &lt;code&gt;setTranslation&lt;/code&gt; to update a single field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'English Title'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ar'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'وصف باللغة العربية'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Translatable attributes don’t need to exist in the parent model’s schema.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Retrieving Translations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To fetch translations, use the &lt;code&gt;transAttr&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get title in the default app locale&lt;/span&gt;
&lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;transAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Get title in a specific locale&lt;/span&gt;
&lt;span class="nv"&gt;$titleInArabic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;transAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ar'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Frontend and Backend Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;h5&gt;
  
  
  Blade Example:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"{{ route('translations.store', $post-&amp;gt;id) }}"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    @csrf
    @foreach (lexi_locales() as $locale)
        &lt;span class="nt"&gt;&amp;lt;h4&amp;gt;&lt;/span&gt;{{ strtoupper($locale) }}&lt;span class="nt"&gt;&amp;lt;/h4&amp;gt;&lt;/span&gt;
        @foreach ($post-&amp;gt;getTranslatableFields() as $field)
            &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"{{ $field }}_{{ $locale }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ ucfirst($field) }} ({{ $locale }})&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"translations[{{ $locale }}][{{ $field }}]"&lt;/span&gt; 
                       &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{ $post-&amp;gt;transAttr($field, $locale) }}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        @endforeach
    @endforeach
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save Translations&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Controller Example:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TranslationsController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$translations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'translations'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$service&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setTranslations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$translations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;back&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Translations updated successfully!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Key Features&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Morph Relationships&lt;/strong&gt;: Manage translations across different models with ease.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Caching&lt;/strong&gt;: Improves performance by caching translations and automatically clearing them when updated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback Mechanism&lt;/strong&gt;: Falls back to the default language if a translation is missing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intuitive API&lt;/strong&gt;: Simple methods for adding, retrieving, and managing translations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Configurations&lt;/strong&gt;: Change table names and locales in the configuration file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in middlewares&lt;/strong&gt; to handle locale switching seamlessly for both web and API requests.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Comparing Lexi Translate with Spatie and Astrotomic&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While &lt;strong&gt;Spatie Laravel Translatable&lt;/strong&gt; and &lt;strong&gt;Astrotomic Laravel Translatable&lt;/strong&gt; are popular alternatives, Lexi Translate offers unique advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Relational Storage&lt;/strong&gt;: Uses a dedicated translations table with dynamic morph relationships for scalability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in Caching&lt;/strong&gt;: Ensures fast retrieval and automatic cache invalidation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic API&lt;/strong&gt;: Provides bulk translation methods and flexible configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support for Large Applications&lt;/strong&gt;: Excels in handling extensive multilingual content compared to JSON-based approaches.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;When to Choose Lexi Translate&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lexi Translate is ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applications managing large volumes of translations.&lt;/li&gt;
&lt;li&gt;Scenarios requiring high performance and caching.&lt;/li&gt;
&lt;li&gt;Projects needing translations for attributes outside the parent model's schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For smaller applications or simpler use cases, &lt;strong&gt;Spatie&lt;/strong&gt; or &lt;strong&gt;Astrotomic&lt;/strong&gt; may suffice.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lexi Translate simplifies multilingual content management in Laravel. Its dynamic relationships, robust caching, and scalability make it a top choice for developers building high-performance, multilingual applications. If JSON-based solutions feel limiting, Lexi Translate offers the flexibility and power you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ready to get started?&lt;/strong&gt; Install Lexi Translate today and elevate your multilingual applications!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
