├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── config └── geolocation.php ├── phpcs.xml ├── phpunit.xml ├── src ├── Console │ └── GeoLocationCommand.php ├── Contracts │ └── LookupInterface.php ├── GeoLocation.php ├── GeoLocationDetails.php ├── GeoLocationException.php ├── GeoLocationManager.php ├── GeoLocationServiceProvider.php └── Providers │ └── IpInfo.php ├── tests ├── ConfigTest.php ├── GeoLocationDetailsTest.php ├── GeoLocationManagerTest.php ├── GeoLocationTest.php ├── Providers │ └── IpInfoTest.php └── TestCase.php └── translations ├── en └── countries.php └── pt_BR └── countries.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 2 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.php] 15 | indent_size = 4 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /vendor/ 3 | .env 4 | .env.* 5 | *.lock 6 | .phpunit.result.cache 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 7.2 4 | - 7.3 5 | - 8.0 6 | - 8.1 7 | 8 | install: 9 | - composer install 10 | 11 | script: vendor/bin/phpunit 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | ### v1.2.0 5 | 6 | - 2023-03-07 - update version constraint for require-dev testbench package 7 | - 2023-03-07 - typo fix 8 | - 2023-03-07 - Merge pull request #6 from BrekiTomasson/dev-l10-compatibility 9 | 10 | ### v1.1.0 11 | 12 | - 2022-04-30 - update Travis config to support PHP `8.0` and `8.1`. 13 | - 2022-04-27 - added support for Laravel `^9.0`. 14 | 15 | ### v1.0.0 16 | 17 | - 2021-01-25 - fix composer requirements 18 | - 2021-01-25 - add return type declaration 19 | - 2021-01-25 - update README 20 | - 2021-01-25 - removed unused class 21 | - 2021-01-25 - upgrade testbench to 6.9 and guzzle to 7.0 22 | - 2021-01-25 - upgrade tests 23 | 24 | ### v0.3.0 25 | 26 | - 2019-11-15 - update requirement version constrain for laravel 7.0 and 8.0 27 | 28 | ### v0.2.0 29 | 30 | - 2019-11-15 - update requirement version constrain for laravel 6.* 31 | 32 | ### v0.1.3 33 | 34 | - 2019-08-29 - Removed DeferrableProvider interface, now the package is not deferred by default 35 | - 2019-08-29 - Add new Facade `GeoLocation::countries` method to get the translation list of countries codes 36 | 37 | ### v0.1.2 38 | 39 | - 2019-08-28 - Add TravisCI 40 | - 2019-08-28 - Add new method GeoLocationDetails::getCountryCode() 41 | 42 | ### v0.1.1 43 | 44 | - 2019-08-22 - Add support for laravel 6.0 45 | 46 | ### v0.1.0 47 | 48 | - 2019-08-13 - Initial Release 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2019, Adriano Rosa 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Adriano Rosa nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Laravel GeoLocation Package 2 | =========================== 3 | 4 | Laravel package to get the details about Region, City and Country for a given IP Address. 5 | 6 | This package is a wrapper for [IpInfo](https://ipinfo.io) Provider, however we have plan to implement a driver for 7 | MaxMind GeoIP2 databases. 8 | 9 | ### Install 10 | 11 | composer require adrianorosa/laravel-geolocation 12 | 13 | > This package supports the latest version of Laravel, for now 5.8+ was tested, but older versions should work fine. 14 | 15 | As of Laravel 5.5 there is no need to add the ServiceProvider within the `AppServiceProvider` array. 16 | Laravel loads this provider using Package Discovery. 17 | 18 | ### Usage 19 | 20 | There is no need to additional setup to start using, once you install it via composer you can call the Facade: 21 | 22 | ```php 23 | getIp(); 29 | // 8.8.8.8 30 | 31 | echo $details->getCity(); 32 | // Mountain View 33 | 34 | echo $details->getRegion(); 35 | // California 36 | 37 | echo $details->getCountry(); 38 | // United States 39 | 40 | echo $details->getLatitude(); 41 | // 37.386 42 | 43 | echo $details->getLongitude(); 44 | // -122.0838 45 | 46 | var_dump($details->toArray()); 47 | // Array 48 | // ( 49 | // [city] => Mountain View 50 | // [region] => California 51 | // [country] => United States 52 | // [countryCode] => US 53 | // [latitude] => 37.386 54 | // [longitude] => -122.0838 55 | //) 56 | ``` 57 | 58 | ### Console Command 59 | 60 | To display details about an Ip or Your current network Ip Address you may use the artisan command: 61 | 62 | ```bash 63 | php artisan geolocation:lookup --ip 8.8.8.8 64 | 65 | +---------+---------------+------------+----------------+-------------+----------+-----------+ 66 | | ip | city | region | country | countryCode | latitude | longitude | 67 | +---------+---------------+------------+----------------+-------------+----------+-----------+ 68 | | 8.8.8.8 | Mountain View | California | Estados Unidos | US | 37.386 | -122.0838 | 69 | +---------+---------------+------------+----------------+-------------+----------+-----------+ 70 | ``` 71 | 72 | ## Override Configuration and translations 73 | 74 | This package comes with a little configuration for IpInfo and translations for Country Names. 75 | 76 | You can stick with default values, which works fine, or publish using the following commands: 77 | 78 | Publish all config and translations 79 | 80 | php artisan vendor:publish 81 | 82 | Publish config 83 | 84 | php artisan vendor:publish --tag=geolocation-config 85 | 86 | Publish translations 87 | 88 | php artisan vendor:publish --tag=geolocation-translations 89 | 90 | 91 | ## Author 92 | 93 | **Adriano Rosa** (https://adrianorosa.com) 94 | 95 | ## Licence 96 | 97 | Copyright © 2021, Adriano Rosa 98 | All rights reserved. 99 | 100 | For the full copyright and license information, please view the LICENSE 101 | file that was distributed within the source root of this project. 102 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adrianorosa/laravel-geolocation", 3 | "description": "Laravel Geo Location package to get details for a given IP Address", 4 | "keywords": ["geolocation", "ipinfo", "geoip", "laravel", "laravel-geolocation"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Adriano Rosa", 9 | "email": "info@adrianorosa.com" 10 | } 11 | ], 12 | "minimum-stability": "dev", 13 | "require": { 14 | "php": ">=7.2", 15 | "ext-openssl": "*", 16 | "ext-json": "*", 17 | "illuminate/support": "~5.7.0|~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", 18 | "guzzlehttp/guzzle": "^6.0|^7.0" 19 | }, 20 | "require-dev": { 21 | "orchestra/testbench": "^7.4|^9.0", 22 | "phpunit/phpunit": "^9.5|^10.5" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Adrianorosa\\GeoLocation\\": "src" 27 | }, 28 | "files": [] 29 | }, 30 | "autoload-dev": { 31 | "psr-4": { 32 | "Adrianorosa\\GeoLocation\\Tests\\": "tests/" 33 | } 34 | }, 35 | "prefer-stable": true, 36 | "extra": { 37 | "laravel": { 38 | "providers": [ 39 | "Adrianorosa\\GeoLocation\\GeoLocationServiceProvider" 40 | ] 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /config/geolocation.php: -------------------------------------------------------------------------------- 1 | [ 16 | 'default' => 'ipinfo', 17 | ], 18 | 19 | /* 20 | |-------------------------------------------------------------------------- 21 | | Configurations for each Provider 22 | |-------------------------------------------------------------------------- 23 | | 24 | */ 25 | 26 | 'providers' => [ 27 | 28 | 'ipinfo' => [ 29 | 'driver' => 'ipinfo', 30 | 'access_token' => env('GEOLOCATION_IPINFO_ACCESS_TOKEN', null), 31 | // These options are passed to GuzzleClient config constructor 32 | 'client_options' => [ 33 | // 34 | ] 35 | ], 36 | ], 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Cache config when using API request like IpInfo and MaxMind WebService 41 | |-------------------------------------------------------------------------- 42 | | 43 | */ 44 | 45 | 'cache' => [ 46 | 'ttl' => env('GEOLOCATION_CACHE_TTL', 86400), 47 | ], 48 | 49 | ]; 50 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | The coding standard 4 | 5 | */vendor/* 6 | 7 | 8 | 9 | 10 | 11 | src 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | ./src 17 | 18 | 19 | 20 | 21 | ./tests 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Console/GeoLocationCommand.php: -------------------------------------------------------------------------------- 1 | 12 | * @date 2019-08-13 20:13 13 | * 14 | * @package Adrianorosa\GeoLocation\Console 15 | */ 16 | class GeoLocationCommand extends Command 17 | { 18 | /** 19 | * The name and signature of the console command. 20 | * 21 | * @var string 22 | */ 23 | protected $signature = 'geolocation:lookup {--ip= : The Ip Address to get the details for.}'; 24 | 25 | /** 26 | * The console command description. 27 | * 28 | * @var string 29 | */ 30 | protected $description = 'The Console GeoLocation Console Command allows one to call this in the background'; 31 | 32 | /** 33 | * Execute the console command. 34 | */ 35 | public function handle() 36 | { 37 | $ipAddress = $this->option('ip'); 38 | 39 | $data = GeoLocation::lookup($ipAddress); 40 | 41 | $data = array_merge(['ip' => $data->getIp()], $data->toArray()); 42 | 43 | $this->table(array_keys($data), [array_values($data)]); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Contracts/LookupInterface.php: -------------------------------------------------------------------------------- 1 | 11 | * @date 2019-08-13 17:50 12 | * 13 | * @package Adrianorosa\GeoLocation 14 | */ 15 | interface LookupInterface 16 | { 17 | /** 18 | * @param string $ipAddress 19 | * 20 | * @param string $responseFilter 21 | * 22 | * @return \Adrianorosa\GeoLocation\GeoLocationDetails 23 | */ 24 | public function lookup($ipAddress, $responseFilter = 'geo'): GeoLocationDetails; 25 | } 26 | -------------------------------------------------------------------------------- /src/GeoLocation.php: -------------------------------------------------------------------------------- 1 | 11 | * @date 2019-08-13 10:02 12 | * 13 | * @package Adrianorosa 14 | * 15 | * @method static|GeoLocationDetails lookup($ipAddress, $responseFilter = 'geo') 16 | * @method static|\Adrianorosa\GeoLocation\Contracts\LookupInterface driver($name) 17 | * 18 | * @see \Adrianorosa\GeoLocation\Providers\IpInfo 19 | */ 20 | class GeoLocation extends Facade 21 | { 22 | /** 23 | * Convenient method to get the translation list of countries codes. 24 | * 25 | * @param null $locale 26 | * 27 | * @return mixed 28 | */ 29 | public static function countries($locale = null) 30 | { 31 | return static::$app['translator']->get('geolocation::countries', [], $locale); 32 | } 33 | 34 | /** 35 | * @return string 36 | */ 37 | protected static function getFacadeAccessor() 38 | { 39 | return 'geolocation'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/GeoLocationDetails.php: -------------------------------------------------------------------------------- 1 | 11 | * @date 2019-08-13 13:24 12 | * 13 | * @package Adrianorosa\GeoLocation 14 | */ 15 | class GeoLocationDetails implements \JsonSerializable, Arrayable 16 | { 17 | /** 18 | * @var string 19 | */ 20 | protected $ip; 21 | 22 | /** 23 | * @var string 24 | */ 25 | protected $city; 26 | 27 | /** 28 | * @var string 29 | */ 30 | protected $region; 31 | 32 | /** 33 | * @var string 34 | */ 35 | protected $country; 36 | 37 | /** 38 | * @var string 39 | */ 40 | protected $countryCode; 41 | 42 | /** 43 | * @var float 44 | */ 45 | protected $latitude; 46 | 47 | /** 48 | * @var float 49 | */ 50 | protected $longitude; 51 | 52 | /** 53 | * GeoLocationDetails constructor. 54 | * 55 | * @param array $data 56 | */ 57 | public function __construct($data = []) 58 | { 59 | $this->parse($data); 60 | } 61 | 62 | /** 63 | * Get the IP Address. 64 | * 65 | * @return string|null 66 | */ 67 | public function getIp() 68 | { 69 | return $this->ip; 70 | } 71 | 72 | /** 73 | * Get the City name. 74 | * 75 | * @return string|null 76 | */ 77 | public function getCity() 78 | { 79 | return $this->city; 80 | } 81 | 82 | /** 83 | * Get teh region name. 84 | * 85 | * @return string|null 86 | */ 87 | public function getRegion() 88 | { 89 | return $this->region; 90 | } 91 | 92 | /** 93 | * Get the country name. 94 | * 95 | * @return string|null 96 | */ 97 | public function getCountry() 98 | { 99 | return $this->country; 100 | } 101 | 102 | /** 103 | * Get the country ISO Code. 104 | * 105 | * @return string|null 106 | */ 107 | public function getCountryCode() 108 | { 109 | return $this->countryCode; 110 | } 111 | 112 | /** 113 | * Get the Latitude value. 114 | * 115 | * @return float|null 116 | */ 117 | public function getLatitude() 118 | { 119 | return $this->latitude; 120 | } 121 | 122 | /** 123 | * Get the Longitude value. 124 | * 125 | * @return float|null 126 | */ 127 | public function getLongitude() 128 | { 129 | return $this->longitude; 130 | } 131 | 132 | /** 133 | * Parses the raw response. 134 | * 135 | * @param mixed $data 136 | */ 137 | protected function parse($data) 138 | { 139 | if (is_string($data)) { 140 | $data = json_decode($data, true); 141 | } 142 | 143 | foreach ((array) $data as $key => $value) { 144 | if (property_exists($this, $key)) { 145 | if ($key === 'country') { 146 | $this->countryCode = $value; 147 | $this->{$key} = $this->formatCountry($value); 148 | } else { 149 | $this->{$key} = $value; 150 | } 151 | } 152 | 153 | if ($key === 'loc') { 154 | $this->formatCoordinates($value); 155 | } 156 | } 157 | } 158 | 159 | /** 160 | * Parses the coordinates values into latitude and longitude. 161 | * 162 | * @param string $value 163 | */ 164 | protected function formatCoordinates($value): void 165 | { 166 | [$latitude, $longitude] = explode(',', $value); 167 | 168 | $this->latitude = (float) $latitude; 169 | $this->longitude = (float) $longitude; 170 | } 171 | 172 | /** 173 | * Format the country name. 174 | * 175 | * @param string $countryCode 176 | * 177 | * @return mixed 178 | */ 179 | protected function formatCountry($countryCode) 180 | { 181 | $countries = trans('geolocation::countries'); 182 | 183 | return array_key_exists($countryCode, $countries) ? $countries[$countryCode] : $countryCode; 184 | } 185 | 186 | /** 187 | * Get list of location items as an array. 188 | * 189 | * @return array 190 | */ 191 | public function toArray() 192 | { 193 | return [ 194 | 'city' => $this->city, 195 | 'region' => $this->region, 196 | 'country' => $this->country, 197 | 'countryCode' => $this->countryCode, 198 | 'latitude' => $this->latitude, 199 | 'longitude' => $this->longitude, 200 | ]; 201 | } 202 | 203 | /** 204 | * {@inheritdoc} 205 | */ 206 | public function jsonSerialize() 207 | { 208 | return $this->toArray(); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/GeoLocationException.php: -------------------------------------------------------------------------------- 1 | 9 | * @date 2019-08-13 16:00 10 | * 11 | * @package Adrianorosa\GeoLocation 12 | */ 13 | class GeoLocationException extends \Exception 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /src/GeoLocationManager.php: -------------------------------------------------------------------------------- 1 | 12 | * @date 2019-08-13 11:50 13 | * 14 | * @package Adrianorosa\GeoLocation 15 | */ 16 | class GeoLocationManager 17 | { 18 | /** 19 | * @var array 20 | */ 21 | protected $config; 22 | 23 | /** 24 | * @var array 25 | */ 26 | protected $providers = []; 27 | 28 | /** 29 | * @var \Illuminate\Cache\CacheManager 30 | */ 31 | protected $cacheProvider; 32 | 33 | /** 34 | * GeoLocation constructor. 35 | * 36 | * @param array $config 37 | * @param \Illuminate\Cache\CacheManager $cacheProvider 38 | */ 39 | public function __construct($config, \Illuminate\Cache\CacheManager $cacheProvider) 40 | { 41 | $this->config = $config; 42 | $this->cacheProvider = $cacheProvider; 43 | 44 | $this->setDefaultDriver(); 45 | } 46 | 47 | /** 48 | * Get a GeoLocation driver instance. 49 | * 50 | * @param $name 51 | * 52 | * @return mixed 53 | */ 54 | public function driver($name) 55 | { 56 | $name = $name ?: $this->getDefaultDriver(); 57 | 58 | return $this->providers[$name] = $this->provider($name); 59 | } 60 | 61 | /** 62 | * @param null $name 63 | */ 64 | protected function setDefaultDriver($name = null) 65 | { 66 | $provider = $name ?? $this->getDefaultDriver(); 67 | 68 | if ($provider) { 69 | $this->providers[$name] = $this->resolve($provider); 70 | } 71 | } 72 | 73 | /** 74 | * @return mixed 75 | */ 76 | protected function getDefaultDriver() 77 | { 78 | return $this->config['drivers']['default']; 79 | } 80 | 81 | /** 82 | * @param array $config 83 | * 84 | * @return \Adrianorosa\GeoLocation\Contracts\LookupInterface 85 | */ 86 | protected function createIpinfoDriver($config) 87 | { 88 | $options = $config['client_options'] ?? []; 89 | 90 | return new Providers\IpInfo(new Client($options), $this->cacheProvider->getStore()); 91 | } 92 | 93 | /** 94 | * @param null $name 95 | * 96 | * @return mixed 97 | */ 98 | protected function provider($name = null) 99 | { 100 | return $this->providers[$name] ?? $this->resolve($name); 101 | } 102 | 103 | /** 104 | * Resolve the given store. 105 | * 106 | * @param string $name 107 | * @return \Adrianorosa\GeoLocation\Contracts\LookupInterface 108 | * 109 | * @throws \InvalidArgumentException 110 | */ 111 | protected function resolve($name) 112 | { 113 | $config = $this->getConfig($name); 114 | 115 | if (is_null($config)) { 116 | throw new InvalidArgumentException("GeoLocation Driver [{$name}] is not defined."); 117 | } 118 | 119 | $driverMethod = 'create'.ucfirst($config['driver']).'Driver'; 120 | 121 | if (method_exists($this, $driverMethod)) { 122 | return $this->{$driverMethod}($config); 123 | } else { 124 | throw new InvalidArgumentException("GeoLocation Driver [{$config['driver']}] is not supported."); 125 | } 126 | } 127 | 128 | /** 129 | * @param $name 130 | * 131 | * @return string|null 132 | */ 133 | protected function getConfig($name) 134 | { 135 | return $this->config['providers'][$name] ?? null; 136 | } 137 | 138 | /** 139 | * Dynamically call the default driver instance. 140 | * 141 | * @param string $method 142 | * @param array $parameters 143 | * @return mixed 144 | */ 145 | public function __call($method, $parameters) 146 | { 147 | return $this->provider()->$method(...$parameters); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/GeoLocationServiceProvider.php: -------------------------------------------------------------------------------- 1 | 12 | * @date 2019-08-13 10:04 13 | * 14 | * @package Adrianorosa 15 | */ 16 | class GeoLocationServiceProvider extends ServiceProvider 17 | { 18 | 19 | /** 20 | * Register any application services. 21 | * 22 | * @return void 23 | */ 24 | public function register() 25 | { 26 | $this->mergeConfigFrom(__DIR__ . '/../config/geolocation.php', 'geolocation'); 27 | 28 | $this->app->singleton('geolocation', function ($app) { 29 | /**@var \Illuminate\Foundation\Application $app*/ 30 | return new GeoLocationManager( 31 | config('geolocation'), 32 | $app->get('cache') 33 | ); 34 | }); 35 | } 36 | 37 | public function boot() 38 | { 39 | $this->publishes([ 40 | __DIR__ . '/../config/geolocation.php' => config_path('geolocation.php'), 41 | ], 'geolocation-config'); 42 | 43 | $this->publishes([ 44 | __DIR__ . '/../translations' => resource_path('lang/vendor/geolocation') 45 | ], 'geolocation-translations'); 46 | 47 | $this->loadTranslationsFrom(__DIR__ . '/../translations', 'geolocation'); 48 | 49 | if ($this->app->runningInConsole()) { 50 | $this->commands([ 51 | Console\GeoLocationCommand::class, 52 | ]); 53 | } 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function provides() 60 | { 61 | return ['geolocation']; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Providers/IpInfo.php: -------------------------------------------------------------------------------- 1 | 15 | * @date 2019-08-13 13:55 16 | * 17 | */ 18 | class IpInfo implements LookupInterface 19 | { 20 | /** 21 | * @const Define the baseurl. 22 | */ 23 | const BASEURL = 'https://ipinfo.io'; 24 | 25 | /** 26 | * @var \GuzzleHttp\Client 27 | */ 28 | protected $client; 29 | 30 | /** 31 | * @var \Illuminate\Contracts\Cache\Store 32 | */ 33 | protected $cache; 34 | 35 | /** 36 | * IpInfo constructor. 37 | * 38 | * @param $client 39 | * @param $cache 40 | */ 41 | public function __construct($client, Store $cache) 42 | { 43 | $this->client = $client; 44 | $this->cache = $cache; 45 | } 46 | 47 | /** 48 | * Filter the API response down to specific fields or objects 49 | * by adding the field or object name to the URL. 50 | * 51 | * @param string|null $ipAddress An Ip or 'me' For yourself IP 52 | * 53 | * @param string $responseFilter Options are: (city / org / geo) 54 | * 55 | * @return \Adrianorosa\GeoLocation\GeoLocationDetails 56 | * @throws \Adrianorosa\GeoLocation\GeoLocationException 57 | */ 58 | public function lookup($ipAddress = null, $responseFilter = 'geo'): GeoLocationDetails 59 | { 60 | // For instance only `geo` filter are accepted, other type of filters 61 | // need a different parse approach for GeoLocationDetails which may 62 | // lead to a creation of a new properties and methods to accept strings 63 | $filter = $responseFilter !== 'geo' ? 'geo' : $responseFilter; 64 | 65 | if (is_null($data = $this->cache->get($ipAddress))) { 66 | $endpoint = static::BASEURL; 67 | $accessToken = config('geolocation.providers.ipinfo.access_token'); 68 | 69 | if ($ipAddress) { 70 | $endpoint .= "/{$ipAddress}/{$filter}"; 71 | } 72 | 73 | try { 74 | $response = $this->client->get( 75 | $endpoint, 76 | [ 77 | 'headers' => [ 78 | 'Authorization' => 'Bearer ' . $accessToken, 79 | 'Accept' => 'application/json' 80 | ], 81 | ] 82 | ); 83 | 84 | $data = json_decode( 85 | $result = $response->getBody()->getContents(), 86 | true 87 | ); 88 | 89 | // Sometimes the response can be a string which will result to a JSON_ERROR 90 | if (json_last_error() !== JSON_ERROR_NONE) { 91 | $data = $result; 92 | } 93 | 94 | $this->cache->put( 95 | $ipAddress, 96 | $data, 97 | config('geolocation.cache.ttl') 98 | ); 99 | } catch (GuzzleException | \Exception $e) { 100 | throw new GeoLocationException($e->getMessage()); 101 | } 102 | } 103 | 104 | return new GeoLocationDetails($data); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/ConfigTest.php: -------------------------------------------------------------------------------- 1 | 9 | * @date 2019-08-13 20:36 10 | * 11 | * @package Adrianorosa\GeoLocation\Tests 12 | */ 13 | class ConfigTest extends TestCase 14 | { 15 | /** 16 | * @covers \Adrianorosa\GeoLocation\GeoLocationServiceProvider::boot 17 | */ 18 | public function testGetConfigValues() 19 | { 20 | $this->assertNotNull(config('geolocation.drivers.default')); 21 | $this->assertNotNull(config('geolocation.providers.ipinfo.access_token')); 22 | $this->assertNotNull(config('geolocation.cache.ttl')); 23 | 24 | $this->assertEquals(4096, config('geolocation.cache.ttl')); 25 | $this->assertEquals('LftDDkrDdJtxhA', config('geolocation.providers.ipinfo.access_token')); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /tests/GeoLocationDetailsTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('44.110.29.111', $details->getIp()); 23 | $this->assertEquals('Sydney', $details->getCity()); 24 | $this->assertEquals('Sydney', $details->getRegion()); 25 | $this->assertEquals('Australia', $details->getCountry()); 26 | $this->assertEquals('AU', $details->getCountryCode()); 27 | $this->assertEquals(-23.5475, $details->getLatitude()); 28 | $this->assertEquals(-46.6361, $details->getLongitude()); 29 | 30 | $this->assertArrayHasKey('city', $details->toArray()); 31 | $this->assertArrayHasKey('region', $details->toArray()); 32 | $this->assertArrayHasKey('country', $details->toArray()); 33 | $this->assertArrayHasKey('countryCode', $details->toArray()); 34 | $this->assertArrayHasKey('latitude', $details->toArray()); 35 | $this->assertArrayHasKey('longitude', $details->toArray()); 36 | } 37 | 38 | /** 39 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getIp() 40 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getCity() 41 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getRegion() 42 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getCountryCode() 43 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getLatitude() 44 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getLongitude() 45 | */ 46 | public function testParseBogon() 47 | { 48 | $data = json_decode('{"ip": "192.168.10.6","bogon": true}', true); 49 | 50 | $details = new GeoLocationDetails($data); 51 | 52 | $this->assertEquals('192.168.10.6', $details->getIp()); 53 | $this->assertEquals(null, $details->getCity()); 54 | $this->assertEquals(null, $details->getRegion()); 55 | $this->assertEquals(null, $details->getCountry()); 56 | $this->assertEquals(null, $details->getCountryCode()); 57 | $this->assertEquals(null, $details->getLatitude()); 58 | $this->assertEquals(null, $details->getLongitude()); 59 | } 60 | 61 | /** 62 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getIp() 63 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getCity() 64 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getRegion() 65 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getCountryCode() 66 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getLatitude() 67 | * @covers \Adrianorosa\GeoLocation\GeoLocationDetails::getLongitude() 68 | */ 69 | public function testParseNull() 70 | { 71 | $data = json_decode('{"invalid JSON ERROR}', true); 72 | 73 | $details = new GeoLocationDetails($data); 74 | 75 | $this->assertEquals(null, $details->getIp()); 76 | $this->assertEquals(null, $details->getCity()); 77 | $this->assertEquals(null, $details->getRegion()); 78 | $this->assertEquals(null, $details->getCountry()); 79 | $this->assertEquals(null, $details->getCountryCode()); 80 | $this->assertEquals(null, $details->getLatitude()); 81 | $this->assertEquals(null, $details->getLongitude()); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tests/GeoLocationManagerTest.php: -------------------------------------------------------------------------------- 1 | expectExceptionMessage('GeoLocation Driver [foo] is not defined.'); 16 | new GeoLocationManager([ 17 | 'drivers' => [ 18 | 'default' => 'foo' 19 | ] 20 | ], $this->app->get('cache')); 21 | } 22 | 23 | /** 24 | * @covers \Adrianorosa\GeoLocation\GeoLocationManager::resolve() 25 | */ 26 | public function testBindManagerMethodNotSupportedException() 27 | { 28 | $this->expectExceptionMessage('GeoLocation Driver [bar] is not supported.'); 29 | new GeoLocationManager([ 30 | 'drivers' => [ 31 | 'default' => 'ipinfo' 32 | ], 33 | 'providers' => [ 34 | 'ipinfo' => [ 35 | 'driver' => 'bar' 36 | ] 37 | ] 38 | ], $this->app->get('cache')); 39 | } 40 | 41 | /** 42 | * @covers \Adrianorosa\GeoLocation\GeoLocationManager::resolve() 43 | */ 44 | public function testCreateUndefinedProvider() 45 | { 46 | $this->expectExceptionMessage('GeoLocation Driver [bar] is not defined.'); 47 | $manager = new GeoLocationManager(config('geolocation'), $this->app->get('cache')); 48 | $manager->driver('bar'); 49 | } 50 | 51 | /** 52 | * @covers GeoLocationManager::createIpinfoDriver() 53 | */ 54 | public function testCreateIpInfoProvider() 55 | { 56 | $manager = new GeoLocationManager(config('geolocation'), $this->app->get('cache')); 57 | $this->assertInstanceOf(IpInfo::class, $manager->driver('ipinfo')); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/GeoLocationTest.php: -------------------------------------------------------------------------------- 1 | assertNotNull($this->app['config']['geolocation']); 17 | } 18 | 19 | /** 20 | * @covers \Adrianorosa\GeoLocation\GeoLocation 21 | */ 22 | public function testProviderBoundInstance() 23 | { 24 | $this->assertTrue($this->app->bound('geolocation')); 25 | } 26 | 27 | /** 28 | * @covers \Adrianorosa\GeoLocation\GeoLocation 29 | */ 30 | public function testProvider() 31 | { 32 | $this->assertTrue($this->app->bound('geolocation')); 33 | } 34 | 35 | /** 36 | * @covers \Adrianorosa\GeoLocation\GeoLocation 37 | */ 38 | public function testGeoLocation() 39 | { 40 | /**@var \Illuminate\Cache\ArrayStore $cache*/ 41 | $cache = $this->app->get('cache')->getStore(); 42 | $ipAddress = '8.8.8.8'; 43 | $data = json_decode('{"ip":"' . $ipAddress . '","city":"Mountain View","region":"California","country":"US","loc":"37.3860,-122.0838"}', true); 44 | $cache->put($ipAddress, $data, 2000); 45 | 46 | $this->app->setLocale('en'); 47 | 48 | $info = GeoLocation::lookup($ipAddress); 49 | 50 | $this->assertInstanceOf(GeoLocationDetails::class, $info); 51 | $this->assertEquals($ipAddress, $info->getIp()); 52 | $this->assertEquals('Mountain View', $info->getCity()); 53 | $this->assertEquals('California', $info->getRegion()); 54 | $this->assertEquals('United States', $info->getCountry()); 55 | $this->assertEquals('US', $info->getCountryCode()); 56 | $this->assertIsFloat($info->getLatitude()); 57 | $this->assertIsFloat($info->getLongitude()); 58 | } 59 | 60 | /** 61 | * @covers \Adrianorosa\GeoLocation\GeoLocation 62 | */ 63 | public function testCountryLocaleChange() 64 | { 65 | /**@var \Illuminate\Cache\ArrayStore $cache*/ 66 | $cache = $this->app->get('cache')->getStore(); 67 | $ipAddress = '8.8.8.8'; 68 | $data = json_decode('{"ip":"' . $ipAddress . '","city":"Mountain View","region":"California","country":"US","loc":"37.3860,-122.0838"}', true); 69 | $cache->put($ipAddress, $data, 2000); 70 | 71 | $this->app->setLocale('pt_BR'); 72 | 73 | $info = GeoLocation::lookup($ipAddress); 74 | 75 | $this->assertInstanceOf(GeoLocationDetails::class, $info); 76 | $this->assertEquals('Estados Unidos', $info->getCountry()); 77 | $this->assertEquals('US', $info->getCountryCode()); 78 | } 79 | 80 | /** 81 | * @covers \Adrianorosa\GeoLocation\GeoLocation 82 | */ 83 | public function testGelLocationException() 84 | { 85 | $this->app->setLocale('pt_BR'); 86 | 87 | $this->expectException(GeoLocationException::class); 88 | GeoLocation::lookup('1222398333'); 89 | } 90 | 91 | /** 92 | * @covers \Adrianorosa\GeoLocation\GeoLocation::countries() 93 | */ 94 | public function testGetTranslationsOfCountriesLocale() 95 | { 96 | $en = GeoLocation::countries('en'); 97 | $this->assertArrayHasKey('US', $en); 98 | $this->assertEquals('United States', $en['US']); 99 | 100 | $pt_BR = GeoLocation::countries('pt_BR'); 101 | $this->assertArrayHasKey('US', $pt_BR); 102 | $this->assertEquals('Estados Unidos', $pt_BR['US']); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /tests/Providers/IpInfoTest.php: -------------------------------------------------------------------------------- 1 | app->get('cache')->getStore(); 18 | 19 | $ipAddress = '127.0.0.1'; 20 | $data = json_decode('{"ip": "127.0.0.1","city": "X","region": "X", "country": "XX","loc": "-23.5475,-46.6361"}', true); 21 | 22 | $cache->put($ipAddress, $data, 2000); 23 | $provider = new IpInfo(new Client(), $this->app->get('cache')->getStore()); 24 | 25 | $detail = $provider->lookup($ipAddress); 26 | 27 | $this->assertEquals('127.0.0.1', $detail->getIp()); 28 | $this->assertEquals('X', $detail->getCity()); 29 | $this->assertEquals('X', $detail->getRegion()); 30 | $this->assertEquals('XX', $detail->getCountry()); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | GeoLocation::class 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /translations/en/countries.php: -------------------------------------------------------------------------------- 1 | 'Afghanistan', 5 | 'AX' => 'Åland Islands', 6 | 'AL' => 'Albania', 7 | 'DZ' => 'Algeria', 8 | 'AS' => 'American Samoa', 9 | 'AD' => 'Andorra', 10 | 'AO' => 'Angola', 11 | 'AI' => 'Anguilla', 12 | 'AQ' => 'Antarctica', 13 | 'AG' => 'Antigua and Barbuda', 14 | 'AR' => 'Argentina', 15 | 'AM' => 'Armenia', 16 | 'AW' => 'Aruba', 17 | 'AU' => 'Australia', 18 | 'AT' => 'Austria', 19 | 'AZ' => 'Azerbaijan', 20 | 'BS' => 'Bahamas', 21 | 'BH' => 'Bahrain', 22 | 'BD' => 'Bangladesh', 23 | 'BB' => 'Barbados', 24 | 'BY' => 'Belarus', 25 | 'BE' => 'Belgium', 26 | 'BZ' => 'Belize', 27 | 'BJ' => 'Benin', 28 | 'BM' => 'Bermuda', 29 | 'BT' => 'Bhutan', 30 | 'BO' => 'Bolivia, Plurinational State of', 31 | 'BQ' => 'Bonaire, Sint Eustatius and Saba', 32 | 'BA' => 'Bosnia and Herzegovina', 33 | 'BW' => 'Botswana', 34 | // 'BV' => 'Bouvet Island', 35 | 'BR' => 'Brazil', 36 | 'IO' => 'British Indian Ocean Territory', 37 | 'BN' => 'Brunei Darussalam', 38 | 'BG' => 'Bulgaria', 39 | 'BF' => 'Burkina Faso', 40 | 'BI' => 'Burundi', 41 | 'KH' => 'Cambodia', 42 | 'CM' => 'Cameroon', 43 | 'CA' => 'Canada', 44 | 'CV' => 'Cabo Verde', 45 | 'KY' => 'Cayman Islands', 46 | 'CF' => 'Central African Republic', 47 | 'TD' => 'Chad', 48 | 'CL' => 'Chile', 49 | 'CN' => 'China', 50 | 'CX' => 'Christmas Island', 51 | 'CC' => 'Cocos (Keeling) Islands', 52 | 'CO' => 'Colombia', 53 | 'KM' => 'Comoros', 54 | 'CG' => 'Congo', 55 | 'CD' => 'Congo, the Democratic Republic of the', 56 | 'CK' => 'Cook Islands', 57 | 'CR' => 'Costa Rica', 58 | 'CI' => 'Côte d\'Ivoire', 59 | 'HR' => 'Croatia', 60 | 'CU' => 'Cuba', 61 | 'CW' => 'Curaçao', 62 | 'CY' => 'Cyprus', 63 | 'CZ' => 'Czech Republic', 64 | 'DK' => 'Denmark', 65 | 'DJ' => 'Djibouti', 66 | 'DM' => 'Dominica', 67 | 'DO' => 'Dominican Republic', 68 | 'EC' => 'Ecuador', 69 | 'EG' => 'Egypt', 70 | 'SV' => 'El Salvador', 71 | 'GQ' => 'Equatorial Guinea', 72 | 'ER' => 'Eritrea', 73 | 'EE' => 'Estonia', 74 | 'ET' => 'Ethiopia', 75 | 'FK' => 'Falkland Islands (Malvinas)', 76 | 'FO' => 'Faroe Islands', 77 | 'FJ' => 'Fiji', 78 | 'FI' => 'Finland', 79 | 'FR' => 'France', 80 | 'GF' => 'French Guiana', 81 | 'PF' => 'French Polynesia', 82 | 'TF' => 'French Southern Territories', 83 | 'GA' => 'Gabon', 84 | 'GM' => 'Gambia', 85 | 'GE' => 'Georgia', 86 | 'DE' => 'Germany', 87 | 'GH' => 'Ghana', 88 | 'GI' => 'Gibraltar', 89 | 'GR' => 'Greece', 90 | 'GL' => 'Greenland', 91 | 'GD' => 'Grenada', 92 | 'GP' => 'Guadeloupe', 93 | 'GU' => 'Guam', 94 | 'GT' => 'Guatemala', 95 | 'GG' => 'Guernsey', 96 | 'GN' => 'Guinea', 97 | 'GW' => 'Guinea-Bissau', 98 | 'GY' => 'Guyana', 99 | 'HT' => 'Haiti', 100 | // 'HM' => 'Heard Island and McDonald Islands', 101 | 'VA' => 'Holy See (Vatican City State)', 102 | 'HN' => 'Honduras', 103 | 'HK' => 'Hong Kong', 104 | 'HU' => 'Hungary', 105 | 'IS' => 'Iceland', 106 | 'IN' => 'India', 107 | 'ID' => 'Indonesia', 108 | 'IR' => 'Iran, Islamic Republic of', 109 | 'IQ' => 'Iraq', 110 | 'IE' => 'Ireland', 111 | 'IM' => 'Isle of Man', 112 | 'IL' => 'Israel', 113 | 'IT' => 'Italy', 114 | 'JM' => 'Jamaica', 115 | 'JP' => 'Japan', 116 | 'JE' => 'Jersey', 117 | 'JO' => 'Jordan', 118 | 'KZ' => 'Kazakhstan', 119 | 'KE' => 'Kenya', 120 | 'KI' => 'Kiribati', 121 | 'KP' => 'Korea, Democratic People\'s Republic of', 122 | 'KR' => 'Korea, Republic of', 123 | 'KW' => 'Kuwait', 124 | 'KG' => 'Kyrgyzstan', 125 | 'LA' => 'Lao People\'s Democratic Republic', 126 | 'LV' => 'Latvia', 127 | 'LB' => 'Lebanon', 128 | 'LS' => 'Lesotho', 129 | 'LR' => 'Liberia', 130 | 'LY' => 'Libya', 131 | 'LI' => 'Liechtenstein', 132 | 'LT' => 'Lithuania', 133 | 'LU' => 'Luxembourg', 134 | 'MO' => 'Macao', 135 | 'MK' => 'Macedonia, the former Yugoslav Republic of', 136 | 'MG' => 'Madagascar', 137 | 'MW' => 'Malawi', 138 | 'MY' => 'Malaysia', 139 | 'MV' => 'Maldives', 140 | 'ML' => 'Mali', 141 | 'MT' => 'Malta', 142 | 'MH' => 'Marshall Islands', 143 | 'MQ' => 'Martinique', 144 | 'MR' => 'Mauritania', 145 | 'MU' => 'Mauritius', 146 | 'YT' => 'Mayotte', 147 | 'MX' => 'Mexico', 148 | 'FM' => 'Micronesia, Federated States of', 149 | 'MD' => 'Moldova, Republic of', 150 | 'MC' => 'Monaco', 151 | 'MN' => 'Mongolia', 152 | 'ME' => 'Montenegro', 153 | 'MS' => 'Montserrat', 154 | 'MA' => 'Morocco', 155 | 'MZ' => 'Mozambique', 156 | 'MM' => 'Myanmar', 157 | 'NA' => 'Namibia', 158 | 'NR' => 'Nauru', 159 | 'NP' => 'Nepal', 160 | 'NL' => 'Netherlands', 161 | 'NC' => 'New Caledonia', 162 | 'NZ' => 'New Zealand', 163 | 'NI' => 'Nicaragua', 164 | 'NE' => 'Niger', 165 | 'NG' => 'Nigeria', 166 | 'NU' => 'Niue', 167 | 'NF' => 'Norfolk Island', 168 | 'MP' => 'Northern Mariana Islands', 169 | 'NO' => 'Norway', 170 | 'OM' => 'Oman', 171 | 'PK' => 'Pakistan', 172 | 'PW' => 'Palau', 173 | 'PS' => 'Palestine, State of', 174 | 'PA' => 'Panama', 175 | 'PG' => 'Papua New Guinea', 176 | 'PY' => 'Paraguay', 177 | 'PE' => 'Peru', 178 | 'PH' => 'Philippines', 179 | 'PN' => 'Pitcairn', 180 | 'PL' => 'Poland', 181 | 'PT' => 'Portugal', 182 | 'PR' => 'Puerto Rico', 183 | 'QA' => 'Qatar', 184 | 'RE' => 'Réunion', 185 | 'RO' => 'Romania', 186 | 'RU' => 'Russian Federation', 187 | 'RW' => 'Rwanda', 188 | 'BL' => 'Saint Barthélemy', 189 | 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', 190 | 'KN' => 'Saint Kitts and Nevis', 191 | 'LC' => 'Saint Lucia', 192 | 'MF' => 'Saint Martin (French part)', 193 | 'PM' => 'Saint Pierre and Miquelon', 194 | 'VC' => 'Saint Vincent and the Grenadines', 195 | 'WS' => 'Samoa', 196 | 'SM' => 'San Marino', 197 | 'ST' => 'Sao Tome and Principe', 198 | 'SA' => 'Saudi Arabia', 199 | 'SN' => 'Senegal', 200 | 'RS' => 'Serbia', 201 | 'SC' => 'Seychelles', 202 | 'SL' => 'Sierra Leone', 203 | 'SG' => 'Singapore', 204 | 'SX' => 'Sint Maarten (Dutch part)', 205 | 'SK' => 'Slovakia', 206 | 'SI' => 'Slovenia', 207 | 'SB' => 'Solomon Islands', 208 | 'SO' => 'Somalia', 209 | 'ZA' => 'South Africa', 210 | 'GS' => 'South Georgia and the South Sandwich Islands', 211 | 'SS' => 'South Sudan', 212 | 'ES' => 'Spain', 213 | 'LK' => 'Sri Lanka', 214 | 'SD' => 'Sudan', 215 | 'SR' => 'Suriname', 216 | 'SJ' => 'Svalbard and Jan Mayen', 217 | 'SZ' => 'Swaziland', 218 | 'SE' => 'Sweden', 219 | 'CH' => 'Switzerland', 220 | 'SY' => 'Syrian Arab Republic', 221 | 'TW' => 'Taiwan, Province of China', 222 | 'TJ' => 'Tajikistan', 223 | 'TZ' => 'Tanzania, United Republic of', 224 | 'TH' => 'Thailand', 225 | 'TL' => 'Timor-Leste', 226 | 'TG' => 'Togo', 227 | 'TK' => 'Tokelau', 228 | 'TO' => 'Tonga', 229 | 'TT' => 'Trinidad and Tobago', 230 | 'TN' => 'Tunisia', 231 | 'TR' => 'Turkey', 232 | 'TM' => 'Turkmenistan', 233 | 'TC' => 'Turks and Caicos Islands', 234 | 'TV' => 'Tuvalu', 235 | 'UG' => 'Uganda', 236 | 'UA' => 'Ukraine', 237 | 'AE' => 'United Arab Emirates', 238 | 'GB' => 'United Kingdom', 239 | 'US' => 'United States', 240 | 'UM' => 'United States Minor Outlying Islands', 241 | 'UY' => 'Uruguay', 242 | 'UZ' => 'Uzbekistan', 243 | 'VU' => 'Vanuatu', 244 | 'VE' => 'Venezuela, Bolivarian Republic of', 245 | 'VN' => 'Viet Nam', 246 | 'VG' => 'Virgin Islands, British', 247 | 'VI' => 'Virgin Islands, U.S.', 248 | 'WF' => 'Wallis and Futuna', 249 | 'EH' => 'Western Sahara', 250 | 'YE' => 'Yemen', 251 | 'ZM' => 'Zambia', 252 | 'ZW' => 'Zimbabwe', 253 | ]; 254 | -------------------------------------------------------------------------------- /translations/pt_BR/countries.php: -------------------------------------------------------------------------------- 1 | 'Afeganistão', 5 | 'ZA' => 'África do Sul', 6 | 'AX' => 'Åland, Ilhas', 7 | 'AL' => 'Albânia', 8 | 'DE' => 'Alemanha', 9 | 'AD' => 'Andorra', 10 | 'AO' => 'Angola', 11 | 'AI' => 'Anguilla', 12 | 'AQ' => 'Antárctida', 13 | 'AG' => 'Antígua e Barbuda', 14 | // 'AN' => 'Antilhas Holandesas', 15 | 'SA' => 'Arábia Saudita', 16 | 'DZ' => 'Argélia', 17 | 'AR' => 'Argentina', 18 | 'AM' => 'Armênia', 19 | 'AW' => 'Aruba', 20 | 'AU' => 'Austrália', 21 | 'AT' => 'Áustria', 22 | 'AZ' => 'Azerbaijão', 23 | 'BS' => 'Bahamas', 24 | 'BH' => 'Bahrain', 25 | 'BD' => 'Bangladesh', 26 | 'BB' => 'Barbados', 27 | 'BE' => 'Bélgica', 28 | 'BZ' => 'Belize', 29 | 'BJ' => 'Benim', 30 | 'BM' => 'Bermudas', 31 | 'BY' => 'Bielorrússia', 32 | 'BO' => 'Bolívia', 33 | 'BA' => 'Bósnia e Herzegovina', 34 | 'BW' => 'Botswana', 35 | // 'BV' => 'Bouvet, Ilha', 36 | 'BR' => 'Brasil', 37 | 'BN' => 'Brunei', 38 | 'BG' => 'Bulgária', 39 | 'BF' => 'Burkina Faso', 40 | 'BI' => 'Burundi', 41 | 'BT' => 'Butão', 42 | 'CV' => 'Cabo Verde', 43 | 'CM' => 'Camarões', 44 | 'KH' => 'Cambodja', 45 | 'CA' => 'Canadá', 46 | 'KY' => 'Cayman, Ilhas', 47 | 'KZ' => 'Cazaquistão', 48 | 'CF' => 'Centro-Africana, República', 49 | 'TD' => 'Chade', 50 | 'CZ' => 'Checa, República', 51 | 'CL' => 'Chile', 52 | 'CN' => 'China', 53 | 'CY' => 'Chipre', 54 | 'CX' => 'Christmas, Ilha', 55 | 'CC' => 'Cocos, Ilhas', 56 | 'CO' => 'Colômbia', 57 | 'KM' => 'Comores', 58 | 'CD' => 'Congo, República Democrática do (antigo Zaire)', 59 | 'CG' => 'Congo, República do', 60 | 'CK' => 'Cook, Ilhas', 61 | 'KR' => 'Coréia do Sul', 62 | 'KP' => 'Coréia do Norte', 63 | 'CI' => 'Costa do Marfim', 64 | 'CR' => 'Costa Rica', 65 | 'HR' => 'Croácia', 66 | 'CU' => 'Cuba', 67 | 'DK' => 'Dinamarca', 68 | 'DJ' => 'Djibouti', 69 | 'DM' => 'Dominica', 70 | 'DO' => 'Dominicana, República', 71 | 'EG' => 'Egito', 72 | 'SV' => 'El Salvador', 73 | 'AE' => 'Emirados Árabes Unidos', 74 | 'EC' => 'Equador', 75 | 'ER' => 'Eritreia', 76 | 'SK' => 'Eslováquia', 77 | 'SI' => 'Eslovênia', 78 | 'ES' => 'Espanha', 79 | 'US' => 'Estados Unidos', 80 | 'EE' => 'Estónia', 81 | 'ET' => 'Etiópia', 82 | 'FO' => 'Feroé, Ilhas', 83 | 'FJ' => 'Fiji', 84 | 'PH' => 'Filipinas', 85 | 'FI' => 'Finlândia', 86 | 'FR' => 'França', 87 | 'GA' => 'Gabão', 88 | 'GM' => 'Gâmbia', 89 | 'GH' => 'Gana', 90 | 'GE' => 'Geórgia', 91 | 'GS' => 'Geórgia do Sul e Sandwich do Sul, Ilhas', 92 | 'GI' => 'Gibraltar', 93 | 'GR' => 'Grécia', 94 | 'GD' => 'Grenada', 95 | 'GL' => 'Groenlândia', 96 | 'GP' => 'Guadalupe', 97 | 'GU' => 'Guam', 98 | 'GT' => 'Guatemala', 99 | 'GG' => 'Guernsey', 100 | 'GY' => 'Guiana', 101 | 'GF' => 'Guiana Francesa', 102 | 'GQ' => 'Guiné Equatorial', 103 | 'GW' => 'Guiné-Bissau', 104 | 'GN' => 'Guiné-Conacri', 105 | 'HT' => 'Haiti', 106 | // 'HM' => 'Heard e Ilhas McDonald, Ilha', 107 | 'HN' => 'Honduras', 108 | 'HK' => 'Hong Kong', 109 | 'HU' => 'Hungria', 110 | 'YE' => 'Iémen', 111 | 'IN' => 'Índia', 112 | 'ID' => 'Indonésia', 113 | 'IR' => 'Irã', 114 | 'IQ' => 'Iraque', 115 | 'IE' => 'Irlanda', 116 | 'IS' => 'Islândia', 117 | 'IL' => 'Israel', 118 | 'IT' => 'Itália', 119 | 'JM' => 'Jamaica', 120 | 'JP' => 'Japão', 121 | 'JE' => 'Jersey', 122 | 'JO' => 'Jordânia', 123 | 'KI' => 'Kiribati', 124 | 'KW' => 'Kuwait', 125 | 'LA' => 'Laos', 126 | 'LS' => 'Lesoto', 127 | 'LV' => 'Letônia', 128 | 'LB' => 'Líbano', 129 | 'LR' => 'Libéria', 130 | 'LY' => 'Líbia', 131 | 'LI' => 'Liechtenstein', 132 | 'LT' => 'Lituânia', 133 | 'LU' => 'Luxemburgo', 134 | 'MO' => 'Macau', 135 | 'MK' => 'Macedônia, República da', 136 | 'MG' => 'Madagáscar', 137 | 'MY' => 'Malásia', 138 | 'MW' => 'Malawi', 139 | 'MV' => 'Maldivas', 140 | 'ML' => 'Mali', 141 | 'MT' => 'Malta', 142 | 'FK' => 'Malvinas, Ilhas (Falkland)', 143 | 'IM' => 'Man, Ilha de', 144 | 'MP' => 'Marianas Setentrionais', 145 | 'MA' => 'Marrocos', 146 | 'MH' => 'Marshall, Ilhas', 147 | 'MQ' => 'Martinica', 148 | 'MU' => 'Maurícia', 149 | 'MR' => 'Mauritânia', 150 | 'YT' => 'Mayotte', 151 | 'UM' => 'Menores Distantes dos Estados Unidos, Ilhas', 152 | 'MX' => 'México', 153 | 'FM' => 'Micronésia, Estados Federados da', 154 | 'MZ' => 'Moçambique', 155 | 'MD' => 'Moldávia', 156 | 'MC' => 'Mônaco', 157 | 'MN' => 'Mongólia', 158 | 'ME' => 'Montenegro', 159 | 'MS' => 'Montserrat', 160 | 'MM' => 'Myanmar (antiga Birmânia)', 161 | 'NA' => 'Namíbia', 162 | 'NR' => 'Nauru', 163 | 'NP' => 'Nepal', 164 | 'NI' => 'Nicarágua', 165 | 'NE' => 'Níger', 166 | 'NG' => 'Nigéria', 167 | 'NU' => 'Niue', 168 | 'NF' => 'Norfolk, Ilha', 169 | 'NO' => 'Noruega', 170 | 'NC' => 'Nova Caledônia', 171 | 'NZ' => 'Nova Zelândia (Aotearoa)', 172 | 'OM' => 'Oman', 173 | 'NL' => 'Países Baixos (Holanda)', 174 | 'PW' => 'Palau', 175 | 'PS' => 'Palestina', 176 | 'PA' => 'Panamá', 177 | 'PG' => 'Papua-Nova Guiné', 178 | 'PK' => 'Paquistão', 179 | 'PY' => 'Paraguai', 180 | 'PE' => 'Peru', 181 | 'PN' => 'Pitcairn', 182 | 'PF' => 'Polinésia Francesa', 183 | 'PL' => 'Polônia', 184 | 'PR' => 'Porto Rico', 185 | 'PT' => 'Portugal', 186 | 'QA' => 'Qatar', 187 | 'KE' => 'Quênia', 188 | 'KG' => 'Quirguistão', 189 | 'GB' => 'Reino Unido da Grã-Bretanha e Irlanda do Norte', 190 | 'RE' => 'Reunião', 191 | 'RO' => 'Romênia', 192 | 'RW' => 'Ruanda', 193 | 'RU' => 'Rússia', 194 | 'EH' => 'Saara Ocidental', 195 | 'PM' => 'Saint Pierre et Miquelon', 196 | 'SB' => 'Salomão, Ilhas', 197 | 'WS' => 'Samoa (Samoa Ocidental)', 198 | 'AS' => 'Samoa Americana', 199 | 'SM' => 'San Marino', 200 | 'SH' => 'Santa Helena', 201 | 'LC' => 'Santa Lúcia', 202 | 'KN' => 'São Cristóvão e Névis (Saint Kitts e Nevis)', 203 | 'ST' => 'São Tomé e Príncipe', 204 | 'VC' => 'São Vicente e Granadinas', 205 | 'SN' => 'Senegal', 206 | 'SL' => 'Serra Leoa', 207 | 'RS' => 'Sérvia', 208 | 'SC' => 'Seychelles', 209 | 'SG' => 'Singapura', 210 | 'SY' => 'Síria', 211 | 'SO' => 'Somália', 212 | 'LK' => 'Sri Lanka', 213 | 'SZ' => 'Suazilândia', 214 | 'SD' => 'Sudão', 215 | 'SS' => 'Sudão do Sul', 216 | 'SE' => 'Suécia', 217 | 'CH' => 'Suíça', 218 | 'SR' => 'Suriname', 219 | 'SJ' => 'Svalbard e Jan Mayen', 220 | 'TH' => 'Tailândia', 221 | 'TW' => 'Taiwan', 222 | 'TJ' => 'Tajiquistão', 223 | 'TZ' => 'Tanzânia', 224 | 'TF' => 'Terras Austrais e Antárticas Francesas (TAAF)', 225 | 'IO' => 'Território Britânico do Oceano Índico', 226 | 'TL' => 'Timor-Leste', 227 | 'TG' => 'Togo', 228 | 'TO' => 'Tonga', 229 | 'TK' => 'Toquelau', 230 | 'TT' => 'Trindade e Tobago', 231 | 'TN' => 'Tunísia', 232 | 'TC' => 'Turks e Caicos', 233 | 'TM' => 'Turquemenistão', 234 | 'TR' => 'Turquia', 235 | 'TV' => 'Tuvalu', 236 | 'UA' => 'Ucrânia', 237 | 'UG' => 'Uganda', 238 | 'UY' => 'Uruguai', 239 | 'UZ' => 'Usbequistão', 240 | 'VU' => 'Vanuatu', 241 | 'VA' => 'Vaticano', 242 | 'VE' => 'Venezuela', 243 | 'VN' => 'Vietnam', 244 | 'VI' => 'Virgens Americanas, Ilhas', 245 | 'VG' => 'Virgens Britânicas, Ilhas', 246 | 'WF' => 'Wallis e Futuna', 247 | 'ZM' => 'Zâmbia', 248 | 'ZW' => 'Zimbabwe' 249 | ]; 250 | --------------------------------------------------------------------------------