Merge pull request #1128 from stanjg/feature/user-specific-language

Add support for user specific languages
This commit is contained in:
Dane Everitt 2018-09-03 15:18:23 -07:00 committed by GitHub
commit 3082a57a4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 51 additions and 34 deletions

View file

@ -7,6 +7,7 @@ APP_CLEAR_TASKLOG=720
APP_DELETE_MINUTES=10 APP_DELETE_MINUTES=10
APP_ENVIRONMENT_ONLY=true APP_ENVIRONMENT_ONLY=true
LOG_CHANNEL=daily LOG_CHANNEL=daily
APP_LOCALE=en
DB_HOST=127.0.0.1 DB_HOST=127.0.0.1
DB_PORT=3306 DB_PORT=3306
@ -27,4 +28,4 @@ MAIL_FROM=no-reply@example.com
QUEUE_HIGH=high QUEUE_HIGH=high
QUEUE_STANDARD=standard QUEUE_STANDARD=standard
QUEUE_LOW=low QUEUE_LOW=low

2
.gitignore vendored
View file

@ -27,5 +27,7 @@ misc
.phpstorm.meta.php .phpstorm.meta.php
.php_cs.cache .php_cs.cache
coverage.xml
# Vagrant # Vagrant
*.log *.log

View file

@ -12,6 +12,9 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
### Changed ### Changed
* Egg and server variable values are no longer limited to 191 characters. Turns out some games require a large number of characters in these fields. * Egg and server variable values are no longer limited to 191 characters. Turns out some games require a large number of characters in these fields.
### Added
* Users can now select their preferred language in their account settings.
## v0.7.9 (Derelict Dermodactylus) ## v0.7.9 (Derelict Dermodactylus)
### Fixed ### Fixed
* Fixes a two-factor authentication bypass present in the password reset process for an account. * Fixes a two-factor authentication bypass present in the password reset process for an account.

View file

