Skip to content

Commit

Permalink
feat: change language dynamically (#932)
Browse files Browse the repository at this point in the history
  • Loading branch information
asbiin committed May 31, 2021
1 parent 49981d4 commit 8d3380b
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 35 deletions.
8 changes: 4 additions & 4 deletions app/Http/Controllers/User/LocaleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace App\Http\Controllers\User;

use Inertia\Response;
use Illuminate\Http\Request;
use App\Services\User\UpdateLocale;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;

class LocaleController extends Controller
Expand All @@ -23,8 +23,8 @@ public function update(Request $request)
'locale' => $request->input('locale'),
]);

return response()->json([
'data' => true,
], 200);
return $request->wantsJson()
? new JsonResponse('', 200)
: back()->with('status', 'locale-changed');
}
}
7 changes: 5 additions & 2 deletions app/Http/Middleware/ShareInertiaData.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace App\Http\Middleware;

use App\Helpers\LocaleHelper;
use Inertia\Inertia;
use Laravel\Jetstream\Jetstream;
use Illuminate\Support\Facades\Session;

/**
Expand All @@ -26,14 +26,17 @@ public function handle($request, $next)
'jetstream' => function () use ($request) {
return [
'flash' => $request->session()->get('flash', []),
'languages' => LocaleHelper::getLocaleList(),
];
},
'user' => function () use ($request) {
if (! $request->user()) {
return;
}

return [];
return [
'two_factor_enabled' => ! is_null($request->user()->two_factor_secret),
];
},
'errorBags' => function () {
return collect(optional(Session::get('errors'))->getBags() ?: [])->mapWithKeys(function ($bag, $key) {
Expand Down
1 change: 1 addition & 0 deletions app/Models/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class User extends Authenticatable implements MustVerifyEmail
'nickname',
'uuid',
'show_help',
'locale',
];

/**
Expand Down
7 changes: 6 additions & 1 deletion app/Services/User/UpdateLocale.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Models\User\User;
use App\Services\BaseService;
use Illuminate\Validation\Rule;

class UpdateLocale extends BaseService
{
Expand All @@ -19,7 +20,11 @@ public function rules(): array
{
return [
'user_id' => 'required|integer|exists:users,id',
'locale' => 'required|string',
'locale' => [
'required',
'string',
Rule::in(config('lang-detector.languages')),
],
];
}

Expand Down
53 changes: 33 additions & 20 deletions resources/js/Pages/Profile/Partials/UpdateLocale.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@
</template>

<template #form>
<select v-model="form.locale">
<option value="en">
{{ $t('app.locale_en') }}
</option>
<option value="fr">
{{ $t('app.locale_fr') }}
</option>
</select>
<select-box v-model="form.locale"
:options="localesFiltered"
:required="true"
/>
</template>

<template #actions>
Expand All @@ -30,44 +26,61 @@
<script>
import LoadingButton from '@/Shared/LoadingButton';
import FormSection from '@/Shared/Layout/FormSection';
import SelectBox from '@/Shared/Select';
import { useForm } from '@inertiajs/inertia-vue3';
export default {
components: {
LoadingButton,
FormSection,
SelectBox,
},
props: {
user: {
type: Object,
default: null,
},
locales: {
type: Array,
default: () => [],
}
},
data() {
return {
form: {
locale: null,
},
loadingState: '',
form: useForm({
locale: '',
}),
};
},
computed: {
localesFiltered: function() {
return _.map(this.locales, locale => {
return {
value: locale.lang,
label: locale['name-orig'] + (locale['name-orig'] !== locale.name ? ' (' + locale.name + ')' : ''),
};
});
}
},
mounted() {
this.form.locale = this.$page.props.auth.user.locale;
},
methods: {
updateLocale() {
axios.post('/locale', this.form)
.then(response => {
this.flash(this.$t('app.saved'), 'success');
this.loadingState = null;
Promise.all([
this.loadLanguage(this.form.locale, true),
this.form.post('/locale', {
preserveScroll: true,
onSuccess: () => {
this.flash(this.$t('app.saved'), 'success');
},
})
.catch(error => {
this.loadingState = null;
});
]);
},
},
};
Expand Down
3 changes: 1 addition & 2 deletions resources/js/Pages/Profile/Show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<update-password-form class="mt1" />

<update-locale :user="$page.props.auth.user" class="mt1" />
<update-locale :user="$page.props.auth.user" :locales="$page.props.jetstream.languages" class="mt1" />

<two-factor-authentication-form class="mt1" />

Expand All @@ -28,7 +28,6 @@ export default {
components: {
Layout,
// DeleteUserForm,
LogoutOtherBrowserSessionsForm,
TwoFactorAuthenticationForm,
UpdatePasswordForm,
Expand Down
7 changes: 6 additions & 1 deletion resources/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ langs.loadLanguage(document.querySelector('html').getAttribute('lang'), true)

Sentry.init(app, process.env.MIX_SENTRY_RELEASE);

app.mixin({ methods: _.assign({ route }, require('./methods').default) })
app.mixin({ methods: _.assign({
route,
loadLanguage: function(locale, set) {
return langs.loadLanguage(locale, set);
}
}, require('./methods').default) })
.use(InertiaPlugin)
.use(langs.i18n)
.mount(el);
Expand Down
7 changes: 2 additions & 5 deletions resources/js/langs.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import pluralization from './pluralization.js';

export default {
i18n: createI18n({
locale: 'en',
locale: 'en', // default locale
fallbackLocale: 'en',
messages: {'en': messages},
pluralizationRules: pluralization,
}),

loadedLanguages : ['en'], // our default language that is preloaded

_setI18nLanguage (lang) {
if (this.i18n.mode === 'legacy') {
this.i18n.global.locale = lang;
Expand All @@ -26,12 +24,11 @@ export default {

_loadLanguageAsync (lang) {
if (this.i18n.locale !== lang) {
if (!this.loadedLanguages.includes(lang)) {
if (!this.i18n.global.availableLocales.includes(lang)) {
return this._loadLanguageMessagesAsync(lang)
.then(msgs => {
if (msgs !== null) {
this.i18n.global.setLocaleMessage(lang, msgs);
this.loadedLanguages.push(lang);
}
return this.i18n;
});
Expand Down
4 changes: 4 additions & 0 deletions resources/lang/fr/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,8 @@
'demo_mode_read_more' => 'En savoir plus',
'demo_mode_deactivated' => 'Cette fonctionnalité est désactivées en mode démo.',
'demo_mode_desc' => 'Il s’agit d’un compte de démo. Certaines fonctionnalités sont désactivées. Les données sont réinitialisées toutes les 5 minutes.',

'locale_en' => 'Anglais',
'locale_fr' => 'Français',

];
64 changes: 64 additions & 0 deletions tests/Unit/Services/User/UpdateLocaleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Tests\Unit\Services\User;

use Tests\TestCase;
use App\Models\User\User;
use App\Services\User\UpdateLocale;
use Illuminate\Validation\ValidationException;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class UpdateLocaleTest extends TestCase
{
use DatabaseTransactions;

/** @test */
public function it_update_the_locale(): void
{
$user = User::factory()->create([
'locale' => 'xx',
]);

$request = [
'user_id' => $user->id,
'locale' => 'en',
];

(new UpdateLocale)->execute($request);

$user->refresh();
$this->assertEquals('en', $user->locale);
}

/** @test */
public function it_fails_if_given_locale_is_wrong(): void
{
$user = User::factory()->create([
'locale' => 'en',
]);

$request = [
'user_id' => $user->id,
'locale' => 'xx',
];

$this->expectException(ValidationException::class);
(new UpdateLocale)->execute($request);
}

/** @test */
public function it_fails_if_given_locale_is_empty(): void
{
$user = User::factory()->create([
'locale' => 'en',
]);

$request = [
'user_id' => $user->id,
'locale' => '',
];

$this->expectException(ValidationException::class);
(new UpdateLocale)->execute($request);
}
}

0 comments on commit 8d3380b

Please sign in to comment.