Skip to content

Commit

Permalink
Merge pull request #44 from fergthh/multilang
Browse files Browse the repository at this point in the history
Allow translate rules descriptions.
  • Loading branch information
mpociot authored Jun 20, 2016
2 parents 920308b + e198f3c commit e24c09b
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 38 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,18 @@ Option | Description
`noResponseCalls` | Disable API response calls
`actAsUserId` | The user ID to use for authenticated API response calls
`router` | The router to use, when processing the route files (can be Laravel or Dingo - defaults to Laravel)
`bindings` | List of route bindings that should be replaced when trying to retrieve route results. Syntax format: `binding_one,id|binding_two,id`
`bindings` | List of route bindings that should be replaced when trying to retrieve route results. Syntax format: `binding_one,id|binding_two,id`

## Publish rule descriptions for customisation or translate.

For default, this package returns the descriptions in the main language of the application. But provides the possibility of publish the language files for customisation or translate.

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

After to publish you can customize or translate the descriptions in the language you want by editing the files in `public/vendor/apidoc/resources/lang`.


### How does it work?

Expand Down
5 changes: 5 additions & 0 deletions src/Mpociot/ApiDoc/ApiDocGeneratorServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ class ApiDocGeneratorServiceProvider extends ServiceProvider
public function boot()
{
$this->loadViewsFrom(__DIR__.'/../../resources/views/', 'apidoc');
$this->loadTranslationsFrom(__DIR__.'/../../resources/lang', 'apidoc');

$this->publishes([
__DIR__.'/../../resources/lang' => resource_path('lang/vendor/apidoc'),
]);
}

