-
-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4396600
commit 9f834d2
Showing
10 changed files
with
555 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Installation | ||
|
||
### Install package | ||
|
||
Add the package in your `composer.json` by executing the command. | ||
|
||
```bash | ||
composer require astrotomic/laravel-translatable | ||
``` | ||
|
||
### Configuration | ||
|
||
We copy the configuration file to our project. | ||
|
||
```bash | ||
php artisan vendor:publish --tag=translatable | ||
``` | ||
|
||
{% hint style="info" %} | ||
There isn't any restriction for the format of the locales. Feel free to use whatever suits you better, like "eng" instead of "en", or "el" instead of "gr". The important is to define your locales and stick to them. | ||
{% endhint %} | ||
|
||
### Migrations | ||
|
||
In this example, we want to translate the model `Post`. We will need an extra table `post_translations`: | ||
|
||
{% code-tabs %} | ||
{% code-tabs-item title="create\_posts\_table.php" %} | ||
```php | ||
Schema::create('posts', function(Blueprint $table) { | ||
$table->increments('id'); | ||
$table->string('author'); | ||
$table->timestamps(); | ||
}); | ||
``` | ||
{% endcode-tabs-item %} | ||
{% endcode-tabs %} | ||
|
||
{% code-tabs %} | ||
{% code-tabs-item title="create\_post\_translations\_table" %} | ||
```php | ||
Schema::create('post_translations', function(Blueprint $table) { | ||
$table->increments('id'); | ||
$table->integer('post_id')->unsigned(); | ||
$table->string('locale')->index(); | ||
$table->string('title'); | ||
$table->text('content'); | ||
|
||
$table->unique(['post_id', 'locale']); | ||
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade'); | ||
}); | ||
``` | ||
{% endcode-tabs-item %} | ||
{% endcode-tabs %} | ||
|
||
### Models | ||
|
||
The translatable model `Post` should [use the trait](http://www.sitepoint.com/using-traits-in-php-5-4/) `Astrotomic\Translatable\Translatable`. The default convention for the translation model is `PostTranslation`. The array `$translatedAttributes` contains the names of the fields being translated in the `PostTranslation` model. | ||
|
||
{% code-tabs %} | ||
{% code-tabs-item title="Post.php" %} | ||
```php | ||
use Astrotomic\Translatable\Contracts\Translatable as TranslatableContract; | ||
use Astrotomic\Translatable\Translatable; | ||
|
||
class Post extends Model implements TranslatableContract | ||
{ | ||
use Translatable; | ||
|
||
public $translatedAttributes = ['title', 'content']; | ||
protected $fillable = ['author']; | ||
} | ||
``` | ||
{% endcode-tabs-item %} | ||
{% endcode-tabs %} | ||
|
||
{% code-tabs %} | ||
{% code-tabs-item title="PostTranslation.php" %} | ||
```php | ||
class PostTranslation extends Model | ||
{ | ||
public $timestamps = false; | ||
protected $fillable = ['title', 'content']; | ||
} | ||
``` | ||
{% endcode-tabs-item %} | ||
{% endcode-tabs %} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# Fallback locale | ||
|
||
## App wide | ||
|
||
If you want to fallback to a default translation when a translation has not been found, enable this in the configuration using the `use_fallback` key. And to select the default locale, use the `fallback_locale` key. | ||
|
||
```php | ||
[ | ||
// ... | ||
'use_fallback' => true, | ||
'fallback_locale' => 'en', | ||
// ... | ||
] | ||
``` | ||
|
||
## per Model | ||
|
||
You can also define per-model the default for "if fallback should be used", by setting the `$useTranslationFallback`property: | ||
|
||
```php | ||
class Post extends Model | ||
{ | ||
public $useTranslationFallback = true; | ||
} | ||
``` | ||
|
||
## for Properties | ||
|
||
Even though we try having all models nicely translated, some fields might left empty. What's the result? You end up with missing translations for those fields! | ||
|
||
The property fallback feature is here to help. When enabled, translatable will return the value of the fallback language for those empty properties. | ||
|
||
The feature is enabled by default on new installations. If your config file was setup before v7.1, make sure to add the following line to enable the feature: | ||
|
||
```php | ||
'use_property_fallback' => true, | ||
``` | ||
|
||
Of course the fallback locales must be enabled to use this feature. | ||
|
||
If the property fallback is enabled in the configuration, then translatable will return the translation of the fallback locale for the fields where the translation is empty. | ||
|
||
### **customize empty translation property detection** | ||
|
||
This package is made to translate strings, but in general it's also able to translate numbers, bools or whatever you want to. By default a simple `empty()` call is used to detect if the translation value is empty or not. If you want to customize this or use different logic per property you can override `isEmptyTranslatableAttribute()` in your main model. | ||
|
||
```php | ||
protected function isEmptyTranslatableAttribute(string $key, $value): bool | ||
{ | ||
switch($key) { | ||
case 'name': | ||
return empty($value); | ||
case 'price': | ||
return !is_number($value); | ||
default: | ||
return is_null($value); | ||
} | ||
} | ||
``` | ||
|
||
## **Country based fallback** | ||
|
||
Since version v5.3 it is possible to use country based locales. For example, you can have the following locales: | ||
|
||
* English: `en` | ||
* Spanish: `es` | ||
* Mexican Spanish: `es-MX` | ||
* Colombian Spanish: `es-CO` | ||
|
||
To configuration for these locales looks like this: | ||
|
||
```php | ||
'locales' => [ | ||
'en', | ||
'es' => [ | ||
'MX', | ||
'CO', | ||
], | ||
]; | ||
``` | ||
|
||
We can also configure the "glue" between the language and country. If for instance we prefer the format `es_MX` instead of `es-MX`, the configuration should look like this: | ||
|
||
```php | ||
'locale_separator' => '_', | ||
``` | ||
|
||
What applies for the fallback of the locales using the `en-MX` format? | ||
|
||
Let's say our fallback locale is `en`. Now, when we try to fetch from the database the translation for the locale `es-MX`but it doesn't exist, we won't get as fallback the translation for `en`. Translatable will use as a fallback `es` \(the first part of `es-MX`\) and only if nothing is found, the translation for `en` is returned. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Interface | ||
|
||
The package provides and interface `\Astrotomic\Translatable\Contracts\Translatable` which describes the public API. It could be that the trait defines more public methods but they aren't part of the defined public API and won't force a new major release if changed or removed. | ||
|
||
In addition to the interface we rely on the following methods which will, if changed or removed, also trigger a new major release. | ||
|
||
## protected Interface | ||
|
||
```php | ||
interface TranslatableProtected | ||
{ | ||
// detect if a given translation attribute value is empty or not | ||
protected function isEmptyTranslatableAttribute(string $key, $value): bool; | ||
|
||
// save all attached translations | ||
protected function saveTranslations(): bool; | ||
} | ||
``` | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# Locales helper | ||
|
||
In addition to the trait we also provide a helper class `\Astrotomic\Translatable\Locales` it's a singleton service available as `translatable.locales` and `\Astrotomic\Translatable\Locales` . | ||
This helper manages all locales available for translation and provides several methods. | ||
|
||
This class also implements the `ArrayAccess` interface to allow you to use it like a normal array. | ||
|
||
## Methods | ||
|
||
### load\(\) | ||
|
||
This method will \(re\)load all locales from the `translatable.locales` config - it's called during service instantiation so you will only need it if you change the config during runtime. | ||
|
||
{% hint style="info" %} | ||
If you don't have to do so to work with other packages we recommend to use the provided methods of this helper service to manipulate the available locales instead of changing the config during runtime. | ||
{% endhint %} | ||
|
||
### all\(\) | ||
|
||
**Alias:** `toArray()` | ||
|
||
Returns all available locales as an array - the structure differs from the config one, the return final generated array with combined country locales. | ||
|
||
```php | ||
[ | ||
'en', | ||
'de', | ||
'es', | ||
'es-MX', | ||
'es-CO', | ||
] | ||
``` | ||
|
||
### current\(\) | ||
|
||
Returns the current locale string. | ||
|
||
### has\(string $locale\) | ||
|
||
Checks if the given locale is available in the configured set of locales. | ||
|
||
### get\(string $locale\) | ||
|
||
Returns the provided locale or `null` if it's not set. | ||
|
||
{% hint style="info" %} | ||
At all this isn't really useful except you want to build your own check if a locale is set. | ||
{% endhint %} | ||
|
||
### add\(string $locale\) | ||
|
||
Adds the given locale to the set of available locales. | ||
|
||
{% hint style="info" %} | ||
The set of available locales will keep unique and this method won't throw an exception if the locale is already present. | ||
{% endhint %} | ||
|
||
### forget\(string $locale\) | ||
|
||
Removes the given locale of the available locales set. | ||
|
||
{% hint style="info" %} | ||
This method won't throw an exception if the locale isn't present. | ||
{% endhint %} | ||
|
||
### getLocaleSeparator\(\) | ||
|
||
Returns the configured `translatable.locale_separator` locale separator used to combine language with country locales. | ||
|
||
### getCountryLocale\(string $locale, string $country\) | ||
|
||
Returns the formatted country based locale. | ||
|
||
### isLocaleCountryBased\(string $locale\) | ||
|
||
Checks if the given locale is a country specific locale. | ||
|
||
### getLanguageFromCountryBasedLocale\(string $locale\) | ||
|
||
Returns the language locale from given country based locale. | ||
|
Oops, something went wrong.