Proyecto multilenguaje en Laravel usando base de datos
Image by Наталия Когут from Pixabay

En un tutorial pasado te mostré cómo crear un proyecto multi idioma en Laravel, ahora te enseñaré a crear un proyecto multilenguaje en Laravel usando una base de datos desde cero paso a paso, al final encontrarás el repositorio del tutorial. Sin más, manos a la obra.

Requisitos previos

  •  Entorno de desarrollo como Xamp o Laragon
  • Tener instalado globalmente composer
  • Editor de textos como VS Code

1. Crear proyecto Laravel nuevo

Para crear rápidamente un proyecto nuevo de Laravel usa composer abriendo la terminal de comandos y escribe:

composer create-project laravel/laravel multi-idioma-base-datos

Una vez que termine de crearse el proyecto en Laravel desde la terminal de comandos ingresa a la carpeta de nuevo proyecto.

2. Crear base de datos

Para crear una base de datos nueva para tu proyecto ingresa a la consola de mysql escribiendo en la terminal la instrucción:

mysql -u root -p

Accede con tus credenciales:

Escribe:

CREATE DATABASE multi_lenguaje CHARACTER SET utf8 COLLATE utf8_spanish_ci;

Para salir de la consola de mysql escribe ‘exit’ y luego oprime la tecla ‘Enter’.

Desde tu editor de texto ve a tu proyecto y abre el archivo .env y agrega la configuración de la base de datos como el nombre de la base de datos y la contraseña (en caso de tener):

Proyecto multilenguaje en Laravel usando base de datos

3. Crear modelo, migración y controlador

Para este proyecto estaré usando un modelo llamado Post con su migración y controlador, para crearlos escribe en la terminal el comando:

php artisan make:model Post -mc

4. Editar archivo de migración

Abre el archivo database/migrations/…create_posts_table.php:

Abre el nuevo archivo de migracion

Agrega los siguientes campos:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration

{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title_en')->nullable();
            $table->text('body_en')->nullable();

            $table->string('title_es')->nullable();
            $table->text('body_es')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */

    public function down()
    {
        Schema::dropIfExists('posts');
    }

};

La tabla ‘posts’ cuenta con los campos ‘title_es’ y ‘body_es’ en donde se guardará la información en español y ‘title_en’ y ‘body_en’ en donde se guardará las traducciones en inglés.
Ahora corre las migraciones desde la terminal de comandos:

php artisan migrate

corre las migraciones en Laravel desde terminal

5. Crear Middleware SetLocale y configurarlo

Para verificar en que idioma se tiene que traer la información que se encuentra en la base de datos tienes que crear el Middleware SetLocale, para ello en tu terminal de comandos escribe la siguiente instrucción:

php artisan make:middleware SetLocale

Con tu editor de textos abre el archivo App\Http\Middleware\SetLocale y agrega la lógica que necesita para funcionar correctamente:

public function handle(Request $request, Closure $next)
    {
        $language = 'en'; // default

        if (request('language')) {
            $language = request('language');
            session()->put('language', $language);
        } elseif (session('language')) {
            $language = session('language');
        }
        app()->setLocale($language);

        return $next($request);
    }
Proyecto multilenguaje en Laravel desde base de datos

Ve al archivo app/Http/Kernel.php y busca el array asociativo $routeMiddleware y agrega la siguiente línea de código:

\App\Http\Middleware\SetLocale::class,

Agregar la clase al array

6. Configurar modelo Post

Para habilitar la asignación masiva abre el archivo app/Models/Post.php y agrega la siguiente línea de código dentro de la clase Post:

protected $guarded = ['id'];

7. Crear rutas

En el archivo routes/web.php agrega las siguientes rutas:

Route::get('/', [Controller::class, 'index'])->name('index');
Route::resource('posts', PostController::class);

8. Configurar controlador

Ahora toca configurar los dos controladores que estas utilizando, ve a app/Http/Controllers/PostController.php y en la clase PostController agrega los siguientes métodos:

public function create(){
return view('posts.create');
}

public function show(){
return view('posts.show');
}

public function store(StorePostRequest $request){
Post::create($request->validated());
return redirect()->route('index');
}

public function edit(Post $post){
return view('posts.edit', compact('post'));
}

public function update(Request $request, Post $post){
$data = $request->validate([
'title_en' => 'required',
'body_en' => 'required',
'title_es' => 'required',
'body_es' => 'required'
]);

$post->title_en = $data['title_en'];
$post->body_en = $data['body_en'];
$post->title_es = $data['title_es'];
$post->body_es = $data['body_es'];

$post->save();

return redirect()->route('index');
}

public function destroy(Post $post, Request $request){
$post->delete();
return redirect()->route('index');
}

También configura el archivo app/Http/Controllers/Controller.php y agrega el método index:

public function index(){

$locale = app()->getLocale();

$posts = Post::select(['id', 'title_' . $locale, 'body_' . $locale])->latest()->where('title_' . $locale, '!=', '')->take(12)->get();

return view('posts.index', compact('posts'));
}

9. Crear form request

Para validar el formulario para crear un nuevo post vas a crear un form request, para ello desde la terminal escribe la instrucción:

php artisan make:request StorePostRequest

Abre el archivo app/Http/Requests/StorePostRequest.php y en el método rules agrega el siguiente código:

public function rules()
    {
        $rules  = [
            'title_en' => 'required',
            'body_en' => 'required'
        ];

        foreach (config('app.available_locales') as $locale){
            $rules['title_' . $locale] = 'string';
            $rules['body_' . $locale] = 'string';
        }
        return $rules;
    }

En el método authorize() en el return debe mandar un true, de otra manera va a dar un error de autorización.

10. Agregar idiomas soportados

Para agregar los idiomas que serán soportados por tu aplicación ve al archivo config/app.php y en apartado de idioma debajo de ‘locale’ => ‘en’ agrega la siguiente línea de código:

'available_locales' => ['en', 'es'],

Si quieres agregar más idiomas recuerda agregarlos en este archivo por ejemplo si quieres agregar el idioma Italiano agrega en el array ‘it’.

11. Crear vistas

Crea la carpteta resources/views/posts y dentro de la carpeta posts crea el archivo index.blade.php agrega el siguiente código:

@extends('layouts.app')

@section('title', 'Index')

@section('content')

<div class="col-12">

    @foreach ($posts as $post)
    <div class="card mt-3">
        <div class="card-body">
          <h5 class="card-title">{{ $post->{'title_'.app()->getLocale()} }}</h5>
          <p class="card-text">{{ substr($post->{'body_'.app()->getLocale()}, 0, 80) }}</p>
          <a href="{{ route('posts.edit') }}" class="btn btn-info">Editar</a>
          <a href="{{ route('posts.destroy') }}" class="btn btn-danger">Borrar</a>

        </div>

      </div>

    @endforeach

</div>

@endsection

Dentro de la misma carpeta crea el archivo create.blade.php:

@extends('layouts.app')

@section('title', 'Create')

@section('content')

    <div class="col-12">
        <div class="card mt-5">
            <div class="card-body">
                <h5 class="card-title">Crear nuevo post</h5>
                <form method="POST" action="{{ route('posts.store') }}">
                    @csrf
                    @foreach (config('app.available_locales') as $locale)
                        <div class="form-group">
                            <label for="title_{{ $locale }}">Titulo ({{ strtoupper($locale) }})</label>
                            <input type="text" class="form-control" name="title_{{ $locale }}" id="title_{{ $locale }}" value="{{ old('title_' . $locale) }}"
                                placeholder="Enter title">
                        </div>
                        <div class="form-group">
                            <label for="body_{{ $locale }}">Contenido ({{ strtoupper($locale) }})</label>
                            <textarea class="form-control" name="body_{{ $locale }}" id="body_{{ $locale }}">{{ old('body_' . $locale) }}</textarea>
                        </div>
                    @endforeach

                    <button type="submit" class="btn btn-primary">Guardar</button>
                </form>
            </div>
        </div>
    </div>

@endsection

También el crea el archivo edit.blade.php:

@extends('layouts.app')

@section('title', 'Edit')

@section('content')

<div class="col-12">
<div class="card mt-5">
<div class="card-body">
<h5 class="card-title">Editar post</h5>
<form action="{{ route('posts.update', $post->id) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group">
<label for="title_en">Titulo (EN)</label>
<input type="text" class="form-control" name="title_en" id="title_en" value="{{ $post->title_en}}"
placeholder="Enter title">
</div>
<div class="form-group">
<label for="body_en">Contenido (EN)</label>
<textarea class="form-control" name="body_en" id="body_en">{{ $post->body_en}}</textarea>
</div>

<div class="form-group">
<label for="title_es">Titulo (ES)</label>
<input type="text" class="form-control" name="title_es" id="title_es" value="{{ $post->title_es}}"
placeholder="Enter title">
</div>
<div class="form-group">
<label for="body_es">Contenido (ES)</label>
<textarea class="form-control" name="body_es" id="body_es">{{ $post->body_es}}</textarea>
</div>

<button type="submit" class="btn btn-primary">Guardar</button>
</form>

</div>
</div>
</div>

@endsection

Sal de la carpeta posts y crea la carpeta resources/views/layouts y dentro de layouts crea el archivo app.blade.php que será la plantilla de las vistas y agrega el siguiente código:

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <meta name="csrf-token" content="{{ csrf_token() }}">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <title>{{ config('app.name') }}</title>
  </head>

  <body>
    <div class="container">
        <div class="row">
            //contenido

            @yield('content')

        </div>
    </div>
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
  </body>
</html>

12. Probar proyecto

Para probar tu proyecto multilenguaje en Laravel desde una base de datos, en tu terminal de comandos escribe la instrucción:

php artisan serve

Abre tu navegador web y ve a la dirección http://127.0.0.1:8000 o localhost:8000 en donde ya puedes crear algunos post de prueba, en mi caso ya hice unas cuantas pruebas y todo funciona correctamente:

Conclusión

En este tutorial aprendiste una de las formas de cómo crear un proyecto multilenguaje en Laravel desde una base de datos, este tipo de traducciones se usa cuando el contenido que se quiere traducir es dinámico, para las traducciones estáticas puedes usar un archivo .json y puedes ver cómo hacerlo aquí. Si este tutorial te sirvió te invito a compartirlo en tus redes sociales para llegar a más personas y si tienes dudas o comentarios déjalos en la caja de comentarios, estaré al pendiente de ellos. Recibe un cordial saludo.

Repositorio del proyecto aquí

8 COMENTARIOS

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.