/**
Expand Down
63 changes: 32 additions & 31 deletions src/Mpociot/ApiDoc/Generators/AbstractGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
namespace Mpociot\ApiDoc\Generators;

use Faker\Factory;
use ReflectionClass;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Mpociot\ApiDoc\Parsers\RuleDescriptionParser as Description;
use ReflectionClass;
use phpDocumentor\Reflection\DocBlock;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Http\FormRequest;

abstract class AbstractGenerator
{
Expand Down Expand Up @@ -196,110 +197,110 @@ protected function parseRule($rule, &$attributeData)
break;
case 'after':
$attributeData['type'] = 'date';
$attributeData['description'][] = 'Must be a date after: `'.date(DATE_RFC850, strtotime($parameters[0])).'`';
$attributeData['description'][] = Description::parse($rule)->with(date(DATE_RFC850, strtotime($parameters[0])))->getDescription();
$attributeData['value'] = date(DATE_RFC850, strtotime('+1 day', strtotime($parameters[0])));
break;
case 'alpha':
$attributeData['description'][] = 'Only alphabetic characters allowed';
$attributeData['description'][] = Description::parse($rule)->getDescription();
$attributeData['value'] = $faker->word;
break;
case 'alpha_dash':
$attributeData['description'][] = 'Allowed: alpha-numeric characters, as well as dashes and underscores.';
$attributeData['description'][] = Description::parse($rule)->getDescription();
break;
case 'alpha_num':
$attributeData['description'][] = 'Only alpha-numeric characters allowed';
$attributeData['description'][] = Description::parse($rule)->getDescription();
break;
case 'in':
$attributeData['description'][] = $this->fancyImplode($parameters, ', ', ' or ');
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
$attributeData['value'] = $faker->randomElement($parameters);
break;
case 'not_in':
$attributeData['description'][] = 'Not in: '.$this->fancyImplode($parameters, ', ', ' or ');
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
$attributeData['value'] = $faker->word;
break;
case 'min':
$attributeData['description'][] = 'Minimum: `'.$parameters[0].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'max':
$attributeData['description'][] = 'Maximum: `'.$parameters[0].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'between':
$attributeData['type'] = 'numeric';
$attributeData['description'][] = 'Between: `'.$parameters[0].'` and `'.$parameters[1].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
$attributeData['value'] = $faker->numberBetween($parameters[0], $parameters[1]);
break;
case 'before':
$attributeData['type'] = 'date';
$attributeData['description'][] = 'Must be a date preceding: `'.date(DATE_RFC850, strtotime($parameters[0])).'`';
$attributeData['description'][] = Description::parse($rule)->with(date(DATE_RFC850, strtotime($parameters[0])))->getDescription();
$attributeData['value'] = date(DATE_RFC850, strtotime('-1 day', strtotime($parameters[0])));
break;
case 'date_format':
$attributeData['type'] = 'date';
$attributeData['description'][] = 'Date format: `'.$parameters[0].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'different':
$attributeData['description'][] = 'Must have a different value than parameter: `'.$parameters[0].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'digits':
$attributeData['type'] = 'numeric';
$attributeData['description'][] = 'Must have an exact length of `'.$parameters[0].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
$attributeData['value'] = $faker->randomNumber($parameters[0], true);
break;
case 'digits_between':
$attributeData['type'] = 'numeric';
$attributeData['description'][] = 'Must have a length between `'.$parameters[0].'` and `'.$parameters[1].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'image':
$attributeData['type'] = 'image';
$attributeData['description'][] = 'Must be an image (jpeg, png, bmp, gif, or svg)';
$attributeData['description'][] = Description::parse($rule)->getDescription();
break;
case 'json':
$attributeData['type'] = 'string';
$attributeData['description'][] = 'Must be a valid JSON string.';
$attributeData['description'][] = Description::parse($rule)->getDescription();
$attributeData['value'] = json_encode(['foo', 'bar', 'baz']);
break;
case 'mimetypes':
case 'mimes':
$attributeData['description'][] = 'Allowed mime types: '.$this->fancyImplode($parameters, ', ', ' or ');
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
break;
case 'required_if':
$attributeData['description'][] = 'Required if `'.$parameters[0].'` is `'.$parameters[1].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'required_unless':
$attributeData['description'][] = 'Required unless `'.$parameters[0].'` is `'.$parameters[1].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'required_with':
$attributeData['description'][] = 'Required if the parameters '.$this->fancyImplode($parameters, ', ', ' or ').' are present.';
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
break;
case 'required_with_all':
$attributeData['description'][] = 'Required if the parameters '.$this->fancyImplode($parameters, ', ', ' and ').' are present.';
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' and '))->getDescription();
break;
case 'required_without':
$attributeData['description'][] = 'Required if the parameters '.$this->fancyImplode($parameters, ', ', ' or ').' are not present.';
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
break;
case 'required_without_all':
$attributeData['description'][] = 'Required if the parameters '.$this->fancyImplode($parameters, ', ', ' and ').' are not present.';
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' and '))->getDescription();
break;
case 'same':
$attributeData['description'][] = 'Must be the same as `'.$parameters[0].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'size':
$attributeData['description'][] = 'Must have the size of `'.$parameters[0].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'timezone':
$attributeData['description'][] = 'Must be a valid timezone identifier';
$attributeData['description'][] = Description::parse($rule)->getDescription();
$attributeData['value'] = $faker->timezone;
break;
case 'exists':
$attributeData['description'][] = 'Valid '.Str::singular($parameters[0]).' '.$parameters[1];
$attributeData['description'][] = Description::parse($rule)->with([Str::singular($parameters[0]), $parameters[1]])->getDescription();
break;
case 'active_url':
$attributeData['type'] = 'url';
$attributeData['value'] = $faker->url;
break;
case 'regex':
$attributeData['type'] = 'string';
$attributeData['description'][] = 'Must match this regular expression: `'.$parameters[0].'`';
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
break;
case 'boolean':
$attributeData['value'] = true;
Expand Down
68 changes: 68 additions & 0 deletions src/Mpociot/ApiDoc/Parsers/RuleDescriptionParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Mpociot\ApiDoc\Parsers;

class RuleDescriptionParser
{
private $rule;

private $parameters = [];

/**
* @param null $rule
*/
public function __construct($rule = null)
{
$this->rule = $rule;
}

/**
* @return array|string
*/
public function getDescription()
{
$key = "apidoc::rules.{$this->rule}";

$description = $this->parameters ? $this->translateWithAttributes($key) : trans($key);

return $description != $key ? $description : [];
}

/**
* @param string|array $parameters
*
* @return $this
*/
public function with($parameters)
{
is_array($parameters) ? $this->parameters += $parameters : $this->parameters[] = $parameters;

return $this;
}

/**
* @param $key
*
* @return string
*/
protected function translateWithAttributes($key)
{
$translate = trans($key);

foreach ($this->parameters as $parameter) {
$translate = preg_replace('/:attribute/', $parameter, $translate, 1);
}

return $translate;
}

/**
* @param null $rule
*
* @return static
*/
public static function parse($rule = null)
{
return new static($rule);
}
}
33 changes: 33 additions & 0 deletions src/resources/lang/en/rules.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

return [
'after' => 'Must be a date after: `:attribute`',
'alpha' => 'Only alphabetic characters allowed',
'alpha_dash' => 'Allowed: alpha-numeric characters, as well as dashes and underscores.',
'alpha_num' => 'Only alpha-numeric characters allowed',
'in' => ':attribute',
'not_in' => 'Not in: :attribute',
'min' => 'Minimum: `:attribute`',
'max' => 'Maximum: `:attribute`',
'between' => 'Between: `:attribute` and `:attribute`',
'before' => 'Must be a date preceding: `:attribute`',
'date_format' => 'Date format: `:attribute`',
'different' => 'Must have a different value than parameter: `:attribute`',
'digits' => 'Must have an exact length of `:attribute`',
'digits_between' => 'Must have a length between `:attribute` and `:attribute`',
'image' => 'Must be an image (jpeg, png, bmp, gif, or svg)',
'json' => 'Must be a valid JSON string.',
'mimetypes' => 'Allowed mime types: :attribute',
'mimes' => 'Allowed mime types: :attribute',
'required_if' => 'Required if `:attribute` is `:attribute`',
'required_unless' => 'Required unless `:attribute` is `:attribute`',
'required_with' => 'Required if the parameters :attribute are present.',
'required_with_all' => 'Required if the parameters :attribute are present.',
'required_without' => 'Required if the parameters :attribute are not present.',
'required_without_all' => 'Required if the parameters :attribute are not present.',
'same' => 'Must be the same as `:attribute`',
'size' => 'Must have the size of `:attribute`',
'timezone' => 'Must be a valid timezone identifier',
'exists' => 'Valid :attribute :attribute',
'regex' => 'Must match this regular expression: `:attribute`',
];
14 changes: 11 additions & 3 deletions tests/ApiDocGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
namespace Mpociot\ApiDoc\Tests;

use Illuminate\Routing\Route;
use Illuminate\Support\Facades\Route as RouteFacade;
use Mpociot\ApiDoc\ApiDocGeneratorServiceProvider;
use Mpociot\ApiDoc\Generators\LaravelGenerator;
use Orchestra\Testbench\TestCase;
use Mpociot\ApiDoc\Tests\Fixtures\TestRequest;
use Mpociot\ApiDoc\Tests\Fixtures\TestController;
use Illuminate\Support\Facades\Route as RouteFacade;
use Mpociot\ApiDoc\Tests\Fixtures\TestRequest;
use Orchestra\Testbench\TestCase;

class ApiDocGeneratorTest extends TestCase
{
Expand All @@ -16,6 +17,13 @@ class ApiDocGeneratorTest extends TestCase
*/
protected $generator;

protected function getPackageProviders($app)
{
return [
ApiDocGeneratorServiceProvider::class,
];
}

/**
* Setup the test environment.
*/
Expand Down
8 changes: 5 additions & 3 deletions tests/DingoGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
namespace Mpociot\ApiDoc\Tests;

use Dingo\Api\Provider\LaravelServiceProvider;
use Mpociot\ApiDoc\Tests\Fixtures\DingoTestController;
use Orchestra\Testbench\TestCase;
use Mpociot\ApiDoc\ApiDocGeneratorServiceProvider;
use Mpociot\ApiDoc\Generators\DingoGenerator;
use Mpociot\ApiDoc\Tests\Fixtures\TestRequest;
use Mpociot\ApiDoc\Tests\Fixtures\DingoTestController;
use Mpociot\ApiDoc\Tests\Fixtures\TestController;
use Mpociot\ApiDoc\Tests\Fixtures\TestRequest;
use Orchestra\Testbench\TestCase;

class DingoGeneratorTest extends TestCase
{
Expand All @@ -20,6 +21,7 @@ protected function getPackageProviders($app)
{
return [
LaravelServiceProvider::class,
ApiDocGeneratorServiceProvider::class,
];
}

Expand Down
Loading

0 comments on commit e24c09b

Please sign in to comment.