@ -8,10 +8,13 @@ use Prologue\Alerts\AlertsMessageBag;
use Illuminate\Contracts\Session\Session; use Illuminate\Contracts\Session\Session;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\Users\UserUpdateService; use Pterodactyl\Services\Users\UserUpdateService;
use Pterodactyl\Traits\Helpers\AvailableLanguages;
use Pterodactyl\Http\Requests\Base\AccountDataFormRequest; use Pterodactyl\Http\Requests\Base\AccountDataFormRequest;
class AccountController extends Controller class AccountController extends Controller
{ {
use AvailableLanguages;
/** /**
* @var \Prologue\Alerts\AlertsMessageBag * @var \Prologue\Alerts\AlertsMessageBag
*/ */
@ -48,7 +51,9 @@ class AccountController extends Controller
*/ */
public function index() public function index()
{ {
return view('base.account'); return view('base.account', [
'languages' => $this->getAvailableLanguages(true),
]);
} }
/** /**
@ -70,7 +75,7 @@ class AccountController extends Controller
if ($request->input('do_action') === 'email') { if ($request->input('do_action') === 'email') {
$data = ['email' => $request->input('new_email')]; $data = ['email' => $request->input('new_email')];
} elseif ($request->input('do_action') === 'identity') { } elseif ($request->input('do_action') === 'identity') {
$data = $request->only(['name_first', 'name_last', 'username']); $data = $request->only(['name_first', 'name_last', 'username', 'language']);
} else { } else {
$data = []; $data = [];
} }

View file

@ -1,18 +1,10 @@
<?php <?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* This software is licensed under the terms of the MIT license.
* https://opensource.org/licenses/MIT
*/
namespace Pterodactyl\Http\Middleware; namespace Pterodactyl\Http\Middleware;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Contracts\Config\Repository;
class LanguageMiddleware class LanguageMiddleware
{ {
@ -21,25 +13,18 @@ class LanguageMiddleware
*/ */
private $app; private $app;
/**
* @var \Illuminate\Contracts\Config\Repository
*/
private $config;
/** /**
* LanguageMiddleware constructor. * LanguageMiddleware constructor.
* *
* @param \Illuminate\Foundation\Application $app * @param \Illuminate\Foundation\Application $app
* @param \Illuminate\Contracts\Config\Repository $config
*/ */
public function __construct(Application $app, Repository $config) public function __construct(Application $app)
{ {
$this->app = $app; $this->app = $app;
$this->config = $config;
} }
/** /**
* Handle an incoming request. * Handle an incoming request and set the user's preferred language.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
@ -47,7 +32,7 @@ class LanguageMiddleware
*/ */
public function handle(Request $request, Closure $next) public function handle(Request $request, Closure $next)
{ {
$this->app->setLocale($this->config->get('app.locale', 'en')); $this->app->setLocale($request->user()->language ?? config('app.locale', 'en'));
return $next($request); return $next($request);
} }

View file

@ -69,6 +69,7 @@ return [
'last_name' => 'Last Name', 'last_name' => 'Last Name',
'update_identity' => 'Update Identity', 'update_identity' => 'Update Identity',
'username_help' => 'Your username must be unique to your account, and may only contain the following characters: :requirements.', 'username_help' => 'Your username must be unique to your account, and may only contain the following characters: :requirements.',
'language' => 'Language',
], ],
'security' => [ 'security' => [
'session_mgmt_disabled' => 'Your host has not enabled the ability to manage account sessions via this interface.', 'session_mgmt_disabled' => 'Your host has not enabled the ability to manage account sessions via this interface.',

View file

@ -90,6 +90,19 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="form-group col-xs-12">
<label for="language" class="control-label">@lang('base.account.language')</label>
<div>
<select name="language" id="language" class="form-control">
{{ debug($languages) }}
@foreach($languages as $key => $value)
<option value="{{ $key }}" {{ Auth::user()->language !== $key ?: 'selected' }}>{{ $value }}</option>
@endforeach
</select>
</div>
</div>
</div>
</div> </div>
<div class="box-footer with-border"> <div class="box-footer with-border">
{!! csrf_field() !!} {!! csrf_field() !!}

View file

@ -107,7 +107,7 @@ class AccountControllerTest extends ControllerTestCase
$user = $this->generateRequestUserModel(); $user = $this->generateRequestUserModel();
$this->request->shouldReceive('input')->with('do_action')->andReturn('identity'); $this->request->shouldReceive('input')->with('do_action')->andReturn('identity');
$this->request->shouldReceive('only')->with(['name_first', 'name_last', 'username'])->once()->andReturn([ $this->request->shouldReceive('only')->with(['name_first', 'name_last', 'username', 'language'])->once()->andReturn([
'test_data' => 'value', 'test_data' => 'value',
]); ]);

View file

@ -3,8 +3,8 @@
namespace Tests\Unit\Http\Middleware; namespace Tests\Unit\Http\Middleware;
use Mockery as m; use Mockery as m;
use Pterodactyl\Models\User;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Contracts\Config\Repository;
use Pterodactyl\Http\Middleware\LanguageMiddleware; use Pterodactyl\Http\Middleware\LanguageMiddleware;
class LanguageMiddlewareTest extends MiddlewareTestCase class LanguageMiddlewareTest extends MiddlewareTestCase
@ -14,11 +14,6 @@ class LanguageMiddlewareTest extends MiddlewareTestCase
*/ */
private $appMock; private $appMock;
/**
* @var \Illuminate\Contracts\Config\Repository|\Mockery\Mock
*/
private $config;
/** /**
* Setup tests. * Setup tests.
*/ */
@ -27,20 +22,32 @@ class LanguageMiddlewareTest extends MiddlewareTestCase
parent::setUp(); parent::setUp();
$this->appMock = m::mock(Application::class); $this->appMock = m::mock(Application::class);
$this->config = m::mock(Repository::class);
} }
/** /**
* Test that a language is defined via the middleware. * Test that a language is defined via the middleware for guests.
*/ */
public function testLanguageIsSet() public function testLanguageIsSetForGuest()
{ {
$this->config->shouldReceive('get')->with('app.locale', 'en')->once()->andReturn('en'); $this->request->shouldReceive('user')->withNoArgs()->andReturnNull();
$this->appMock->shouldReceive('setLocale')->with('en')->once()->andReturnNull(); $this->appMock->shouldReceive('setLocale')->with('en')->once()->andReturnNull();
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions()); $this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
} }
/**
* Test that a language is defined via the middleware for a user.
*/
public function testLanguageIsSetWithAuthenticatedUser()
{
$user = factory(User::class)->make(['language' => 'de']);
$this->request->shouldReceive('user')->withNoArgs()->andReturn($user);
$this->appMock->shouldReceive('setLocale')->with('de')->once()->andReturnNull();
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
}
/** /**
* Return an instance of the middleware using mocked dependencies. * Return an instance of the middleware using mocked dependencies.
* *
@ -48,6 +55,6 @@ class LanguageMiddlewareTest extends MiddlewareTestCase
*/ */
private function getMiddleware(): LanguageMiddleware private function getMiddleware(): LanguageMiddleware
{ {
return new LanguageMiddleware($this->appMock, $this->config); return new LanguageMiddleware($this->appMock);
} }
} }