Skip to content

Commit

Permalink
Update everything
Browse files Browse the repository at this point in the history
  • Loading branch information
guidocella committed Sep 13, 2020
1 parent d67cdef commit e02983a
Show file tree
Hide file tree
Showing 19 changed files with 241 additions and 567 deletions.
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/.gitattributes export-ignore
/.gitignore export-ignore
phpunit.xml.dist export-ignore
/tests export-ignore
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/vendor
composer.lock
.idea/
phpunit.xml
.phpunit.result.cache
1 change: 1 addition & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# The MIT License (MIT)

Copyright (c) 2015 Mohamed Said <theMohamedSaid@gmail.com>
Copyright (c) 2020 Guido Cella <guidocella91@gmail.com>

> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
Expand Down
103 changes: 43 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,30 @@
# Laravel 5 Multilingual Models
# Laravel Multilingual Models

[![Latest Version on Packagist](https://img.shields.io/packagist/v/themsaid/laravel-multilingual.svg?style=flat-square)](https://packagist.org/packages/themsaid/laravel-multilingual)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
[![Total Downloads](https://img.shields.io/packagist/dt/themsaid/laravel-multilingual.svg?style=flat-square)](https://packagist.org/packages/themsaid/laravel-multilingual)
Make Eloquent model attributes translatable without separate database tables for translation values.

Simply access `$country->name` and you get a value based on your application's current locale.

This laravel package makes Eloquent Models attributes translatable without the need to separate database tables for translation values.
`$country->nameTranslations->en` will be the value of a specific locale.

You simply call `$country->name` and you get a value based on your application's current locale.

You can also call `$country->nameTranslations->en` to get the value of a specific locale.

You can check all the translations of a given attributes as easy as `$country->nameTranslations->toArray()`.
You can get all the translations of a given attributes with `$country->nameTranslations->toArray()`.

## Installation

Begin by installing the package through Composer. Run the following command in your terminal:
Install the package through Composer:

```
composer require themsaid/laravel-multilingual
```

Once composer is done, add the package service provider in the providers array in `config/app.php`

```
Themsaid\Multilingual\MultilingualServiceProvider::class
```sh
composer require guidocella/laravel-multilingual
```

Finally publish the config file:
Then publish the config file:

```
```sh
php artisan vendor:publish
```

That's all, you are now good to go.

# Usage

First you need to make sure that the translatable attributes has a mysql field type of text or json, if you are building the database from a migration file you may do this:
First make sure that the translatable attributes' field type is `text` or `json`. If you are building the database from a migration file you may do this:

```php
<?php
Expand All @@ -49,106 +36,102 @@ Schema::create('countries', function (Blueprint $table)
});
```

Now that you have the database ready to save a JSON string, you need to prepare your models:
Now that you have the database ready to save a JSON string, add the `Translatable` trait to your models and a public array property `$translatable` that holds the names of the translatable fields.

```php
<?php

class Country extends Model
{
use Themsaid\Multilingual\Translatable;
use GuidoCella\Multilingual\Translatable;

protected $table = 'countries';
public $translatable = ['name'];
public $casts = ['name' => 'array'];
}
```

- Add the `Translatable` trait to your model class
- Add a public class property `$translatable` as an array that holds the names of the translatable fields in your model.
- Remember to cast the translatable attribute as 'array' in the `$casts` property of the model.
The trait will override the `getCasts` method to instruct Eloquent to cast all `$translatable` attributes to `array` without having to specify them again in `$casts`.

Now our model has the `name` attribute translatable, so on creating a new Model you may specify the name field as follow:
Now that our model's `name` attribute is translatable, when creating a new model you may specify the name field as follows:

```php
<?php

Country::create([
'name' => [
'en' => "Spain",
'sp' => 'España'
'en' => 'Spain',
'es' => 'España'
]
]);
```

It'll be automatically converted to a JSON string and saved in the name field of the database, you can later retrieve the name like this:
It will be automatically converted to a JSON string and saved in the name field of the database. You can later retrieve the name like this:

```
```php
$country->name
```

This will return the country name based on the current locale, if the current locale doesn't have a value then the `fallback_locale` defined in the config file will be used.
This will return the country name based on the current locale. If the translation in the current locale doesn't have a non-null value then the `fallback_locale` defined in the config file will be used.

In case nothing can be found an empty string will be returned.
In case nothing can be found `null` will be returned.

You may also want to return the value for a specific locale, you can do that using the following syntax:
You may also want to return the value for a specific locale; you can do it using the following syntax:

```
```php
$country->nameTranslations->en
```

This will return the English name of the country.

To return an array of all the available translations you may use:

```
```php
$country->nameTranslations->toArray()
```

You can update the translation in a single locale with Eloquent's arrow syntax for JSON fields:

```php
$country->update(['name->'.App::getLocale() => 'Spain']);
```

# Validation
You can use the new array validation features released with laravel 5.2 to validate the presence of specific locales:

You can validate the presence of specific locales like so:

```php
<?php

$validator = Validator::make(
['name' => ['en'=>'One', 'sp'=>'Uno']],
$validator = validator(
['name' => ['en' => 'One', 'es' => 'Uno']],
['name.en' => 'required']
);
```

However a validation rule is included in this package that deals with requiring all the validations to be provided:
However, this package includes the `translatable_required` validation rule for requiring that the translations are provided in every locale:

```php
<?php

$validator = Validator::make(
['name' => ['en'=>'One', 'sp'=>'Uno']],
$validator = validator(
['name' => ['en' => 'One', 'es' => 'Uno']],
['name' => 'translatable_required']
);
```

The `translatable_required` rule will make sure all the values of the available locales are set.
You may define the available locales as well as the `fallback_locale` from the package config file.

You may define the available locales as well as the fallback_locale from the package config file.
Now you only need to add the translated message of our new validation rule: add this to the `validation.php` translation file:

Now you only need to add the translated message of our new validation rule, add this to the `validation.php` translation file:

```
```php
'translatable_required' => 'The :attribute translations must be provided.',
```

# Queries
If you're using MySQL 5.7 or above, it's recommended that you use the json data type for housing translations in the Database,
this will allow you to query these columns like this:

```php
Company::whereRaw('name->"$.en" = \'Monsters Inc.\'')->orderByRaw('specs->"$.founded_at"')->get();
```

However in laravel 5.2.23 and above you can use the fluent syntax:
Laravel lets you query JSON columns with the `->` operator:

```php
Company::where('name->en', 'Monsters Inc.')->orderBy('specs->founded_at')->get();
Company::where('name->en', 'Monsters Inc.')->first();

Country::orderBy('name->'.App::getLocale())->get();
```
34 changes: 15 additions & 19 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
{
"name": "themsaid/laravel-multilingual",
"description": "Easy multilingual laravel models",
"name": "guidocella/laravel-multilingual",
"description": "Easy multilingual Laravel models",
"keywords": ["laravel", "multilingual", "translation"],
"homepage": "https://github.com/themsaid/laravel-multilingual",
"homepage": "https://github.com/guidocella/laravel-multilingual",
"license": "MIT",
"authors": [
{
"name": "Mohamed Said",
"email": "theMohamedSaid@gmail.com"
}
],
"require": {
"illuminate/support": "^5.1||^6.0",
"php" : ">=5.3.0"
"illuminate/database": "^8",
"php" : ">=7.4"
},
"require-dev": {
"phpunit/phpunit" : "^8.0",
"orchestra/testbench": "^4.0"
"laravel/laravel": "^8",
"phpunit/phpunit" : "^9"
},
"autoload": {
"psr-4": {
"Themsaid\\Multilingual\\": "src"
},
"classmap": [
"tests"
]
"GuidoCella\\Multilingual\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"GuidoCella\\Multilingual\\": "tests"
}
},
"extra": {
"laravel": {
"providers": [
"Themsaid\\Multilingual\\MultilingualServiceProvider"
"GuidoCella\\Multilingual\\ServiceProvider"
]
}
}
Expand Down
16 changes: 0 additions & 16 deletions phpunit.xml

This file was deleted.

8 changes: 8 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="Eloquent Populator Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
56 changes: 0 additions & 56 deletions src/MultilingualServiceProvider.php

This file was deleted.

24 changes: 24 additions & 0 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace GuidoCella\Multilingual;

class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
public function boot(): void
{
$this->publishes([__DIR__.'/config/multilingual.php' => config_path('multilingual.php')]);

$this->app['validator']->extendImplicit('translatable_required', function ($attribute, $value, $parameters) {
if (!is_array($value)) {
return false;
}

return collect(config('multilingual.locales'))->every(fn ($locale) => !empty($value[$locale]));
});
}

public function register(): void
{
$this->mergeConfigFrom(__DIR__.'/config/multilingual.php', 'multilingual');
}
}
Loading

0 comments on commit e02983a

Please sign in to comment.