Merge branch 'lang'
This commit is contained in:
commit
6325109e80
20 changed files with 346 additions and 15 deletions
19
app/Http/Controllers/LocaleSessionController.php
Normal file
19
app/Http/Controllers/LocaleSessionController.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LocaleSessionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Set locale
|
||||
*/
|
||||
public function store(Request $request, $locale)
|
||||
{
|
||||
if (array_key_exists($locale, config('lang'))) {
|
||||
$request->session()->put('locale', $locale);
|
||||
}
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ class Kernel extends HttpKernel
|
|||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\App\Http\Middleware\Locale::class,
|
||||
// \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class Recipes extends Component
|
|||
return [Str::lower($item['name']) => $item['name']];
|
||||
});
|
||||
|
||||
$this->profession_options = collect(['' => '-- Profession --'])
|
||||
$this->profession_options = collect(['' => '-- ' . __('Profession') . ' --'])
|
||||
->merge($options)
|
||||
->toArray();
|
||||
}
|
||||
|
|
|
|||
25
app/Http/Middleware/Locale.php
Normal file
25
app/Http/Middleware/Locale.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class Locale extends Middleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (session()->has('locale')) {
|
||||
app()->setlocale(session()->get('locale'));
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
17
config/lang.php
Normal file
17
config/lang.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Language configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define available languages as locale (key), name (value) pairs.
|
||||
|
|
||||
*/
|
||||
|
||||
'en' => 'English',
|
||||
'se' => 'Svenska',
|
||||
|
||||
];
|
||||
7
resources/icons/flags/en.svg
Normal file
7
resources/icons/flags/en.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480">
|
||||
<path fill="#012169" d="M0 0h640v480H0z"/>
|
||||
<path fill="#FFF" d="M75 0l244 181L562 0h78v62L400 241l240 178v61h-80L320 301 81 480H0v-60l239-178L0 64V0h75z"/>
|
||||
<path fill="#C8102E" d="M424 281l216 159v40L369 281h55zm-184 20l6 35L54 480H0l240-179zM640 0v3L391 191l2-44L590 0h50zM0 0l239 176h-60L0 42V0z"/>
|
||||
<path fill="#FFF" d="M241 0v480h160V0H241zM0 160v160h640V160H0z"/>
|
||||
<path fill="#C8102E" d="M0 193v96h640v-96H0zM273 0v480h96V0h-96z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 516 B |
5
resources/icons/flags/se.svg
Normal file
5
resources/icons/flags/se.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480">
|
||||
<path fill="#066aa7" d="M0 0h640v480H0z"/>
|
||||
<path fill="#fecc00" d="M0 192h640v96H0z"/>
|
||||
<path fill="#fecc00" d="M176 0h96v480h-96z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 209 B |
39
resources/lang/se.json
Normal file
39
resources/lang/se.json
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"Add character": "Lägg till karaktär",
|
||||
"Character": "Karaktär",
|
||||
"Characters": "Karaktärer",
|
||||
"Class": "Klass",
|
||||
"Crafted item": "Tillverkat föremål",
|
||||
"Crafter": "Hantverkare",
|
||||
"Crafters": "Hantverkare",
|
||||
"Create": "Skapa",
|
||||
"Download this": "Ladda ner detta",
|
||||
"Gender": "Kön",
|
||||
"Import Profession": "Importera yrke",
|
||||
"Import string": "Import sträng",
|
||||
"Import": "Importera",
|
||||
"Items": "Föremål",
|
||||
"Login": "Logga in",
|
||||
"Logout": "Logga ut",
|
||||
"Name": "Namn",
|
||||
"None": "Ingen",
|
||||
"Only reagents": "Bara reagenser",
|
||||
"Owner": "Ägare",
|
||||
"Password": "Lösenord",
|
||||
"Profession": "Yrke",
|
||||
"Professions": "Yrken",
|
||||
"Race": "Ras",
|
||||
"Reagent for": "Reagens för",
|
||||
"Reagents": "Reagenser",
|
||||
"Recipe": "Recept",
|
||||
"Recipes": "Recept",
|
||||
"Roster": "Medlemmar",
|
||||
"Save": "Spara",
|
||||
"Showing": "Visar",
|
||||
"User": "Användare",
|
||||
"Username": "Användarnamn",
|
||||
"of": "av",
|
||||
"or": "eller",
|
||||
"results": "resultat",
|
||||
"to": "till"
|
||||
}
|
||||
20
resources/lang/se/auth.php
Normal file
20
resources/lang/se/auth.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used during authentication for various
|
||||
| messages that we need to display to the user. You are free to modify
|
||||
| these language lines according to your application's requirements.
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => 'Dessa uppgifter stämmer inte överens med vårt register.',
|
||||
'password' => 'Lösenordet var inte korrekt',
|
||||
'throttle' => 'För många inloggningsförsök. Var vänlig försök igen om :seconds sekunder.',
|
||||
|
||||
];
|
||||
19
resources/lang/se/pagination.php
Normal file
19
resources/lang/se/pagination.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pagination Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used by the paginator library to build
|
||||
| the simple pagination links. You are free to change them to anything
|
||||
| you want to customize your views to better match your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'previous' => '« Föregående',
|
||||
'next' => 'Nästa »',
|
||||
|
||||
];
|
||||
164
resources/lang/se/validation.php
Normal file
164
resources/lang/se/validation.php
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines contain the default error messages used by
|
||||
| the validator class. Some of these rules have multiple versions such
|
||||
| as the size rules. Feel free to tweak each of these messages here.
|
||||
|
|
||||
*/
|
||||
|
||||
'accepted' => ':Attribute måste accepteras.',
|
||||
'active_url' => ':Attribute är inte en giltig webbadress.',
|
||||
'after' => ':Attribute måste vara ett datum efter :date.',
|
||||
'after_or_equal' => ':Attribute måste vara ett datum senare eller samma dag som :date.',
|
||||
'alpha' => ':Attribute får endast innehålla bokstäver.',
|
||||
'alpha_dash' => ':Attribute får endast innehålla bokstäver, siffror och bindestreck.',
|
||||
'alpha_num' => ':Attribute får endast innehålla bokstäver och siffror.',
|
||||
'array' => ':Attribute måste vara en array.',
|
||||
'attached' => 'Denna :attribute är redan bifogad.',
|
||||
'before' => ':Attribute måste vara ett datum innan :date.',
|
||||
'before_or_equal' => ':Attribute måste vara ett datum före eller samma dag som :date.',
|
||||
'between' => [
|
||||
'array' => ':Attribute måste innehålla mellan :min - :max objekt.',
|
||||
'file' => ':Attribute måste vara mellan :min till :max kilobyte stor.',
|
||||
'numeric' => ':Attribute måste vara en siffra mellan :min och :max.',
|
||||
'string' => ':Attribute måste innehålla :min till :max tecken.',
|
||||
],
|
||||
'boolean' => ':Attribute måste vara sant eller falskt.',
|
||||
'confirmed' => ':Attribute bekräftelsen matchar inte.',
|
||||
'current_password' => 'The password is incorrect.',
|
||||
'date' => ':Attribute är inte ett giltigt datum.',
|
||||
'date_equals' => ':Attribute måste vara ett datum lika med :date.',
|
||||
'date_format' => ':Attribute matchar inte formatet :format.',
|
||||
'different' => ':Attribute och :other får inte vara lika.',
|
||||
'digits' => ':Attribute måste vara :digits tecken.',
|
||||
'digits_between' => ':Attribute måste vara mellan :min och :max tecken.',
|
||||
'dimensions' => ':Attribute har felaktiga bilddimensioner.',
|
||||
'distinct' => ':Attribute innehåller fler än en repetition av samma element.',
|
||||
'email' => ':Attribute måste innehålla en korrekt e-postadress.',
|
||||
'ends_with' => ':Attribute måste sluta med en av följande: :values.',
|
||||
'exists' => ':Attribute är ogiltigt.',
|
||||
'file' => ':Attribute måste vara en fil.',
|
||||
'filled' => ':Attribute är obligatoriskt.',
|
||||
'gt' => [
|
||||
'array' => ':Attribute måste innehålla fler än :value objekt.',
|
||||
'file' => ':Attribute måste vara större än :value kilobyte stor.',
|
||||
'numeric' => ':Attribute måste vara större än :value.',
|
||||
'string' => ':Attribute måste vara längre än :value tecken.',
|
||||
],
|
||||
'gte' => [
|
||||
'array' => ':Attribute måste innehålla lika många eller fler än :value objekt.',
|
||||
'file' => ':Attribute måste vara lika med eller större än :value kilobyte stor.',
|
||||
'numeric' => ':Attribute måste vara lika med eller större än :value.',
|
||||
'string' => ':Attribute måste vara lika med eller längre än :value tecken.',
|
||||
],
|
||||
'image' => ':Attribute måste vara en bild.',
|
||||
'in' => ':Attribute är ogiltigt.',
|
||||
'in_array' => ':Attribute finns inte i :other.',
|
||||
'integer' => ':Attribute måste vara en siffra.',
|
||||
'ip' => ':Attribute måste vara en giltig IP-adress.',
|
||||
'ipv4' => ':Attribute måste vara en giltig IPv4-adress.',
|
||||
'ipv6' => ':Attribute måste vara en giltig IPv6-adress.',
|
||||
'json' => ':Attribute måste vara en giltig JSON-sträng.',
|
||||
'lt' => [
|
||||
'array' => ':Attribute måste innehålla färre än :value objekt.',
|
||||
'file' => ':Attribute måste vara mindre än :value kilobyte stor.',
|
||||
'numeric' => ':Attribute måste vara mindre än :value.',
|
||||
'string' => ':Attribute måste vara kortare än :value tecken.',
|
||||
],
|
||||
'lte' => [
|
||||
'array' => ':Attribute måste innehålla lika många eller färre än :value objekt.',
|
||||
'file' => ':Attribute måste vara lika med eller mindre än :value kilobyte stor.',
|
||||
'numeric' => ':Attribute måste vara lika med eller mindre än :value.',
|
||||
'string' => ':Attribute måste vara lika med eller kortare än :value tecken.',
|
||||
],
|
||||
'max' => [
|
||||
'array' => ':Attribute får inte innehålla mer än :max objekt.',
|
||||
'file' => ':Attribute får max vara :max kilobyte stor.',
|
||||
'numeric' => ':Attribute får inte vara större än :max.',
|
||||
'string' => ':Attribute får max innehålla :max tecken.',
|
||||
],
|
||||
'mimes' => ':Attribute måste vara en fil av typen: :values.',
|
||||
'mimetypes' => ':Attribute måste vara en fil av typen: :values.',
|
||||
'min' => [
|
||||
'array' => ':Attribute måste innehålla minst :min objekt.',
|
||||
'file' => ':Attribute måste vara minst :min kilobyte stor.',
|
||||
'numeric' => ':Attribute måste vara större än :min.',
|
||||
'string' => ':Attribute måste innehålla minst :min tecken.',
|
||||
],
|
||||
'multiple_of' => ':attribute måste vara en multipel av :value',
|
||||
'not_in' => ':Attribute är ogiltigt.',
|
||||
'not_regex' => 'Formatet för :attribute är ogiltigt.',
|
||||
'numeric' => ':Attribute måste vara en siffra.',
|
||||
'password' => 'Lösenordet är fel.',
|
||||
'present' => ':Attribute måste finnas med.',
|
||||
'prohibited' => 'Fältet :attribute är förbjudet.',
|
||||
'prohibited_if' => ':attribute är förbjudet när :other är :value.',
|
||||
'prohibited_unless' => ':attribute är förbjudet om inte :other är :values.',
|
||||
'regex' => ':Attribute har ogiltigt format.',
|
||||
'relatable' => 'Denna :attribute kanske inte är associerad med den här resursen.',
|
||||
'required' => ':Attribute är obligatoriskt.',
|
||||
'required_if' => ':Attribute är obligatoriskt när :other är :value.',
|
||||
'required_unless' => ':Attribute är obligatoriskt när inte :other finns bland :values.',
|
||||
'required_with' => ':Attribute är obligatoriskt när :values är ifyllt.',
|
||||
'required_with_all' => ':Attribute är obligatoriskt när :values är ifyllt.',
|
||||
'required_without' => ':Attribute är obligatoriskt när :values ej är ifyllt.',
|
||||
'required_without_all' => ':Attribute är obligatoriskt när ingen av :values är ifyllt.',
|
||||
'same' => ':Attribute och :other måste vara lika.',
|
||||
'size' => [
|
||||
'array' => ':Attribute måste innehålla :size objekt.',
|
||||
'file' => ':Attribute får endast vara :size kilobyte stor.',
|
||||
'numeric' => ':Attribute måste vara :size.',
|
||||
'string' => ':Attribute måste innehålla :size tecken.',
|
||||
],
|
||||
'starts_with' => ':Attribute måste börja med en av följande: :values',
|
||||
'string' => ':Attribute måste vara en sträng.',
|
||||
'timezone' => ':Attribute måste vara en giltig tidszon.',
|
||||
'unique' => ':Attribute används redan.',
|
||||
'uploaded' => ':Attribute kunde inte laddas upp.',
|
||||
'url' => ':Attribute har ett ogiltigt format.',
|
||||
'uuid' => ':Attribute måste vara ett giltigt UUID.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify custom validation messages for attributes using the
|
||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||
| specify a specific custom language line for a given attribute rule.
|
||||
|
|
||||
*/
|
||||
|
||||
'custom' => [
|
||||
'attribute-name' => [
|
||||
'rule-name' => 'custom-message',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Attributes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used to swap our attribute placeholder
|
||||
| with something more reader friendly such as "E-Mail Address" instead
|
||||
| of "email". This simply helps us make our message more expressive.
|
||||
|
|
||||
*/
|
||||
|
||||
'attributes' => [
|
||||
'username' => 'användarnamn',
|
||||
'password' => 'lösenord',
|
||||
'name' => 'namn',
|
||||
'race' => 'ras',
|
||||
'class' => 'klass',
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
<x-layout name="auth">
|
||||
|
||||
<h1 class="text-gray-500 text-3xl text-center mb-4">Login</h1>
|
||||
<h1 class="text-gray-500 text-3xl text-center mb-4">{{ __('Login') }}</h1>
|
||||
|
||||
<x-form action="{{ route('auth.login.store') }}">
|
||||
<x-input name="username" placeholder="{{ __('Username') }}" class="mb-2"/>
|
||||
<x-input-password placeholder="{{ __('Password') }}" class="mb-2" />
|
||||
<x-button element="input" type="submit" name="submit" value="Login" class="w-full" />
|
||||
<x-button element="input" type="submit" name="submit" value="{{ __('Login') }}" class="w-full" />
|
||||
</x-form>
|
||||
|
||||
@if (config('services.discord.client_id'))
|
||||
<div class="flex items-center justify-between my-4">
|
||||
<div class="bg-gray-200 h-px w-full"></div>
|
||||
<div class="text-gray-400 mx-4">OR</div>
|
||||
<div class="text-gray-400 mx-4 uppercase">{{ __('or') }}</div>
|
||||
<div class="bg-gray-200 h-px w-full"></div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@
|
|||
</x-slot>
|
||||
|
||||
<div class="mx-auto max-w-sm p-4">
|
||||
<p>Download this <x-link href="https://www.curseforge.com/wow/addons/professions-exporter" target="_blank">exporter addon</x-link>
|
||||
<p>
|
||||
{{ __('Download this') }}
|
||||
<x-link href="https://www.curseforge.com/wow/addons/professions-exporter" target="_blank">{{ __('addon') }}</x-link>
|
||||
</p>
|
||||
|
||||
<x-form action="{{ route('character.profession.store', [ 'character' => $character->slug ]) }}">
|
||||
<div class="mb-2">
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
</x-link>
|
||||
|
||||
<x-section-heading>
|
||||
<h2 class="text-3xl">Professions</h2>
|
||||
<h2 class="text-3xl">{{ __('Professions') }}</h2>
|
||||
<div>
|
||||
@can('import_profession', $character)
|
||||
<x-button element="a" class="flex items-center" href="{{ route('character.profession.create', [ 'character' => $character->slug ]) }}">
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
<div class="flex justify-between">
|
||||
<p>
|
||||
{{ Str::ucfirst($character->race) }}
|
||||
{{ Str::ucfirst($character->class) }}
|
||||
{{ __(Str::ucfirst($character->race)) }}
|
||||
{{ __(Str::ucfirst($character->class)) }}
|
||||
</p>
|
||||
|
||||
<div class="flex gap-1">
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<x-button element="input" type="submit" value="{{$this->character->exists ? 'Save' : 'Create' }}" />
|
||||
<x-button element="input" type="submit" value="{{ __($this->character->exists ? 'Save' : 'Create') }}" />
|
||||
</div>
|
||||
|
||||
</x-form>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-4 mb-2">
|
||||
<x-input wire:model="name" name="name" placeholder="Recipe" />
|
||||
<x-input wire:model="crafter" name="crafter" placeholder="Crafter" />
|
||||
<x-input wire:model="name" name="name" placeholder="{{ __('Recipe') }}" />
|
||||
<x-input wire:model="crafter" name="crafter" placeholder="{{ __('Crafter') }}" />
|
||||
<x-select wire:model="profession" name="profession" :options="$profession_options" />
|
||||
</div>
|
||||
|
||||
|
|
@ -10,9 +10,9 @@
|
|||
<table class="w-full whitespace-nowrap">
|
||||
<thead>
|
||||
<tr tabindex="0" class="focus:outline-none w-full text-sm leading-none text-gray-800">
|
||||
<th class="text-left px-3 py-4">Recipe</th>
|
||||
<th class="text-left px-3 py-4">Profession</th>
|
||||
<th class="text-left px-3 py-4">Crafters</th>
|
||||
<th class="text-left px-3 py-4">{{ __('Recipe') }}</th>
|
||||
<th class="text-left px-3 py-4">{{ __('Profession') }}</th>
|
||||
<th class="text-left px-3 py-4">{{ __('Crafters') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="w-full">
|
||||
|
|
|
|||
|
|
@ -26,6 +26,15 @@
|
|||
@else
|
||||
<a href="{{ route('auth.login') }}">{{ __('Login') }}</a>
|
||||
@endauth
|
||||
|
||||
<div class="flex space-x-2">
|
||||
@foreach(config('lang') as $locale => $name)
|
||||
<a href="{{ route('locale.store', ['locale' => $locale ]) }}" title="{{ $name }}">
|
||||
<x-icon class="w-6 h-6" name="flags.{{ $locale }}" />
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
@if ($recipe->craft)
|
||||
<div class="mb-4">
|
||||
<x-section-heading>
|
||||
<h2 class="text-3xl">{{ __('Created item') }}</h2>
|
||||
<h2 class="text-3xl">{{ __('Crafted item') }}</h2>
|
||||
</x-section-heading>
|
||||
<p class="px-4 space-y-2">
|
||||
@if ($recipe->craft->external_id)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
use App\Http\Controllers\LocaleSessionController;
|
||||
use App\Http\Controllers\UserController;
|
||||
use App\Http\Controllers\ProfileController;
|
||||
use App\Http\Controllers\CharacterController;
|
||||
|
|
@ -38,6 +39,8 @@ Route::name('auth.')->group(function () {
|
|||
// Public section
|
||||
// ----------------------------
|
||||
|
||||
Route::get('/lang/{locale}', [LocaleSessionController::class, 'store'])->name('locale.store');
|
||||
|
||||
Route::prefix('user')->name('user.')->group(function() {
|
||||
Route::get('{user}', [UserController::class, 'show'])->name('show');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue