├── .gitignore ├── .styleci.yml ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml ├── src ├── AbstractTranslator.php ├── Contracts │ └── TranslatorInterface.php ├── Facades │ └── TranslatorFacade.php ├── Presenters │ └── ResultsCollection.php ├── Translator.php ├── WatsonTranslateServiceProvider.php └── config │ └── watson-translate.php └── tests ├── Mocks └── MockResponses.php └── TestTranslator.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | composer.lock 3 | composer.phar 4 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: laravel 2 | 3 | disabled: 4 | - concat_without_spaces 5 | 6 | enabled: 7 | - concat_with_spaces 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - '5.5' 5 | - '5.6' 6 | - '7.0' 7 | 8 | before_script: 9 | - composer self-update 10 | 11 | install: 12 | - composer install --prefer-source --no-interaction --dev 13 | 14 | script: vendor/bin/phpunit 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 FindBrok 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel 5 IBM Watson Translate 2 | [![SensioLabsInsight](https://insight.sensiolabs.com/projects/5383ddb7-8c07-433e-98c0-0cda2eedba76/big.png)](https://insight.sensiolabs.com/projects/5383ddb7-8c07-433e-98c0-0cda2eedba76) 3 | 4 | [![StyleCI](https://styleci.io/repos/50762162/shield?style=flat)](https://styleci.io/repos/50762162) 5 | [![Build Status](https://travis-ci.org/findbrok/laravel-watson-translate.svg?branch=master)](https://travis-ci.org/findbrok/laravel-watson-translate) 6 | [![Latest Stable Version](https://poser.pugx.org/findbrok/laravel-watson-translate/v/stable)](https://packagist.org/packages/findbrok/laravel-watson-translate) 7 | [![Total Downloads](https://poser.pugx.org/findbrok/laravel-watson-translate/downloads)](https://packagist.org/packages/findbrok/laravel-watson-translate) 8 | [![Latest Unstable Version](https://poser.pugx.org/findbrok/laravel-watson-translate/v/unstable)](https://packagist.org/packages/findbrok/laravel-watson-translate) 9 | [![License](https://poser.pugx.org/findbrok/laravel-watson-translate/license)](https://packagist.org/packages/findbrok/laravel-watson-translate) 10 | 11 | This package provides a simple api to perform translations using the IBM Watson Language Translation service. 12 | 13 | To get a better understanding of how this package works read the documentation for Watson Language Translation service first. 14 | 15 | - [Getting started with the Language Translation service](https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/language-translation/) 16 | - [API Explorer](https://watson-api-explorer.mybluemix.net/apis/language-translation-v2) 17 | - [API reference](https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/language-translation/api/v2/) 18 | 19 | ## Installation 20 | Begin by installing this package through Composer. 21 | 22 | ```php 23 | { 24 | "require": { 25 | "findbrok/laravel-watson-translate": "~1.0" 26 | } 27 | } 28 | ``` 29 | 30 | Add the WatsonTranslateServiceProvider to your providers array 31 | 32 | ```php 33 | // config/app.php 34 | 35 | 'providers' => [ 36 | ... 37 | FindBrok\WatsonTranslate\WatsonTranslateServiceProvider::class, 38 | ]; 39 | ``` 40 | 41 | ## Configuration 42 | 43 | First publish the configuration file 44 | 45 | ```php 46 | php artisan vendor:publish --provider="FindBrok\WatsonTranslate\WatsonTranslateServiceProvider" 47 | ``` 48 | 49 | Set your correct credentials and default configuration for using your IBM Watson Language translation service 50 | > config/watson-translate.php 51 | 52 | ## Usage 53 | 54 | Read the [Docs](https://github.com/findbrok/laravel-watson-translate/wiki) 55 | 56 | ## Credits 57 | 58 | [![Percy Mamedy](https://img.shields.io/badge/Author-Percy%20Mamedy-orange.svg)](https://twitter.com/PercyMamedy) 59 | 60 | Twitter: [@PercyMamedy](https://twitter.com/PercyMamedy) 61 |
62 | GitHub: [percymamedy](https://github.com/percymamedy) 63 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "findbrok/laravel-watson-translate", 3 | "description": "Use IBM Watson language translation service with laravel", 4 | "keywords": ["laravel", "ibm", "watson", "translation"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Percy Mamedy", 9 | "email": "percymamedy@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.5.0", 14 | "laravel/framework": "5.0 - 5.3", 15 | "findbrok/php-watson-api-bridge": "1.0.*" 16 | }, 17 | "require-dev": { 18 | "fzaninotto/faker": "~1.4", 19 | "phpunit/phpunit": "~4.0", 20 | "mockery/mockery": "0.9.*", 21 | "orchestra/testbench": "~3.0", 22 | "guzzlehttp/guzzle": "~5.3|~6.0|~6.2" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "FindBrok\\WatsonTranslate\\": "src/" 27 | } 28 | }, 29 | "autoload-dev": { 30 | "psr-4": { 31 | "FindBrok\\WatsonTranslate\\Tests\\": "tests/" 32 | } 33 | }, 34 | "extra": { 35 | "branch-alias": { 36 | "dev-master": "1.0.x-dev" 37 | } 38 | }, 39 | "minimum-stability": "dev", 40 | "prefer-stable": true 41 | } 42 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/AbstractTranslator.php: -------------------------------------------------------------------------------- 1 | 'application/json', 52 | ]; 53 | 54 | /** 55 | * Getting attributes. 56 | * 57 | * @param $variable 58 | * @return mixed 59 | */ 60 | public function __get($attribute) 61 | { 62 | //Attributes exists 63 | if (property_exists($this, $attribute)) { 64 | //return the attribute value 65 | return $this->$attribute; 66 | } 67 | //We return null 68 | } 69 | 70 | /** 71 | * Append Headers to request. 72 | * 73 | * @param array $headers 74 | * @return self 75 | */ 76 | public function appendHeaders($headers = []) 77 | { 78 | //Append headers 79 | $this->headers = collect($this->headers)->merge($headers)->all(); 80 | //Return calling object 81 | return $this; 82 | } 83 | 84 | /** 85 | * Return the headers used for making request. 86 | * 87 | * @return array 88 | */ 89 | private function getHeaders() 90 | { 91 | //Return headers 92 | return collect($this->headers)->merge([ 93 | 'X-Watson-Learning-Opt-Out' => config('watson-translate.x_watson_learning_opt_out'), 94 | ])->all(); 95 | } 96 | 97 | /** 98 | * Make a Bridge to Send API Request to Watson. 99 | * 100 | * @return \FindBrok\WatsonBridge\Bridge 101 | */ 102 | public function makeBridge() 103 | { 104 | return app()->make('WatsonTranslateBridge')->appendHeaders($this->getHeaders()); 105 | } 106 | 107 | /** 108 | * Return the results from API. 109 | * 110 | * @return string|null 111 | */ 112 | public function getResults() 113 | { 114 | return $this->results; 115 | } 116 | 117 | /** 118 | * Return Model id to Use. 119 | * 120 | * @return string|null 121 | */ 122 | public function getModelId() 123 | { 124 | return $this->modelId; 125 | } 126 | 127 | /** 128 | * Set the language code of the language 129 | * we are translating from. 130 | * 131 | * @param string $lang 132 | * @return self 133 | */ 134 | public function from($lang = '') 135 | { 136 | //Set the language from code 137 | $this->from = $lang; 138 | //return the translator 139 | return $this; 140 | } 141 | 142 | /** 143 | * Set the language code of the language 144 | * we are translating to. 145 | * 146 | * @param string $lang 147 | * @return self 148 | */ 149 | public function to($lang = '') 150 | { 151 | //Set the language to code 152 | $this->to = $lang; 153 | //return the translator 154 | return $this; 155 | } 156 | 157 | /** 158 | * Set the model id of the model we want to use 159 | * for translation, overrides to and from. 160 | * 161 | * @param string $modelName 162 | * @return self 163 | */ 164 | public function usingModel($modelName = '') 165 | { 166 | //Set the model id 167 | $this->modelId = ($modelName == '') ? 168 | config('watson-translate.models.default') : 169 | config('watson-translate.models.' . $modelName); 170 | //return the translator 171 | return $this; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/Contracts/TranslatorInterface.php: -------------------------------------------------------------------------------- 1 | collectResults()->get('translations')) > 0; 18 | } 19 | 20 | /** 21 | * Checks and see if we have multiple translations in the results. 22 | * 23 | * @return bool 24 | */ 25 | public function hasMoreThanOneTranslation() 26 | { 27 | return count($this->collectResults()->get('translations')) > 1; 28 | } 29 | 30 | /** 31 | * Returns the results of the response array. 32 | * 33 | * @return array|null 34 | */ 35 | public function arrayResults() 36 | { 37 | return json_decode($this->getResults(), true); 38 | } 39 | 40 | /** 41 | * Returns the results of the response as a collection. 42 | * 43 | * @return \Illuminate\Support\Collection 44 | */ 45 | public function collectResults() 46 | { 47 | return collect($this->arrayResults()); 48 | } 49 | 50 | /** 51 | * Returns only the translations from results. 52 | * 53 | * @param bool $asCollection 54 | * @return mixed 55 | */ 56 | public function getTranslation($asCollection = false) 57 | { 58 | //We have some translations 59 | if ($this->hasTranslations()) { 60 | //More than one 61 | if ($this->hasMoreThanOneTranslation()) { 62 | //Get only translations 63 | $translations = collect($this->collectResults()->get('translations'))->transform(function ($item) { 64 | return $item['translation']; 65 | }); 66 | //Return the translations as array or collection 67 | return $asCollection ? $translations : $translations->all(); 68 | } 69 | //Return the single translation as collection or string 70 | return $asCollection ? 71 | collect($this->collectResults()->get('translations')) : 72 | collect(collect($this->collectResults()->get('translations'))->first())->get('translation'); 73 | } 74 | //Nothing to return 75 | } 76 | 77 | /** 78 | * Return languages names only. 79 | * 80 | * @param bool $asCollection 81 | * @return array|\Illuminate\Support\Collection 82 | */ 83 | public function languagesNames($asCollection = false) 84 | { 85 | //Get languages name only 86 | $languagesName = collect($this->collectResults()->get('languages'))->transform(function ($item) { 87 | return isset($item['name']) ? $item['name'] : null; 88 | })->reject(function ($item) { 89 | return is_null($item); 90 | }); 91 | 92 | //No language 93 | if ($languagesName->count() == 0) { 94 | //we return null 95 | return; 96 | } 97 | 98 | //return languages as array or collection 99 | return $asCollection ? $languagesName : $languagesName->all(); 100 | } 101 | 102 | /** 103 | * Return languages codes only. 104 | * 105 | * @param bool $asCollection 106 | * @return array|\Illuminate\Support\Collection 107 | */ 108 | public function languagesCodes($asCollection = false) 109 | { 110 | //Get languages codes only 111 | $languagesCodes = collect($this->collectResults()->get('languages'))->transform(function ($item) { 112 | return isset($item['language']) ? $item['language'] : null; 113 | })->reject(function ($item) { 114 | return is_null($item); 115 | }); 116 | 117 | //No language 118 | if ($languagesCodes->count() == 0) { 119 | //we return null 120 | return; 121 | } 122 | 123 | //return languages as array or collection 124 | return $asCollection ? $languagesCodes : $languagesCodes->all(); 125 | } 126 | 127 | /** 128 | * Get the language with the highest level of 129 | * confidence. 130 | * 131 | * @return array|\Illuminate\Support\Collection 132 | */ 133 | public function bestGuess($asCollection = false) 134 | { 135 | //Get the language with the highest score 136 | $highestScore = collect($this->collectResults()->get('languages'))->reduce(function ($results, $item) { 137 | //return item with highest score 138 | return ($item['confidence'] >= $results['confidence']) ? $item : $results; 139 | }, ['confidence' => 0]); 140 | 141 | //Return array or collection 142 | return $asCollection ? collect($highestScore) : $highestScore; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Translator.php: -------------------------------------------------------------------------------- 1 | results = $this->makeBridge()->get('v2/translate', collect([ 24 | 'model_id' => $this->getModelId(), 25 | 'source' => $this->from, 26 | 'target' => $this->to, 27 | 'text' => $text, 28 | ])->reject(function ($item) { 29 | return is_null($item) || empty($item); 30 | })->all())->getBody()->getContents(); 31 | //Return translator object 32 | return $this; 33 | } 34 | 35 | /** 36 | * Translate a large text from the source language to the target language. 37 | * Also used to translate multiple paragraphs or multiple inputs. 38 | * 39 | * @param string|array $text 40 | * @throws WatsonBridgeException 41 | * @return self 42 | */ 43 | public function bulkTranslate($text) 44 | { 45 | //Send request to Watson 46 | $this->results = $this->makeBridge()->post('v2/translate', collect([ 47 | 'model_id' => $this->getModelId(), 48 | 'source' => $this->from, 49 | 'target' => $this->to, 50 | 'text' => $text, 51 | ])->reject(function ($item) { 52 | return is_null($item) || empty($item); 53 | })->all())->getBody()->getContents(); 54 | //Return translator object 55 | return $this; 56 | } 57 | 58 | /** 59 | * List all languages that can be identified by watson. 60 | * 61 | * @throws WatsonBridgeException 62 | * @return self 63 | */ 64 | public function listLanguages() 65 | { 66 | //Send request to Watson 67 | $this->results = $this->makeBridge() 68 | ->get('v2/identifiable_languages') 69 | ->getBody() 70 | ->getContents(); 71 | //Return translator object 72 | return $this; 73 | } 74 | 75 | /** 76 | * Identify the language in which the text is written 77 | * with a certain level of confidence. 78 | * 79 | * @param string $text 80 | * @throws WatsonBridgeException 81 | * @return self 82 | */ 83 | public function identifyLanguage($text) 84 | { 85 | //Send request to Watson 86 | $this->results = $this->makeBridge() 87 | ->post('v2/identify', ['text' => $text], 'query') 88 | ->getBody() 89 | ->getContents(); 90 | //Return translator object 91 | return $this; 92 | } 93 | 94 | /** 95 | * Lists available standard and custom models by source or target language. 96 | * 97 | * @param bool $defaultOnly 98 | * @param string $sourceFilter 99 | * @param string $targetFilter 100 | * @throws WatsonBridgeException 101 | * @return self 102 | */ 103 | public function listModels($defaultOnly = null, $sourceFilter = null, $targetFilter = null) 104 | { 105 | //Send request to Watson 106 | $this->results = $this->makeBridge() 107 | ->get('v2/models', collect([ 108 | 'source' => $sourceFilter, 109 | 'target' => $targetFilter, 110 | 'default' => $defaultOnly, 111 | ])->reject(function ($item) { 112 | return is_null($item) || empty($item); 113 | })->all())->getBody()->getContents(); 114 | //Return translator object 115 | return $this; 116 | } 117 | 118 | /** 119 | * Returns information, including training status, about a specified translation model. 120 | * 121 | * @throws WatsonBridgeException 122 | * @return self 123 | */ 124 | public function getModelDetails() 125 | { 126 | //Send request to Watson 127 | $this->results = $this->makeBridge() 128 | ->get('v2/models/' . $this->getModelId()) 129 | ->getBody() 130 | ->getContents(); 131 | //Return translator object 132 | return $this; 133 | } 134 | 135 | /** 136 | * Creates a new translation model. 137 | * 138 | * @param string $baseModelId 139 | * @param string $modelName 140 | * @return self 141 | */ 142 | public function createModel($baseModelId = null, $modelName = null) 143 | { 144 | //Send request to Watson 145 | $this->results = $this->makeBridge() 146 | ->post('v2/models', collect([ 147 | [ 148 | 'name' => 'base_model_id', 149 | 'contents' => $baseModelId, 150 | ], 151 | [ 152 | 'name' => 'name', 153 | 'contents' => $modelName, 154 | ], 155 | ])->reject(function ($item) { 156 | return is_null($item) || empty($item); 157 | })->all(), 'multipart')->getBody()->getContents(); 158 | //Return translator object 159 | return $this; 160 | } 161 | 162 | /** 163 | * Delete a translation model. 164 | * 165 | * @param string $modelId 166 | * @throws WatsonBridgeException 167 | * @return self 168 | */ 169 | public function deleteModel($modelId = null) 170 | { 171 | //Send request to Watson 172 | $this->results = $this->makeBridge() 173 | ->delete('v2/models/' . $modelId, null) 174 | ->getBody()->getContents(); 175 | //Return translator object 176 | return $this; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/WatsonTranslateServiceProvider.php: -------------------------------------------------------------------------------- 1 | TranslatorFacade::class, 23 | ]; 24 | 25 | /** 26 | * Bootstrap the application services. 27 | * 28 | * @return void 29 | */ 30 | public function boot() 31 | { 32 | //Publish config file 33 | $this->publishes([ 34 | __DIR__ . '/config/watson-translate.php' => config_path('watson-translate.php'), 35 | ], 'config'); 36 | } 37 | 38 | /** 39 | * Register the application services. 40 | * 41 | * @return void 42 | */ 43 | public function register() 44 | { 45 | //Merge config file 46 | $this->mergeConfigFrom(__DIR__ . '/config/watson-translate.php', 'watson-translate'); 47 | //Register Bindings 48 | $this->registerBinding(); 49 | //Add Facades to the Translator service 50 | $this->registerFacades(); 51 | } 52 | 53 | /** 54 | * Register all bindings in the IOC. 55 | * 56 | * @return void 57 | */ 58 | public function registerBinding() 59 | { 60 | //Bind Implementation of the Translator interface 61 | $this->app->bind(TranslatorInterface::class, config('watson-translate.translator_implementation')); 62 | 63 | //Bind WatsonBridge for WatsonTranslate that we depend on 64 | $this->app->bind('WatsonTranslateBridge', function () { 65 | //Return bridge 66 | return new Bridge( 67 | config('watson-translate.service_credentials.username'), 68 | config('watson-translate.service_credentials.password'), 69 | config('watson-translate.api_endpoint') 70 | ); 71 | }); 72 | } 73 | 74 | /** 75 | * Registers all facades. 76 | * 77 | * @return void 78 | */ 79 | public function registerFacades() 80 | { 81 | //Register all facades 82 | collect($this->facades)->each(function ($facadeClass, $alias) { 83 | //Add Facade 84 | $this->app->booting(function () use ($alias, $facadeClass) { 85 | //Get loader instance 86 | $loader = AliasLoader::getInstance(); 87 | //Add alias 88 | $loader->alias($alias, $facadeClass); 89 | }); 90 | }); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/config/watson-translate.php: -------------------------------------------------------------------------------- 1 | [ 15 | 'username' => env('WATSON_TRANSLATE_USERNAME', 'SomeUsername'), 16 | 'password' => env('WATSON_TRANSLATE_PASSWORD', 'SomePassword'), 17 | ], 18 | 19 | /* 20 | |-------------------------------------------------------------------------- 21 | | API EndPoint 22 | |-------------------------------------------------------------------------- 23 | | 24 | | Set api endpoint for Watson Language Translation service 25 | | 26 | */ 27 | 'api_endpoint' => env('WATSON_TRANSLATE_API_ENDPOINT', 'https://gateway.watsonplatform.net/language-translation/api/'), 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | X-Watson-Learning-Opt-Out 32 | |-------------------------------------------------------------------------- 33 | | 34 | | By default, Watson collects data from all requests and uses the 35 | | data to improve the service. If you do not want to share 36 | | your data, set this value to true. 37 | | 38 | */ 39 | 'x_watson_learning_opt_out' => false, 40 | 41 | /* 42 | |-------------------------------------------------------------------------- 43 | | Translator Implementation 44 | |-------------------------------------------------------------------------- 45 | | 46 | | By default the interface is implemented by FindBrok\WatsonTranslate\Translator 47 | | Change this value to your own implementation if you wish to override the 48 | | implementation of the Translator interface 49 | | 50 | */ 51 | 'translator_implementation' => 'FindBrok\WatsonTranslate\Translator', 52 | 53 | /* 54 | |-------------------------------------------------------------------------- 55 | | Translations Models 56 | |-------------------------------------------------------------------------- 57 | | 58 | | Here you may specify a name to give to each Watson Language translation 59 | | Service models to be used. You will use these model names 60 | | instead of their id when performing translations. 61 | | Feel free to add as many models as you want 62 | | and give any name that you see fit. 63 | | 64 | */ 65 | 'models' => [ 66 | 'default' => env('WATSON_TRANSLATE_DEFAULT_MODEL', 'en-fr'), 67 | ], 68 | ]; 69 | -------------------------------------------------------------------------------- /tests/Mocks/MockResponses.php: -------------------------------------------------------------------------------- 1 | faker = Faker::create(); 29 | } 30 | 31 | /** 32 | * Mock a response for text translate function. 33 | * 34 | * @return GuzzleHttp\Psr7\Response 35 | */ 36 | public function pretendTextTranslateResponse() 37 | { 38 | //New sentence 39 | $sentence = 'Lorem ipsum'; 40 | //Build a new successful response for text translate 41 | return new Response(202, [ 42 | 'Content-Type' => 'application/json', 43 | ], collect([ 44 | 'translations' => [ 45 | ['translation' => $sentence], 46 | ], 47 | 'word_count' => count(explode(' ', $sentence)), 48 | 'character_count' => strlen($sentence), 49 | ])->toJson()); 50 | } 51 | 52 | /** 53 | * Mock a raw json results for text translate function. 54 | * 55 | * @return string 56 | */ 57 | public function pretendTextTranslateRaw() 58 | { 59 | return $this->pretendTextTranslateResponse()->getBody()->getContents(); 60 | } 61 | 62 | /** 63 | * Mock a response for the bulk translate function. 64 | * 65 | * @return GuzzleHttp\Psr7\Response 66 | */ 67 | public function pretendBulkTranslateResponse() 68 | { 69 | //Build a new successful response for bulk translate 70 | return new Response(202, [ 71 | 'Content-Type' => 'application/json', 72 | ], collect([ 73 | 'translations' => [ 74 | ['translation' => 'Lorem ipsum'], 75 | ['translation' => 'Lorem nam dolor'], 76 | ], 77 | 'word_count' => 100, 78 | 'character_count' => 200, 79 | ])->toJson()); 80 | } 81 | 82 | /** 83 | * Mock a raw json results for Bulk translate. 84 | * 85 | * @return string 86 | */ 87 | public function pretendBulkTranslateRaw() 88 | { 89 | //Return content of pretended response 90 | return $this->pretendBulkTranslateResponse()->getBody()->getContents(); 91 | } 92 | 93 | /** 94 | * Mock a response list languages. 95 | * 96 | * @return GuzzleHttp\Psr7\Response 97 | */ 98 | public function pretendListLanguages() 99 | { 100 | //Build a new successful response for list languages 101 | return new Response(202, [ 102 | 'Content-Type' => 'application/json', 103 | ], collect([ 104 | 'languages' => [ 105 | ['language' => 'af', 'name' => 'Afrikaans'], 106 | ['language' => 'ar', 'name' => 'Arabic'], 107 | ['language' => 'az', 'name' => 'Azerbaijani'], 108 | ['language' => 'en', 'name' => 'English'], 109 | ['language' => 'fr', 'name' => 'French'], 110 | ], 111 | ])->toJson()); 112 | } 113 | 114 | /** 115 | * Mock a response for identify language. 116 | * 117 | * @return GuzzleHttp\Psr7\Response 118 | */ 119 | public function pretendIdentifyLanguage() 120 | { 121 | //Build a new successful response for identify languages 122 | return new Response(202, [ 123 | 'Content-Type' => 'application/json', 124 | ], collect([ 125 | 'languages' => [ 126 | ['language' => 'af', 'confidence' => $this->faker->randomFloat(null, 0.0001, 0.9999)], 127 | ['language' => 'ar', 'confidence' => $this->faker->randomFloat(null, 0.0001, 0.9999)], 128 | ['language' => 'az', 'confidence' => $this->faker->randomFloat(null, 0.0001, 0.9999)], 129 | ['language' => 'en', 'confidence' => $this->faker->randomFloat(null, 0.0001, 0.9999)], 130 | ['language' => 'fr', 'confidence' => $this->faker->randomFloat(null, 0.0001, 0.9999)], 131 | ], 132 | ])->toJson()); 133 | } 134 | 135 | /** 136 | * Mock a response for model details. 137 | * 138 | * @return GuzzleHttp\Psr7\Response 139 | */ 140 | public function pretendListModels() 141 | { 142 | //Build a new successful response for models list 143 | return new Response(202, [ 144 | 'Content-Type' => 'application/json', 145 | ], collect([ 146 | 'models' => [ 147 | [ 148 | 'model_id' => 'ar-en', 149 | 'source' => 'ar', 150 | 'target' => 'en', 151 | 'base_model_id' => '', 152 | 'domain' => 'news', 153 | 'customizable' => true, 154 | 'default_model' => true, 155 | 'owner' => '', 156 | 'status' => 'available', 157 | 'name' => '', 158 | 'train_log' => null, 159 | ], 160 | [ 161 | 'model_id' => 'ar-en-conversational', 162 | 'source' => 'ar', 163 | 'target' => 'en', 164 | 'base_model_id' => '', 165 | 'domain' => 'conversational', 166 | 'customizable' => false, 167 | 'default_model' => false, 168 | 'owner' => '', 169 | 'status' => 'available', 170 | 'name' => '', 171 | 'train_log' => null, 172 | ], 173 | [ 174 | 'model_id' => 'arz-en', 175 | 'source' => 'arz', 176 | 'target' => 'en', 177 | 'base_model_id' => '', 178 | 'domain' => 'news', 179 | 'customizable' => true, 180 | 'default_model' => true, 181 | 'owner' => '', 182 | 'status' => 'available', 183 | 'name' => '', 184 | 'train_log' => null, 185 | ], 186 | ], 187 | ])->toJson()); 188 | } 189 | 190 | /** 191 | * Get Model details. 192 | * 193 | * @return GuzzleHttp\Psr7\Response 194 | */ 195 | public function pretendGetModelDetails() 196 | { 197 | //Build a new successful response for list languages 198 | return new Response(202, [ 199 | 'Content-Type' => 'application/json', 200 | ], collect([ 201 | 'model_id' => 'en-fr', 202 | 'source' => 'en', 203 | 'target' => 'fr', 204 | 'base_model_id' => '', 205 | 'domain' => 'news', 206 | 'customizable' => true, 207 | 'default_model' => true, 208 | 'owner' => '', 209 | 'status' => 'available', 210 | 'name' => '', 211 | 'train_log' => null, 212 | ])->toJson()); 213 | } 214 | 215 | /** 216 | * Mock a response for delete model. 217 | * 218 | * @return GuzzleHttp\Psr7\Response 219 | */ 220 | public function pretendDeleteModelResponse() 221 | { 222 | //Build a new successful response for delete model 223 | return new Response(200, [ 224 | 'Content-Type' => 'application/json', 225 | ], collect([ 226 | 'status' => 'OK', 227 | ])->toJson()); 228 | } 229 | 230 | /** 231 | * Mock a raw json results for delete model function. 232 | * 233 | * @return string 234 | */ 235 | public function pretendDeleteModelRaw() 236 | { 237 | return $this->pretendDeleteModelResponse()->getBody()->getContents(); 238 | } 239 | 240 | /** 241 | * Mock a response for create model. 242 | * 243 | * @return GuzzleHttp\Psr7\Response 244 | */ 245 | public function pretendCreateModelResponse() 246 | { 247 | //Build a new successful response for delete model 248 | return new Response(200, [ 249 | 'Content-Type' => 'application/json', 250 | ], collect([ 251 | 'model_id' => 'newModelId', 252 | ])->toJson()); 253 | } 254 | 255 | /** 256 | * Mock a raw json results for create model function. 257 | * 258 | * @return string 259 | */ 260 | public function pretendCreateModelRaw() 261 | { 262 | return $this->pretendCreateModelResponse()->getBody()->getContents(); 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /tests/TestTranslator.php: -------------------------------------------------------------------------------- 1 | mockResponses = new MockResponses; 49 | //Translator Class namespace 50 | $this->translatorClass = 'FindBrok\WatsonTranslate\Translator'; 51 | //Make translator 52 | $this->translator = app()->make($this->translatorClass); 53 | //Mock Watson Bridge 54 | $this->bridge = $this->getMockBuilder('FindBrok\WatsonBridge\Bridge') 55 | ->disableOriginalConstructor() 56 | ->setMethods(['post', 'get', 'delete']) 57 | ->getMock(); 58 | } 59 | 60 | /** 61 | * Get package providers. 62 | * 63 | * @param \Illuminate\Foundation\Application $app 64 | * @return array 65 | */ 66 | protected function getPackageProviders($app) 67 | { 68 | return ['FindBrok\WatsonTranslate\WatsonTranslateServiceProvider']; 69 | } 70 | 71 | /** 72 | * Test if the getter really returns the property 73 | * and that property is set. 74 | */ 75 | public function testSetterGetter() 76 | { 77 | $this->translator->from('en')->to('fr')->usingModel('default'); 78 | $this->assertEquals('en', $this->translator->from); 79 | $this->assertEquals('fr', $this->translator->to); 80 | $this->assertEquals(config('watson-translate.models.default'), $this->translator->modelId); 81 | } 82 | 83 | /** 84 | * Test that when a property does not exists getter 85 | * returns null. 86 | */ 87 | public function testPropertyInexistent_ReturnNull() 88 | { 89 | $this->assertNull($this->translator->foo); 90 | } 91 | 92 | /** 93 | * Test textTranslate with getTranslation method returns string. 94 | */ 95 | public function testTextTranslate_WithGetTranslation_ReturnString() 96 | { 97 | //Set return value of post method 98 | $this->bridge->method('get') 99 | ->withAnyParameters() 100 | ->willReturn($this->mockResponses->pretendTextTranslateResponse()); 101 | //Override Bridge in IOC 102 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 103 | 104 | //Fake Watson Bridge 105 | $this->assertEquals( 106 | 'Lorem ipsum', 107 | $this->translator->textTranslate('Lorem ipsum')->getTranslation() 108 | ); 109 | } 110 | 111 | /** 112 | * Test the textTranslate with rawResults method returns json. 113 | */ 114 | public function testTextTranslate_WithRawResults_ReturnJson() 115 | { 116 | //Set return value of post method 117 | $this->bridge->method('get') 118 | ->withAnyParameters() 119 | ->willReturn($this->mockResponses->pretendTextTranslateResponse()); 120 | //Override Bridge in IOC 121 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 122 | 123 | $this->assertJsonStringEqualsJsonString( 124 | $this->mockResponses->pretendTextTranslateRaw(), 125 | $this->translator->textTranslate('Lorem ipsum')->getResults() 126 | ); 127 | } 128 | 129 | /** 130 | * Test the textTranslate with arrayResults method returns array. 131 | */ 132 | public function testTextTranslate_WithArrayResults_ReturnArray() 133 | { 134 | //Set return value of post method 135 | $this->bridge->method('get') 136 | ->withAnyParameters() 137 | ->willReturn($this->mockResponses->pretendTextTranslateResponse()); 138 | //Override Bridge in IOC 139 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 140 | 141 | $this->assertEquals( 142 | json_decode($this->mockResponses->pretendTextTranslateRaw(), true), 143 | $this->translator->textTranslate('Lorem ipsum')->arrayResults() 144 | ); 145 | } 146 | 147 | /** 148 | * Test textTranslate with collectResults method returns collection. 149 | */ 150 | public function testTextTranslate_WithCollectionResults_ReturnCollection() 151 | { 152 | //Set return value of post method 153 | $this->bridge->method('get') 154 | ->withAnyParameters() 155 | ->willReturn($this->mockResponses->pretendTextTranslateResponse()); 156 | //Override Bridge in IOC 157 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 158 | 159 | $this->assertEquals( 160 | collect(json_decode($this->mockResponses->pretendTextTranslateRaw(), true)), 161 | $this->translator->textTranslate('Lorem ipsum')->collectResults() 162 | ); 163 | } 164 | 165 | /** 166 | * Test textTranslate throws WatsonBridgeException. 167 | * 168 | * @expectedException \FindBrok\WatsonBridge\Exceptions\WatsonBridgeException 169 | */ 170 | public function testTextTranslate_WithGetTranslation_ThrowsClientException_ReturnsNull() 171 | { 172 | //Set return value of post method 173 | $this->bridge->method('get') 174 | ->withAnyParameters() 175 | ->will($this->throwException(new \FindBrok\WatsonBridge\Exceptions\WatsonBridgeException('Foo', 400))); 176 | //Override Bridge in IOC 177 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 178 | 179 | $this->translator->textTranslate('lorem ipsum')->getTranslation(); 180 | } 181 | 182 | /** 183 | * Test the bulkTranslate method with getTranslation method returns string. 184 | */ 185 | public function testBulkTranslate_WithGetTranslation_ReturnArray() 186 | { 187 | //Set return value of post method 188 | $this->bridge->method('post') 189 | ->withAnyParameters() 190 | ->willReturn($this->mockResponses->pretendBulkTranslateResponse()); 191 | //Override Bridge in IOC 192 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 193 | 194 | $this->assertEquals( 195 | ['Lorem ipsum', 'Lorem nam dolor'], 196 | $this->translator->bulkTranslate(['lorem', 'nam'])->getTranslation() 197 | ); 198 | } 199 | 200 | /** 201 | * Test the bulkTranslate method with rawResults method returns json. 202 | */ 203 | public function testBulkTranslate_WithRawResults_ReturnJson() 204 | { 205 | //Set return value of post method 206 | $this->bridge->method('post') 207 | ->withAnyParameters() 208 | ->willReturn($this->mockResponses->pretendBulkTranslateResponse()); 209 | //Override Bridge in IOC 210 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 211 | 212 | $this->assertJsonStringEqualsJsonString( 213 | $this->mockResponses->pretendBulkTranslateRaw(), 214 | $this->translator->bulkTranslate(['lorem', 'nam'])->getResults() 215 | ); 216 | } 217 | 218 | /** 219 | * Test the bulkTranslate method with arrayResults method returns array. 220 | */ 221 | public function testBulkTranslate_WithArrayResults_ReturnArray() 222 | { 223 | //Set return value of post method 224 | $this->bridge->method('post') 225 | ->withAnyParameters() 226 | ->willReturn($this->mockResponses->pretendBulkTranslateResponse()); 227 | //Override Bridge in IOC 228 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 229 | 230 | $this->assertEquals( 231 | json_decode($this->mockResponses->pretendBulkTranslateRaw(), true), 232 | $this->translator->bulkTranslate(['lorem', 'nam'])->arrayResults() 233 | ); 234 | } 235 | 236 | /** 237 | * Test the bulkTranslate method with collectResults method returns collection. 238 | */ 239 | public function testBulkTranslate_WithCollectionResults_ReturnCollection() 240 | { 241 | //Set return value of post method 242 | $this->bridge->method('post') 243 | ->withAnyParameters() 244 | ->willReturn($this->mockResponses->pretendBulkTranslateResponse()); 245 | //Override Bridge in IOC 246 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 247 | 248 | $this->assertEquals( 249 | collect(json_decode($this->mockResponses->pretendBulkTranslateRaw(), true)), 250 | $this->translator->bulkTranslate(['lorem', 'nam'])->collectResults() 251 | ); 252 | } 253 | 254 | /** 255 | * Test the bulkTranslate method throws WatsonBridgeException. 256 | * 257 | * @expectedException \FindBrok\WatsonBridge\Exceptions\WatsonBridgeException 258 | */ 259 | public function testBulkTranslate_WithGetTranslation_ThrowsClientException_ReturnsNull() 260 | { 261 | //Set return value of post method 262 | $this->bridge->method('post') 263 | ->withAnyParameters() 264 | ->will($this->throwException(new \FindBrok\WatsonBridge\Exceptions\WatsonBridgeException('Foo', 400))); 265 | //Override Bridge in IOC 266 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 267 | 268 | $this->translator->bulkTranslate(['lorem', 'nam'])->getTranslation(); 269 | } 270 | 271 | /** 272 | * Test the deleteModel method throws WatsonBridgeException. 273 | * 274 | * @expectedException \FindBrok\WatsonBridge\Exceptions\WatsonBridgeException 275 | */ 276 | public function testDeleteModel_With_AnInvalidModelId_ThrowsClientException_ReturnsNull() 277 | { 278 | //Set return value of delete method 279 | $this->bridge->method('delete') 280 | ->withAnyParameters() 281 | ->will($this->throwException(new \FindBrok\WatsonBridge\Exceptions\WatsonBridgeException('InvalidUuidMessage', 400))); 282 | //Override Bridge in IOC 283 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 284 | 285 | $this->translator->deleteModel('invalid-uid'); 286 | } 287 | 288 | /** 289 | * Test the deleteModel method results in an OK status response. 290 | */ 291 | public function testDeleteModel_Results_In_An_OK_Status_Response() 292 | { 293 | //Set return value of delete method 294 | $this->bridge->method('delete') 295 | ->withAnyParameters() 296 | ->willReturn($this->mockResponses->pretendDeleteModelResponse()); 297 | //Override Bridge in IOC 298 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 299 | 300 | $this->assertEquals( 301 | collect(json_decode($this->mockResponses->pretendDeleteModelRaw(), true)), 302 | $this->translator->deleteModel('model-uid')->collectResults() 303 | ); 304 | } 305 | 306 | /** 307 | * Test the createModel method throws WatsonBridgeException. 308 | * 309 | * @expectedException \FindBrok\WatsonBridge\Exceptions\WatsonBridgeException 310 | */ 311 | public function testCreateModel_ThrowsClientException_ReturnsNull() 312 | { 313 | //Set return value of delete method 314 | $this->bridge->method('post') 315 | ->withAnyParameters() 316 | ->will($this->throwException(new \FindBrok\WatsonBridge\Exceptions\WatsonBridgeException('ErrorCreatingModel', 403))); 317 | //Override Bridge in IOC 318 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 319 | 320 | $this->translator->createModel('base_model_id', 'name'); 321 | } 322 | 323 | /** 324 | * Test the createModel method results contains new model id. 325 | */ 326 | public function testCreateModel_Results_Contains_The_New_Model_Id() 327 | { 328 | //Set return value of delete method 329 | $this->bridge->method('post') 330 | ->withAnyParameters() 331 | ->willReturn($this->mockResponses->pretendCreateModelResponse()); 332 | //Override Bridge in IOC 333 | $this->app->instance('WatsonTranslateBridge', $this->bridge); 334 | 335 | $this->assertEquals( 336 | collect(json_decode($this->mockResponses->pretendCreateModelRaw(), true)), 337 | $this->translator->createModel('base-model-id', 'name')->collectResults() 338 | ); 339 | } 340 | } 341 | --------------------------------------------------------------------------------