diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index a76105fa6..eebd4cd4f 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -62,6 +62,7 @@ class UserController extends Controller
$this->checkPermission('users-manage');
$authMethod = config('auth.method');
$roles = $this->userRepo->getAllRoles();
+ $this->setPageTitle(trans('settings.users_add_new'));
return view('users.create', ['authMethod' => $authMethod, 'roles' => $roles]);
}
@@ -78,6 +79,7 @@ class UserController extends Controller
$validationRules = [
'name' => ['required'],
'email' => ['required', 'email', 'unique:users,email'],
+ 'setting' => ['array'],
];
$authMethod = config('auth.method');
@@ -104,6 +106,13 @@ class UserController extends Controller
DB::transaction(function () use ($user, $sendInvite, $request) {
$user->save();
+ // Save user-specific settings
+ if ($request->filled('setting')) {
+ foreach ($request->get('setting') as $key => $value) {
+ setting()->putUser($user, $key, $value);
+ }
+ }
+
if ($sendInvite) {
$this->inviteService->sendInvitation($user);
}
@@ -198,7 +207,7 @@ class UserController extends Controller
$user->external_auth_id = $request->get('external_auth_id');
}
- // Save an user-specific settings
+ // Save user-specific settings
if ($request->filled('setting')) {
foreach ($request->get('setting') as $key => $value) {
setting()->putUser($user, $key, $value);
diff --git a/app/Notifications/UserInvite.php b/app/Notifications/UserInvite.php
index b0dc9afac..3bae32721 100644
--- a/app/Notifications/UserInvite.php
+++ b/app/Notifications/UserInvite.php
@@ -2,35 +2,33 @@
namespace BookStack\Notifications;
+use BookStack\Auth\User;
+use Illuminate\Notifications\Messages\MailMessage;
+
class UserInvite extends MailNotification
{
public $token;
/**
* Create a new notification instance.
- *
- * @param string $token
*/
- public function __construct($token)
+ public function __construct(string $token)
{
$this->token = $token;
}
/**
* Get the mail representation of the notification.
- *
- * @param mixed $notifiable
- *
- * @return \Illuminate\Notifications\Messages\MailMessage
*/
- public function toMail($notifiable)
+ public function toMail(User $notifiable): MailMessage
{
$appName = ['appName' => setting('app-name')];
+ $language = setting()->getUser($notifiable, 'language');
return $this->newMailMessage()
- ->subject(trans('auth.user_invite_email_subject', $appName))
- ->greeting(trans('auth.user_invite_email_greeting', $appName))
- ->line(trans('auth.user_invite_email_text'))
- ->action(trans('auth.user_invite_email_action'), url('/register/invite/' . $this->token));
+ ->subject(trans('auth.user_invite_email_subject', $appName, $language))
+ ->greeting(trans('auth.user_invite_email_greeting', $appName, $language))
+ ->line(trans('auth.user_invite_email_text', [], $language))
+ ->action(trans('auth.user_invite_email_action', [], $language), url('/register/invite/' . $this->token));
}
}
diff --git a/resources/views/users/create.blade.php b/resources/views/users/create.blade.php
index 960e38f7c..7015b162a 100644
--- a/resources/views/users/create.blade.php
+++ b/resources/views/users/create.blade.php
@@ -16,6 +16,7 @@
@include('users.parts.form')
+ @include('users.parts.language-option-row', ['value' => old('setting.language') ?? config('app.default_locale')])
diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php
index 997fd1bf0..41e64dbb9 100644
--- a/resources/views/users/edit.blade.php
+++ b/resources/views/users/edit.blade.php
@@ -35,22 +35,7 @@
-
-
-
-
- {{ trans('settings.users_preferred_language_desc') }}
-
-
-
-
-
-
-
+ @include('users.parts.language-option-row', ['value' => setting()->getUser($user, 'language', config('app.default_locale'))])
diff --git a/resources/views/users/parts/language-option-row.blade.php b/resources/views/users/parts/language-option-row.blade.php
new file mode 100644
index 000000000..82907b53d
--- /dev/null
+++ b/resources/views/users/parts/language-option-row.blade.php
@@ -0,0 +1,18 @@
+{{--
+$value - Currently selected lanuage value
+--}}
+
+
+
+
+ {{ trans('settings.users_preferred_language_desc') }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Auth/UserInviteTest.php b/tests/Auth/UserInviteTest.php
index 1e1235f33..5b9b14e60 100644
--- a/tests/Auth/UserInviteTest.php
+++ b/tests/Auth/UserInviteTest.php
@@ -6,6 +6,7 @@ use BookStack\Auth\Access\UserInviteService;
use BookStack\Auth\User;
use BookStack\Notifications\UserInvite;
use Carbon\Carbon;
+use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Str;
@@ -20,8 +21,8 @@ class UserInviteTest extends TestCase
$email = Str::random(16) . '@example.com';
$resp = $this->actingAs($admin)->post('/settings/users/create', [
- 'name' => 'Barry',
- 'email' => $email,
+ 'name' => 'Barry',
+ 'email' => $email,
'send_invite' => 'true',
]);
$resp->assertRedirect('/settings/users');
@@ -34,6 +35,31 @@ class UserInviteTest extends TestCase
]);
}
+ public function test_user_invite_sent_in_selected_language()
+ {
+ Notification::fake();
+ $admin = $this->getAdmin();
+
+ $email = Str::random(16) . '@example.com';
+ $resp = $this->actingAs($admin)->post('/settings/users/create', [
+ 'name' => 'Barry',
+ 'email' => $email,
+ 'send_invite' => 'true',
+ 'setting' => [
+ 'language' => 'de',
+ ]
+ ]);
+ $resp->assertRedirect('/settings/users');
+
+ $newUser = User::query()->where('email', '=', $email)->orderBy('id', 'desc')->first();
+ Notification::assertSentTo($newUser, UserInvite::class, function ($notification, $channels, $notifiable) {
+ /** @var MailMessage $mail */
+ $mail = $notification->toMail($notifiable);
+ return 'Du wurdest eingeladen BookStack beizutreten!' === $mail->subject &&
+ 'Ein Konto wurde für Sie auf BookStack erstellt.' === $mail->greeting;
+ });
+ }
+
public function test_invite_set_password()
{
Notification::fake();
@@ -54,7 +80,7 @@ class UserInviteTest extends TestCase
]);
$setPasswordResp->assertSee('Password set, you should now be able to login using your set password to access BookStack!');
$newPasswordValid = auth()->validate([
- 'email' => $user->email,
+ 'email' => $user->email,
'password' => 'my test password',
]);
$this->assertTrue($newPasswordValid);
diff --git a/tests/User/UserManagementTest.php b/tests/User/UserManagementTest.php
index 806e35ad4..2fbbee7e2 100644
--- a/tests/User/UserManagementTest.php
+++ b/tests/User/UserManagementTest.php
@@ -183,6 +183,16 @@ class UserManagementTest extends TestCase
$resp->assertSee('cannot delete the guest user');
}
+ public function test_user_create_language_reflects_default_system_locale()
+ {
+ $langs = ['en', 'fr', 'hr'];
+ foreach ($langs as $lang) {
+ config()->set('app.locale', $lang);
+ $resp = $this->asAdmin()->get('/settings/users/create');
+ $resp->assertElementExists('select[name="setting[language]"] option[value="' . $lang . '"][selected]');
+ }
+ }
+
public function test_user_creation_is_not_performed_if_the_invitation_sending_fails()
{
/** @var User $user */