From 4c9a26c74da32acc8956d106f8499c43808a2625 Mon Sep 17 00:00:00 2001 From: Matthew RONCHETTO Date: Fri, 27 Oct 2023 09:47:34 -0700 Subject: [PATCH 001/102] chore: add osu!supporter link to profile badge (fixes #10301) --- resources/js/profile-page/cover.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/js/profile-page/cover.tsx b/resources/js/profile-page/cover.tsx index da2f5591c48..4bd07af69fb 100644 --- a/resources/js/profile-page/cover.tsx +++ b/resources/js/profile-page/cover.tsx @@ -126,9 +126,11 @@ export default class Cover extends React.Component { return ( <> {this.props.user.is_supporter && - - {times(this.props.user.support_level ?? 0, (i) => )} - + + + {times(this.props.user.support_level ?? 0, (i) => )} + + } From 0dd3ff7959c0f6eda75e8534edfdcb53d0da5cff Mon Sep 17 00:00:00 2001 From: Matt Ronchetto Date: Mon, 30 Oct 2023 23:10:46 -0700 Subject: [PATCH 002/102] fix: alignment on mobile --- resources/js/profile-page/cover.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/js/profile-page/cover.tsx b/resources/js/profile-page/cover.tsx index 4bd07af69fb..2b697df647a 100644 --- a/resources/js/profile-page/cover.tsx +++ b/resources/js/profile-page/cover.tsx @@ -126,10 +126,8 @@ export default class Cover extends React.Component { return ( <> {this.props.user.is_supporter && - - + {times(this.props.user.support_level ?? 0, (i) => )} - } From 1a9ea8cee25b50e4440479220c5ffd1d442054a3 Mon Sep 17 00:00:00 2001 From: Sam Verhaegen Date: Thu, 9 Nov 2023 20:52:29 +0200 Subject: [PATCH 003/102] make beatmapset status link to wiki --- resources/js/beatmapsets-show/header.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/resources/js/beatmapsets-show/header.tsx b/resources/js/beatmapsets-show/header.tsx index 33d1f38de70..c12d78bfaa1 100644 --- a/resources/js/beatmapsets-show/header.tsx +++ b/resources/js/beatmapsets-show/header.tsx @@ -352,13 +352,25 @@ export default class Header extends React.Component { } -
- {trans(`beatmapsets.show.status.${this.controller.currentBeatmap.status}`)} -
+ +
+ {trans(`beatmapsets.show.status.${this.controller.currentBeatmap.status}`)} +
+
); } + private statusToWikiLink(status: string): string { + let fragment: string; + if (status === 'wip' || status === 'pending') { + fragment = 'work-in-progress-and-pending'; + } else { + fragment = status; + } + return wikiUrl(`Beatmap/Category#${fragment}`); + } + private readonly updateFavouritePopup = () => { if (!this.hoveredFavouriteIcon) { return; From 3d34d3005e4cd770d437915646c4bf2b1b7e2aaa Mon Sep 17 00:00:00 2001 From: Sam Verhaegen Date: Fri, 10 Nov 2023 14:18:45 +0200 Subject: [PATCH 004/102] fix styling --- resources/js/beatmapsets-show/header.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/resources/js/beatmapsets-show/header.tsx b/resources/js/beatmapsets-show/header.tsx index c12d78bfaa1..e89a12f45fb 100644 --- a/resources/js/beatmapsets-show/header.tsx +++ b/resources/js/beatmapsets-show/header.tsx @@ -352,10 +352,8 @@ export default class Header extends React.Component { } - -
- {trans(`beatmapsets.show.status.${this.controller.currentBeatmap.status}`)} -
+
+ {trans(`beatmapsets.show.status.${this.controller.currentBeatmap.status}`)} ); From 1bee8a98a512d3ce7706acac4996af5ffb206a10 Mon Sep 17 00:00:00 2001 From: Sam Verhaegen Date: Fri, 10 Nov 2023 17:55:30 +0200 Subject: [PATCH 005/102] shorten `work-in-progress-and-pending` fragment --- resources/js/beatmapsets-show/header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/beatmapsets-show/header.tsx b/resources/js/beatmapsets-show/header.tsx index e89a12f45fb..a5de41aa565 100644 --- a/resources/js/beatmapsets-show/header.tsx +++ b/resources/js/beatmapsets-show/header.tsx @@ -362,7 +362,7 @@ export default class Header extends React.Component { private statusToWikiLink(status: string): string { let fragment: string; if (status === 'wip' || status === 'pending') { - fragment = 'work-in-progress-and-pending'; + fragment = 'wip-and-pending'; } else { fragment = status; } From 2b60dc8ec7f9b2e4218444e966b58a8adc105035 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 24 Nov 2023 22:33:08 +0900 Subject: [PATCH 006/102] Clean up oauth client and token models - add missing scope property on client - add token scope set memoize - add faster attribute getter to token --- app/Models/Model.php | 43 +-------------- app/Models/OAuth/Client.php | 2 + app/Models/OAuth/Token.php | 75 +++++++++++++++++--------- app/Models/Traits/FasterAttributes.php | 53 ++++++++++++++++++ 4 files changed, 106 insertions(+), 67 deletions(-) create mode 100644 app/Models/Traits/FasterAttributes.php diff --git a/app/Models/Model.php b/app/Models/Model.php index d04ddb8f140..441ac65ed74 100644 --- a/app/Models/Model.php +++ b/app/Models/Model.php @@ -12,7 +12,6 @@ use App\Libraries\TransactionStateManager; use App\Scopes\MacroableModelScope; use App\Traits\Validatable; -use Carbon\Carbon; use Exception; use Illuminate\Database\ClassMorphViolationException; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -20,7 +19,7 @@ abstract class Model extends BaseModel { - use HasFactory, Validatable; + use HasFactory, Traits\FasterAttributes, Validatable; const MAX_FIELD_LENGTHS = []; @@ -72,11 +71,6 @@ public function getMorphClass() throw new ClassMorphViolationException($this); } - public function getRawAttribute(string $key) - { - return $this->attributes[$key] ?? null; - } - /** * Locks the current model for update with `select for update`. * @@ -240,41 +234,6 @@ public function tableName(bool $includeDbPrefix = false) return ($includeDbPrefix ? $this->dbName().'.' : '').$this->getTable(); } - /** - * Fast Time Attribute Getter (kind of) - * - * This is only usable for models with default dateFormat (`Y-m-d H:i:s`). - */ - protected function getTimeFast(string $key): ?Carbon - { - $value = $this->getRawAttribute($key); - - return $value === null - ? null - : Carbon::createFromFormat('Y-m-d H:i:s', $value); - } - - /** - * Fast Time Attribute to Json Transformer - * - * Key must be suffixed with `_json`. - * This is only usable for models with default dateFormat (`Y-m-d H:i:s`). - */ - protected function getJsonTimeFast(string $key): ?string - { - $value = $this->getRawAttribute(substr($key, 0, -5)); - - if ($value === null) { - return null; - } - - // From: "2020-10-10 10:10:10" - // To: "2020-10-10T10:10:10Z" - $value[10] = 'T'; - - return "{$value}Z"; - } - // Allows save/update/delete to work with composite primary keys. // Note this doesn't fix 'find' method and a bunch of other laravel things // which rely on getKeyName and getKey (and they themselves are broken as well). diff --git a/app/Models/OAuth/Client.php b/app/Models/OAuth/Client.php index de0060a1b7f..d15fc1a7912 100644 --- a/app/Models/OAuth/Client.php +++ b/app/Models/OAuth/Client.php @@ -63,6 +63,8 @@ public static function newFactory() return null; } + public ?array $scopes = null; + public function refreshTokens() { return $this->hasManyThrough( diff --git a/app/Models/OAuth/Token.php b/app/Models/OAuth/Token.php index 91c08122520..402388f50cf 100644 --- a/app/Models/OAuth/Token.php +++ b/app/Models/OAuth/Token.php @@ -7,6 +7,7 @@ use App\Events\UserSessionEvent; use App\Exceptions\InvalidScopeException; +use App\Models\Traits\FasterAttributes; use App\Models\User; use Ds\Set; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -16,9 +17,19 @@ class Token extends PassportToken { // PassportToken doesn't have factory - use HasFactory; + use HasFactory, FasterAttributes; - public $timestamps = true; + private ?Set $scopeSet; + + public function refreshToken() + { + return $this->hasOne(RefreshToken::class, 'access_token_id'); + } + + public function user() + { + return $this->belongsTo(User::class, 'user_id'); + } /** * Whether the resource owner is delegated to the client's owner. @@ -27,7 +38,28 @@ class Token extends PassportToken */ public function delegatesOwner(): bool { - return in_array('delegate', $this->scopes, true); + return $this->scopeSet()->contains('delegate'); + } + + public function getAttribute($key) + { + return match ($key) { + 'client_id', + 'id', + 'name', + 'user_id' => $this->getRawAttribute($key), + + 'revoked' => (bool) $this->getRawAttribute($key), + 'scopes' => json_decode($this->getRawAttribute($key), true), + + 'created_at', + 'expires_at', + 'updated_at' => $this->getTimeFast($key), + + 'client', + 'refreshToken', + 'user' => $this->getRelationValue($key), + }; } /** @@ -53,18 +85,15 @@ public function isClientCredentials() public function isOwnToken(): bool { - return $this->client->user_id !== null && $this->client->user_id === $this->user_id; - } + $clientUserId = $this->client->user_id; - public function refreshToken() - { - return $this->hasOne(RefreshToken::class, 'access_token_id'); + return $clientUserId !== null && $clientUserId === $this->user_id; } public function revokeRecursive() { $result = $this->revoke(); - optional($this->refreshToken)->revoke(); + $this->refreshToken?->revoke(); return $result; } @@ -91,23 +120,24 @@ public function setScopesAttribute(?array $value) sort($value); } + $this->scopeSet = null; $this->attributes['scopes'] = $this->castAttributeAsJson('scopes', $value); } - public function validate() + public function validate(): void { - static $scopesRequireDelegation; - $scopesRequireDelegation ??= new Set(['chat.write', 'chat.write_manage', 'delegate']); + static $scopesRequireDelegation = new Set(['chat.write', 'chat.write_manage', 'delegate']); - if (empty($this->scopes)) { + $scopes = $this->scopeSet(); + if ($scopes->isEmpty()) { throw new InvalidScopeException('Tokens without scopes are not valid.'); } - if ($this->client === null) { + $client = $this->client; + if ($client === null) { throw new InvalidScopeException('The client is not authorized.', 'unauthorized_client'); } - $scopes = new Set($this->scopes); // no silly scopes. if ($scopes->contains('*') && $scopes->count() > 1) { throw new InvalidScopeException('* is not valid with other scopes'); @@ -118,7 +148,7 @@ public function validate() throw new InvalidScopeException('* is not allowed with Client Credentials'); } - if ($this->delegatesOwner() && !$this->client->user->isBot()) { + if ($this->delegatesOwner() && !$client->user->isBot()) { throw new InvalidScopeException('Delegation with Client Credentials is only available to chat bots.'); } @@ -140,18 +170,15 @@ public function validate() // only clients owned by bots are allowed to act on behalf of another user. // the user's own client can send messages as themselves for authorization code flows. - static $ownClientScopes; - $ownClientScopes ??= new Set([ + static $ownClientScopes = new Set([ 'chat.read', 'chat.write', 'chat.write_manage', ]); - if (!$scopes->intersect($ownClientScopes)->isEmpty() && !($this->isOwnToken() || $this->client->user->isBot())) { + if (!$scopes->intersect($ownClientScopes)->isEmpty() && !($this->isOwnToken() || $client->user->isBot())) { throw new InvalidScopeException('This scope is only available for chat bots or your own clients.'); } } - - return true; } public function save(array $options = []) @@ -162,10 +189,8 @@ public function save(array $options = []) return parent::save($options); } - public function user() + private function scopeSet(): Set { - $provider = config('auth.guards.api.provider'); - - return $this->belongsTo(config('auth.providers.'.$provider.'.model'), 'user_id'); + return $this->scopeSet ??= new Set($this->scopes ?? []); } } diff --git a/app/Models/Traits/FasterAttributes.php b/app/Models/Traits/FasterAttributes.php new file mode 100644 index 00000000000..f54fc880274 --- /dev/null +++ b/app/Models/Traits/FasterAttributes.php @@ -0,0 +1,53 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Models\Traits; + +use Carbon\Carbon; + +trait FasterAttributes +{ + public function getRawAttribute(string $key) + { + return $this->attributes[$key] ?? null; + } + + /** + * Fast Time Attribute to Json Transformer + * + * Key must be suffixed with `_json`. + * This is only usable for models with default dateFormat (`Y-m-d H:i:s`). + */ + protected function getJsonTimeFast(string $key): ?string + { + $value = $this->getRawAttribute(substr($key, 0, -5)); + + if ($value === null) { + return null; + } + + // From: "2020-10-10 10:10:10" + // To: "2020-10-10T10:10:10Z" + $value[10] = 'T'; + + return "{$value}Z"; + } + + /** + * Fast Time Attribute Getter (kind of) + * + * This is only usable for models with default dateFormat (`Y-m-d H:i:s`). + */ + protected function getTimeFast(string $key): ?Carbon + { + $value = $this->getRawAttribute($key); + + return $value === null + ? null + : Carbon::createFromFormat('Y-m-d H:i:s', $value); + } +} From a1fbcc5b816a9f6a42e95bdd003056227ff39bcd Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 27 Nov 2023 17:38:56 +0900 Subject: [PATCH 007/102] Accept any attributes for score statistics Removes need to synchronise with the client. Only up to 32 attributes are accepted and they must are all ints. --- app/Models/Solo/Score.php | 8 +-- app/Models/Solo/ScoreDataStatistics.php | 96 ++++++------------------- tests/Models/Solo/ScoreTest.php | 2 +- 3 files changed, 25 insertions(+), 81 deletions(-) diff --git a/app/Models/Solo/Score.php b/app/Models/Solo/Score.php index 5a74a042819..65507e4ad8c 100644 --- a/app/Models/Solo/Score.php +++ b/app/Models/Solo/Score.php @@ -215,7 +215,7 @@ public function makeLegacyEntry(): LegacyScore\Model 'enabled_mods' => app('mods')->idsToBitset(array_column($data->mods, 'acronym')), 'maxcombo' => $data->maxCombo, 'pass' => $data->passed, - 'perfect' => $data->passed && $statistics->miss + $statistics->largeTickMiss === 0, + 'perfect' => $data->passed && $statistics->miss + $statistics->large_tick_miss === 0, 'rank' => $data->rank, 'score' => $data->totalScore, 'scorechecksum' => "\0", @@ -234,9 +234,9 @@ public function makeLegacyEntry(): LegacyScore\Model break; case 'fruits': $score->count300 = $statistics->great; - $score->count100 = $statistics->largeTickHit; - $score->countkatu = $statistics->smallTickMiss; - $score->count50 = $statistics->smallTickHit; + $score->count100 = $statistics->large_tick_hit; + $score->countkatu = $statistics->small_tick_miss; + $score->count50 = $statistics->small_tick_hit; break; case 'mania': $score->countgeki = $statistics->perfect; diff --git a/app/Models/Solo/ScoreDataStatistics.php b/app/Models/Solo/ScoreDataStatistics.php index 77680551cf4..7005924537c 100644 --- a/app/Models/Solo/ScoreDataStatistics.php +++ b/app/Models/Solo/ScoreDataStatistics.php @@ -7,103 +7,47 @@ namespace App\Models\Solo; -use JsonSerializable; - -class ScoreDataStatistics implements JsonSerializable +class ScoreDataStatistics implements \JsonSerializable { - public int $good; - public int $great; - public int $ignoreHit; - public int $ignoreMiss; - public int $largeBonus; - public int $largeTickHit; - public int $largeTickMiss; - public int $legacyComboIncrease; - public int $meh; - public int $miss; - public int $ok; - public int $perfect; - public int $smallBonus; - public int $smallTickHit; - public int $smallTickMiss; + public array $attributes = []; public function __construct($inputData) { - $inputData = get_arr($inputData) ?? []; - - foreach (static::fields() as $field => $map) { - $this->$field = get_int($inputData[$map['json']] ?? $inputData[$map['json_old']] ?? 0) ?? 0; - } - } - - private static function fields(): array - { - static $map; + $n = 0; + foreach (get_arr($inputData) ?? [] as $key => $value) { + if ($n >= 32) { + break; + } else { + $n++; + } - if (!isset($map)) { - $map = []; - $fields = [ - 'good', - 'great', - 'ignoreHit', - 'ignoreMiss', - 'largeBonus', - 'largeTickHit', - 'largeTickMiss', - 'legacyComboIncrease', - 'meh', - 'miss', - 'ok', - 'perfect', - 'smallBonus', - 'smallTickHit', - 'smallTickMiss', - ]; + $intValue = get_int($value); - foreach ($fields as $field) { - $map[$field] = [ - 'json' => snake_case($field), - 'json_old' => studly_case($field), - ]; + if ($intValue !== null && $intValue !== 0) { + $this->attributes[snake_case($key)] = $intValue; } } + } - return $map; + public function __get($key) + { + return $this->attributes[$key] ?? 0; } public function isEmpty(): bool { - foreach (static::fields() as $field => $_map) { - if ($this->$field !== 0) { - return false; - } - } - - return true; + return empty($this->attributes); } public function jsonSerialize(): array { - $ret = []; - - $fields = static::fields(); - foreach ($fields as $field => $map) { - $value = $this->$field; - - if ($value !== 0) { - $ret[$map['json']] = $value; - } - } - // This shouldn't be needed but it's to guarantee the return has // at least one thing so php doesn't json encode it as array. // Using stdClass is an alternative but it's a lot of hacks // for what shouldn't be possible in the first place (short of // completely bogus score data). - if (empty($ret)) { - $ret[$fields['miss']['json']] = $this->miss; - } - - return $ret; + return $this->isEmpty() + ? ['miss' => 0] + : $this->attributes; } } diff --git a/tests/Models/Solo/ScoreTest.php b/tests/Models/Solo/ScoreTest.php index 4f3d6c2d677..aff52ab6b38 100644 --- a/tests/Models/Solo/ScoreTest.php +++ b/tests/Models/Solo/ScoreTest.php @@ -31,7 +31,7 @@ public function testStatisticsStoredInCorrectCasing() $score = $score->fresh(); $this->assertSame(1, json_decode($score->getAttributes()['data'], true)['statistics']['small_tick_hit']); - $this->assertSame(1, $score->data->statistics->smallTickHit); + $this->assertSame(1, $score->data->statistics->small_tick_hit); } public function testLegacyPassScoreRetainsRank() From d8259f18e3df13467af2b304264d1143b596de33 Mon Sep 17 00:00:00 2001 From: Venix <30481900+venix12@users.noreply.github.com> Date: Mon, 27 Nov 2023 19:03:25 +0100 Subject: [PATCH 008/102] add video display to artist page --- app/Models/Artist.php | 1 + ..._11_27_173516_add_video_url_on_artists.php | 28 ++++ resources/css/bem/artist.less | 153 +++++++++--------- resources/views/artists/show.blade.php | 8 + 4 files changed, 117 insertions(+), 73 deletions(-) create mode 100644 database/migrations/2023_11_27_173516_add_video_url_on_artists.php diff --git a/app/Models/Artist.php b/app/Models/Artist.php index 2505f299d84..f524de19266 100644 --- a/app/Models/Artist.php +++ b/app/Models/Artist.php @@ -27,6 +27,7 @@ * @property string|null $twitter * @property \Carbon\Carbon|null $updated_at * @property int|null $user_id + * @property string|null $video_url * @property int $visible * @property string|null $website * @property string|null $youtube diff --git a/database/migrations/2023_11_27_173516_add_video_url_on_artists.php b/database/migrations/2023_11_27_173516_add_video_url_on_artists.php new file mode 100644 index 00000000000..57f350ff681 --- /dev/null +++ b/database/migrations/2023_11_27_173516_add_video_url_on_artists.php @@ -0,0 +1,28 @@ +string('video_url')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('multiplayer_scores_high', function (Blueprint $table) { + $table->dropColumn('video_url'); + }); + } +}; diff --git a/resources/css/bem/artist.less b/resources/css/bem/artist.less index 4d1d3a9fb9c..c5a20f7289e 100644 --- a/resources/css/bem/artist.less +++ b/resources/css/bem/artist.less @@ -3,15 +3,19 @@ .artist { @_top: artist; - &__index { - background-color: @osu-colour-b4; - padding: 10px; - .default-box-shadow(); - display: flex; - justify-content: space-around; - flex-direction: row; - flex-wrap: wrap; - overflow: hidden; + + &__admin-note { + background-color: @osu-colour-h2; + color: black; + font-weight: bold; + padding: 20px; + margin-bottom: 10px; + + text-align: center; + + @media @desktop { + .default-box-shadow(); + } } &__badge-wrapper { @@ -33,38 +37,6 @@ } } - &__admin-note { - background-color: @osu-colour-h2; - color: black; - font-weight: bold; - padding: 20px; - margin-bottom: 10px; - - text-align: center; - - @media @desktop { - .default-box-shadow(); - } - } - - &__name { - white-space: nowrap; - color: @osu-colour-l1; - font-size: @font-size--title-small-3; - font-weight: bold; - margin-top: 5px; - display: block; - &:hover { - color: white; - } - } - - &__track-count { - color: @osu-colour-f1; - font-size: 12px; - text-align: center; - } - &__description { .default-gutter-v2(); background-color: @osu-colour-b5; @@ -88,10 +60,60 @@ } } - &__portrait-wrapper { - width: 200px; - height: 200px; - position: relative; + &__index { + background-color: @osu-colour-b4; + padding: 10px; + .default-box-shadow(); + display: flex; + justify-content: space-around; + flex-direction: row; + flex-wrap: wrap; + overflow: hidden; + } + + &__label-overlay { + width: 64px; + height: 64px; + background-size: cover; + bottom: 0; + right: 0; + position: absolute; + border-radius: 4px 0 3px 0; + .at2x-simple-var(--artist-label-overlay); + } + + &__links-area { + margin: 0 auto 10px auto; + width: 270px; + padding: 10px; + + @media @desktop { + .default-box-shadow(); + background: @osu-colour-b5; + } + + &--albums { + overflow: hidden; + display: flex; + flex-direction: column; + align-items: center; + + @media @mobile { + display: none; + } + } + } + + &__name { + white-space: nowrap; + color: @osu-colour-l1; + font-size: @font-size--title-small-3; + font-weight: bold; + margin-top: 5px; + display: block; + &:hover { + color: white; + } } &__portrait { @@ -125,37 +147,22 @@ } } - &__label-overlay { - width: 64px; - height: 64px; - background-size: cover; - bottom: 0; - right: 0; - position: absolute; - border-radius: 4px 0 3px 0; - .at2x-simple-var(--artist-label-overlay); + &__portrait-wrapper { + width: 200px; + height: 200px; + position: relative; } - &__links-area { - margin: 0 auto 10px auto; - width: 270px; - padding: 10px; - - @media @desktop { - .default-box-shadow(); - background: @osu-colour-b5; - } - - &--albums { - overflow: hidden; - display: flex; - flex-direction: column; - align-items: center; + &__track-count { + color: @osu-colour-f1; + font-size: 12px; + text-align: center; + } - @media @mobile { - display: none; - } - } + &__video { + margin: 20px auto 0; + border-radius: @border-radius-large; + overflow: hidden; } &__white-link { diff --git a/resources/views/artists/show.blade.php b/resources/views/artists/show.blade.php index 44ae241fb03..a589dcb2c7a 100644 --- a/resources/views/artists/show.blade.php +++ b/resources/views/artists/show.blade.php @@ -46,6 +46,14 @@

{{ $artist->name }}

{!! markdown($artist->description) !!} + + @if ($artist->video_url !== null) +
+
+ +
+
+ @endif @if (count($json['albums']) > 0)
From cdd3987ec50ff367fe4a7d7fc1f394c460cf58d0 Mon Sep 17 00:00:00 2001 From: Venix <30481900+venix12@users.noreply.github.com> Date: Mon, 27 Nov 2023 19:25:42 +0100 Subject: [PATCH 009/102] proper table --- .../migrations/2023_11_27_173516_add_video_url_on_artists.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2023_11_27_173516_add_video_url_on_artists.php b/database/migrations/2023_11_27_173516_add_video_url_on_artists.php index 57f350ff681..00c1b5186dc 100644 --- a/database/migrations/2023_11_27_173516_add_video_url_on_artists.php +++ b/database/migrations/2023_11_27_173516_add_video_url_on_artists.php @@ -21,7 +21,7 @@ public function up(): void */ public function down(): void { - Schema::table('multiplayer_scores_high', function (Blueprint $table) { + Schema::table('artists', function (Blueprint $table) { $table->dropColumn('video_url'); }); } From 093f2f2175acea50f8926c0f46137f48207153b9 Mon Sep 17 00:00:00 2001 From: Venix <30481900+venix12@users.noreply.github.com> Date: Mon, 27 Nov 2023 19:26:15 +0100 Subject: [PATCH 010/102] licence header --- .../migrations/2023_11_27_173516_add_video_url_on_artists.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/migrations/2023_11_27_173516_add_video_url_on_artists.php b/database/migrations/2023_11_27_173516_add_video_url_on_artists.php index 00c1b5186dc..a66b05eb14c 100644 --- a/database/migrations/2023_11_27_173516_add_video_url_on_artists.php +++ b/database/migrations/2023_11_27_173516_add_video_url_on_artists.php @@ -1,5 +1,8 @@ . Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; From d7141ab8ec688e94ed8f8481d78e2219bc35dc34 Mon Sep 17 00:00:00 2001 From: Venix <30481900+venix12@users.noreply.github.com> Date: Mon, 27 Nov 2023 19:31:32 +0100 Subject: [PATCH 011/102] simplify --- resources/css/bem/artist.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/css/bem/artist.less b/resources/css/bem/artist.less index c5a20f7289e..e25a6bd7350 100644 --- a/resources/css/bem/artist.less +++ b/resources/css/bem/artist.less @@ -160,7 +160,7 @@ } &__video { - margin: 20px auto 0; + margin-top: 20px; border-radius: @border-radius-large; overflow: hidden; } From b6f62b54481d25183758f26ef154554c9181571a Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 29 Nov 2023 18:18:35 +0900 Subject: [PATCH 012/102] Add test for verification link --- .env.example | 6 +-- .github/workflows/tests.yml | 2 - app/Libraries/Session/SessionManager.php | 11 +++++ app/Libraries/Session/Store.php | 5 +++ app/Libraries/UserVerificationState.php | 6 +-- config/cache.php | 2 +- config/session.php | 2 +- docker-compose.yml | 2 - phpunit.xml | 2 - tests/Libraries/UserVerificationTest.php | 53 ++++++++++++++++++++++++ tests/TestCase.php | 10 +++++ 11 files changed, 85 insertions(+), 16 deletions(-) diff --git a/.env.example b/.env.example index c411a13507f..a6b68b781f0 100644 --- a/.env.example +++ b/.env.example @@ -40,9 +40,9 @@ DB_USERNAME=osuweb OSU_API_KEY= -BROADCAST_DRIVER=log -CACHE_DRIVER=file -SESSION_DRIVER=file +# BROADCAST_DRIVER=redis +# CACHE_DRIVER=redis +# SESSION_DRIVER=redis # SESSION_DOMAIN= # SESSION_SECURE_COOKIE=false diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cf9d0a35f83..2bc058412c5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,6 @@ env: APP_ENV: testing APP_KEY: base64:q7U5qyAkedR1F6UhN0SQlUxBpAMDyfHy3NNFkqmiMqA= APP_URL: http://localhost:8000 - CACHE_DRIVER: redis DB_HOST: 127.0.0.1 ES_SOLO_SCORES_HOST: http://localhost:9200 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -87,7 +86,6 @@ env: HQZdh/ScL40oDGb6HRdKan0CAwEAAQ== -----END PUBLIC KEY----- REDIS_HOST: 127.0.0.1 - SESSION_DRIVER: redis SHOPIFY_DOMAIN: notarealdomainortld SHOPIFY_STOREFRONT_TOKEN: notreal SLACK_ENDPOINT: https://myconan.net/null/ diff --git a/app/Libraries/Session/SessionManager.php b/app/Libraries/Session/SessionManager.php index 039b75504f8..63140fe86aa 100644 --- a/app/Libraries/Session/SessionManager.php +++ b/app/Libraries/Session/SessionManager.php @@ -7,6 +7,17 @@ class SessionManager extends \Illuminate\Session\SessionManager { + public static function create(?string $sessionId = null): Store + { + $ret = (new static(app()))->instance(); + if ($sessionId !== null) { + $ret->setId($sessionId); + } + $ret->start(); + + return $ret; + } + /** * Build the session instance. * diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 7a2e07307da..061c80aa555 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -114,6 +114,11 @@ public function destroyUserSession($sessionId) return false; } + public function instance(): static + { + return $this; + } + /** * Return whether the given id matches the current session's id. * diff --git a/app/Libraries/UserVerificationState.php b/app/Libraries/UserVerificationState.php index 61c336ee09a..f18441dc79d 100644 --- a/app/Libraries/UserVerificationState.php +++ b/app/Libraries/UserVerificationState.php @@ -41,11 +41,7 @@ public static function fromVerifyLink($linkKey) public static function load($params) { - $session = new SessionManager(app()); - $session->setId($params['sessionId']); - $session->start(); - - return new static(User::find($params['userId']), $session); + return new static(User::find($params['userId']), SessionManager::create($params['sessionId'])); } private function __construct($user, $session) diff --git a/config/cache.php b/config/cache.php index 98f45767b86..68ca5bff37b 100644 --- a/config/cache.php +++ b/config/cache.php @@ -13,7 +13,7 @@ | */ - 'default' => env('CACHE_DRIVER', 'file'), + 'default' => env('CACHE_DRIVER', 'redis'), /* |-------------------------------------------------------------------------- diff --git a/config/session.php b/config/session.php index 2da7990bb91..36297032603 100644 --- a/config/session.php +++ b/config/session.php @@ -16,7 +16,7 @@ | */ - 'driver' => env('SESSION_DRIVER', 'file'), + 'driver' => env('SESSION_DRIVER', 'redis'), /* |-------------------------------------------------------------------------- diff --git a/docker-compose.yml b/docker-compose.yml index eb65755916f..ad823c25b1c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,6 @@ x-env: &x-env APP_KEY: "${APP_KEY}" BEATMAPS_DIFFICULTY_CACHE_SERVER_URL: http://beatmap-difficulty-lookup-cache BROADCAST_DRIVER: redis - CACHE_DRIVER: redis DB_CONNECTION_STRING: Server=db;Database=osu;Uid=osuweb; DB_HOST: db ES_HOST: http://elasticsearch:9200 @@ -14,7 +13,6 @@ x-env: &x-env NOTIFICATION_REDIS_HOST: redis PASSPORT_PUBLIC_KEY: "${PASSPORT_PUBLIC_KEY:-}" REDIS_HOST: redis - SESSION_DRIVER: redis x-web: &x-web build: diff --git a/phpunit.xml b/phpunit.xml index 4015d372f6c..02c1458af45 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -18,9 +18,7 @@ - - diff --git a/tests/Libraries/UserVerificationTest.php b/tests/Libraries/UserVerificationTest.php index 42352d72c08..654601c1c54 100644 --- a/tests/Libraries/UserVerificationTest.php +++ b/tests/Libraries/UserVerificationTest.php @@ -3,9 +3,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +declare(strict_types=1); + namespace Tests\Libraries; +use App\Libraries\Session\SessionManager; use App\Libraries\UserVerification; +use App\Libraries\UserVerificationState; use App\Models\LoginAttempt; use App\Models\User; use Tests\TestCase; @@ -50,6 +54,55 @@ public function testVerify() $this->assertTrue(UserVerification::fromCurrentRequest()->isDone()); } + public function testVerifyLink(): void + { + $user = User::factory()->create(); + $session = \Session::instance(); + $sessionId = $session->getId(); + + $this + ->be($user) + ->withPersistentSession($session) + ->get(route('account.edit')) + ->assertStatus(401) + ->assertViewIs('users.verify'); + + $linkKey = $session->get('verification_link_key'); + + $guestSession = SessionManager::create(); + $this + ->withPersistentSession($guestSession) + ->get(route('account.verify', ['key' => $linkKey])) + ->assertSuccessful(); + + $record = LoginAttempt::find('127.0.0.1'); + + $this->assertFalse($record->containsUser($user, 'verify-mismatch:')); + $this->assertTrue(UserVerificationState::load(['userId' => $user->getKey(), 'sessionId' => $sessionId])->isDone()); + } + + public function testVerifyLinkMismatch(): void + { + $user = User::factory()->create(); + $session = \Session::instance(); + $sessionId = $session->getId(); + + $this + ->be($user) + ->withPersistentSession($session) + ->get(route('account.edit')) + ->assertStatus(401) + ->assertViewIs('users.verify'); + + $guestSession = SessionManager::create(); + $this + ->withPersistentSession($guestSession) + ->get(route('account.verify', ['key' => 'invalid'])) + ->assertStatus(404); + + $this->assertFalse(UserVerificationState::load(['userId' => $user->getKey(), 'sessionId' => $sessionId])->isDone()); + } + public function testVerifyMismatch() { $user = User::factory()->create(); diff --git a/tests/TestCase.php b/tests/TestCase.php index fb3b10e1670..2e2ba688e04 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -9,6 +9,7 @@ use App\Http\Middleware\AuthApi; use App\Jobs\Notifications\BroadcastNotificationBase; use App\Libraries\Search\ScoreSearch; +use App\Libraries\Session\Store as SessionStore; use App\Models\Beatmapset; use App\Models\OAuth\Client; use App\Models\User; @@ -339,6 +340,15 @@ protected function withInterOpHeader($url) ]); } + protected function withPersistentSession(SessionStore $session): static + { + $session->save(); + + return $this->withCookies([ + $session->getName() => $session->getId(), + ]); + } + private function runExpectedCountsCallbacks() { foreach ($this->expectedCountsCallbacks as $expectedCount) { From 84ba15479659a3282672910282bfdfb4a4a442e7 Mon Sep 17 00:00:00 2001 From: Venix <30481900+venix12@users.noreply.github.com> Date: Thu, 30 Nov 2023 01:42:18 +0100 Subject: [PATCH 013/102] use video instead of iframe --- resources/css/bem/artist.less | 1 + resources/views/artists/show.blade.php | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/resources/css/bem/artist.less b/resources/css/bem/artist.less index e25a6bd7350..3d976b05d62 100644 --- a/resources/css/bem/artist.less +++ b/resources/css/bem/artist.less @@ -161,6 +161,7 @@ &__video { margin-top: 20px; + max-width: 100%; border-radius: @border-radius-large; overflow: hidden; } diff --git a/resources/views/artists/show.blade.php b/resources/views/artists/show.blade.php index a589dcb2c7a..5972d88313f 100644 --- a/resources/views/artists/show.blade.php +++ b/resources/views/artists/show.blade.php @@ -48,11 +48,7 @@ {!! markdown($artist->description) !!} @if ($artist->video_url !== null) -
-
- -
-
+ @endif
@if (count($json['albums']) > 0) From d1a2f69a7368b4f0e18565690a0b562f2b4fc6c7 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 30 Nov 2023 22:06:13 +0900 Subject: [PATCH 014/102] Fields (and constructor) before methods --- app/Models/OAuth/Client.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/OAuth/Client.php b/app/Models/OAuth/Client.php index d15fc1a7912..a9b037d0035 100644 --- a/app/Models/OAuth/Client.php +++ b/app/Models/OAuth/Client.php @@ -33,6 +33,8 @@ class Client extends PassportClient { use Validatable; + public ?array $scopes = null; + public static function forUser(User $user) { // Get clients matching non-revoked tokens. Expired tokens should be included. @@ -63,8 +65,6 @@ public static function newFactory() return null; } - public ?array $scopes = null; - public function refreshTokens() { return $this->hasManyThrough( From 7c4a2968f40fe89396bef13ca41835dcee884b37 Mon Sep 17 00:00:00 2001 From: nanaya Date: Sat, 2 Dec 2023 23:48:31 +0900 Subject: [PATCH 015/102] Fix incorrect check for completed playlist item --- app/Models/Multiplayer/UserScoreAggregate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Multiplayer/UserScoreAggregate.php b/app/Models/Multiplayer/UserScoreAggregate.php index bc3a6998c75..a4dd85002cd 100644 --- a/app/Models/Multiplayer/UserScoreAggregate.php +++ b/app/Models/Multiplayer/UserScoreAggregate.php @@ -202,7 +202,7 @@ public function userRank() private function updateUserTotal(ScoreLink $currentScoreLink, PlaylistItemUserHighScore $prev) { - if ($prev->exists) { + if ($prev->last_score_id !== null) { $this->total_score -= $prev->total_score; $this->accuracy -= $prev->accuracy; $this->pp -= $prev->pp; From 031ff9ef28fe2d43e8573b654a763b8ade31fd48 Mon Sep 17 00:00:00 2001 From: Venix <30481900+venix12@users.noreply.github.com> Date: Sat, 2 Dec 2023 21:12:07 +0100 Subject: [PATCH 016/102] use fixed size/ratio for artist video --- resources/css/bem/artist.less | 9 +++++++-- resources/views/artists/show.blade.php | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/resources/css/bem/artist.less b/resources/css/bem/artist.less index 3d976b05d62..2c5994ffad5 100644 --- a/resources/css/bem/artist.less +++ b/resources/css/bem/artist.less @@ -160,12 +160,17 @@ } &__video { - margin-top: 20px; - max-width: 100%; + position: absolute; + width: 100%; + height: 100%; border-radius: @border-radius-large; overflow: hidden; } + &__video-wrapper { + margin-top: 20px; + } + &__white-link { .link-white(); .link-plain(); diff --git a/resources/views/artists/show.blade.php b/resources/views/artists/show.blade.php index 5972d88313f..f9247f687ae 100644 --- a/resources/views/artists/show.blade.php +++ b/resources/views/artists/show.blade.php @@ -48,7 +48,9 @@ {!! markdown($artist->description) !!} @if ($artist->video_url !== null) - +
+ +
@endif @if (count($json['albums']) > 0) From 4e5c82325eab15665d34410a5371de2fca4c105d Mon Sep 17 00:00:00 2001 From: bakaneko Date: Sun, 3 Dec 2023 22:58:22 +0900 Subject: [PATCH 017/102] should be score_id --- app/Models/Multiplayer/UserScoreAggregate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Multiplayer/UserScoreAggregate.php b/app/Models/Multiplayer/UserScoreAggregate.php index a4dd85002cd..73db8fcc1da 100644 --- a/app/Models/Multiplayer/UserScoreAggregate.php +++ b/app/Models/Multiplayer/UserScoreAggregate.php @@ -202,7 +202,7 @@ public function userRank() private function updateUserTotal(ScoreLink $currentScoreLink, PlaylistItemUserHighScore $prev) { - if ($prev->last_score_id !== null) { + if ($prev->score_id !== null) { $this->total_score -= $prev->total_score; $this->accuracy -= $prev->accuracy; $this->pp -= $prev->pp; From c5b59e77a6de3bc0af70c61c70474d2e18cd347f Mon Sep 17 00:00:00 2001 From: Venix <30481900+venix12@users.noreply.github.com> Date: Sun, 3 Dec 2023 16:29:17 +0100 Subject: [PATCH 018/102] use aspect-ratio css property --- resources/css/bem/artist.less | 9 ++------- resources/views/artists/show.blade.php | 4 +--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/resources/css/bem/artist.less b/resources/css/bem/artist.less index 2c5994ffad5..ba7645f0549 100644 --- a/resources/css/bem/artist.less +++ b/resources/css/bem/artist.less @@ -160,17 +160,12 @@ } &__video { - position: absolute; + margin-top: 20px; + aspect-ratio: 16 / 9; width: 100%; - height: 100%; border-radius: @border-radius-large; overflow: hidden; } - - &__video-wrapper { - margin-top: 20px; - } - &__white-link { .link-white(); .link-plain(); diff --git a/resources/views/artists/show.blade.php b/resources/views/artists/show.blade.php index f9247f687ae..5972d88313f 100644 --- a/resources/views/artists/show.blade.php +++ b/resources/views/artists/show.blade.php @@ -48,9 +48,7 @@ {!! markdown($artist->description) !!} @if ($artist->video_url !== null) -
- -
+ @endif @if (count($json['albums']) > 0) From 9c84b5cccddcd678919760cfcc880d22623a4486 Mon Sep 17 00:00:00 2001 From: Venix <30481900+venix12@users.noreply.github.com> Date: Sun, 3 Dec 2023 16:30:50 +0100 Subject: [PATCH 019/102] newline --- resources/css/bem/artist.less | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/css/bem/artist.less b/resources/css/bem/artist.less index ba7645f0549..8bbeb9111b0 100644 --- a/resources/css/bem/artist.less +++ b/resources/css/bem/artist.less @@ -166,6 +166,7 @@ border-radius: @border-radius-large; overflow: hidden; } + &__white-link { .link-white(); .link-plain(); From 5045ae948aec52877d6c44146c11c8122f6e0b5e Mon Sep 17 00:00:00 2001 From: nanaya Date: Sun, 3 Dec 2023 06:06:38 +0900 Subject: [PATCH 020/102] Use css aspect-ratio to set iframe aspect ratio --- app/Libraries/BBCodeFromDB.php | 10 ++-- resources/css/utilities.less | 11 +--- resources/js/components/build.coffee | 8 +-- resources/views/home/download.blade.php | 9 ++- .../bbcode_examples/basic_youtube.html | 60 +++++++++---------- 5 files changed, 46 insertions(+), 52 deletions(-) diff --git a/app/Libraries/BBCodeFromDB.php b/app/Libraries/BBCodeFromDB.php index 6f85ef2720f..7bfde54fb68 100644 --- a/app/Libraries/BBCodeFromDB.php +++ b/app/Libraries/BBCodeFromDB.php @@ -342,12 +342,12 @@ public function parseUrl($text) return $text; } - public function parseYoutube($text) + public function parseYoutube(string $text): string { - $text = str_replace("[youtube:{$this->uid}]", "
", $text); - - return $text; + return strtr($text, [ + "[youtube:{$this->uid}]" => "
", + ]); } public function toHTML() diff --git a/resources/css/utilities.less b/resources/css/utilities.less index 8f4e49230ab..8dc44d2e4b5 100644 --- a/resources/css/utilities.less +++ b/resources/css/utilities.less @@ -41,14 +41,9 @@ } .u-embed-wide { - // this trick maintains the video's aspect ratio while resizing - // see: http://alistapart.com/article/creating-intrinsic-ratios-for-video - padding-bottom: 56.25%; /* 16:9 */ - position: relative; - - > iframe { - .full-size(); - } + display: block; + aspect-ratio: 16 / 9; + width: 100%; } .u-fancy-scrollbar { diff --git a/resources/js/components/build.coffee b/resources/js/components/build.coffee index 121ad53bea3..078ebbf160d 100644 --- a/resources/js/components/build.coffee +++ b/resources/js/components/build.coffee @@ -33,10 +33,10 @@ export class Build extends React.PureComponent if @props.build.youtube_id? && (@props.showVideo ? false) div className: 'build__video', - div className: 'u-embed-wide', - iframe - allowFullScreen: true - src: "https://www.youtube.com/embed/#{@props.build.youtube_id}?rel=0" + iframe + className: 'u-embed-wide' + allowFullScreen: true + src: "https://www.youtube.com/embed/#{@props.build.youtube_id}?rel=0" for category in categories div key: category diff --git a/resources/views/home/download.blade.php b/resources/views/home/download.blade.php index af85789c086..185857232a4 100644 --- a/resources/views/home/download.blade.php +++ b/resources/views/home/download.blade.php @@ -148,11 +148,10 @@ class="btn-osu-big btn-osu-big--download btn-osu-big--download-lazer"

{{ osu_trans('home.download.video-guide') }}

-
- -
+ diff --git a/tests/Libraries/bbcode_examples/basic_youtube.html b/tests/Libraries/bbcode_examples/basic_youtube.html index e65d4accbfb..a0b528309f6 100644 --- a/tests/Libraries/bbcode_examples/basic_youtube.html +++ b/tests/Libraries/bbcode_examples/basic_youtube.html @@ -1,39 +1,39 @@ -
- -
+
+ +


-
- -
+
+ +


-
- -
+
+ +


-
- -
+
+ +


-
- -
+
+ +


-
- -
+
+ +


-
- -
+
+ +


-
- -
+
+ +


-
- -
+
+ +


-
- -
+
+ +
From 2c8e4a452aaec42198d4d473e4888b114bf6103c Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 18:55:42 +0900 Subject: [PATCH 021/102] Note about the instance function --- app/Libraries/Session/Store.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 061c80aa555..c71c21ae822 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -114,6 +114,9 @@ public function destroyUserSession($sessionId) return false; } + /** + * Used to obtain the instance from Session facade or SessionManager instance + */ public function instance(): static { return $this; From bf3981d9d6f159b11f881e1cc9ebc5cbafa65afd Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 21:45:34 +0900 Subject: [PATCH 022/102] Fix recalculate not resetting playlist item score id --- app/Models/Multiplayer/UserScoreAggregate.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/Models/Multiplayer/UserScoreAggregate.php b/app/Models/Multiplayer/UserScoreAggregate.php index 73db8fcc1da..db0a9146378 100644 --- a/app/Models/Multiplayer/UserScoreAggregate.php +++ b/app/Models/Multiplayer/UserScoreAggregate.php @@ -152,11 +152,21 @@ public function removeRunningTotals() ::whereHas('playlistItem', fn ($q) => $q->where('room_id', $this->room_id)) ->where('user_id', $this->user_id) ->update([ - 'total_score' => 0, 'accuracy' => 0, + 'score_id' => null, + 'total_score' => 0, ]); - foreach (['total_score', 'accuracy', 'pp', 'attempts', 'completed'] as $key) { + static $resetAttributes = [ + 'accuracy', + 'attempts', + 'completed', + 'last_score_id', + 'pp', + 'total_score', + ]; + + foreach ($resetAttributes as $key) { // init if required $this->$key = 0; } From 649100a6cd62fc0df088ac82e4bb27cbd47b711b Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 22:06:27 +0900 Subject: [PATCH 023/102] Add test for room high score recalculate --- .../Multiplayer/UserScoreAggregateTest.php | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/Models/Multiplayer/UserScoreAggregateTest.php b/tests/Models/Multiplayer/UserScoreAggregateTest.php index 9fc01b8c874..2e34396be54 100644 --- a/tests/Models/Multiplayer/UserScoreAggregateTest.php +++ b/tests/Models/Multiplayer/UserScoreAggregateTest.php @@ -131,6 +131,25 @@ public function testPassedScoresAreAveraged() $this->assertSame(0.65, $result['accuracy']); } + public function testRecalculate(): void + { + $playlistItem = $this->playlistItem(); + $user = User::factory()->create(); + $this->addPlay($user, $playlistItem, [ + 'total_score' => 1, + 'accuracy' => 0.3, + 'passed' => true, + ]); + $agg = UserScoreAggregate::new($user, $this->room); + $agg->recalculate(); + $agg->refresh(); + + $this->assertSame(1, $agg->total_score); + $this->assertSame(1, $agg->attempts); + $this->assertSame(0.3, $agg->accuracy); + $this->assertSame(1, $agg->completed); + } + protected function setUp(): void { parent::setUp(); @@ -138,6 +157,20 @@ protected function setUp(): void $this->room = Room::factory()->create(); } + private function addPlay(User $user, PlaylistItem $playlistItem, array $params): ScoreLink + { + $token = $playlistItem->room->startPlay($user, $playlistItem, 0); + + return $playlistItem->room->completePlay($token, [ + ...$params, + 'beatmap_id' => $playlistItem->beatmap_id, + 'ended_at' => json_time(new \DateTime()), + 'ruleset_id' => $playlistItem->ruleset_id, + 'statistics' => ['good' => 1], + 'user_id' => $user->getKey(), + ]); + } + private function playlistItem() { return PlaylistItem::factory()->create([ From a10009d3c2274d6c0d8a420b3856a147dc02bfcb Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 22:20:36 +0900 Subject: [PATCH 024/102] Update other tests to use the addPlay helper --- .../Multiplayer/UserScoreAggregateTest.php | 144 ++++++++---------- 1 file changed, 61 insertions(+), 83 deletions(-) diff --git a/tests/Models/Multiplayer/UserScoreAggregateTest.php b/tests/Models/Multiplayer/UserScoreAggregateTest.php index 2e34396be54..aafd82fd03a 100644 --- a/tests/Models/Multiplayer/UserScoreAggregateTest.php +++ b/tests/Models/Multiplayer/UserScoreAggregateTest.php @@ -3,6 +3,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +declare(strict_types=1); + namespace Tests\Models\Multiplayer; use App\Models\Multiplayer\PlaylistItem; @@ -10,13 +12,14 @@ use App\Models\Multiplayer\ScoreLink; use App\Models\Multiplayer\UserScoreAggregate; use App\Models\User; +use App\Transformers\Multiplayer\UserScoreAggregateTransformer; use Tests\TestCase; class UserScoreAggregateTest extends TestCase { - private $room; + private Room $room; - public function testStartingPlayIncreasesAttempts() + public function testStartingPlayIncreasesAttempts(): void { $user = User::factory()->create(); $playlistItem = $this->playlistItem(); @@ -28,105 +31,80 @@ public function testStartingPlayIncreasesAttempts() $this->assertSame(0, $agg->completed); } - public function testFailedScoresAreAttemptsOnly() + public function testFailedScoresAreAttemptsOnly(): void { $user = User::factory()->create(); $playlistItem = $this->playlistItem(); + + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 0.1, + 'passed' => false, + 'total_score' => 10, + ]); + + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 1, + 'passed' => true, + 'total_score' => 1, + ]); + $agg = UserScoreAggregate::new($user, $this->room); - $agg->addScoreLink( - ScoreLink - ::factory() - ->state([ - 'playlist_item_id' => $playlistItem, - 'user_id' => $user, - ])->failed() - ->create() - ); - - $agg->addScoreLink( - ScoreLink::factory() - ->state([ - 'playlist_item_id' => $playlistItem, - 'user_id' => $user, - ])->completed([], ['passed' => true, 'total_score' => 1]) - ->create() - ); - - $result = json_item($agg, 'Multiplayer\UserScoreAggregate'); - - $this->assertSame(1, $result['completed']); - $this->assertSame(1, $result['total_score']); + $this->assertSame(2, $agg->attempts); + $this->assertSame(1, $agg->completed); + $this->assertSame(1, $agg->total_score); } - public function testPassedScoresIncrementsCompletedCount() + public function testPassedScoresIncrementsCompletedCount(): void { $user = User::factory()->create(); $playlistItem = $this->playlistItem(); - $agg = UserScoreAggregate::new($user, $this->room); - $agg->addScoreLink( - ScoreLink::factory() - ->state([ - 'playlist_item_id' => $playlistItem, - 'user_id' => $user, - ])->completed([], ['passed' => true, 'total_score' => 1]) - ->create() - ); + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 1, + 'passed' => true, + 'total_score' => 1, + ]); - $result = json_item($agg, 'Multiplayer\UserScoreAggregate'); + $agg = UserScoreAggregate::new($user, $this->room); - $this->assertSame(1, $result['completed']); - $this->assertSame(1, $result['total_score']); + $this->assertSame(1, $agg->completed); + $this->assertSame(1, $agg->total_score); } - public function testPassedScoresAreAveraged() + public function testPassedScoresAreAveragedInTransformer(): void { $user = User::factory()->create(); $playlistItem = $this->playlistItem(); $playlistItem2 = $this->playlistItem(); + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 0.1, + 'passed' => false, + 'total_score' => 1, + ]); + + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 0.3, + 'passed' => false, + 'total_score' => 1, + ]); + + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 0.5, + 'passed' => true, + 'total_score' => 1, + ]); + + $this->addPlay($user, $playlistItem2, [ + 'accuracy' => 0.8, + 'passed' => true, + 'total_score' => 1, + ]); + $agg = UserScoreAggregate::new($user, $this->room); - $agg->addScoreLink(ScoreLink::factory() - ->state([ - 'playlist_item_id' => $playlistItem, - 'user_id' => $user, - ])->completed([], [ - 'total_score' => 1, - 'passed' => false, - ])->create()); - - $agg->addScoreLink(ScoreLink::factory() - ->state([ - 'playlist_item_id' => $playlistItem, - 'user_id' => $user, - ])->completed([], [ - 'total_score' => 1, - 'accuracy' => 0.3, - 'passed' => false, - ])->create()); - - $agg->addScoreLink(ScoreLink::factory() - ->state([ - 'playlist_item_id' => $playlistItem, - 'user_id' => $user, - ])->completed([], [ - 'total_score' => 1, - 'accuracy' => 0.5, - 'passed' => true, - ])->create()); - - $agg->addScoreLink(ScoreLink::factory() - ->state([ - 'playlist_item_id' => $playlistItem2, - 'user_id' => $user, - ])->completed([], [ - 'total_score' => 1, - 'accuracy' => 0.8, - 'passed' => true, - ])->create()); - - $result = json_item($agg, 'Multiplayer\UserScoreAggregate'); + + $result = json_item($agg, new UserScoreAggregateTransformer()); $this->assertSame(0.65, $result['accuracy']); } @@ -136,9 +114,9 @@ public function testRecalculate(): void $playlistItem = $this->playlistItem(); $user = User::factory()->create(); $this->addPlay($user, $playlistItem, [ - 'total_score' => 1, 'accuracy' => 0.3, 'passed' => true, + 'total_score' => 1, ]); $agg = UserScoreAggregate::new($user, $this->room); $agg->recalculate(); @@ -162,16 +140,16 @@ private function addPlay(User $user, PlaylistItem $playlistItem, array $params): $token = $playlistItem->room->startPlay($user, $playlistItem, 0); return $playlistItem->room->completePlay($token, [ - ...$params, 'beatmap_id' => $playlistItem->beatmap_id, 'ended_at' => json_time(new \DateTime()), 'ruleset_id' => $playlistItem->ruleset_id, 'statistics' => ['good' => 1], 'user_id' => $user->getKey(), + ...$params, ]); } - private function playlistItem() + private function playlistItem(): PlaylistItem { return PlaylistItem::factory()->create([ 'room_id' => $this->room, From e7210561c2bd91a91fde0bb8895864e6297adb7c Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 16:55:26 +0900 Subject: [PATCH 025/102] Add test for multiplayer completed function --- .../Rooms/Playlist/ScoresControllerTest.php | 7 +- tests/Models/Multiplayer/RoomTest.php | 89 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/tests/Controllers/Multiplayer/Rooms/Playlist/ScoresControllerTest.php b/tests/Controllers/Multiplayer/Rooms/Playlist/ScoresControllerTest.php index 418bba27501..54ec6fd4c30 100644 --- a/tests/Controllers/Multiplayer/Rooms/Playlist/ScoresControllerTest.php +++ b/tests/Controllers/Multiplayer/Rooms/Playlist/ScoresControllerTest.php @@ -132,17 +132,20 @@ public function testUpdate($bodyParams, $status) $playlistItem = PlaylistItem::factory()->create(); $room = $playlistItem->room; $build = Build::factory()->create(['allow_ranking' => true]); - $scoreLink = $room->startPlay($user, $playlistItem, 0); + $scoreToken = $room->startPlay($user, $playlistItem, 0); $this->actAsScopedUser($user, ['*']); $url = route('api.rooms.playlist.scores.update', [ 'room' => $room, 'playlist' => $playlistItem, - 'score' => $scoreLink, + 'score' => $scoreToken, ]); $this->json('PUT', $url, $bodyParams)->assertStatus($status); + + $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); + $this->assertSame($status === 200 ? 1 : 0, $roomHigh->completed); } public static function dataProviderForTestStore() diff --git a/tests/Models/Multiplayer/RoomTest.php b/tests/Models/Multiplayer/RoomTest.php index 1a0bd1077ac..1be67b2e4cf 100644 --- a/tests/Models/Multiplayer/RoomTest.php +++ b/tests/Models/Multiplayer/RoomTest.php @@ -15,6 +15,95 @@ class RoomTest extends TestCase { + public function testCompletePlayHigherScore() + { + $user = User::factory()->create(); + $playlistItem = PlaylistItem::factory()->create(); + $room = $playlistItem->room; + + $params = [ + 'accuracy' => 1, + 'beatmap_id' => $playlistItem->beatmap_id, + 'ruleset_id' => $playlistItem->ruleset_id, + 'user_id' => $user->getKey(), + 'ended_at' => json_time(new \DateTime()), + 'max_combo' => 10, + 'passed' => true, + 'rank' => 'A', + 'statistics' => ['Good' => 1], + 'total_score' => 10, + ]; + + // first play + $room->completePlay( + $room->startPlay($user, $playlistItem, 0), + $params, + ); + $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); + $this->assertSame(1, $roomHigh->completed); + $this->assertSame(1.0, $roomHigh->accuracy); + + // second, higher score play + $room->completePlay( + $room->startPlay($user, $playlistItem, 0), + [...$params, 'accuracy' => 2, 'total_score' => 100], + ); + + $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); + $this->assertSame(1, $roomHigh->completed); + $this->assertSame(2.0, $roomHigh->accuracy); + } + + public function testCompletePlayMultiplePlaylistItems() + { + $user = User::factory()->create(); + $playlistItem = PlaylistItem::factory()->create(); + $room = $playlistItem->room; + $playlistItem2 = PlaylistItem::factory()->create([ + 'room_id' => $room, + ]); + + $params = [ + 'accuracy' => 1, + 'beatmap_id' => $playlistItem->beatmap_id, + 'ruleset_id' => $playlistItem->ruleset_id, + 'user_id' => $user->getKey(), + 'ended_at' => json_time(new \DateTime()), + 'max_combo' => 10, + 'passed' => true, + 'rank' => 'A', + 'statistics' => ['Good' => 1], + 'total_score' => 10, + ]; + + // first playlist item + $room->completePlay( + $room->startPlay($user, $playlistItem, 0), + $params, + ); + $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); + $this->assertSame(1, $roomHigh->completed); + $this->assertSame(1.0, $roomHigh->accuracy); + $this->assertSame(1.0, $roomHigh->averageAccuracy()); + + // second playlist item + $room->completePlay( + $room->startPlay($user, $playlistItem2, 0), + [ + ...$params, + 'accuracy' => 2, + 'total_score' => 100, + 'beatmap_id' => $playlistItem2->beatmap_id, + 'ruleset_id' => $playlistItem2->ruleset_id, + ], + ); + + $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); + $this->assertSame(2, $roomHigh->completed); + $this->assertSame(3.0, $roomHigh->accuracy); + $this->assertSame(1.5, $roomHigh->averageAccuracy()); + } + /** * @dataProvider startGameDurationDataProvider */ From 941885eda6f765ef7fca3bb919196c877df343c9 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 19:52:16 +0900 Subject: [PATCH 026/102] Add test for lower total score --- tests/Models/Multiplayer/RoomTest.php | 43 +++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/tests/Models/Multiplayer/RoomTest.php b/tests/Models/Multiplayer/RoomTest.php index 1be67b2e4cf..8f2b38d4153 100644 --- a/tests/Models/Multiplayer/RoomTest.php +++ b/tests/Models/Multiplayer/RoomTest.php @@ -49,11 +49,50 @@ public function testCompletePlayHigherScore() [...$params, 'accuracy' => 2, 'total_score' => 100], ); - $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); + $roomHigh->refresh(); $this->assertSame(1, $roomHigh->completed); $this->assertSame(2.0, $roomHigh->accuracy); } + public function testCompletePlayLowerScore() + { + $user = User::factory()->create(); + $playlistItem = PlaylistItem::factory()->create(); + $room = $playlistItem->room; + + $params = [ + 'accuracy' => 1, + 'beatmap_id' => $playlistItem->beatmap_id, + 'ruleset_id' => $playlistItem->ruleset_id, + 'user_id' => $user->getKey(), + 'ended_at' => json_time(new \DateTime()), + 'max_combo' => 10, + 'passed' => true, + 'rank' => 'A', + 'statistics' => ['Good' => 1], + 'total_score' => 10, + ]; + + // first play + $room->completePlay( + $room->startPlay($user, $playlistItem, 0), + $params, + ); + $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); + $this->assertSame(1, $roomHigh->completed); + $this->assertSame(1.0, $roomHigh->accuracy); + + // second, lower score play + $room->completePlay( + $room->startPlay($user, $playlistItem, 0), + [...$params, 'accuracy' => 2, 'total_score' => 1], + ); + + $roomHigh->refresh(); + $this->assertSame(1, $roomHigh->completed); + $this->assertSame(1.0, $roomHigh->accuracy); + } + public function testCompletePlayMultiplePlaylistItems() { $user = User::factory()->create(); @@ -98,7 +137,7 @@ public function testCompletePlayMultiplePlaylistItems() ], ); - $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); + $roomHigh->refresh(); $this->assertSame(2, $roomHigh->completed); $this->assertSame(3.0, $roomHigh->accuracy); $this->assertSame(1.5, $roomHigh->averageAccuracy()); From 43a1e9458b01c2f9e29a73351642d26e3a3e3d09 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 20:20:53 +0900 Subject: [PATCH 027/102] Sort keys --- tests/Models/Multiplayer/RoomTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/Models/Multiplayer/RoomTest.php b/tests/Models/Multiplayer/RoomTest.php index 8f2b38d4153..441f9833194 100644 --- a/tests/Models/Multiplayer/RoomTest.php +++ b/tests/Models/Multiplayer/RoomTest.php @@ -24,14 +24,14 @@ public function testCompletePlayHigherScore() $params = [ 'accuracy' => 1, 'beatmap_id' => $playlistItem->beatmap_id, - 'ruleset_id' => $playlistItem->ruleset_id, - 'user_id' => $user->getKey(), 'ended_at' => json_time(new \DateTime()), 'max_combo' => 10, 'passed' => true, 'rank' => 'A', + 'ruleset_id' => $playlistItem->ruleset_id, 'statistics' => ['Good' => 1], 'total_score' => 10, + 'user_id' => $user->getKey(), ]; // first play @@ -63,14 +63,14 @@ public function testCompletePlayLowerScore() $params = [ 'accuracy' => 1, 'beatmap_id' => $playlistItem->beatmap_id, - 'ruleset_id' => $playlistItem->ruleset_id, - 'user_id' => $user->getKey(), 'ended_at' => json_time(new \DateTime()), 'max_combo' => 10, 'passed' => true, 'rank' => 'A', + 'ruleset_id' => $playlistItem->ruleset_id, 'statistics' => ['Good' => 1], 'total_score' => 10, + 'user_id' => $user->getKey(), ]; // first play @@ -105,14 +105,14 @@ public function testCompletePlayMultiplePlaylistItems() $params = [ 'accuracy' => 1, 'beatmap_id' => $playlistItem->beatmap_id, - 'ruleset_id' => $playlistItem->ruleset_id, - 'user_id' => $user->getKey(), 'ended_at' => json_time(new \DateTime()), 'max_combo' => 10, 'passed' => true, 'rank' => 'A', + 'ruleset_id' => $playlistItem->ruleset_id, 'statistics' => ['Good' => 1], 'total_score' => 10, + 'user_id' => $user->getKey(), ]; // first playlist item @@ -131,9 +131,9 @@ public function testCompletePlayMultiplePlaylistItems() [ ...$params, 'accuracy' => 2, - 'total_score' => 100, 'beatmap_id' => $playlistItem2->beatmap_id, 'ruleset_id' => $playlistItem2->ruleset_id, + 'total_score' => 100, ], ); From e9dae1654555da6a3ff3097964b5bc92cdab1b9e Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 20:20:05 +0900 Subject: [PATCH 028/102] Also check total score --- tests/Models/Multiplayer/RoomTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Models/Multiplayer/RoomTest.php b/tests/Models/Multiplayer/RoomTest.php index 441f9833194..ceb23d3006b 100644 --- a/tests/Models/Multiplayer/RoomTest.php +++ b/tests/Models/Multiplayer/RoomTest.php @@ -42,6 +42,7 @@ public function testCompletePlayHigherScore() $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); $this->assertSame(1, $roomHigh->completed); $this->assertSame(1.0, $roomHigh->accuracy); + $this->assertSame(10, $roomHigh->total_score); // second, higher score play $room->completePlay( @@ -52,6 +53,7 @@ public function testCompletePlayHigherScore() $roomHigh->refresh(); $this->assertSame(1, $roomHigh->completed); $this->assertSame(2.0, $roomHigh->accuracy); + $this->assertSame(100, $roomHigh->total_score); } public function testCompletePlayLowerScore() @@ -81,6 +83,7 @@ public function testCompletePlayLowerScore() $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); $this->assertSame(1, $roomHigh->completed); $this->assertSame(1.0, $roomHigh->accuracy); + $this->assertSame(10, $roomHigh->total_score); // second, lower score play $room->completePlay( @@ -91,6 +94,7 @@ public function testCompletePlayLowerScore() $roomHigh->refresh(); $this->assertSame(1, $roomHigh->completed); $this->assertSame(1.0, $roomHigh->accuracy); + $this->assertSame(10, $roomHigh->total_score); } public function testCompletePlayMultiplePlaylistItems() @@ -124,6 +128,7 @@ public function testCompletePlayMultiplePlaylistItems() $this->assertSame(1, $roomHigh->completed); $this->assertSame(1.0, $roomHigh->accuracy); $this->assertSame(1.0, $roomHigh->averageAccuracy()); + $this->assertSame(10, $roomHigh->total_score); // second playlist item $room->completePlay( @@ -141,6 +146,7 @@ public function testCompletePlayMultiplePlaylistItems() $this->assertSame(2, $roomHigh->completed); $this->assertSame(3.0, $roomHigh->accuracy); $this->assertSame(1.5, $roomHigh->averageAccuracy()); + $this->assertSame(110, $roomHigh->total_score); } /** From 96e1f49ef0453b827d23c8663ccbb88710036805 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 22:33:19 +0900 Subject: [PATCH 029/102] Move aggregate tests to its model --- tests/Models/Multiplayer/RoomTest.php | 134 ------------------ .../Multiplayer/UserScoreAggregateTest.php | 128 ++++++++++++++--- 2 files changed, 111 insertions(+), 151 deletions(-) diff --git a/tests/Models/Multiplayer/RoomTest.php b/tests/Models/Multiplayer/RoomTest.php index ceb23d3006b..1a0bd1077ac 100644 --- a/tests/Models/Multiplayer/RoomTest.php +++ b/tests/Models/Multiplayer/RoomTest.php @@ -15,140 +15,6 @@ class RoomTest extends TestCase { - public function testCompletePlayHigherScore() - { - $user = User::factory()->create(); - $playlistItem = PlaylistItem::factory()->create(); - $room = $playlistItem->room; - - $params = [ - 'accuracy' => 1, - 'beatmap_id' => $playlistItem->beatmap_id, - 'ended_at' => json_time(new \DateTime()), - 'max_combo' => 10, - 'passed' => true, - 'rank' => 'A', - 'ruleset_id' => $playlistItem->ruleset_id, - 'statistics' => ['Good' => 1], - 'total_score' => 10, - 'user_id' => $user->getKey(), - ]; - - // first play - $room->completePlay( - $room->startPlay($user, $playlistItem, 0), - $params, - ); - $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); - $this->assertSame(1, $roomHigh->completed); - $this->assertSame(1.0, $roomHigh->accuracy); - $this->assertSame(10, $roomHigh->total_score); - - // second, higher score play - $room->completePlay( - $room->startPlay($user, $playlistItem, 0), - [...$params, 'accuracy' => 2, 'total_score' => 100], - ); - - $roomHigh->refresh(); - $this->assertSame(1, $roomHigh->completed); - $this->assertSame(2.0, $roomHigh->accuracy); - $this->assertSame(100, $roomHigh->total_score); - } - - public function testCompletePlayLowerScore() - { - $user = User::factory()->create(); - $playlistItem = PlaylistItem::factory()->create(); - $room = $playlistItem->room; - - $params = [ - 'accuracy' => 1, - 'beatmap_id' => $playlistItem->beatmap_id, - 'ended_at' => json_time(new \DateTime()), - 'max_combo' => 10, - 'passed' => true, - 'rank' => 'A', - 'ruleset_id' => $playlistItem->ruleset_id, - 'statistics' => ['Good' => 1], - 'total_score' => 10, - 'user_id' => $user->getKey(), - ]; - - // first play - $room->completePlay( - $room->startPlay($user, $playlistItem, 0), - $params, - ); - $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); - $this->assertSame(1, $roomHigh->completed); - $this->assertSame(1.0, $roomHigh->accuracy); - $this->assertSame(10, $roomHigh->total_score); - - // second, lower score play - $room->completePlay( - $room->startPlay($user, $playlistItem, 0), - [...$params, 'accuracy' => 2, 'total_score' => 1], - ); - - $roomHigh->refresh(); - $this->assertSame(1, $roomHigh->completed); - $this->assertSame(1.0, $roomHigh->accuracy); - $this->assertSame(10, $roomHigh->total_score); - } - - public function testCompletePlayMultiplePlaylistItems() - { - $user = User::factory()->create(); - $playlistItem = PlaylistItem::factory()->create(); - $room = $playlistItem->room; - $playlistItem2 = PlaylistItem::factory()->create([ - 'room_id' => $room, - ]); - - $params = [ - 'accuracy' => 1, - 'beatmap_id' => $playlistItem->beatmap_id, - 'ended_at' => json_time(new \DateTime()), - 'max_combo' => 10, - 'passed' => true, - 'rank' => 'A', - 'ruleset_id' => $playlistItem->ruleset_id, - 'statistics' => ['Good' => 1], - 'total_score' => 10, - 'user_id' => $user->getKey(), - ]; - - // first playlist item - $room->completePlay( - $room->startPlay($user, $playlistItem, 0), - $params, - ); - $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); - $this->assertSame(1, $roomHigh->completed); - $this->assertSame(1.0, $roomHigh->accuracy); - $this->assertSame(1.0, $roomHigh->averageAccuracy()); - $this->assertSame(10, $roomHigh->total_score); - - // second playlist item - $room->completePlay( - $room->startPlay($user, $playlistItem2, 0), - [ - ...$params, - 'accuracy' => 2, - 'beatmap_id' => $playlistItem2->beatmap_id, - 'ruleset_id' => $playlistItem2->ruleset_id, - 'total_score' => 100, - ], - ); - - $roomHigh->refresh(); - $this->assertSame(2, $roomHigh->completed); - $this->assertSame(3.0, $roomHigh->accuracy); - $this->assertSame(1.5, $roomHigh->averageAccuracy()); - $this->assertSame(110, $roomHigh->total_score); - } - /** * @dataProvider startGameDurationDataProvider */ diff --git a/tests/Models/Multiplayer/UserScoreAggregateTest.php b/tests/Models/Multiplayer/UserScoreAggregateTest.php index aafd82fd03a..61babf19423 100644 --- a/tests/Models/Multiplayer/UserScoreAggregateTest.php +++ b/tests/Models/Multiplayer/UserScoreAggregateTest.php @@ -19,10 +19,102 @@ class UserScoreAggregateTest extends TestCase { private Room $room; + public function testAddingHigherScore(): void + { + $user = User::factory()->create(); + $playlistItem = $this->createPlaylistItem(); + + // first play + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 1, + 'passed' => true, + 'total_score' => 10, + ]); + + $agg = UserScoreAggregate::new($user, $this->room); + $this->assertSame(1, $agg->completed); + $this->assertSame(1.0, $agg->accuracy); + $this->assertSame(10, $agg->total_score); + + // second, higher score play + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 2, + 'passed' => true, + 'total_score' => 100, + ]); + + $agg->refresh(); + $this->assertSame(1, $agg->completed); + $this->assertSame(2.0, $agg->accuracy); + $this->assertSame(100, $agg->total_score); + } + + public function testAddingLowerScore(): void + { + $user = User::factory()->create(); + $playlistItem = $this->createPlaylistItem(); + + // first play + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 1, + 'passed' => true, + 'total_score' => 10, + ]); + $agg = UserScoreAggregate::new($user, $this->room); + $this->assertSame(1, $agg->completed); + $this->assertSame(1.0, $agg->accuracy); + $this->assertSame(10, $agg->total_score); + + // second, lower score play + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 2, + 'passed' => true, + 'total_score' => 1, + ]); + + $agg->refresh(); + $this->assertSame(1, $agg->completed); + $this->assertSame(1.0, $agg->accuracy); + $this->assertSame(10, $agg->total_score); + } + + public function testAddingMultiplePlaylistItems(): void + { + $user = User::factory()->create(); + $playlistItem = $this->createPlaylistItem(); + $playlistItem2 = $this->createPlaylistItem(); + + // first playlist item + $this->addPlay($user, $playlistItem, [ + 'accuracy' => 1, + 'passed' => true, + 'total_score' => 10, + ]); + + $agg = UserScoreAggregate::new($user, $this->room); + $this->assertSame(1, $agg->completed); + $this->assertSame(1.0, $agg->accuracy); + $this->assertSame(1.0, $agg->averageAccuracy()); + $this->assertSame(10, $agg->total_score); + + // second playlist item + $this->addPlay($user, $playlistItem2, [ + 'accuracy' => 2, + 'passed' => true, + 'total_score' => 100, + ]); + + $agg->refresh(); + $this->assertSame(2, $agg->completed); + $this->assertSame(3.0, $agg->accuracy); + $this->assertSame(1.5, $agg->averageAccuracy()); + $this->assertSame(110, $agg->total_score); + } + public function testStartingPlayIncreasesAttempts(): void { $user = User::factory()->create(); - $playlistItem = $this->playlistItem(); + $playlistItem = $this->createPlaylistItem(); $this->room->startPlay($user, $playlistItem, 0); $agg = UserScoreAggregate::new($user, $this->room); @@ -34,7 +126,7 @@ public function testStartingPlayIncreasesAttempts(): void public function testFailedScoresAreAttemptsOnly(): void { $user = User::factory()->create(); - $playlistItem = $this->playlistItem(); + $playlistItem = $this->createPlaylistItem(); $this->addPlay($user, $playlistItem, [ 'accuracy' => 0.1, @@ -58,7 +150,7 @@ public function testFailedScoresAreAttemptsOnly(): void public function testPassedScoresIncrementsCompletedCount(): void { $user = User::factory()->create(); - $playlistItem = $this->playlistItem(); + $playlistItem = $this->createPlaylistItem(); $this->addPlay($user, $playlistItem, [ 'accuracy' => 1, @@ -75,8 +167,8 @@ public function testPassedScoresIncrementsCompletedCount(): void public function testPassedScoresAreAveragedInTransformer(): void { $user = User::factory()->create(); - $playlistItem = $this->playlistItem(); - $playlistItem2 = $this->playlistItem(); + $playlistItem = $this->createPlaylistItem(); + $playlistItem2 = $this->createPlaylistItem(); $this->addPlay($user, $playlistItem, [ 'accuracy' => 0.1, @@ -111,7 +203,7 @@ public function testPassedScoresAreAveragedInTransformer(): void public function testRecalculate(): void { - $playlistItem = $this->playlistItem(); + $playlistItem = $this->createPlaylistItem(); $user = User::factory()->create(); $this->addPlay($user, $playlistItem, [ 'accuracy' => 0.3, @@ -137,22 +229,24 @@ protected function setUp(): void private function addPlay(User $user, PlaylistItem $playlistItem, array $params): ScoreLink { - $token = $playlistItem->room->startPlay($user, $playlistItem, 0); - - return $playlistItem->room->completePlay($token, [ - 'beatmap_id' => $playlistItem->beatmap_id, - 'ended_at' => json_time(new \DateTime()), - 'ruleset_id' => $playlistItem->ruleset_id, - 'statistics' => ['good' => 1], - 'user_id' => $user->getKey(), - ...$params, - ]); + return $playlistItem->room->completePlay( + $playlistItem->room->startPlay($user, $playlistItem, 0), + [ + 'beatmap_id' => $playlistItem->beatmap_id, + 'ended_at' => json_time(new \DateTime()), + 'ruleset_id' => $playlistItem->ruleset_id, + 'statistics' => ['good' => 1], + 'user_id' => $user->getKey(), + ...$params, + ], + ); } - private function playlistItem(): PlaylistItem + private function createPlaylistItem(): PlaylistItem { return PlaylistItem::factory()->create([ 'room_id' => $this->room, + 'owner_id' => $this->room->host, ]); } } From f78e6cdf440edfc9aa8ee48c02a4e7edf67ce4fe Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 22:35:56 +0900 Subject: [PATCH 030/102] Update variable name and lookup method --- .../Multiplayer/Rooms/Playlist/ScoresControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Controllers/Multiplayer/Rooms/Playlist/ScoresControllerTest.php b/tests/Controllers/Multiplayer/Rooms/Playlist/ScoresControllerTest.php index 54ec6fd4c30..d9efb5b7fb9 100644 --- a/tests/Controllers/Multiplayer/Rooms/Playlist/ScoresControllerTest.php +++ b/tests/Controllers/Multiplayer/Rooms/Playlist/ScoresControllerTest.php @@ -144,8 +144,8 @@ public function testUpdate($bodyParams, $status) $this->json('PUT', $url, $bodyParams)->assertStatus($status); - $roomHigh = $room->userHighScores()->where(['user_id' => $user->getKey()])->first(); - $this->assertSame($status === 200 ? 1 : 0, $roomHigh->completed); + $roomAgg = UserScoreAggregate::new($user, $room); + $this->assertSame($status === 200 ? 1 : 0, $roomAgg->completed); } public static function dataProviderForTestStore() From 7ddad24d505f207300d28c11d0e09da8da5d1957 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 22:38:01 +0900 Subject: [PATCH 031/102] Sort keys --- tests/Models/Multiplayer/UserScoreAggregateTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Models/Multiplayer/UserScoreAggregateTest.php b/tests/Models/Multiplayer/UserScoreAggregateTest.php index 61babf19423..a947adc6ae0 100644 --- a/tests/Models/Multiplayer/UserScoreAggregateTest.php +++ b/tests/Models/Multiplayer/UserScoreAggregateTest.php @@ -245,8 +245,8 @@ private function addPlay(User $user, PlaylistItem $playlistItem, array $params): private function createPlaylistItem(): PlaylistItem { return PlaylistItem::factory()->create([ - 'room_id' => $this->room, 'owner_id' => $this->room->host, + 'room_id' => $this->room, ]); } } From cf2c6de2022a8e4ca0057b60be2ce0720285a32b Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 4 Dec 2023 23:52:30 +0900 Subject: [PATCH 032/102] Add last score id assignment assertions --- .../Models/Multiplayer/UserScoreAggregateTest.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/Models/Multiplayer/UserScoreAggregateTest.php b/tests/Models/Multiplayer/UserScoreAggregateTest.php index a947adc6ae0..37ded3882f9 100644 --- a/tests/Models/Multiplayer/UserScoreAggregateTest.php +++ b/tests/Models/Multiplayer/UserScoreAggregateTest.php @@ -25,7 +25,7 @@ public function testAddingHigherScore(): void $playlistItem = $this->createPlaylistItem(); // first play - $this->addPlay($user, $playlistItem, [ + $scoreLink = $this->addPlay($user, $playlistItem, [ 'accuracy' => 1, 'passed' => true, 'total_score' => 10, @@ -35,9 +35,10 @@ public function testAddingHigherScore(): void $this->assertSame(1, $agg->completed); $this->assertSame(1.0, $agg->accuracy); $this->assertSame(10, $agg->total_score); + $this->assertSame($scoreLink->getKey(), $agg->last_score_id); // second, higher score play - $this->addPlay($user, $playlistItem, [ + $scoreLink2 = $this->addPlay($user, $playlistItem, [ 'accuracy' => 2, 'passed' => true, 'total_score' => 100, @@ -47,6 +48,7 @@ public function testAddingHigherScore(): void $this->assertSame(1, $agg->completed); $this->assertSame(2.0, $agg->accuracy); $this->assertSame(100, $agg->total_score); + $this->assertSame($scoreLink2->getKey(), $agg->last_score_id); } public function testAddingLowerScore(): void @@ -55,15 +57,17 @@ public function testAddingLowerScore(): void $playlistItem = $this->createPlaylistItem(); // first play - $this->addPlay($user, $playlistItem, [ + $scoreLink = $this->addPlay($user, $playlistItem, [ 'accuracy' => 1, 'passed' => true, 'total_score' => 10, ]); + $agg = UserScoreAggregate::new($user, $this->room); $this->assertSame(1, $agg->completed); $this->assertSame(1.0, $agg->accuracy); $this->assertSame(10, $agg->total_score); + $this->assertSame($scoreLink->getKey(), $agg->last_score_id); // second, lower score play $this->addPlay($user, $playlistItem, [ @@ -76,6 +80,7 @@ public function testAddingLowerScore(): void $this->assertSame(1, $agg->completed); $this->assertSame(1.0, $agg->accuracy); $this->assertSame(10, $agg->total_score); + $this->assertSame($scoreLink->getKey(), $agg->last_score_id); } public function testAddingMultiplePlaylistItems(): void @@ -98,7 +103,7 @@ public function testAddingMultiplePlaylistItems(): void $this->assertSame(10, $agg->total_score); // second playlist item - $this->addPlay($user, $playlistItem2, [ + $scoreLink = $this->addPlay($user, $playlistItem2, [ 'accuracy' => 2, 'passed' => true, 'total_score' => 100, @@ -109,6 +114,7 @@ public function testAddingMultiplePlaylistItems(): void $this->assertSame(3.0, $agg->accuracy); $this->assertSame(1.5, $agg->averageAccuracy()); $this->assertSame(110, $agg->total_score); + $this->assertSame($scoreLink->getKey(), $agg->last_score_id); } public function testStartingPlayIncreasesAttempts(): void From dc7940f25e463083b89479466614b832f7f2e92f Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 30 Nov 2023 20:57:43 +0900 Subject: [PATCH 033/102] Simplify session id - make non-instance specific session functions static - combine various instance delete functions - let laravel handles osu-next prefix - make the whole `sessions:$user:id` the id instead of considering parts of them prefix of the actual id - always return current session when looking up by session id - obtain session user id from attribute instead of prefix - add more session related tests --- .../Account/SessionsController.php | 16 +- app/Http/Controllers/AccountController.php | 10 +- app/Http/Controllers/Controller.php | 2 +- app/Libraries/Session/SessionManager.php | 13 +- app/Libraries/Session/Store.php | 314 +++++++----------- app/Libraries/User/ForceReactivation.php | 2 +- app/Libraries/UserVerificationState.php | 31 +- app/Models/User.php | 11 +- config/cache.php | 2 +- config/database.php | 2 +- config/session.php | 2 +- .../Account/SessionsControllerTest.php | 66 ++++ tests/Libraries/Session/StoreTest.php | 38 +++ tests/Libraries/UserVerificationTest.php | 6 +- tests/Models/UserTest.php | 8 +- tests/TestCase.php | 11 + 16 files changed, 271 insertions(+), 263 deletions(-) create mode 100644 tests/Controllers/Account/SessionsControllerTest.php create mode 100644 tests/Libraries/Session/StoreTest.php diff --git a/app/Http/Controllers/Account/SessionsController.php b/app/Http/Controllers/Account/SessionsController.php index 2ec6f550e00..c2af5c7b2d1 100644 --- a/app/Http/Controllers/Account/SessionsController.php +++ b/app/Http/Controllers/Account/SessionsController.php @@ -6,8 +6,7 @@ namespace App\Http\Controllers\Account; use App\Http\Controllers\Controller; -use Auth; -use Request; +use App\Libraries\Session\Store as SessionStore; class SessionsController extends Controller { @@ -21,15 +20,16 @@ public function __construct() public function destroy($id) { - if (!Auth::check()) { - abort(403); - } - - if (Request::session()->isCurrentSession($id)) { + if (\Session::getId() === $id) { // current session logout(); } else { - Request::session()->destroyUserSession($id); + $session = SessionStore::findOrCreate($id); + if ($session->userId() === \Auth::user()->getKey()) { + $session->delete(); + } else { + abort(404); + } } return response([], 204); diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index c44353cd325..9388137daa1 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -7,6 +7,7 @@ use App\Exceptions\ImageProcessorException; use App\Exceptions\ModelNotSavedException; +use App\Libraries\Session\Store as SessionStore; use App\Libraries\User\AvatarHelper; use App\Libraries\User\CountryChange; use App\Libraries\User\CountryChangeTarget; @@ -109,11 +110,8 @@ public function edit() ->orderBy('username') ->get(); - $sessions = Request::session() - ->currentUserSessions(); - - $currentSessionId = Request::session() - ->getIdWithoutKeyPrefix(); + $sessions = SessionStore::sessions($user->getKey()); + $currentSessionId = \Session::getId(); $authorizedClients = json_collection(Client::forUser($user), 'OAuth\Client', 'user'); $ownClients = json_collection($user->oauthClients()->where('revoked', false)->get(), 'OAuth\Client', ['redirect', 'secret']); @@ -294,7 +292,7 @@ public function updatePassword() Mail::to($user)->send(new UserPasswordUpdated($user)); } - $user->resetSessions(session()->getKey()); + $user->resetSessions(\Session::getId()); return response([], 204); } else { diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 50a7e33656f..502e79dd236 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -46,7 +46,7 @@ protected function login($user, $remember = false) if (config('osu.user.bypass_verification')) { UserVerificationState::fromCurrentRequest()->markVerified(); } - $session->migrate(true, $user->getKey()); + $session->migrate(true); } protected function logout() diff --git a/app/Libraries/Session/SessionManager.php b/app/Libraries/Session/SessionManager.php index 63140fe86aa..0fab6219109 100644 --- a/app/Libraries/Session/SessionManager.php +++ b/app/Libraries/Session/SessionManager.php @@ -3,21 +3,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +declare(strict_types=1); + namespace App\Libraries\Session; class SessionManager extends \Illuminate\Session\SessionManager { - public static function create(?string $sessionId = null): Store - { - $ret = (new static(app()))->instance(); - if ($sessionId !== null) { - $ret->setId($sessionId); - } - $ret->start(); - - return $ret; - } - /** * Build the session instance. * diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index c71c21ae822..8cb331286d2 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -3,180 +3,97 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +declare(strict_types=1); + namespace App\Libraries\Session; use App\Events\UserSessionEvent; -use Auth; -use Illuminate\Support\Str; +use Illuminate\Redis\Connections\PhpRedisConnection; +use Illuminate\Support\Arr; use Jenssegers\Agent\Agent; -use LaravelRedis as Redis; class Store extends \Illuminate\Session\Store { - const SESSION_ID_LENGTH = 40; - - public static function destroy($userId, ?string $excludedSessionId = null) - { - if (!static::isUsingRedis()) { - return; - } - - $keys = static::keys($userId); - if ($excludedSessionId !== null) { - $keys = array_filter($keys, fn ($key) => $key !== $excludedSessionId); - } - UserSessionEvent::newLogout($userId, $keys)->broadcast(); - Redis::del(array_merge([static::listKey($userId)], $keys)); - } + private const PREFIX = 'sessions:'; - public static function isUsingRedis() - { - return config('session.driver') === 'redis'; - } + private static PhpRedisConnection $redis; - /** - * Get the redis key prefix for the given user (excluding cache prefix). - * - * @return string - */ - public static function keyPrefix($userId) + public static function batchDelete(int $userId, ?array $ids = null): void { - return 'sessions:'.($userId ?? 'guest'); - } - - public static function keys($userId) - { - if (!static::isUsingRedis()) { - return []; - } - - return Redis::smembers(static::listKey($userId)); - } - - /** - * Get the redis key containing the session list for the given user. - * - * @return string - */ - public static function listKey($userId) - { - return config('cache.prefix').':'.static::keyPrefix($userId); - } + $ids ??= static::ids($userId); - public static function parseKey($key) - { - $pattern = '/^'.preg_quote(config('cache.prefix'), '/').':sessions:(?[0-9]+):(?.{'.static::SESSION_ID_LENGTH.'})$/'; - preg_match($pattern, $key, $matches); - - return [ - 'userId' => get_int($matches['userId'] ?? null), - 'id' => $matches['id'] ?? null, - ]; - } - - public static function removeFullId($userId, $fullId) - { - static::removeKey($userId, config('cache.prefix').':'.$fullId); - } - - public static function removeKey($userId, $key) - { - if (!static::isUsingRedis()) { + if (empty($ids)) { return; } - if ($userId === null) { - $userId = static::parseKey($key)['userId']; + $currentSession = \Session::instance(); + if (in_array($currentSession->getId(), $ids, true)) { + $currentSession->flush(); } - UserSessionEvent::newLogout($userId, [$key])->broadcast(); - Redis::srem(static::listKey($userId), $key); - Redis::del($key); + $redis = static::redis(); + $redis->del($ids); + $redis->srem(static::listKey($userId), ...$ids); + UserSessionEvent::newLogout($userId, $ids)->broadcast(); } - /** - * Destroys a session owned by the current user that is identified by the given id. - * - * @return bool - */ - public function destroyUserSession($sessionId) + public static function findOrCreate(?string $id = null): static { - if (Auth::check()) { - $userId = Auth::user()->user_id; - $fullSessionId = static::keyPrefix($userId).':'.$sessionId; - $this->handler->destroy($fullSessionId); + if ($id !== null) { + $currentSession = \Session::instance(); - static::removeFullId($userId, $fullSessionId); + if ($currentSession->getId() === $id) { + return $currentSession; + } + } - return true; + $ret = (new SessionManager(\App::getInstance()))->instance(); + if ($id !== null) { + $ret->setId($id); } + $ret->start(); - return false; + return $ret; } - /** - * Used to obtain the instance from Session facade or SessionManager instance - */ - public function instance(): static + public static function ids(int $userId): array { - return $this; + return array_map( + fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id, + static::redis()->smembers(static::listKey($userId)), + ); } - /** - * Return whether the given id matches the current session's id. - * - * @return bool - */ - public function isCurrentSession($sessionId) + public static function sessions($userId): array { - return $this->getIdWithoutKeyPrefix() === $this->stripKeyPrefix($sessionId); - } - - /** - * Returns whether the current session is a guest session based on the key prefix of the session id. - * - * @return bool - */ - public function isGuestSession() - { - return starts_with($this->getId(), static::keyPrefix(null).':'); - } - - public function currentUserSessions() - { - if (!Auth::check()) { - return; - } - - if (config('session.driver') !== 'redis') { + $ids = static::ids($userId); + if (empty($ids)) { return []; } - $userId = Auth::user()->user_id; - - // prevent the following save from clearing up current flash data - $this->reflash(); - // flush the current session data to redis early, otherwise we will get stale metadata for the current session - $this->save(); - - // TODO: When(if?) the session driver config is decoupled from the cache driver config, update the prefix below: - $sessionIds = static::keys($userId); - if (empty($sessionIds)) { - return []; + $sessions = array_combine( + $ids, + // Sessions are stored double-serialized in redis (session serialization + cache backend serialization) + array_map( + fn ($s) => $s === null ? null : unserialize(unserialize($s)), + static::redis()->mget($ids), + ), + ); + + // Current session data in redis may be stale + $currentSession = \Session::instance(); + if ($currentSession->userId() === $userId) { + $sessions[$currentSession->getId()] = $currentSession->attributes; } - $sessions = array_combine($sessionIds, Redis::mget($sessionIds)); - $sessionMeta = []; $agent = new Agent(); + $expiredIds = []; foreach ($sessions as $id => $session) { if ($session === null) { - // cleanup expired sessions - static::removeKey($userId, $id); + $expiredIds[] = $id; continue; } - // Sessions are stored double-serialized in redis (session serialization + cache backend serialization) - $session = unserialize(unserialize($session)); if (!isset($session['meta'])) { continue; @@ -184,48 +101,57 @@ public function currentUserSessions() $meta = $session['meta']; $agent->setUserAgent($meta['agent']); - $id = $this->stripKeyPrefix($id); - - $sessionMeta[$id] = $meta; - $sessionMeta[$id]['mobile'] = $agent->isMobile() || $agent->isTablet(); - $sessionMeta[$id]['device'] = $agent->device(); - $sessionMeta[$id]['platform'] = $agent->platform(); - $sessionMeta[$id]['browser'] = $agent->browser(); - $sessionMeta[$id]['verified'] = (bool) ($session['verified'] ?? false); + + $sessionMeta[$id] = [ + ...$meta, + 'mobile' => $agent->isMobile() || $agent->isTablet(), + 'device' => $agent->device(), + 'platform' => $agent->platform(), + 'browser' => $agent->browser(), + 'verified' => (bool) ($session['verified'] ?? false), + ]; } + // cleanup expired sessions + static::batchDelete($userId, $expiredIds); + // returns sessions sorted from most to least recently active - return array_reverse(array_sort($sessionMeta, function ($value) { - return $value['last_visit']; - }), true); + return Arr::sortDesc( + $sessionMeta, + fn ($value) => $value['last_visit'], + ); } /** - * Returns current session key (cache prefix + prefix + id) - * - * @return string + * Get the redis key containing the session list for the given user. */ - public function getKey() + private static function listKey(int $userId): string + { + return static::PREFIX.$userId; + } + + private static function redis(): PhpRedisConnection + { + return static::$redis ??= \LaravelRedis::connection(\Config::get('session.connection')); + } + + public function delete(): void { - return config('cache.prefix').':'.$this->getId(); + static::batchDelete($this->userId(), [$this->getId()]); } /** - * Determine if this is a valid session ID. - * - * @param string $id - * @return bool + * Used to obtain the instance from Session facade or SessionManager instance */ - public function isValidId($id) + public function instance(): static { - // Overriden to allow using symbols for namespacing the keys in redis - - return is_string($id); + return $this; } - public function getIdWithoutKeyPrefix() + public function isValidId($id) { - return $this->stripKeyPrefix($this->getId()); + // Overridden to allow prefixed id + return is_string($id); } /** @@ -235,63 +161,58 @@ public function getIdWithoutKeyPrefix() * @param string $sessionId * @return bool */ - public function migrate($destroy = false, int $userId = null) + public function migrate($destroy = false) { - // Overriden to allow passing through $userId to namespace session ids - if ($destroy) { - if (!$this->isGuestSession()) { - static::removeFullId($userId, $this->getId()); + $userId = $this->userId(); + if ($userId !== null) { + // Keep existing attributes + $attributes = $this->attributes; + static::batchDelete($userId, [$this->getId()]); + $this->attributes = $attributes; } - $this->handler->destroy($this->getId()); } - $this->setExists(false); - $this->setId($this->generateSessionId($userId)); - return true; + return parent::migrate($destroy); } /** * Save the session data to storage. + * + * Overriden to track user sessions in Redis and shorten lifetime for guest sessions. */ public function save() { - $isGuest = $this->isGuestSession(); + $userId = $this->userId(); if ($this->handler instanceof CacheBasedSessionHandler) { - $this->handler->setMinutes($isGuest ? 120 : config('session.lifetime')); + $this->handler->setMinutes($userId === null ? 120 : config('session.lifetime')); } - // Overriden to track user sessions in Redis parent::save(); - if (!$isGuest) { - Redis::sadd(config('cache.prefix').':'.$this->getCurrentKeyPrefix(), $this->getKey()); + // TODO: move this to migrate and validate session id in readFromHandler + if ($userId !== null) { + static::redis()->sadd(static::listKey($userId), $this->getId()); } } - /** - * Get a new, random session ID. - * - * @return string - */ - protected function generateSessionId(int $userId = null) + public function userId(): ?int { - // Overriden to allow namespacing the session id (used as the redis key) - - return static::keyPrefix($userId).':'.Str::random(static::SESSION_ID_LENGTH); + // From `Auth::getName()`. + // Hardcoded because Auth depends on this class instance which then + // calls this functions and would otherwise cause circular dependency. + return $this->attributes['login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d'] ?? null; } - /** - * Get the redis key prefix of the current session (excluding cache prefix). - * - * @return string - */ - protected function getCurrentKeyPrefix() + protected function generateSessionId() { - $sessionId = $this->getId(); + $userId = $this->userId(); - return substr($sessionId, 0, strlen($sessionId) - static::SESSION_ID_LENGTH - 1); + return static::PREFIX + .($userId === null ? 'guest' : "user:{$userId}") + .':' + .parent::generateSessionId(); } /** @@ -302,7 +223,6 @@ protected function getCurrentKeyPrefix() protected function readFromHandler() { // Overridden to force session ids to be regenerated when trying to load a session that doesn't exist anymore - if ($data = $this->handler->read($this->getId())) { $data = @unserialize($this->prepareForUnserialize($data)); @@ -315,14 +235,4 @@ protected function readFromHandler() return []; } - - /** - * Returns the session id without the key prefix. - * - * @return string - */ - protected function stripKeyPrefix($sessionId) - { - return substr($sessionId, -static::SESSION_ID_LENGTH); - } } diff --git a/app/Libraries/User/ForceReactivation.php b/app/Libraries/User/ForceReactivation.php index 9f0763f1ab9..e062efd4803 100644 --- a/app/Libraries/User/ForceReactivation.php +++ b/app/Libraries/User/ForceReactivation.php @@ -44,7 +44,7 @@ public function run() $this->addHistoryNote(); $this->user->update(['user_password' => '']); - SessionStore::destroy($userId); + SessionStore::batchDelete($userId); UserClient::where('user_id', $userId)->update(['verified' => false]); if (!$waitingActivation && is_valid_email_format($this->user->user_email)) { diff --git a/app/Libraries/UserVerificationState.php b/app/Libraries/UserVerificationState.php index f18441dc79d..3f8072b003c 100644 --- a/app/Libraries/UserVerificationState.php +++ b/app/Libraries/UserVerificationState.php @@ -7,18 +7,18 @@ use App\Events\UserSessionEvent; use App\Exceptions\UserVerificationException; -use App\Libraries\Session\SessionManager; +use App\Libraries\Session\Store as SessionStore; use App\Models\User; class UserVerificationState { - protected $user; - - private $session; + private function __construct(private User $user, private SessionStore $session) + { + } public static function fromCurrentRequest() { - return new static(auth()->user(), session()); + return new static(\Auth::user(), \Session::instance()); } public static function fromVerifyLink($linkKey) @@ -41,21 +41,10 @@ public static function fromVerifyLink($linkKey) public static function load($params) { - return new static(User::find($params['userId']), SessionManager::create($params['sessionId'])); - } - - private function __construct($user, $session) - { - $this->session = $session; - $this->user = $user; - - $currentSession = session(); - if ($this->session->getId() === $currentSession->getId()) { - // Override passed session if it's the same as current session - // otherwise the changes here will be overriden when current - // session is saved. - $this->session = $currentSession; - } + return new static( + User::find($params['userId']), + SessionStore::findOrCreate($params['sessionId']), + ); } public function dump() @@ -119,7 +108,7 @@ public function markVerified() $this->session->put('verified', true); $this->session->save(); - UserSessionEvent::newVerified($this->user->getKey(), $this->session->getKey())->broadcast(); + UserSessionEvent::newVerified($this->user->getKey(), $this->session->getId())->broadcast(); } public function verify($inputKey) diff --git a/app/Models/User.php b/app/Models/User.php index 04a34a07aa9..45a5c87c985 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -1798,7 +1798,16 @@ public function authHash(): string public function resetSessions(?string $excludedSessionId = null): void { - SessionStore::destroy($this->getKey(), $excludedSessionId); + $userId = $this->getKey(); + $sessionIds = SessionStore::ids($userId); + if ($excludedSessionId !== null) { + $sessionIds = array_filter( + $sessionIds, + fn ($sessionId) => $sessionId !== $excludedSessionId, + ); + } + SessionStore::batchDelete($userId, $sessionIds); + $this ->tokens() ->with('refreshToken') diff --git a/config/cache.php b/config/cache.php index 68ca5bff37b..1a182c5f3e4 100644 --- a/config/cache.php +++ b/config/cache.php @@ -77,6 +77,6 @@ | */ - 'prefix' => 'osu-next', + 'prefix' => null, ]; diff --git a/config/database.php b/config/database.php index 2102aef0463..e929cdb61e6 100644 --- a/config/database.php +++ b/config/database.php @@ -134,6 +134,7 @@ 'database' => get_int(env('CACHE_REDIS_DB')) ?? 0, 'password' => presence(env('CACHE_REDIS_PASSWORD')) ?? presence(env('REDIS_PASSWORD')), 'persistent' => true, + 'prefix' => 'osu-next:', ], 'default' => [ @@ -151,7 +152,6 @@ 'password' => presence(env('NOTIFICATION_REDIS_PASSWORD')), 'persistent' => true, ], - ], ]; diff --git a/config/session.php b/config/session.php index 36297032603..a6285afe53c 100644 --- a/config/session.php +++ b/config/session.php @@ -71,7 +71,7 @@ | */ - 'connection' => null, + 'connection' => 'cache', /* |-------------------------------------------------------------------------- diff --git a/tests/Controllers/Account/SessionsControllerTest.php b/tests/Controllers/Account/SessionsControllerTest.php new file mode 100644 index 00000000000..356cf6c1134 --- /dev/null +++ b/tests/Controllers/Account/SessionsControllerTest.php @@ -0,0 +1,66 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace Tests\Controllers\Account; + +use App\Libraries\Session\Store as SessionStore; +use App\Models\User; +use Tests\TestCase; + +class SessionsControllerTest extends TestCase +{ + public function testDestroyOther(): void + { + $user = User::factory()->create(); + $oldSessionId = $this->createVerifiedSession($user)->getId(); + + $session = $this->createVerifiedSession($user); + + $this + ->withPersistentSession($session) + ->delete(route('account.sessions.destroy', ['session' => $oldSessionId])) + ->assertSuccessful(); + + $sessionIds = SessionStore::ids($user->getKey()); + $this->assertContains($session->getId(), $sessionIds); + $this->assertNotContains($oldSessionId, $sessionIds); + $this->assertNull(SessionStore::findOrCreate($oldSessionId)->userId()); + } + + public function testDestroyOtherUser(): void + { + $otherUser = User::factory()->create(); + $otherUserSessionId = $this->createVerifiedSession($otherUser)->getId(); + + $user = User::factory()->create(); + $session = $this->createVerifiedSession($user); + + $this + ->withPersistentSession($session) + ->delete(route('account.sessions.destroy', ['session' => $otherUserSessionId])) + ->assertStatus(404); + + $this->assertSame( + $otherUser->getKey(), + SessionStore::findOrCreate($otherUserSessionId)->userId(), + ); + } + + public function testDestroySelf(): void + { + $user = User::factory()->create(); + $session = $this->createVerifiedSession($user); + $sessionId = $session->getId(); + + $this + ->withPersistentSession($session) + ->delete(route('account.sessions.destroy', ['session' => $sessionId])) + ->assertSuccessful(); + + $this->assertNull(SessionStore::findOrCreate($sessionId)->userId()); + } +} diff --git a/tests/Libraries/Session/StoreTest.php b/tests/Libraries/Session/StoreTest.php new file mode 100644 index 00000000000..770c254584d --- /dev/null +++ b/tests/Libraries/Session/StoreTest.php @@ -0,0 +1,38 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace Tests\Libraries\Session; + +use App\Libraries\Session\Store; +use App\Models\User; +use Tests\TestCase; + +class StoreTest extends TestCase +{ + public function testBatchDeleteRemovesCurrentSessionUserId(): void + { + $user = User::factory()->create(); + \Auth::login($user); + $session = \Session::instance(); + + $this->assertSame($user->getKey(), $session->userId()); + + Store::batchDelete($user->getKey(), [$session->getId()]); + + $this->assertNull($session->userId()); + } + + public function testUserId(): void + { + $this->assertNull(\Session::userId()); + + $user = User::factory()->create(); + \Auth::login($user); + + $this->assertSame(\Session::userId(), $user->getKey()); + } +} diff --git a/tests/Libraries/UserVerificationTest.php b/tests/Libraries/UserVerificationTest.php index 654601c1c54..66304d5a7aa 100644 --- a/tests/Libraries/UserVerificationTest.php +++ b/tests/Libraries/UserVerificationTest.php @@ -7,7 +7,7 @@ namespace Tests\Libraries; -use App\Libraries\Session\SessionManager; +use App\Libraries\Session\Store as SessionStore; use App\Libraries\UserVerification; use App\Libraries\UserVerificationState; use App\Models\LoginAttempt; @@ -69,7 +69,7 @@ public function testVerifyLink(): void $linkKey = $session->get('verification_link_key'); - $guestSession = SessionManager::create(); + $guestSession = SessionStore::findOrCreate(); $this ->withPersistentSession($guestSession) ->get(route('account.verify', ['key' => $linkKey])) @@ -94,7 +94,7 @@ public function testVerifyLinkMismatch(): void ->assertStatus(401) ->assertViewIs('users.verify'); - $guestSession = SessionManager::create(); + $guestSession = SessionStore::findOrCreate(); $this ->withPersistentSession($guestSession) ->get(route('account.verify', ['key' => 'invalid'])) diff --git a/tests/Models/UserTest.php b/tests/Models/UserTest.php index 3cc898371b7..457b193e05c 100644 --- a/tests/Models/UserTest.php +++ b/tests/Models/UserTest.php @@ -67,16 +67,12 @@ public function testUsernameAvailableAtForNonDefaultGroup() public function testResetSessions(): void { - if (!Store::isUsingRedis()) { - $this->markTestSkipped('reset sessions test requires redis based session'); - } - $user = User::factory()->create(); // create session $this->post(route('login'), ['username' => $user->username, 'password' => User::factory()::DEFAULT_PASSWORD]); // sanity check - $this->assertNotEmpty(Store::keys($user->getKey())); + $this->assertNotEmpty(Store::ids($user->getKey())); // create token $token = Token::factory()->create(['user_id' => $user, 'revoked' => false]); @@ -84,7 +80,7 @@ public function testResetSessions(): void $user->resetSessions(); - $this->assertEmpty(Store::keys($user->getKey())); + $this->assertEmpty(Store::ids($user->getKey())); $this->assertTrue($token->fresh()->revoked); $this->assertTrue($refreshToken->fresh()->revoked); } diff --git a/tests/TestCase.php b/tests/TestCase.php index 48ca35963ba..c34a5e6811c 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -235,6 +235,17 @@ protected function createAllowedScopesDataProvider(array $allowedScopes) return $data; } + protected function createVerifiedSession($user): SessionStore + { + $ret = SessionStore::findOrCreate(); + $ret->put(\Auth::getName(), $user->getKey()); + $ret->put('verified', true); + $ret->migrate(false); + $ret->save(); + + return $ret; + } + protected function clearMailFake() { $mailer = app('mailer'); From 7b130256f566fbe676ea5782113398d9b2e956e6 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 5 Dec 2023 22:45:34 +0900 Subject: [PATCH 034/102] Use request facade --- app/Libraries/RouteSection.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/Libraries/RouteSection.php b/app/Libraries/RouteSection.php index af03c091baf..d4c1f731d6c 100644 --- a/app/Libraries/RouteSection.php +++ b/app/Libraries/RouteSection.php @@ -142,7 +142,7 @@ class RouteSection public function getCurrent($key = null) { - $data = request()->attributes->get('route_section_error') ?? $this->getOriginal(); + $data = \Request::instance()->attributes->get('route_section_error') ?? $this->getOriginal(); if ($key === null) { return $data; @@ -153,19 +153,19 @@ public function getCurrent($key = null) public function getOriginal() { - $default = request()->attributes->get('route_section'); + $request = \Request::instance(); + $default = $request->attributes->get('route_section'); if ($default === null) { - $currentRoute = request()->route(); - $currentController = optional($currentRoute)->controller; + $currentRoute = $request->route(); + $currentController = $currentRoute?->controller; - if (isset($currentRoute) && isset($currentController)) { - $className = get_class($currentController); + if (isset($currentController)) { + $className = $currentController::class; $namespace = get_class_namespace($className); - $namespace = str_replace('App\\Http\\Controllers', '', $namespace); - $namespace = snake_case(str_replace('\\', '', $namespace)); - $namespace = presence($namespace) ?? 'main'; + $namespace = strtr($namespace, ['\\' => '', 'App\\Http\\Controllers' => '']); + $namespace = presence(snake_case($namespace)) ?? 'main'; $controller = snake_case(get_class_basename($className)); $action = snake_case($currentRoute->getActionMethod()); @@ -182,7 +182,7 @@ public function getOriginal() 'namespace' => $namespace ?? 'unknown', 'section' => $section ?? 'unknown', ]; - request()->attributes->set('route_section', $default); + $request->attributes->set('route_section', $default); } return $default; @@ -190,7 +190,7 @@ public function getOriginal() public function setError($statusCode) { - request()->attributes->set('route_section_error', [ + \Request::instance()->attributes->set('route_section_error', [ 'action' => $statusCode, 'controller' => 'error', 'namespace' => 'error', From 8d2a03689be3ad29309802849c96173633a485ea Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 5 Dec 2023 22:45:51 +0900 Subject: [PATCH 035/102] Call getCurrent once --- app/Libraries/RouteSection.php | 11 +++-------- resources/views/home/_user_header_default.blade.php | 3 ++- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/app/Libraries/RouteSection.php b/app/Libraries/RouteSection.php index d4c1f731d6c..aac4a727a9b 100644 --- a/app/Libraries/RouteSection.php +++ b/app/Libraries/RouteSection.php @@ -140,15 +140,10 @@ class RouteSection ], ]; - public function getCurrent($key = null) + public function getCurrent(): array { - $data = \Request::instance()->attributes->get('route_section_error') ?? $this->getOriginal(); - - if ($key === null) { - return $data; - } - - return $data[$key]; + return \Request::instance()->attributes->get('route_section_error') + ?? $this->getOriginal(); } public function getOriginal() diff --git a/resources/views/home/_user_header_default.blade.php b/resources/views/home/_user_header_default.blade.php index cdf6dc936a3..817fc198478 100644 --- a/resources/views/home/_user_header_default.blade.php +++ b/resources/views/home/_user_header_default.blade.php @@ -3,7 +3,8 @@ See the LICENCE file in the repository root for full licence text. --}} @php - $currentActive = app('route-section')->getCurrent('controller').'.'.app('route-section')->getCurrent('action'); + $currentRoute = app('route-section')->getCurrent(); + $currentActive = $currentRoute['controller'].'.'.$currentRoute['action']; @endphp @include('layout._page_header_v4', ['params' => [ 'backgroundExtraClass' => 'js-current-user-cover', From 6b3fd438bc56206a8a6c04d3c29ed037c51237d6 Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 6 Dec 2023 21:35:54 +0900 Subject: [PATCH 036/102] Don't permanently cache the connection --- app/Libraries/Session/Store.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 8cb331286d2..2ea74c13ffc 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -16,8 +16,6 @@ class Store extends \Illuminate\Session\Store { private const PREFIX = 'sessions:'; - private static PhpRedisConnection $redis; - public static function batchDelete(int $userId, ?array $ids = null): void { $ids ??= static::ids($userId); @@ -132,7 +130,7 @@ private static function listKey(int $userId): string private static function redis(): PhpRedisConnection { - return static::$redis ??= \LaravelRedis::connection(\Config::get('session.connection')); + return \LaravelRedis::connection(\Config::get('session.connection')); } public function delete(): void From 57494f818b1d5f99476f393833ce6cb30750f834 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 7 Dec 2023 20:11:52 +0900 Subject: [PATCH 037/102] The current session connection is default It just takes the cache settings and replace the connection with default. --- config/database.php | 24 ++++++++++++++++-------- config/session.php | 2 +- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/config/database.php b/config/database.php index e929cdb61e6..ee1685a6e2b 100644 --- a/config/database.php +++ b/config/database.php @@ -41,6 +41,15 @@ ], ]; +$redisDefault = [ + 'host' => presence(env('REDIS_HOST')) ?? '127.0.0.1', + 'port' => get_int(env('REDIS_PORT')) ?? 6379, + 'database' => get_int(env('REDIS_DB')) ?? 0, + 'password' => presence(env('REDIS_PASSWORD')), + 'persistent' => true, +]; +$redisCachePrefix = 'osu-next:'; + return [ /* @@ -134,16 +143,10 @@ 'database' => get_int(env('CACHE_REDIS_DB')) ?? 0, 'password' => presence(env('CACHE_REDIS_PASSWORD')) ?? presence(env('REDIS_PASSWORD')), 'persistent' => true, - 'prefix' => 'osu-next:', + 'prefix' => $redisCachePrefix, ], - 'default' => [ - 'host' => presence(env('REDIS_HOST')) ?? '127.0.0.1', - 'port' => get_int(env('REDIS_PORT')) ?? 6379, - 'database' => get_int(env('REDIS_DB')) ?? 0, - 'password' => presence(env('REDIS_PASSWORD')), - 'persistent' => true, - ], + 'default' => $redisDefault, 'notification' => [ 'host' => presence(env('NOTIFICATION_REDIS_HOST')) ?? '127.0.0.1', @@ -152,6 +155,11 @@ 'password' => presence(env('NOTIFICATION_REDIS_PASSWORD')), 'persistent' => true, ], + + 'session' => [ + ...$redisDefault, + 'prefix' => $redisCachePrefix, + ], ], ]; diff --git a/config/session.php b/config/session.php index a6285afe53c..1957716d6d0 100644 --- a/config/session.php +++ b/config/session.php @@ -71,7 +71,7 @@ | */ - 'connection' => 'cache', + 'connection' => 'session', /* |-------------------------------------------------------------------------- From 3355e936529c08b2f224c38dfe6c4595e0a80116 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 7 Dec 2023 20:14:49 +0900 Subject: [PATCH 038/102] It doesn't save new session --- app/Http/Controllers/Account/SessionsController.php | 2 +- app/Libraries/Session/Store.php | 2 +- app/Libraries/UserVerificationState.php | 2 +- tests/Controllers/Account/SessionsControllerTest.php | 6 +++--- tests/Libraries/UserVerificationTest.php | 4 ++-- tests/TestCase.php | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/Account/SessionsController.php b/app/Http/Controllers/Account/SessionsController.php index c2af5c7b2d1..e9aa11f157b 100644 --- a/app/Http/Controllers/Account/SessionsController.php +++ b/app/Http/Controllers/Account/SessionsController.php @@ -24,7 +24,7 @@ public function destroy($id) // current session logout(); } else { - $session = SessionStore::findOrCreate($id); + $session = SessionStore::findOrNew($id); if ($session->userId() === \Auth::user()->getKey()) { $session->delete(); } else { diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 2ea74c13ffc..f574e34f9e7 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -35,7 +35,7 @@ public static function batchDelete(int $userId, ?array $ids = null): void UserSessionEvent::newLogout($userId, $ids)->broadcast(); } - public static function findOrCreate(?string $id = null): static + public static function findOrNew(?string $id = null): static { if ($id !== null) { $currentSession = \Session::instance(); diff --git a/app/Libraries/UserVerificationState.php b/app/Libraries/UserVerificationState.php index 3f8072b003c..9639c560243 100644 --- a/app/Libraries/UserVerificationState.php +++ b/app/Libraries/UserVerificationState.php @@ -43,7 +43,7 @@ public static function load($params) { return new static( User::find($params['userId']), - SessionStore::findOrCreate($params['sessionId']), + SessionStore::findOrNew($params['sessionId']), ); } diff --git a/tests/Controllers/Account/SessionsControllerTest.php b/tests/Controllers/Account/SessionsControllerTest.php index 356cf6c1134..5d9fbe5fae6 100644 --- a/tests/Controllers/Account/SessionsControllerTest.php +++ b/tests/Controllers/Account/SessionsControllerTest.php @@ -28,7 +28,7 @@ public function testDestroyOther(): void $sessionIds = SessionStore::ids($user->getKey()); $this->assertContains($session->getId(), $sessionIds); $this->assertNotContains($oldSessionId, $sessionIds); - $this->assertNull(SessionStore::findOrCreate($oldSessionId)->userId()); + $this->assertNull(SessionStore::findOrNew($oldSessionId)->userId()); } public function testDestroyOtherUser(): void @@ -46,7 +46,7 @@ public function testDestroyOtherUser(): void $this->assertSame( $otherUser->getKey(), - SessionStore::findOrCreate($otherUserSessionId)->userId(), + SessionStore::findOrNew($otherUserSessionId)->userId(), ); } @@ -61,6 +61,6 @@ public function testDestroySelf(): void ->delete(route('account.sessions.destroy', ['session' => $sessionId])) ->assertSuccessful(); - $this->assertNull(SessionStore::findOrCreate($sessionId)->userId()); + $this->assertNull(SessionStore::findOrNew($sessionId)->userId()); } } diff --git a/tests/Libraries/UserVerificationTest.php b/tests/Libraries/UserVerificationTest.php index 66304d5a7aa..bf92b06c124 100644 --- a/tests/Libraries/UserVerificationTest.php +++ b/tests/Libraries/UserVerificationTest.php @@ -69,7 +69,7 @@ public function testVerifyLink(): void $linkKey = $session->get('verification_link_key'); - $guestSession = SessionStore::findOrCreate(); + $guestSession = SessionStore::findOrNew(); $this ->withPersistentSession($guestSession) ->get(route('account.verify', ['key' => $linkKey])) @@ -94,7 +94,7 @@ public function testVerifyLinkMismatch(): void ->assertStatus(401) ->assertViewIs('users.verify'); - $guestSession = SessionStore::findOrCreate(); + $guestSession = SessionStore::findOrNew(); $this ->withPersistentSession($guestSession) ->get(route('account.verify', ['key' => 'invalid'])) diff --git a/tests/TestCase.php b/tests/TestCase.php index c34a5e6811c..9fcf5257b79 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -237,7 +237,7 @@ protected function createAllowedScopesDataProvider(array $allowedScopes) protected function createVerifiedSession($user): SessionStore { - $ret = SessionStore::findOrCreate(); + $ret = SessionStore::findOrNew(); $ret->put(\Auth::getName(), $user->getKey()); $ret->put('verified', true); $ret->migrate(false); From 0412d4232124e7f0a13e7de391e3e059c2a419e4 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 21:19:34 +0900 Subject: [PATCH 039/102] There's no user: prefix --- app/Libraries/Session/Store.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index f574e34f9e7..fcd484ff588 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -208,7 +208,7 @@ protected function generateSessionId() $userId = $this->userId(); return static::PREFIX - .($userId === null ? 'guest' : "user:{$userId}") + .($userId ?? 'guest') .':' .parent::generateSessionId(); } From 9cc9c68bf413169889aa531e9d665fc931b9ec17 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 21:20:25 +0900 Subject: [PATCH 040/102] Add missing typing --- app/Libraries/Session/Store.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index fcd484ff588..08415ea8b8c 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -62,7 +62,7 @@ public static function ids(int $userId): array ); } - public static function sessions($userId): array + public static function sessions(int $userId): array { $ids = static::ids($userId); if (empty($ids)) { From c85179a3b0604bb02243e63917afd5cd84293baa Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 21:36:50 +0900 Subject: [PATCH 041/102] More thorough logout --- app/helpers.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/helpers.php b/app/helpers.php index dbfe75eacf5..e5ea926803e 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -464,14 +464,17 @@ function log_error($exception) function logout() { - $guard = auth()->guard(); + $session = Session::instance(); + $session->delete(); + + $guard = Auth::guard(); if ($guard instanceof Illuminate\Contracts\Auth\StatefulGuard) { $guard->logout(); } cleanup_cookies(); - session()->invalidate(); + $session->invalidate(); } function markdown($input, $preset = 'default') From bac7411002ca3a1e9c16581a0dcd96e4121f9b16 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 21:42:53 +0900 Subject: [PATCH 042/102] Don't fail deleting guest session --- app/Libraries/Session/Store.php | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 08415ea8b8c..29e0cff2581 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -16,7 +16,7 @@ class Store extends \Illuminate\Session\Store { private const PREFIX = 'sessions:'; - public static function batchDelete(int $userId, ?array $ids = null): void + public static function batchDelete(?int $userId, ?array $ids = null): void { $ids ??= static::ids($userId); @@ -29,10 +29,18 @@ public static function batchDelete(int $userId, ?array $ids = null): void $currentSession->flush(); } + // Older sessions are stored with connection prefix included. + $ids = array_map( + fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id, + $ids, + ); + $redis = static::redis(); $redis->del($ids); - $redis->srem(static::listKey($userId), ...$ids); - UserSessionEvent::newLogout($userId, $ids)->broadcast(); + if ($userId !== null) { + $redis->srem(static::listKey($userId), ...$ids); + UserSessionEvent::newLogout($userId, $ids)->broadcast(); + } } public static function findOrNew(?string $id = null): static @@ -54,12 +62,11 @@ public static function findOrNew(?string $id = null): static return $ret; } - public static function ids(int $userId): array + public static function ids(?int $userId): array { - return array_map( - fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id, - static::redis()->smembers(static::listKey($userId)), - ); + return $userId === null + ? [] + : static::redis()->smembers(static::listKey($userId)); } public static function sessions(int $userId): array From 374836ccc8249ff72d89740a21ec7339c171577e Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 21:45:18 +0900 Subject: [PATCH 043/102] Update comment --- app/Libraries/Session/Store.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 29e0cff2581..87d39568199 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -160,11 +160,9 @@ public function isValidId($id) } /** - * Generate a new session ID for the session. + * Generate a new session id. * - * @param bool $destroy - * @param string $sessionId - * @return bool + * Overridden to delete session from redis - both entry and list. */ public function migrate($destroy = false) { From 42657ac330db04773a319859413f123b0acd5dc5 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 21:47:11 +0900 Subject: [PATCH 044/102] Add note about notification server usage of the hashed key --- app/Libraries/Session/Store.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 87d39568199..57371b6e4ff 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -205,6 +205,8 @@ public function userId(): ?int // From `Auth::getName()`. // Hardcoded because Auth depends on this class instance which then // calls this functions and would otherwise cause circular dependency. + // Note that osu-notification-server also checks this key. Make sure + // to also update it if the value changes. return $this->attributes['login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d'] ?? null; } From 38915f9242bd08d348faf5093b7e8ee356c8585e Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 21:52:50 +0900 Subject: [PATCH 045/102] del shouldn't use the prefix but srem should --- app/Libraries/Session/Store.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 57371b6e4ff..1cbe3c87fc2 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -29,14 +29,15 @@ public static function batchDelete(?int $userId, ?array $ids = null): void $currentSession->flush(); } - // Older sessions are stored with connection prefix included. - $ids = array_map( + // Older sessions are stored in list with connection prefix included + // but del automatically adds it. + $delIds = array_map( fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id, $ids, ); $redis = static::redis(); - $redis->del($ids); + $redis->del($delIds); if ($userId !== null) { $redis->srem(static::listKey($userId), ...$ids); UserSessionEvent::newLogout($userId, $ids)->broadcast(); From 66c6ab07f92f63f9dea124be2a27a89869f402cf Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 21:59:29 +0900 Subject: [PATCH 046/102] Or more like never return older prefixed ids And include the prefixed id when removing from list. --- app/Libraries/Session/Store.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 1cbe3c87fc2..0b189ea41e1 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -29,16 +29,17 @@ public static function batchDelete(?int $userId, ?array $ids = null): void $currentSession->flush(); } - // Older sessions are stored in list with connection prefix included - // but del automatically adds it. - $delIds = array_map( - fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id, - $ids, - ); - $redis = static::redis(); - $redis->del($delIds); + $redis->del($ids); if ($userId !== null) { + $listIds = [ + ...$ids, + // Also delete ids that were previously stored with prefix. + ...array_map( + fn ($id) => "osu-next:{$id}", + $ids, + ), + ]; $redis->srem(static::listKey($userId), ...$ids); UserSessionEvent::newLogout($userId, $ids)->broadcast(); } @@ -67,7 +68,11 @@ public static function ids(?int $userId): array { return $userId === null ? [] - : static::redis()->smembers(static::listKey($userId)); + : array_map( + // The ids were previously stored with prefix. + fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id, + static::redis()->smembers(static::listKey($userId)); + ); } public static function sessions(int $userId): array From 3839de12b810937924cd1081c3f11c7e6852c520 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 22:06:17 +0900 Subject: [PATCH 047/102] Nvm the extra cleanup, it's already part of the invalidate --- app/helpers.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/helpers.php b/app/helpers.php index e5ea926803e..75aab1faf97 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -464,9 +464,6 @@ function log_error($exception) function logout() { - $session = Session::instance(); - $session->delete(); - $guard = Auth::guard(); if ($guard instanceof Illuminate\Contracts\Auth\StatefulGuard) { $guard->logout(); @@ -474,7 +471,7 @@ function logout() cleanup_cookies(); - $session->invalidate(); + \Session::invalidate(); } function markdown($input, $preset = 'default') From 95e10aa2cafe29cac5e619b8f1ce9acc2d5db2bc Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 8 Dec 2023 22:06:48 +0900 Subject: [PATCH 048/102] Fix syntax error --- app/Libraries/Session/Store.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 0b189ea41e1..c50d7ad5fe8 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -71,7 +71,7 @@ public static function ids(?int $userId): array : array_map( // The ids were previously stored with prefix. fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id, - static::redis()->smembers(static::listKey($userId)); + static::redis()->smembers(static::listKey($userId)), ); } From 1e6d6cdda00db770ceff0e0f960d85ffae3d6d04 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 11 Dec 2023 16:12:06 +0900 Subject: [PATCH 049/102] Use self for private access --- app/Libraries/Session/Store.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index c50d7ad5fe8..6bceab1be57 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -29,7 +29,7 @@ public static function batchDelete(?int $userId, ?array $ids = null): void $currentSession->flush(); } - $redis = static::redis(); + $redis = self::redis(); $redis->del($ids); if ($userId !== null) { $listIds = [ @@ -40,7 +40,7 @@ public static function batchDelete(?int $userId, ?array $ids = null): void $ids, ), ]; - $redis->srem(static::listKey($userId), ...$ids); + $redis->srem(self::listKey($userId), ...$ids); UserSessionEvent::newLogout($userId, $ids)->broadcast(); } } @@ -71,7 +71,7 @@ public static function ids(?int $userId): array : array_map( // The ids were previously stored with prefix. fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id, - static::redis()->smembers(static::listKey($userId)), + self::redis()->smembers(self::listKey($userId)), ); } @@ -87,7 +87,7 @@ public static function sessions(int $userId): array // Sessions are stored double-serialized in redis (session serialization + cache backend serialization) array_map( fn ($s) => $s === null ? null : unserialize(unserialize($s)), - static::redis()->mget($ids), + self::redis()->mget($ids), ), ); @@ -202,7 +202,7 @@ public function save() // TODO: move this to migrate and validate session id in readFromHandler if ($userId !== null) { - static::redis()->sadd(static::listKey($userId), $this->getId()); + self::redis()->sadd(self::listKey($userId), $this->getId()); } } @@ -220,7 +220,7 @@ protected function generateSessionId() { $userId = $this->userId(); - return static::PREFIX + return self::PREFIX .($userId ?? 'guest') .':' .parent::generateSessionId(); From 112bd2244b2e310713b6f4528ff27c62ca326b74 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 11 Dec 2023 17:11:26 +0900 Subject: [PATCH 050/102] Limit beatmapset discussion post message length --- app/Models/BeatmapDiscussionPost.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/Models/BeatmapDiscussionPost.php b/app/Models/BeatmapDiscussionPost.php index 179eff3f923..22d8efea995 100644 --- a/app/Models/BeatmapDiscussionPost.php +++ b/app/Models/BeatmapDiscussionPost.php @@ -29,6 +29,7 @@ class BeatmapDiscussionPost extends Model implements Traits\ReportableInterface { use Traits\Reportable, Validatable; + const MESSAGE_LIMIT = 16_000; // column limit for 4 bytes utf8 const MESSAGE_LIMIT_TIMELINE = 750; protected $touches = ['beatmapDiscussion']; @@ -226,9 +227,10 @@ public function isValid() $this->validationErrors()->add('message', 'required'); } - if ($this->beatmapDiscussion?->timestamp !== null) { - $this->validateDbFieldLength(static::MESSAGE_LIMIT_TIMELINE, 'message'); - } + $limit = $this->beatmapDiscussion?->timestamp === null + ? static::MESSAGE_LIMIT + : static::MESSAGE_LIMIT_TIMELINE; + $this->validateDbFieldLength($limit, 'message'); } return $this->validationErrors()->isEmpty(); From 92b77e807bd81ff5702424cae10c5b76dbcf4bb8 Mon Sep 17 00:00:00 2001 From: Edho Arief Date: Mon, 11 Dec 2023 18:01:21 +0900 Subject: [PATCH 051/102] Use correct variable Co-authored-by: bakaneko --- app/Libraries/Session/Store.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 6bceab1be57..e9d9fea9b82 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -40,7 +40,7 @@ public static function batchDelete(?int $userId, ?array $ids = null): void $ids, ), ]; - $redis->srem(self::listKey($userId), ...$ids); + $redis->srem(self::listKey($userId), ...$listIds); UserSessionEvent::newLogout($userId, $ids)->broadcast(); } } From 3168561e3b5b947a202127c9a782dc8b3234a380 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 11 Dec 2023 20:45:24 +0900 Subject: [PATCH 052/102] Fix logout event --- app/Events/UserSessionEvent.php | 30 +++++++++++------------------- app/Libraries/Session/Store.php | 16 ++++++++++++---- app/helpers.php | 9 ++------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/app/Events/UserSessionEvent.php b/app/Events/UserSessionEvent.php index 4f099c50535..a073b29d1bb 100644 --- a/app/Events/UserSessionEvent.php +++ b/app/Events/UserSessionEvent.php @@ -5,17 +5,21 @@ namespace App\Events; +use App\Libraries\Session; use Illuminate\Broadcasting\Channel; class UserSessionEvent extends NotificationEventBase { - public $action; - public $data; - public $userId; + private function __construct(public $action, public $userId, public $data) + { + parent::__construct(); + } public static function newLogout($userId, $keys) { - return new static('logout', $userId, compact('keys')); + return new static('logout', $userId, [ + 'keys' => Session\Store::keysForRedis($keys), + ]); } public static function newVerificationRequirementChange($userId, $isRequired) @@ -27,21 +31,9 @@ public static function newVerificationRequirementChange($userId, $isRequired) public static function newVerified($userId, $key) { - return new static('verified', $userId, compact('key')); - } - - /** - * Create a new event instance. - * - * @return void - */ - private function __construct($action, $userId, $data) - { - parent::__construct(); - - $this->action = $action; - $this->userId = $userId; - $this->data = $data; + return new static('verified', $userId, [ + 'key' => Session\Store::keyForRedis($key), + ]); } public function broadcastAs() diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index e9d9fea9b82..9e4ffe342a9 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -35,10 +35,7 @@ public static function batchDelete(?int $userId, ?array $ids = null): void $listIds = [ ...$ids, // Also delete ids that were previously stored with prefix. - ...array_map( - fn ($id) => "osu-next:{$id}", - $ids, - ), + ...self::keysForRedis($ids), ]; $redis->srem(self::listKey($userId), ...$listIds); UserSessionEvent::newLogout($userId, $ids)->broadcast(); @@ -75,6 +72,17 @@ public static function ids(?int $userId): array ); } + public static function keyForRedis(string $id): string + { + // TODO: use config's database.redis.session.prefix (also in notification-server) + return "osu-next:{$id}"; + } + + public static function keysForRedis(array $ids): array + { + return array_map(static::keyForRedis(...), $ids); + } + public static function sessions(int $userId): array { $ids = static::ids($userId); diff --git a/app/helpers.php b/app/helpers.php index 75aab1faf97..218d0c9bc1d 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -464,14 +464,9 @@ function log_error($exception) function logout() { - $guard = Auth::guard(); - if ($guard instanceof Illuminate\Contracts\Auth\StatefulGuard) { - $guard->logout(); - } - + \Session::delete(); + Auth::logout(); cleanup_cookies(); - - \Session::invalidate(); } function markdown($input, $preset = 'default') From 919cd22fc9ed3c4109d5e80264f33f86dd73c9e0 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Dec 2023 06:31:50 +0900 Subject: [PATCH 053/102] Pass actual key listened by notification server Otherwise it breaks the one in Token model. --- app/Events/UserSessionEvent.php | 8 ++------ app/Libraries/Session/Store.php | 21 ++++++++++++--------- app/Libraries/UserVerificationState.php | 2 +- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/app/Events/UserSessionEvent.php b/app/Events/UserSessionEvent.php index a073b29d1bb..9514d8307f8 100644 --- a/app/Events/UserSessionEvent.php +++ b/app/Events/UserSessionEvent.php @@ -17,9 +17,7 @@ private function __construct(public $action, public $userId, public $data) public static function newLogout($userId, $keys) { - return new static('logout', $userId, [ - 'keys' => Session\Store::keysForRedis($keys), - ]); + return new static('logout', $userId, compact('keys')); } public static function newVerificationRequirementChange($userId, $isRequired) @@ -31,9 +29,7 @@ public static function newVerificationRequirementChange($userId, $isRequired) public static function newVerified($userId, $key) { - return new static('verified', $userId, [ - 'key' => Session\Store::keyForRedis($key), - ]); + return new static('verified', $userId, compact('key')); } public function broadcastAs() diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 9e4ffe342a9..612301eaf0b 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -32,12 +32,10 @@ public static function batchDelete(?int $userId, ?array $ids = null): void $redis = self::redis(); $redis->del($ids); if ($userId !== null) { - $listIds = [ - ...$ids, - // Also delete ids that were previously stored with prefix. - ...self::keysForRedis($ids), - ]; - $redis->srem(self::listKey($userId), ...$listIds); + $idsForEvent = self::keysForEvent($ids); + // Also delete ids that were previously stored with prefix which is + // the full redis key just like for event. + $redis->srem(self::listKey($userId), ...[...$ids, ...$idsForEvent]); UserSessionEvent::newLogout($userId, $ids)->broadcast(); } } @@ -72,15 +70,15 @@ public static function ids(?int $userId): array ); } - public static function keyForRedis(string $id): string + public static function keyForEvent(string $id): string { // TODO: use config's database.redis.session.prefix (also in notification-server) return "osu-next:{$id}"; } - public static function keysForRedis(array $ids): array + public static function keysForEvent(array $ids): array { - return array_map(static::keyForRedis(...), $ids); + return array_map(static::keyForEvent(...), $ids); } public static function sessions(int $userId): array @@ -159,6 +157,11 @@ public function delete(): void static::batchDelete($this->userId(), [$this->getId()]); } + public function getKeyForEvent(): string + { + return self::keyForEvent($this->getId()); + } + /** * Used to obtain the instance from Session facade or SessionManager instance */ diff --git a/app/Libraries/UserVerificationState.php b/app/Libraries/UserVerificationState.php index 9639c560243..ff1d99eac84 100644 --- a/app/Libraries/UserVerificationState.php +++ b/app/Libraries/UserVerificationState.php @@ -108,7 +108,7 @@ public function markVerified() $this->session->put('verified', true); $this->session->save(); - UserSessionEvent::newVerified($this->user->getKey(), $this->session->getId())->broadcast(); + UserSessionEvent::newVerified($this->user->getKey(), $this->session->getKeyForEvent())->broadcast(); } public function verify($inputKey) From 4ff40f12a3400b9390f6bc63ac2dfda3907a8d5b Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Dec 2023 06:36:35 +0900 Subject: [PATCH 054/102] Unused import --- app/Events/UserSessionEvent.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Events/UserSessionEvent.php b/app/Events/UserSessionEvent.php index 9514d8307f8..2357725f447 100644 --- a/app/Events/UserSessionEvent.php +++ b/app/Events/UserSessionEvent.php @@ -5,7 +5,6 @@ namespace App\Events; -use App\Libraries\Session; use Illuminate\Broadcasting\Channel; class UserSessionEvent extends NotificationEventBase From c4ea1394a1fc7de88dcd631aee0cab7d9981bfaf Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Dec 2023 16:09:58 +0900 Subject: [PATCH 055/102] Simpler --- app/Libraries/Session/Store.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 612301eaf0b..0093ca22452 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -35,7 +35,7 @@ public static function batchDelete(?int $userId, ?array $ids = null): void $idsForEvent = self::keysForEvent($ids); // Also delete ids that were previously stored with prefix which is // the full redis key just like for event. - $redis->srem(self::listKey($userId), ...[...$ids, ...$idsForEvent]); + $redis->srem(self::listKey($userId), ...$ids, ...$idsForEvent); UserSessionEvent::newLogout($userId, $ids)->broadcast(); } } From 0a5427d8dd0fded8ece61d8caad3526fb34b4c03 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Dec 2023 17:08:38 +0900 Subject: [PATCH 056/102] Would be useful to actually use idsForEvent for event --- app/Libraries/Session/Store.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 0093ca22452..04a0d82cd4c 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -36,7 +36,7 @@ public static function batchDelete(?int $userId, ?array $ids = null): void // Also delete ids that were previously stored with prefix which is // the full redis key just like for event. $redis->srem(self::listKey($userId), ...$ids, ...$idsForEvent); - UserSessionEvent::newLogout($userId, $ids)->broadcast(); + UserSessionEvent::newLogout($userId, $idsForEvent)->broadcast(); } } From 0194b3ae1a0b1e6042defe6940820ca3ef403625 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 7 Dec 2023 22:37:14 +0900 Subject: [PATCH 057/102] Store session verification request data in redis --- app/Exceptions/Handler.php | 9 +- app/Http/Controllers/AccountController.php | 20 +-- app/Http/Controllers/Controller.php | 5 +- .../Middleware/SetSessionVerification.php | 7 +- app/Http/Middleware/VerifyUser.php | 4 +- .../SessionVerificationInterface.php | 17 ++ app/Libraries/Session/Store.php | 25 ++- .../SessionVerification/Controller.php | 107 ++++++++++++ app/Libraries/SessionVerification/Helper.php | 55 ++++++ app/Libraries/SessionVerification/State.php | 105 +++++++++++ app/Libraries/UserVerification.php | 165 ------------------ app/Libraries/UserVerificationState.php | 143 --------------- .../AdditionalDuskServiceProvider.php | 5 +- .../ControllerTest.php} | 27 +-- 14 files changed, 340 insertions(+), 354 deletions(-) create mode 100644 app/Interfaces/SessionVerificationInterface.php create mode 100644 app/Libraries/SessionVerification/Controller.php create mode 100644 app/Libraries/SessionVerification/Helper.php create mode 100644 app/Libraries/SessionVerification/State.php delete mode 100644 app/Libraries/UserVerification.php delete mode 100644 app/Libraries/UserVerificationState.php rename tests/Libraries/{UserVerificationTest.php => SessionVerification/ControllerTest.php} (78%) diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index c2bfb2aa3c2..62fabda0009 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -5,7 +5,7 @@ namespace App\Exceptions; -use App\Libraries\UserVerification; +use App\Libraries\SessionVerification; use Auth; use Illuminate\Auth\Access\AuthorizationException as LaravelAuthorizationException; use Illuminate\Auth\AuthenticationException; @@ -121,7 +121,7 @@ public function render($request, Throwable $e) } if ($e instanceof VerificationRequiredException) { - return $this->unverified(); + return SessionVerification\Controller::initiate(); } if ($e instanceof AuthenticationException) { @@ -166,11 +166,6 @@ protected function unauthenticated($request, AuthenticationException $exception) return ext_view('users.login', null, null, 401); } - protected function unverified() - { - return UserVerification::fromCurrentRequest()->initiate(); - } - private function reportWithSentry($e) { if (Auth::check()) { diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 9388137daa1..63a3c005c32 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -8,11 +8,10 @@ use App\Exceptions\ImageProcessorException; use App\Exceptions\ModelNotSavedException; use App\Libraries\Session\Store as SessionStore; +use App\Libraries\SessionVerification; use App\Libraries\User\AvatarHelper; use App\Libraries\User\CountryChange; use App\Libraries\User\CountryChangeTarget; -use App\Libraries\UserVerification; -use App\Libraries\UserVerificationState; use App\Mail\UserEmailUpdated; use App\Mail\UserPasswordUpdated; use App\Models\GithubUser; @@ -302,27 +301,16 @@ public function updatePassword() public function verify() { - return UserVerification::fromCurrentRequest()->verify(); + return SessionVerification\Controller::verify(); } public function verifyLink() { - $state = UserVerificationState::fromVerifyLink(get_string(request('key')) ?? ''); - - if ($state === null) { - UserVerification::logAttempt('link', 'fail', 'incorrect_key'); - - return ext_view('accounts.verification_invalid', null, null, 404); - } - - UserVerification::logAttempt('link', 'success'); - $state->markVerified(); - - return ext_view('accounts.verification_completed'); + return SessionVerification\Controller::verifyLink(); } public function reissueCode() { - return UserVerification::fromCurrentRequest()->reissue(); + return SessionVerification\Controller::reissue(); } } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 502e79dd236..7069b96afa0 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -8,7 +8,6 @@ use App; use App\Http\Middleware\VerifyUserAlways; use App\Libraries\LocaleMeta; -use App\Libraries\UserVerificationState; use App\Models\Log; use Auth; use Carbon\Carbon; @@ -38,13 +37,13 @@ protected function login($user, $remember = false) { cleanup_cookies(); - $session = session(); + $session = \Session::instance(); $session->flush(); $session->regenerateToken(); $session->put('requires_verification', VerifyUserAlways::isRequired($user)); Auth::login($user, $remember); if (config('osu.user.bypass_verification')) { - UserVerificationState::fromCurrentRequest()->markVerified(); + $session->markVerified(); } $session->migrate(true); } diff --git a/app/Http/Middleware/SetSessionVerification.php b/app/Http/Middleware/SetSessionVerification.php index 19c661672eb..01c30386135 100644 --- a/app/Http/Middleware/SetSessionVerification.php +++ b/app/Http/Middleware/SetSessionVerification.php @@ -8,7 +8,6 @@ namespace App\Http\Middleware; use App\Events\UserSessionEvent; -use App\Libraries\UserVerificationState; use Closure; use Illuminate\Http\Request; @@ -16,15 +15,15 @@ class SetSessionVerification { public function handle(Request $request, Closure $next) { - $user = auth()->user(); + $user = \Auth::user(); if ($user !== null) { - $isVerified = UserVerificationState::fromCurrentRequest()->isDone(); + $session = \Session::instance(); + $isVerified = $session->isVerified(); if ($isVerified) { $user->markSessionVerified(); } else { $isRequired = VerifyUserAlways::isRequired($user); - $session = session(); if ($session->get('requires_verification') !== $isRequired) { $session->put('requires_verification', $isRequired); $session->save(); diff --git a/app/Http/Middleware/VerifyUser.php b/app/Http/Middleware/VerifyUser.php index 12bca6c2450..f50855bf4da 100644 --- a/app/Http/Middleware/VerifyUser.php +++ b/app/Http/Middleware/VerifyUser.php @@ -5,7 +5,7 @@ namespace App\Http\Middleware; -use App\Libraries\UserVerification; +use App\Libraries\SessionVerification; use Closure; use Illuminate\Contracts\Auth\Guard as AuthGuard; use Illuminate\Http\Request; @@ -40,7 +40,7 @@ public function handle(Request $request, Closure $next) && !$this->alwaysSkipVerification() && $this->requiresVerification($request) ) { - return UserVerification::fromCurrentRequest()->initiate(); + return SessionVerification\Controller::initiate(); } return $next($request); diff --git a/app/Interfaces/SessionVerificationInterface.php b/app/Interfaces/SessionVerificationInterface.php new file mode 100644 index 00000000000..4dd3e775d29 --- /dev/null +++ b/app/Interfaces/SessionVerificationInterface.php @@ -0,0 +1,17 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Interfaces; + +interface SessionVerificationInterface +{ + public static function findForVerification(string $id): ?static; + + public function getKey(); + public function isVerified(): bool; + public function markVerified(): void; +} diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 04a0d82cd4c..7ca89263760 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -8,11 +8,13 @@ namespace App\Libraries\Session; use App\Events\UserSessionEvent; +use App\Interfaces\SessionVerificationInterface; use Illuminate\Redis\Connections\PhpRedisConnection; +use Illuminate\Session\Store as BaseStore; use Illuminate\Support\Arr; use Jenssegers\Agent\Agent; -class Store extends \Illuminate\Session\Store +class Store extends BaseStore implements SessionVerificationInterface { private const PREFIX = 'sessions:'; @@ -40,6 +42,11 @@ public static function batchDelete(?int $userId, ?array $ids = null): void } } + public static function findForVerification(string $id): static + { + return static::findOrNew($id); + } + public static function findOrNew(?string $id = null): static { if ($id !== null) { @@ -157,6 +164,11 @@ public function delete(): void static::batchDelete($this->userId(), [$this->getId()]); } + public function getKey(): string + { + return $this->getId(); + } + public function getKeyForEvent(): string { return self::keyForEvent($this->getId()); @@ -176,6 +188,17 @@ public function isValidId($id) return is_string($id); } + public function isVerified(): bool + { + return $this->attributes['verified'] ?? false; + } + + public function markVerified(): void + { + $this->attributes['verified'] = true; + $this->save(); + } + /** * Generate a new session id. * diff --git a/app/Libraries/SessionVerification/Controller.php b/app/Libraries/SessionVerification/Controller.php new file mode 100644 index 00000000000..ac17d75db18 --- /dev/null +++ b/app/Libraries/SessionVerification/Controller.php @@ -0,0 +1,107 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Libraries\SessionVerification; + +use App\Exceptions\UserVerificationException; +use App\Models\LoginAttempt; + +class Controller +{ + public static function initiate() + { + static $statusCode = 401; + + app('route-section')->setError("{$statusCode}-verification"); + + $user = \Auth::user(); + $email = $user->user_email; + + $session = \Session::instance(); + if (State::fromSession($session) === null) { + Helper::logAttempt('input', 'new'); + + Helper::issue($session, $user); + } + + if (\Request::ajax()) { + return response([ + 'authentication' => 'verify', + 'box' => view( + 'users._verify_box', + compact('email') + )->render(), + ], $statusCode); + } + + return ext_view('users.verify', compact('email'), null, $statusCode); + } + + public static function reissue() + { + $session = \Session::instance(); + if ($session->isVerified()) { + return response(null, 204); + } + + Helper::issue($session, \Auth::user()); + + return response(['message' => osu_trans('user_verification.errors.reissued')], 200); + } + + public static function verify() + { + $key = strtr(get_string(\Request::input('verification_key')) ?? '', [' ' => '']); + $user = \Auth::user(); + $session = \Session::instance(); + $state = State::fromSession($session); + + try { + if ($state === null) { + throw new UserVerificationException('expired', true); + } + $state->verify($key); + } catch (UserVerificationException $e) { + Helper::logAttempt('input', 'fail', $e->reasonKey()); + + if ($e->reasonKey() === 'incorrect_key') { + LoginAttempt::logAttempt(\Request::getClientIp(), $user, 'verify-mismatch', $key); + } + + if ($e->shouldReissue()) { + Helper::issue($session, $user); + } + + return error_popup($e->getMessage()); + } + + Helper::logAttempt('input', 'success'); + Helper::markVerified($session); + + return response(null, 204); + } + + public static function verifyLink() + { + $state = State::fromVerifyLink(get_string(\Request::input('key')) ?? ''); + + if ($state === null) { + Helper::logAttempt('link', 'fail', 'incorrect_key'); + + return ext_view('accounts.verification_invalid', null, null, 404); + } + + $session = $state->findSession(); + // Otherwise pretend everything is okay if session is missing + if ($session !== null) { + Helper::logAttempt('link', 'success'); + Helper::markVerified($session); + } + + return ext_view('accounts.verification_completed'); + } +} diff --git a/app/Libraries/SessionVerification/Helper.php b/app/Libraries/SessionVerification/Helper.php new file mode 100644 index 00000000000..037c49f5b82 --- /dev/null +++ b/app/Libraries/SessionVerification/Helper.php @@ -0,0 +1,55 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Libraries\SessionVerification; + +use App\Events\UserSessionEvent; +use App\Interfaces\SessionVerificationInterface; +use App\Mail\UserVerification as UserVerificationMail; +use App\Models\LoginAttempt; +use App\Models\User; + +class Helper +{ + public static function issue(SessionVerificationInterface $session, User $user): void + { + if (!is_valid_email_format($user->user_email)) { + return; + } + + $state = State::create($session); + $keys = [ + 'link' => $state->linkKey, + 'main' => $state->key, + ]; + + $request = \Request::instance(); + LoginAttempt::logAttempt($request->getClientIp(), $user, 'verify'); + + $requestCountry = app('countries')->byCode(request_country($request) ?? '')?->name; + + \Mail::to($user) + ->queue(new UserVerificationMail( + compact('keys', 'user', 'requestCountry') + )); + } + + public static function logAttempt(string $source, string $type, string $reason = null): void + { + \Datadog::increment( + \Config::get('datadog-helper.prefix_web').'.verification.attempts', + 1, + compact('reason', 'source', 'type') + ); + } + + public static function markVerified(SessionVerificationInterface $session) + { + $session->markVerified(); + UserSessionEvent::newVerified($session->userId(), $session->getKeyForEvent())->broadcast(); + } +} diff --git a/app/Libraries/SessionVerification/State.php b/app/Libraries/SessionVerification/State.php new file mode 100644 index 00000000000..1f8d814dce1 --- /dev/null +++ b/app/Libraries/SessionVerification/State.php @@ -0,0 +1,105 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Libraries\SessionVerification; + +use App\Exceptions\UserVerificationException; +use App\Interfaces\SessionVerificationInterface; +use App\Libraries\SignedRandomString; +use Carbon\CarbonImmutable; + +class State +{ + private const KEY_VALID_DURATION = 5 * 3600; + + public readonly \DateTimeInterface $expiresAt; + public readonly string $key; + public readonly string $linkKey; + public int $tries = 0; + + private function __construct( + private readonly string $sessionClass, + private readonly string $sessionId, + ) { + // 1 byte = 8 bits = 2^8 = 16^2 = 2 hex characters + $this->key = bin2hex(random_bytes(\Config::get('osu.user.verification_key_length_hex') / 2)); + $this->linkKey = SignedRandomString::create(32); + $this->expiresAt = CarbonImmutable::now()->addSeconds(static::KEY_VALID_DURATION); + } + + public static function create(SessionVerificationInterface $session): static + { + $state = new static($session::class, $session->getKey()); + $state->save(true); + + return $state; + } + + public static function fromSession(SessionVerificationInterface $session): ?static + { + return \Cache::get(static::cacheKey($session::class, $session->getKey())); + } + + public static function fromVerifyLink(string $linkKey): ?static + { + if (!SignedRandomString::isValid($linkKey)) { + return null; + } + + $cacheKey = \Cache::get(static::cacheLinkKey($linkKey)); + + return $cacheKey === null ? null : \Cache::get($cacheKey); + } + + private static function cacheKey(string $class, string $id): string + { + return "session_verification:{$class}:{$id}"; + } + + private static function cacheLinkKey(string $linkKey): string + { + return "session_verification_link:{$linkKey}"; + } + + public function delete(): void + { + \Cache::delete(static::cacheKey($this->sessionClass, $this->sessionId)); + \Cache::delete(static::cacheLinkKey($state->linkKey)); + } + + public function findSession(): ?SessionVerificationInterface + { + return $this->sessionClass::findForVerification($this->sessionId); + } + + public function verify(string $inputKey): void + { + $this->tries++; + + if ($this->expiresAt->isPast()) { + throw new UserVerificationException('expired', true); + } + + if (!hash_equals($this->key, $inputKey)) { + if ($this->tries >= \Config::get('osu.user.verification_key_tries_limit')) { + throw new UserVerificationException('retries_exceeded', true); + } else { + $this->save(false); + throw new UserVerificationException('incorrect_key', false); + } + } + } + + private function save(bool $saveLinkKey): void + { + $cacheKey = static::cacheKey($this->sessionClass, $this->sessionId); + \Cache::put($cacheKey, $this, $this->expiresAt); + if ($saveLinkKey) { + \Cache::put(static::cacheLinkKey($this->linkKey), $cacheKey, $this->expiresAt); + } + } +} diff --git a/app/Libraries/UserVerification.php b/app/Libraries/UserVerification.php deleted file mode 100644 index 14d370f6666..00000000000 --- a/app/Libraries/UserVerification.php +++ /dev/null @@ -1,165 +0,0 @@ -. Licensed under the GNU Affero General Public License v3.0. -// See the LICENCE file in the repository root for full licence text. - -namespace App\Libraries; - -use App\Exceptions\UserVerificationException; -use App\Mail\UserVerification as UserVerificationMail; -use App\Models\Country; -use App\Models\LoginAttempt; -use Datadog; -use Mail; - -class UserVerification -{ - private $request; - private $state; - private $user; - - public static function fromCurrentRequest() - { - $request = request(); - $attributes = $request->attributes; - $verification = $attributes->get('user_verification'); - - if ($verification === null) { - $verification = new static( - auth()->user(), - $request, - UserVerificationState::fromCurrentRequest() - ); - $attributes->set('user_verification', $verification); - } - - return $verification; - } - - public static function logAttempt(string $source, string $type, string $reason = null): void - { - Datadog::increment( - config('datadog-helper.prefix_web').'.verification.attempts', - 1, - compact('reason', 'source', 'type') - ); - } - - private function __construct($user, $request, $state) - { - $this->user = $user; - $this->request = $request; - $this->state = $state; - } - - public function initiate() - { - $statusCode = 401; - app('route-section')->setError("{$statusCode}-verification"); - - // Workaround race condition causing $this->issue() to be called in parallel. - // Mainly observed when logging in as privileged user. - if ($this->request->ajax()) { - $routeData = app('route-section')->getOriginal(); - if ($routeData['controller'] === 'notifications_controller' && $routeData['action'] === 'index') { - return response(['error' => 'verification'], $statusCode); - } - } - - $email = $this->user->user_email; - - if (!$this->state->issued()) { - static::logAttempt('input', 'new'); - - $this->issue(); - } - - if ($this->request->ajax()) { - return response([ - 'authentication' => 'verify', - 'box' => view( - 'users._verify_box', - compact('email') - )->render(), - ], $statusCode); - } else { - return ext_view('users.verify', compact('email'), null, $statusCode); - } - } - - public function isDone() - { - return $this->state->isDone(); - } - - public function issue() - { - $user = $this->user; - - if (!is_valid_email_format($user->user_email)) { - return; - } - - $keys = $this->state->issue(); - - LoginAttempt::logAttempt($this->request->getClientIp(), $this->user, 'verify'); - - $requestCountry = Country - ::where('acronym', request_country($this->request)) - ->pluck('name') - ->first(); - - Mail::to($user) - ->queue(new UserVerificationMail( - compact('keys', 'user', 'requestCountry') - )); - } - - public function markVerified() - { - $this->state->markVerified(); - } - - public function markVerifiedAndRespond() - { - $this->markVerified(); - - return response([], 200); - } - - public function reissue() - { - if ($this->state->isDone()) { - return $this->markVerifiedAndRespond(); - } - - $this->issue(); - - return response(['message' => osu_trans('user_verification.errors.reissued')], 200); - } - - public function verify() - { - $key = str_replace(' ', '', $this->request->input('verification_key')); - - try { - $this->state->verify($key); - } catch (UserVerificationException $e) { - static::logAttempt('input', 'fail', $e->reasonKey()); - - if ($e->reasonKey() === 'incorrect_key') { - LoginAttempt::logAttempt($this->request->getClientIp(), $this->user, 'verify-mismatch', $key); - } - - if ($e->shouldReissue()) { - $this->issue(); - } - - return error_popup($e->getMessage()); - } - - static::logAttempt('input', 'success'); - - return $this->markVerifiedAndRespond(); - } -} diff --git a/app/Libraries/UserVerificationState.php b/app/Libraries/UserVerificationState.php deleted file mode 100644 index ff1d99eac84..00000000000 --- a/app/Libraries/UserVerificationState.php +++ /dev/null @@ -1,143 +0,0 @@ -. Licensed under the GNU Affero General Public License v3.0. -// See the LICENCE file in the repository root for full licence text. - -namespace App\Libraries; - -use App\Events\UserSessionEvent; -use App\Exceptions\UserVerificationException; -use App\Libraries\Session\Store as SessionStore; -use App\Models\User; - -class UserVerificationState -{ - private function __construct(private User $user, private SessionStore $session) - { - } - - public static function fromCurrentRequest() - { - return new static(\Auth::user(), \Session::instance()); - } - - public static function fromVerifyLink($linkKey) - { - if (!SignedRandomString::isValid($linkKey)) { - return null; - } - - $params = cache()->get("verification:{$linkKey}"); - - if ($params !== null) { - $state = static::load($params); - - // As it's from verify link, make sure the state is waiting for verification. - if ($state->issued()) { - return $state; - } - } - } - - public static function load($params) - { - return new static( - User::find($params['userId']), - SessionStore::findOrNew($params['sessionId']), - ); - } - - public function dump() - { - return [ - 'userId' => $this->user->getKey(), - 'sessionId' => $this->session->getId(), - ]; - } - - public function issue() - { - $previousLinkKey = $this->session->get('verification_link_key'); - - if (present($previousLinkKey)) { - cache()->forget("verification:{$previousLinkKey}"); - } - - // 1 byte = 2^8 bits = 16^2 bits = 2 hex characters - $key = bin2hex(random_bytes(config('osu.user.verification_key_length_hex') / 2)); - $linkKey = SignedRandomString::create(32); - $expires = now()->addHours(5); - - $this->session->put('verification_key', $key); - $this->session->put('verification_link_key', $linkKey); - $this->session->put('verification_expire_date', $expires); - $this->session->put('verification_tries', 0); - $this->session->save(); - - cache()->put("verification:{$linkKey}", $this->dump(), $expires); - - return [ - 'link' => $linkKey, - 'main' => $key, - ]; - } - - public function issued() - { - return present($this->session->get('verification_key')); - } - - public function isDone() - { - if ($this->user === null) { - return true; - } - - if ($this->session->get('verified')) { - return true; - } - - return false; - } - - public function markVerified() - { - $this->session->forget('verification_expire_date'); - $this->session->forget('verification_tries'); - $this->session->forget('verification_key'); - $this->session->put('verified', true); - $this->session->save(); - - UserSessionEvent::newVerified($this->user->getKey(), $this->session->getKeyForEvent())->broadcast(); - } - - public function verify($inputKey) - { - if ($this->isDone()) { - return; - } - - $expireDate = $this->session->get('verification_expire_date'); - $tries = $this->session->get('verification_tries'); - $key = $this->session->get('verification_key'); - - if (!present($expireDate) || !present($tries) || !present($key)) { - throw new UserVerificationException('expired', true); - } - - if ($expireDate->isPast()) { - throw new UserVerificationException('expired', true); - } - - if ($tries > config('osu.user.verification_key_tries_limit')) { - throw new UserVerificationException('retries_exceeded', true); - } - - if (!hash_equals($key, $inputKey)) { - $this->session->put('verification_tries', $tries + 1); - $this->session->save(); - - throw new UserVerificationException('incorrect_key', false); - } - } -} diff --git a/app/Providers/AdditionalDuskServiceProvider.php b/app/Providers/AdditionalDuskServiceProvider.php index a334e2935c9..63d95831bfe 100644 --- a/app/Providers/AdditionalDuskServiceProvider.php +++ b/app/Providers/AdditionalDuskServiceProvider.php @@ -5,7 +5,6 @@ namespace App\Providers; -use App\Libraries\UserVerification; use Illuminate\Support\ServiceProvider; use Route; @@ -19,7 +18,9 @@ class AdditionalDuskServiceProvider extends ServiceProvider public function boot() { Route::get('/_dusk/verify', function () { - return UserVerification::fromCurrentRequest()->markVerifiedAndRespond(); + \Session::instance()->markVerified(); + + return response(null, 204); })->middleware('web'); } } diff --git a/tests/Libraries/UserVerificationTest.php b/tests/Libraries/SessionVerification/ControllerTest.php similarity index 78% rename from tests/Libraries/UserVerificationTest.php rename to tests/Libraries/SessionVerification/ControllerTest.php index bf92b06c124..bae424919e9 100644 --- a/tests/Libraries/UserVerificationTest.php +++ b/tests/Libraries/SessionVerification/ControllerTest.php @@ -5,16 +5,15 @@ declare(strict_types=1); -namespace Tests\Libraries; +namespace Tests\Libraries\SessionVerification; use App\Libraries\Session\Store as SessionStore; -use App\Libraries\UserVerification; -use App\Libraries\UserVerificationState; +use App\Libraries\SessionVerification; use App\Models\LoginAttempt; use App\Models\User; use Tests\TestCase; -class UserVerificationTest extends TestCase +class ControllerTest extends TestCase { public function testIssue() { @@ -29,29 +28,32 @@ public function testIssue() $record = LoginAttempt::find('127.0.0.1'); $this->assertTrue($record->containsUser($user, 'verify')); - $this->assertFalse(UserVerification::fromCurrentRequest()->isDone()); + $this->assertFalse(\Session::isVerified()); } public function testVerify() { $user = User::factory()->create(); + $session = \Session::instance(); $this ->be($user) + ->withPersistentSession($session) ->get(route('account.edit')) ->assertStatus(401) ->assertViewIs('users.verify'); - $key = session()->get('verification_key'); + $key = SessionVerification\State::fromSession($session)->key; $this + ->withPersistentSession($session) ->post(route('account.verify'), ['verification_key' => $key]) ->assertSuccessful(); $record = LoginAttempt::find('127.0.0.1'); $this->assertFalse($record->containsUser($user, 'verify-mismatch:')); - $this->assertTrue(UserVerification::fromCurrentRequest()->isDone()); + $this->assertTrue($session->isVerified()); } public function testVerifyLink(): void @@ -67,7 +69,7 @@ public function testVerifyLink(): void ->assertStatus(401) ->assertViewIs('users.verify'); - $linkKey = $session->get('verification_link_key'); + $linkKey = SessionVerification\State::fromSession($session)->linkKey; $guestSession = SessionStore::findOrNew(); $this @@ -78,7 +80,7 @@ public function testVerifyLink(): void $record = LoginAttempt::find('127.0.0.1'); $this->assertFalse($record->containsUser($user, 'verify-mismatch:')); - $this->assertTrue(UserVerificationState::load(['userId' => $user->getKey(), 'sessionId' => $sessionId])->isDone()); + $this->assertTrue(SessionStore::findOrNew($sessionId)->isVerified()); } public function testVerifyLinkMismatch(): void @@ -100,15 +102,17 @@ public function testVerifyLinkMismatch(): void ->get(route('account.verify', ['key' => 'invalid'])) ->assertStatus(404); - $this->assertFalse(UserVerificationState::load(['userId' => $user->getKey(), 'sessionId' => $sessionId])->isDone()); + $this->assertFalse(SessionStore::findOrNew($sessionId)->isVerified()); } public function testVerifyMismatch() { $user = User::factory()->create(); + $session = \Session::instance(); $this ->be($user) + ->withPersistentSession($session) ->get(route('account.edit')) ->assertStatus(401) ->assertViewIs('users.verify'); @@ -117,12 +121,13 @@ public function testVerifyMismatch() $this->assertFalse($record->containsUser($user, 'verify-mismatch:')); $this + ->withPersistentSession($session) ->post(route('account.verify'), ['verification_key' => 'invalid']) ->assertStatus(422); $record = LoginAttempt::find('127.0.0.1'); $this->assertTrue($record->containsUser($user, 'verify-mismatch:')); - $this->assertFalse(UserVerification::fromCurrentRequest()->isDone()); + $this->assertFalse($session->isVerified()); } } From 0d52dfa63f726ff730be3d984ec085671d24f604 Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 13 Dec 2023 18:33:06 +0900 Subject: [PATCH 058/102] Pass actual oauth token in test --- tests/TestCase.php | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index 9fcf5257b79..b888c28428b 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -23,8 +23,6 @@ use Illuminate\Support\Testing\Fakes\MailFake; use Laravel\Passport\Passport; use Laravel\Passport\Token; -use League\OAuth2\Server\ResourceServer; -use Mockery; use Queue; use ReflectionMethod; use ReflectionProperty; @@ -123,34 +121,14 @@ protected function tearDown(): void /** * Act as a User with OAuth scope permissions. - * This is for tests that will run the request middleware stack. - * - * @param User|null $user User to act as, or null for guest. - * @param array|null $scopes OAuth token scopes. - * @param string $driver Auth driver to use. - * @return void */ - protected function actAsScopedUser(?User $user, ?array $scopes = ['*'], ?Client $client = null, $driver = null) + protected function actAsScopedUser(?User $user, ?array $scopes = ['*'], ?Client $client = null): void { - $client ??= Client::factory()->create(); - - // create valid token - $token = $this->createToken($user, $scopes, $client); - - // mock the minimal number of things. - // this skips the need to form a request with all the headers. - $mock = Mockery::mock(ResourceServer::class); - $mock->shouldReceive('validateAuthenticatedRequest') - ->andReturnUsing(function ($request) use ($token) { - return $request->withAttribute('oauth_client_id', $token->client->id) - ->withAttribute('oauth_access_token_id', $token->id) - ->withAttribute('oauth_user_id', $token->user_id); - }); - - app()->instance(ResourceServer::class, $mock); - $this->withHeader('Authorization', 'Bearer tests_using_this_do_not_verify_this_header_because_of_the_mock'); - - $this->actAsUserWithToken($token, $driver); + $this->actingWithToken($this->createToken( + $user, + $scopes, + $client ?? Client::factory()->create(), + )); } protected function actAsUser(?User $user, bool $verified = false, $driver = null) @@ -218,6 +196,8 @@ protected function actingWithToken($token) 'scopes' => $token->scopes, ], $privateKey, 'RS256'); + $this->actAsUserWithToken($token); + return $this->withHeaders([ 'Authorization' => "Bearer {$encryptedToken}", ]); From 6811e9c74e3da44a88368b1636d2d088efa0d03c Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 13 Dec 2023 21:47:37 +0900 Subject: [PATCH 059/102] Adjust interface --- app/Interfaces/SessionVerificationInterface.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Interfaces/SessionVerificationInterface.php b/app/Interfaces/SessionVerificationInterface.php index 4dd3e775d29..027c09063f4 100644 --- a/app/Interfaces/SessionVerificationInterface.php +++ b/app/Interfaces/SessionVerificationInterface.php @@ -12,6 +12,8 @@ interface SessionVerificationInterface public static function findForVerification(string $id): ?static; public function getKey(); + public function getKeyForEvent(); public function isVerified(): bool; public function markVerified(): void; + public function userId(): ?int; } From f248f2b222578c2c0267b1342ff60a802f8d1222 Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 13 Dec 2023 21:49:07 +0900 Subject: [PATCH 060/102] Add test for reissue --- .../SessionVerification/ControllerTest.php | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/Libraries/SessionVerification/ControllerTest.php b/tests/Libraries/SessionVerification/ControllerTest.php index bae424919e9..cb03a541a06 100644 --- a/tests/Libraries/SessionVerification/ControllerTest.php +++ b/tests/Libraries/SessionVerification/ControllerTest.php @@ -9,6 +9,7 @@ use App\Libraries\Session\Store as SessionStore; use App\Libraries\SessionVerification; +use App\Mail\UserVerification as UserVerificationMail; use App\Models\LoginAttempt; use App\Models\User; use Tests\TestCase; @@ -31,6 +32,28 @@ public function testIssue() $this->assertFalse(\Session::isVerified()); } + public function testReissue(): void + { + \Mail::fake(); + $user = User::factory()->create(); + $session = \Session::instance(); + + $this + ->be($user) + ->withPersistentSession($session) + ->get(route('account.edit')); + + $state = SessionVerification\State::fromSession($session); + + $this + ->withPersistentSession($session) + ->post(route('account.reissue-code')) + ->assertSuccessful(); + + \Mail::assertQueued(UserVerificationMail::class, 2); + $this->assertNotSame($state->key, SessionVerification\State::fromSession($session)->key); + } + public function testVerify() { $user = User::factory()->create(); From b4a49291fc6916034d697928997765227db74f40 Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 13 Dec 2023 21:50:24 +0900 Subject: [PATCH 061/102] Add return type --- tests/Libraries/SessionVerification/ControllerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Libraries/SessionVerification/ControllerTest.php b/tests/Libraries/SessionVerification/ControllerTest.php index cb03a541a06..b3051485644 100644 --- a/tests/Libraries/SessionVerification/ControllerTest.php +++ b/tests/Libraries/SessionVerification/ControllerTest.php @@ -16,7 +16,7 @@ class ControllerTest extends TestCase { - public function testIssue() + public function testIssue(): void { $user = User::factory()->create(); @@ -54,7 +54,7 @@ public function testReissue(): void $this->assertNotSame($state->key, SessionVerification\State::fromSession($session)->key); } - public function testVerify() + public function testVerify(): void { $user = User::factory()->create(); $session = \Session::instance(); @@ -128,7 +128,7 @@ public function testVerifyLinkMismatch(): void $this->assertFalse(SessionStore::findOrNew($sessionId)->isVerified()); } - public function testVerifyMismatch() + public function testVerifyMismatch(): void { $user = User::factory()->create(); $session = \Session::instance(); From 6388556c2afec2f0dfb15a3b782c64fd22bcdb23 Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 13 Dec 2023 21:52:41 +0900 Subject: [PATCH 062/102] Test for mail on issue --- tests/Libraries/SessionVerification/ControllerTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Libraries/SessionVerification/ControllerTest.php b/tests/Libraries/SessionVerification/ControllerTest.php index b3051485644..cf8455084bf 100644 --- a/tests/Libraries/SessionVerification/ControllerTest.php +++ b/tests/Libraries/SessionVerification/ControllerTest.php @@ -18,6 +18,7 @@ class ControllerTest extends TestCase { public function testIssue(): void { + \Mail::fake(); $user = User::factory()->create(); $this @@ -28,6 +29,7 @@ public function testIssue(): void $record = LoginAttempt::find('127.0.0.1'); + \Mail::assertQueued(UserVerificationMail::class, 1); $this->assertTrue($record->containsUser($user, 'verify')); $this->assertFalse(\Session::isVerified()); } From 7e543fc7510413fa3caf97e7921898f6d372bdd0 Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 13 Dec 2023 21:53:58 +0900 Subject: [PATCH 063/102] Forgot return type --- app/Interfaces/SessionVerificationInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Interfaces/SessionVerificationInterface.php b/app/Interfaces/SessionVerificationInterface.php index 027c09063f4..41649787441 100644 --- a/app/Interfaces/SessionVerificationInterface.php +++ b/app/Interfaces/SessionVerificationInterface.php @@ -12,7 +12,7 @@ interface SessionVerificationInterface public static function findForVerification(string $id): ?static; public function getKey(); - public function getKeyForEvent(); + public function getKeyForEvent(): string; public function isVerified(): bool; public function markVerified(): void; public function userId(): ?int; From 62ef4e02b1e3d28705bb8f5234c2ab14a5d2e9e0 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 21 Nov 2023 22:51:52 +0900 Subject: [PATCH 064/102] Store config in global variable instead --- .../BuildsUpdatePropagationHistory.php | 2 +- app/Console/Commands/DbCreate.php | 4 +- .../Commands/EsCreateSearchBlacklist.php | 2 +- .../Commands/MigrateFreshAllCommand.php | 2 +- app/Console/Commands/ModdingRankCommand.php | 4 +- app/Console/Commands/NotificationsCleanup.php | 4 +- .../Commands/OAuthDeleteExpiredTokens.php | 2 +- .../Commands/UserNotificationsCleanup.php | 6 +-- app/Events/NotificationEventBase.php | 2 +- app/Exceptions/Handler.php | 5 +- .../Account/GithubUsersController.php | 4 +- .../Controllers/BeatmapsetsController.php | 2 +- app/Http/Controllers/ChangelogController.php | 12 ++--- app/Http/Controllers/ChatController.php | 2 +- app/Http/Controllers/Controller.php | 2 +- app/Http/Controllers/HomeController.php | 24 +++++----- .../InterOp/BeatmapsetsController.php | 4 +- .../Controllers/LegacyInterOpController.php | 2 +- .../Rooms/Playlist/ScoresController.php | 2 +- .../Controllers/NotificationsController.php | 2 +- .../Controllers/Payments/XsollaController.php | 10 ++-- app/Http/Controllers/RankingController.php | 2 +- .../Controllers/ScoreTokensController.php | 2 +- .../SeasonalBackgroundsController.php | 4 +- app/Http/Controllers/SessionsController.php | 2 +- app/Http/Controllers/Store/Controller.php | 2 +- app/Http/Controllers/UsersController.php | 14 +++--- app/Http/Middleware/DatadogMetrics.php | 2 +- app/Http/Middleware/LegacyInterOpAuth.php | 2 +- app/Http/Middleware/SetLocale.php | 2 +- app/Http/Middleware/ThrottleRequests.php | 2 +- app/Http/Middleware/VerifyUserAlways.php | 2 +- app/Jobs/EsDocument.php | 2 +- app/Jobs/RegenerateBeatmapsetCover.php | 4 +- app/Jobs/RemoveBeatmapsetBestScores.php | 2 +- app/Jobs/UserNotificationDigest.php | 2 +- app/Libraries/AcceptHttpLanguage/Parser.php | 2 +- app/Libraries/BBCodeForDB.php | 4 +- app/Libraries/BBCodeFromDB.php | 2 +- app/Libraries/BeatmapDifficultyAttributes.php | 2 +- app/Libraries/BeatmapsetDiscussion/Review.php | 6 +-- app/Libraries/ClientCheck.php | 2 +- app/Libraries/CommentBundle.php | 2 +- app/Libraries/Elasticsearch/Es.php | 2 +- app/Libraries/Elasticsearch/Search.php | 6 +-- app/Libraries/Elasticsearch/SearchParams.php | 2 +- app/Libraries/ImageProcessorService.php | 2 +- app/Libraries/LocalCacheManager.php | 2 +- .../Markdown/Osu/DocumentProcessor.php | 4 +- app/Libraries/OrderCheckout.php | 8 ++-- app/Libraries/OsuAuthorize.php | 22 ++++----- app/Libraries/OsuWiki.php | 6 +-- .../Payments/CentiliPaymentProcessor.php | 4 +- app/Libraries/Payments/CentiliSignature.php | 2 +- app/Libraries/Payments/PaymentProcessor.php | 4 +- app/Libraries/Payments/PaypalApiContext.php | 6 +-- .../Payments/PaypalPaymentProcessor.php | 2 +- app/Libraries/Payments/PaypalSignature.php | 2 +- app/Libraries/Payments/ShopifySignature.php | 2 +- app/Libraries/Payments/XsollaSignature.php | 2 +- app/Libraries/ProfileCover.php | 2 +- app/Libraries/ReplayFile.php | 2 +- app/Libraries/Score/BeatmapScores.php | 2 +- app/Libraries/Score/UserRankCache.php | 8 ++-- app/Libraries/Search/BeatmapsetSearch.php | 2 +- .../Search/BeatmapsetSearchCached.php | 2 +- .../Search/BeatmapsetSearchParams.php | 2 +- app/Libraries/Search/ScoreSearch.php | 6 +-- app/Libraries/Search/UserSearch.php | 2 +- app/Libraries/Search/WikiSearch.php | 2 +- app/Libraries/Search/WikiSuggestions.php | 2 +- app/Libraries/Session/SessionManager.php | 6 +-- app/Libraries/Session/Store.php | 4 +- app/Libraries/StorageUrl.php | 4 +- app/Libraries/User/AvatarHelper.php | 10 ++-- app/Libraries/User/CountryChangeTarget.php | 4 +- app/Libraries/User/DatadogLoginAttempt.php | 2 +- app/Libraries/User/PasswordResetData.php | 6 +-- app/Libraries/UserBestScoresCheck.php | 4 +- app/Libraries/UserChannelList.php | 2 +- app/Libraries/UserVerification.php | 2 +- app/Libraries/UserVerificationState.php | 4 +- app/Libraries/Wiki/WikiSitemap.php | 2 +- app/Mail/DonationThanks.php | 6 +-- app/Models/Achievement.php | 2 +- app/Models/BeatmapDiscussion.php | 2 +- app/Models/Beatmapset.php | 16 +++---- app/Models/Build.php | 2 +- app/Models/BuildPropagationHistory.php | 4 +- app/Models/Changelog.php | 2 +- app/Models/Chat/Channel.php | 10 ++-- app/Models/Chat/Message.php | 2 +- app/Models/Count.php | 2 +- app/Models/Event.php | 4 +- app/Models/Forum/Forum.php | 4 +- app/Models/Forum/Post.php | 2 +- app/Models/Forum/Topic.php | 12 ++--- app/Models/Forum/TopicPoll.php | 4 +- app/Models/GithubUser.php | 4 +- app/Models/LivestreamCollection.php | 6 +-- app/Models/LoginAttempt.php | 2 +- app/Models/Model.php | 6 +-- app/Models/Multiplayer/PlaylistItem.php | 2 +- app/Models/Multiplayer/Room.php | 2 +- app/Models/NewsPost.php | 2 +- app/Models/OAuth/Client.php | 2 +- app/Models/ProfileBanner.php | 14 +++--- app/Models/RankHistory.php | 2 +- app/Models/Repository.php | 2 +- app/Models/Score/Best/Model.php | 2 +- app/Models/ScorePin.php | 2 +- app/Models/Solo/Score.php | 2 +- app/Models/Store/Order.php | 6 +-- app/Models/Traits/Es/BaseDbIndexable.php | 2 +- app/Models/Traits/Es/BeatmapsetSearch.php | 2 +- app/Models/Traits/Es/ForumPostSearch.php | 2 +- app/Models/Traits/Es/UserSearch.php | 2 +- app/Models/Traits/Es/WikiPageSearch.php | 2 +- app/Models/Traits/UserScoreable.php | 4 +- app/Models/UpdateStream.php | 2 +- app/Models/User.php | 28 +++++------ app/Models/UserAccountHistory.php | 2 +- app/Models/UserRelation.php | 4 +- app/Models/UserReport.php | 6 +-- app/Models/UserStatistics/Model.php | 4 +- app/Models/Wiki/Page.php | 6 +-- app/Notifications/Store/ErrorMessage.php | 2 +- app/Notifications/Store/Message.php | 4 +- app/Notifications/Store/OrderMessage.php | 2 +- app/Notifications/Store/StoreMessage.php | 2 +- app/Notifications/Store/ValidationMessage.php | 2 +- app/Providers/AppServiceProvider.php | 10 ++-- app/Providers/AuthServiceProvider.php | 4 +- app/Traits/NotificationQueue.php | 2 +- app/Traits/StoreNotifiable.php | 2 +- .../UserStatisticsTransformer.php | 2 +- app/helpers.php | 46 +++++++++++-------- config/osu.php | 31 +++++-------- config/scribe.php | 6 +-- config/sentry.php | 4 +- database/factories/BeatmapMirrorFactory.php | 2 +- database/factories/BeatmapsetFactory.php | 2 +- database/factories/BuildFactory.php | 2 +- database/factories/UserFactory.php | 2 +- database/seeders/ModelSeeders/ForumSeeder.php | 10 ++-- .../views/accounts/_edit_email.blade.php | 2 +- resources/views/docs/auth.blade.php | 6 +-- resources/views/docs/endpoint.blade.php | 2 +- resources/views/docs/info.md.blade.php | 2 +- resources/views/emails/_signature.blade.php | 2 +- .../forum/topics/_feature_vote.blade.php | 2 +- .../views/home/_landing_locales.blade.php | 2 +- .../views/home/_search_results.blade.php | 2 +- resources/views/home/download.blade.php | 16 +++---- resources/views/home/landing.blade.php | 4 +- resources/views/home/opensearch.blade.php | 2 +- resources/views/home/testflight.blade.php | 25 ++++++---- .../layout/header_mobile/_locales.blade.php | 2 +- resources/views/layout/metadata.blade.php | 16 +++---- .../views/layout/nav2/_locales.blade.php | 2 +- resources/views/master.blade.php | 4 +- resources/views/news/index-atom.blade.php | 2 +- .../views/objects/_captcha_script.blade.php | 2 +- resources/views/objects/_enchant.blade.php | 4 +- .../views/password_reset/index.blade.php | 2 +- resources/views/store/header.blade.php | 4 +- resources/views/store/layout.blade.php | 4 +- resources/views/users/_verify_box.blade.php | 2 +- resources/views/users/disabled.blade.php | 2 +- resources/views/wiki/_notice.blade.php | 4 +- .../views/wiki/_sitemap_section.blade.php | 2 +- resources/views/wiki/sitemap.blade.php | 2 +- routes/web.php | 2 +- tests/BeatmapsetEventNominationResetTest.php | 6 +-- tests/Browser/SanityTest.php | 6 +-- tests/Commands/ModdingRankCommandTest.php | 4 +- .../Commands/OAuthDeleteExpiredTokensTest.php | 2 +- tests/Controllers/CommentsControllerTest.php | 4 +- .../Controllers/ForumTopicsControllerTest.php | 4 +- .../InterOp/BeatmapsetsControllerTest.php | 2 +- .../Passport/AuthorizationControllerTest.php | 2 +- .../Payments/CentiliControllerTest.php | 11 ++--- .../Payments/ShopifyControllerTest.php | 2 +- .../Payments/XsollaControllerTest.php | 3 +- tests/Controllers/ScorePinsControllerTest.php | 4 +- tests/Controllers/ScoresControllerTest.php | 16 +++---- tests/Controllers/SessionsControllerTest.php | 4 +- tests/Controllers/UsersControllerTest.php | 22 ++++----- .../Jobs/UpdateUserForumTopicFollowsTest.php | 2 +- tests/Libraries/BBCodeForDBTest.php | 2 +- tests/Libraries/BBCodeFromDBTest.php | 2 +- .../BeatmapsetDiscussion/DiscussionTest.php | 8 ++-- .../BeatmapsetDiscussion/ReplyTest.php | 2 +- .../BeatmapsetDiscussion/ReviewTest.php | 2 +- tests/Libraries/ChatTest.php | 10 ++-- tests/Libraries/ClientCheckTest.php | 2 +- .../Payments/CentiliPaymentProcessorTest.php | 9 ++-- .../Payments/CentiliSignatureTest.php | 3 +- .../Payments/PaymentProcessorTest.php | 2 +- .../Payments/ShopifySignatureTest.php | 3 +- .../Payments/XsollaPaymentProcessorTest.php | 3 +- .../Payments/XsollaSignatureTest.php | 3 +- tests/Middleware/ThrottleRequestsTest.php | 4 +- tests/Models/Forum/TopicTest.php | 4 +- tests/Models/Multiplayer/RoomTest.php | 4 +- tests/Models/OAuth/ClientTest.php | 4 +- tests/Models/UserTest.php | 8 ++-- tests/OAuthAuthCodeRequestTest.php | 2 +- tests/OAuthClientCredentialsRequestTest.php | 2 +- tests/TestCase.php | 8 ++-- 210 files changed, 481 insertions(+), 481 deletions(-) diff --git a/app/Console/Commands/BuildsUpdatePropagationHistory.php b/app/Console/Commands/BuildsUpdatePropagationHistory.php index 9c0140d20c2..1a0576ac0a7 100644 --- a/app/Console/Commands/BuildsUpdatePropagationHistory.php +++ b/app/Console/Commands/BuildsUpdatePropagationHistory.php @@ -48,7 +48,7 @@ public function handle() $date = Carbon::now(); $builds = Build::propagationHistory() - ->whereIn('stream_id', config('osu.changelog.update_streams')) + ->whereIn('stream_id', $GLOBALS['cfg']['osu']['changelog']['update_streams']) ->get(); foreach ($builds as $build) { diff --git a/app/Console/Commands/DbCreate.php b/app/Console/Commands/DbCreate.php index 211686a9d7c..957af7cf2fd 100644 --- a/app/Console/Commands/DbCreate.php +++ b/app/Console/Commands/DbCreate.php @@ -16,7 +16,7 @@ class DbCreate extends Command public function handle() { - $defaultConnection = config('database.connections.mysql'); + $defaultConnection = $GLOBALS['cfg']['database']['connections']['mysql']; $dsn = isset($defaultConnection['unix_socket']) ? "mysql:unix_socket={$defaultConnection['unix_socket']}" @@ -24,7 +24,7 @@ public function handle() $pdo = new PDO($dsn, $defaultConnection['username'], $defaultConnection['password']); - foreach (config('database.connections') as $connection) { + foreach ($GLOBALS['cfg']['database']['connections'] as $connection) { $db = $connection['database']; $this->info("Creating database '{$db}'"); diff --git a/app/Console/Commands/EsCreateSearchBlacklist.php b/app/Console/Commands/EsCreateSearchBlacklist.php index 87cb2375613..669bd166657 100644 --- a/app/Console/Commands/EsCreateSearchBlacklist.php +++ b/app/Console/Commands/EsCreateSearchBlacklist.php @@ -31,7 +31,7 @@ class EsCreateSearchBlacklist extends Command */ public function handle() { - $alias = config('osu.elasticsearch.prefix').'blacklist'; + $alias = $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'blacklist'; $client = Es::getClient(); /** @var array $response The type-hint in the doc is wrong. */ diff --git a/app/Console/Commands/MigrateFreshAllCommand.php b/app/Console/Commands/MigrateFreshAllCommand.php index 759d78a3836..cba5436d975 100644 --- a/app/Console/Commands/MigrateFreshAllCommand.php +++ b/app/Console/Commands/MigrateFreshAllCommand.php @@ -16,7 +16,7 @@ public function handle() return 1; } - $connections = config('database.connections'); + $connections = $GLOBALS['cfg']['database']['connections']; $this->warn('This will drop tables in the following databases:'); diff --git a/app/Console/Commands/ModdingRankCommand.php b/app/Console/Commands/ModdingRankCommand.php index 2022e68bd68..b0e6dfe3397 100644 --- a/app/Console/Commands/ModdingRankCommand.php +++ b/app/Console/Commands/ModdingRankCommand.php @@ -37,7 +37,7 @@ public static function getStats(Ruleset $ruleset) ->count(); return [ - 'availableQuota' => config('osu.beatmapset.rank_per_day') - $rankedTodayCount, + 'availableQuota' => $GLOBALS['cfg']['osu']['beatmapset']['rank_per_day'] - $rankedTodayCount, 'inQueue' => Beatmapset::toBeRanked($ruleset)->count(), 'rankedToday' => $rankedTodayCount, ]; @@ -92,7 +92,7 @@ private function rankAll(Ruleset $ruleset) return; } - $toRankLimit = min(config('osu.beatmapset.rank_per_run'), $stats['availableQuota']); + $toRankLimit = min($GLOBALS['cfg']['osu']['beatmapset']['rank_per_run'], $stats['availableQuota']); $toBeRanked = Beatmapset::tobeRanked($ruleset) ->orderBy('queued_at', 'ASC') diff --git a/app/Console/Commands/NotificationsCleanup.php b/app/Console/Commands/NotificationsCleanup.php index 8d5086f7aec..09e9bf95bc6 100644 --- a/app/Console/Commands/NotificationsCleanup.php +++ b/app/Console/Commands/NotificationsCleanup.php @@ -21,7 +21,7 @@ class NotificationsCleanup extends Command public function handle() { - $total = config('osu.notification.cleanup.max_delete_per_run'); + $total = $GLOBALS['cfg']['osu']['notification']['cleanup']['max_delete_per_run']; if ($total === 0) { return; @@ -46,7 +46,7 @@ public function handle() for ($i = 0; $i < $loops; $i++) { $deleted = Notification::where('id', '<', $maxNotificationId)->limit($perLoop)->delete(); - Datadog::increment(config('datadog-helper.prefix_web').'.notifications_cleanup.notifications', 1, null, $deleted); + Datadog::increment($GLOBALS['cfg']['datadog-helper']['prefix_web'].'.notifications_cleanup.notifications', 1, null, $deleted); $deletedTotal += $deleted; } diff --git a/app/Console/Commands/OAuthDeleteExpiredTokens.php b/app/Console/Commands/OAuthDeleteExpiredTokens.php index cf6c97982a8..d470ea2b4aa 100644 --- a/app/Console/Commands/OAuthDeleteExpiredTokens.php +++ b/app/Console/Commands/OAuthDeleteExpiredTokens.php @@ -24,7 +24,7 @@ class OAuthDeleteExpiredTokens extends Command public function handle() { - $this->expiredBefore = now()->subDays(config('osu.oauth.retain_expired_tokens_days')); + $this->expiredBefore = now()->subDays($GLOBALS['cfg']['osu']['oauth']['retain_expired_tokens_days']); $this->line("Deleting before {$this->expiredBefore}"); $this->deleteAuthCodes(); diff --git a/app/Console/Commands/UserNotificationsCleanup.php b/app/Console/Commands/UserNotificationsCleanup.php index 27abe061a73..77bcb75e0a8 100644 --- a/app/Console/Commands/UserNotificationsCleanup.php +++ b/app/Console/Commands/UserNotificationsCleanup.php @@ -18,7 +18,7 @@ class UserNotificationsCleanup extends Command public function handle() { - $total = config('osu.notification.cleanup.max_delete_per_run'); + $total = $GLOBALS['cfg']['osu']['notification']['cleanup']['max_delete_per_run']; if ($total === 0) { return; @@ -27,7 +27,7 @@ public function handle() $perLoop = min($total, 10000); $loops = $total / $perLoop; - $createdBefore = now()->subDays(config('osu.notification.cleanup.keep_days')); + $createdBefore = now()->subDays($GLOBALS['cfg']['osu']['notification']['cleanup']['keep_days']); $this->line("Deleting user notifications before {$createdBefore}"); $progress = $this->output->createProgressBar($total); @@ -59,7 +59,7 @@ public function handle() ); $deleted = count($notificationIds); $deletedTotal += $deleted; - Datadog::increment(config('datadog-helper.prefix_web').'.notifications_cleanup.user_notifications', 1, null, $deleted); + Datadog::increment($GLOBALS['cfg']['datadog-helper']['prefix_web'].'.notifications_cleanup.user_notifications', 1, null, $deleted); $progress->advance($deleted); } diff --git a/app/Events/NotificationEventBase.php b/app/Events/NotificationEventBase.php index de6156f7a6e..12332fc26b0 100644 --- a/app/Events/NotificationEventBase.php +++ b/app/Events/NotificationEventBase.php @@ -24,6 +24,6 @@ public static function generateChannelName($notifiable, $subtype) public function __construct() { - $this->broadcastQueue = config('osu.notification.queue_name'); + $this->broadcastQueue = $GLOBALS['cfg']['osu']['notification']['queue_name']; } } diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index c2bfb2aa3c2..9d30091a2c8 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -99,7 +99,8 @@ public function report(Throwable $e) return; } - if (config('sentry.dsn')) { + // Fallback in case error happening before config is initialised + if ($GLOBALS['cfg']['sentry']['dsn'] ?? false) { $this->reportWithSentry($e); } @@ -134,7 +135,7 @@ public function render($request, Throwable $e) $isJsonRequest = is_json_request(); - if (config('app.debug') || ($isJsonRequest && static::isOAuthServerException($e))) { + if ($GLOBALS['cfg']['app']['debug'] || ($isJsonRequest && static::isOAuthServerException($e))) { $response = parent::render($request, $e); } else { $message = static::exceptionMessage($e); diff --git a/app/Http/Controllers/Account/GithubUsersController.php b/app/Http/Controllers/Account/GithubUsersController.php index a20c2f4b5ec..44b6df739e5 100644 --- a/app/Http/Controllers/Account/GithubUsersController.php +++ b/app/Http/Controllers/Account/GithubUsersController.php @@ -111,8 +111,8 @@ public function destroy() private function makeGithubOAuthProvider(): GithubProvider { return new GithubProvider([ - 'clientId' => config('osu.github.client_id'), - 'clientSecret' => config('osu.github.client_secret'), + 'clientId' => $GLOBALS['cfg']['osu']['github']['client_id'], + 'clientSecret' => $GLOBALS['cfg']['osu']['github']['client_secret'], ]); } } diff --git a/app/Http/Controllers/BeatmapsetsController.php b/app/Http/Controllers/BeatmapsetsController.php index 4f0a90663b9..e41e0be88ce 100644 --- a/app/Http/Controllers/BeatmapsetsController.php +++ b/app/Http/Controllers/BeatmapsetsController.php @@ -371,7 +371,7 @@ private function getSearchResponse(?array $params = null) $records = datadog_timing(function () use ($search) { return $search->records(); - }, config('datadog-helper.prefix_web').'.search', ['type' => 'beatmapset']); + }, $GLOBALS['cfg']['datadog-helper']['prefix_web'].'.search', ['type' => 'beatmapset']); $error = $search->getError(); diff --git a/app/Http/Controllers/ChangelogController.php b/app/Http/Controllers/ChangelogController.php index a481546bf1e..058e09501cd 100644 --- a/app/Http/Controllers/ChangelogController.php +++ b/app/Http/Controllers/ChangelogController.php @@ -191,7 +191,7 @@ public function index() } else { $chartConfig = Cache::remember( 'chart_config_global', - config('osu.changelog.build_history_interval'), + $GLOBALS['cfg']['osu']['changelog']['build_history_interval'], function () { return $this->chartConfig(null); } @@ -203,7 +203,7 @@ function () { public function github() { - $token = config('osu.changelog.github_token'); + $token = $GLOBALS['cfg']['osu']['changelog']['github_token']; $signatureHeader = explode('=', request()->header('X-Hub-Signature') ?? ''); @@ -371,7 +371,7 @@ public function build($streamName, $version) $chartConfig = Cache::remember( "chart_config:v2:{$build->updateStream->getKey()}", - config('osu.changelog.build_history_interval'), + $GLOBALS['cfg']['osu']['changelog']['build_history_interval'], function () use ($build) { return $this->chartConfig($build->updateStream); } @@ -400,8 +400,8 @@ private function getUpdateStreams() { return $this->updateStreams ??= json_collection( UpdateStream::whereHasBuilds() - ->orderByField('stream_id', config('osu.changelog.update_streams')) - ->find(config('osu.changelog.update_streams')) + ->orderByField('stream_id', $GLOBALS['cfg']['osu']['changelog']['update_streams']) + ->find($GLOBALS['cfg']['osu']['changelog']['update_streams']) ->sortBy(function ($i) { return $i->isFeatured() ? 0 : 1; }), @@ -412,7 +412,7 @@ private function getUpdateStreams() private function chartConfig($stream) { - $history = BuildPropagationHistory::changelog(optional($stream)->getKey(), config('osu.changelog.chart_days'))->get(); + $history = BuildPropagationHistory::changelog(optional($stream)->getKey(), $GLOBALS['cfg']['osu']['changelog']['chart_days'])->get(); if ($stream === null) { $chartOrder = array_map(function ($b) { diff --git a/app/Http/Controllers/ChatController.php b/app/Http/Controllers/ChatController.php index 2487992f2f4..2b0f7136a5c 100644 --- a/app/Http/Controllers/ChatController.php +++ b/app/Http/Controllers/ChatController.php @@ -19,7 +19,7 @@ public function __construct() // TODO: notification server and chat client needs some updating // to handle verification_requirement_change properly. - if (config('osu.user.post_action_verification')) { + if ($GLOBALS['cfg']['osu']['user']['post_action_verification']) { $this->middleware('verify-user'); } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 502e79dd236..6726afebedf 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -43,7 +43,7 @@ protected function login($user, $remember = false) $session->regenerateToken(); $session->put('requires_verification', VerifyUserAlways::isRequired($user)); Auth::login($user, $remember); - if (config('osu.user.bypass_verification')) { + if ($GLOBALS['cfg']['osu']['user']['bypass_verification']) { UserVerificationState::fromCurrentRequest()->markVerified(); } $session->migrate(true); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index c884fed500e..69e7d5f8b90 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -80,7 +80,7 @@ public function getDownload() }; return ext_view('home.download', [ - 'lazerUrl' => config("osu.urls.lazer_dl.{$platform}"), + 'lazerUrl' => osu_url("lazer_dl.{$platform}"), 'lazerPlatformName' => $lazerPlatformNames[$platform], ]); } @@ -197,7 +197,7 @@ public function search() public function setLocale() { - $newLocale = get_valid_locale(Request::input('locale')) ?? config('app.fallback_locale'); + $newLocale = get_valid_locale(Request::input('locale')) ?? $GLOBALS['cfg']['app']['fallback_locale']; App::setLocale($newLocale); if (Auth::check()) { @@ -327,12 +327,12 @@ public function supportTheGame() 'more_beatmaps' => [ 'icons' => ['fas fa-file-upload'], 'translation_options' => [ - 'base' => config('osu.beatmapset.upload_allowed'), - 'bonus' => config('osu.beatmapset.upload_bonus_per_ranked'), - 'bonus_max' => config('osu.beatmapset.upload_bonus_per_ranked_max'), - 'supporter_base' => config('osu.beatmapset.upload_allowed_supporter'), - 'supporter_bonus' => config('osu.beatmapset.upload_bonus_per_ranked_supporter'), - 'supporter_bonus_max' => config('osu.beatmapset.upload_bonus_per_ranked_max_supporter'), + 'base' => $GLOBALS['cfg']['osu']['beatmapset']['upload_allowed'], + 'bonus' => $GLOBALS['cfg']['osu']['beatmapset']['upload_bonus_per_ranked'], + 'bonus_max' => $GLOBALS['cfg']['osu']['beatmapset']['upload_bonus_per_ranked_max'], + 'supporter_base' => $GLOBALS['cfg']['osu']['beatmapset']['upload_allowed_supporter'], + 'supporter_bonus' => $GLOBALS['cfg']['osu']['beatmapset']['upload_bonus_per_ranked_supporter'], + 'supporter_bonus_max' => $GLOBALS['cfg']['osu']['beatmapset']['upload_bonus_per_ranked_max_supporter'], ], ], 'early_access' => [ @@ -351,15 +351,15 @@ public function supportTheGame() 'more_favourites' => [ 'icons' => ['fas fa-star'], 'translation_options' => [ - 'normally' => config('osu.beatmapset.favourite_limit'), - 'supporter' => config('osu.beatmapset.favourite_limit_supporter'), + 'normally' => $GLOBALS['cfg']['osu']['beatmapset']['favourite_limit'], + 'supporter' => $GLOBALS['cfg']['osu']['beatmapset']['favourite_limit_supporter'], ], ], 'more_friends' => [ 'icons' => ['fas fa-user-friends'], 'translation_options' => [ - 'normally' => config('osu.user.max_friends'), - 'supporter' => config('osu.user.max_friends_supporter'), + 'normally' => $GLOBALS['cfg']['osu']['user']['max_friends'], + 'supporter' => $GLOBALS['cfg']['osu']['user']['max_friends_supporter'], ], ], 'friend_filtering' => [ diff --git a/app/Http/Controllers/InterOp/BeatmapsetsController.php b/app/Http/Controllers/InterOp/BeatmapsetsController.php index 8bc2d143575..ed8a9de7803 100644 --- a/app/Http/Controllers/InterOp/BeatmapsetsController.php +++ b/app/Http/Controllers/InterOp/BeatmapsetsController.php @@ -37,7 +37,7 @@ public function broadcastRevive($id) public function destroy($id) { $beatmapset = Beatmapset::findOrFail($id); - $user = User::findOrFail(config('osu.legacy.bancho_bot_user_id')); + $user = User::findOrFail($GLOBALS['cfg']['osu']['legacy']['bancho_bot_user_id']); (new BeatmapsetDelete($beatmapset, $user))->handle(); @@ -47,7 +47,7 @@ public function destroy($id) public function disqualify($id) { $beatmapset = Beatmapset::findOrFail($id); - $user = User::findOrFail(config('osu.legacy.bancho_bot_user_id')); + $user = User::findOrFail($GLOBALS['cfg']['osu']['legacy']['bancho_bot_user_id']); $message = request('message') ?? null; diff --git a/app/Http/Controllers/LegacyInterOpController.php b/app/Http/Controllers/LegacyInterOpController.php index 728399fa715..b3179372b90 100644 --- a/app/Http/Controllers/LegacyInterOpController.php +++ b/app/Http/Controllers/LegacyInterOpController.php @@ -288,7 +288,7 @@ public function userBatchSendMessage() ]; } - Datadog::increment(config('datadog-helper.prefix_web').'.chat.batch', 1, [ + Datadog::increment($GLOBALS['cfg']['datadog-helper']['prefix_web'].'.chat.batch', 1, [ 'status' => $result['status'], ]); diff --git a/app/Http/Controllers/Multiplayer/Rooms/Playlist/ScoresController.php b/app/Http/Controllers/Multiplayer/Rooms/Playlist/ScoresController.php index 23bd4842a72..a55dc88afac 100644 --- a/app/Http/Controllers/Multiplayer/Rooms/Playlist/ScoresController.php +++ b/app/Http/Controllers/Multiplayer/Rooms/Playlist/ScoresController.php @@ -169,7 +169,7 @@ public function store($roomId, $playlistId) $params = request()->all(); $buildId = ClientCheck::findBuild($user, $params)?->getKey() - ?? config('osu.client.default_build_id'); + ?? $GLOBALS['cfg']['osu']['client']['default_build_id']; $scoreToken = $room->startPlay($user, $playlistItem, $buildId); diff --git a/app/Http/Controllers/NotificationsController.php b/app/Http/Controllers/NotificationsController.php index 9db62a08679..b65192d69e0 100644 --- a/app/Http/Controllers/NotificationsController.php +++ b/app/Http/Controllers/NotificationsController.php @@ -128,7 +128,7 @@ public function markRead() private function endpointUrl() { - $url = config('osu.notification.endpoint'); + $url = $GLOBALS['cfg']['osu']['notification']['endpoint']; if (($url[0] ?? null) === '/') { $host = request()->getHttpHost(); diff --git a/app/Http/Controllers/Payments/XsollaController.php b/app/Http/Controllers/Payments/XsollaController.php index 493053456eb..52007f4bdc3 100644 --- a/app/Http/Controllers/Payments/XsollaController.php +++ b/app/Http/Controllers/Payments/XsollaController.php @@ -33,7 +33,7 @@ public function __construct() public function token() { - $projectId = config('payments.xsolla.project_id'); + $projectId = $GLOBALS['cfg']['payments']['xsolla']['project_id']; $user = Auth::user(); $order = Order::whereOrderNumber(request('orderNumber')) ->whereCanCheckout() @@ -45,7 +45,7 @@ public function token() $tokenRequest = new TokenRequest($projectId, (string) $user->user_id); $tokenRequest - ->setSandboxMode(config('payments.sandbox')) + ->setSandboxMode($GLOBALS['cfg']['payments']['sandbox']) ->setExternalPaymentId($order->getOrderNumber()) ->setUserEmail($user->user_email) ->setUserName($user->username) @@ -57,14 +57,14 @@ public function token() ]); $xsollaClient = XsollaClient::factory([ - 'merchant_id' => config('payments.xsolla.merchant_id'), - 'api_key' => config('payments.xsolla.api_key'), + 'merchant_id' => $GLOBALS['cfg']['payments']['xsolla']['merchant_id'], + 'api_key' => $GLOBALS['cfg']['payments']['xsolla']['api_key'], ]); // This will be used for XPayStationWidget options. return [ 'access_token' => $xsollaClient->createPaymentUITokenFromRequest($tokenRequest), - 'sandbox' => config('payments.sandbox'), + 'sandbox' => $GLOBALS['cfg']['payments']['sandbox'], ]; } diff --git a/app/Http/Controllers/RankingController.php b/app/Http/Controllers/RankingController.php index 5dbe7dd0543..11549cbc4b2 100644 --- a/app/Http/Controllers/RankingController.php +++ b/app/Http/Controllers/RankingController.php @@ -148,7 +148,7 @@ public function index($mode, $type) }); if ($type === 'performance') { - $isExperimentalRank = config('osu.scores.experimental_rank_as_default'); + $isExperimentalRank = $GLOBALS['cfg']['osu']['scores']['experimental_rank_as_default']; if ($this->country !== null) { $stats->where('country_acronym', $this->country['acronym']); // preferrable to rank_score when filtering by country. diff --git a/app/Http/Controllers/ScoreTokensController.php b/app/Http/Controllers/ScoreTokensController.php index 27671cf6d6c..b746f9f113b 100644 --- a/app/Http/Controllers/ScoreTokensController.php +++ b/app/Http/Controllers/ScoreTokensController.php @@ -48,7 +48,7 @@ public function store($beatmapId) try { $scoreToken = ScoreToken::create([ 'beatmap_id' => $beatmap->getKey(), - 'build_id' => $build?->getKey() ?? config('osu.client.default_build_id'), + 'build_id' => $build?->getKey() ?? $GLOBALS['cfg']['osu']['client']['default_build_id'], 'ruleset_id' => $params['ruleset_id'], 'user_id' => $user->getKey(), ]); diff --git a/app/Http/Controllers/SeasonalBackgroundsController.php b/app/Http/Controllers/SeasonalBackgroundsController.php index 77659c9bcb5..beb5c0ea35d 100644 --- a/app/Http/Controllers/SeasonalBackgroundsController.php +++ b/app/Http/Controllers/SeasonalBackgroundsController.php @@ -13,7 +13,7 @@ class SeasonalBackgroundsController extends Controller { public function index() { - $contest = Contest::find(config('osu.seasonal.contest_id')); + $contest = Contest::find($GLOBALS['cfg']['osu']['seasonal']['contest_id']); if ($contest === null) { return response()->json(new stdClass()); @@ -22,7 +22,7 @@ public function index() $backgrounds = $contest->userContestEntries()->where('show_in_client', true)->get(); return [ - 'ends_at' => json_time(Carbon::parse(config('osu.seasonal.ends_at'))), + 'ends_at' => json_time(Carbon::parse($GLOBALS['cfg']['osu']['seasonal']['ends_at'])), 'backgrounds' => json_collection($backgrounds, 'SeasonalBackground'), ]; diff --git a/app/Http/Controllers/SessionsController.php b/app/Http/Controllers/SessionsController.php index a0a58433070..03f82c03fcc 100644 --- a/app/Http/Controllers/SessionsController.php +++ b/app/Http/Controllers/SessionsController.php @@ -67,7 +67,7 @@ public function store() $user = User::findForLogin($username); - if ($user === null && strpos($username, '@') !== false && !config('osu.user.allow_email_login')) { + if ($user === null && strpos($username, '@') !== false && !$GLOBALS['cfg']['osu']['user']['allow_email_login']) { $authError = osu_trans('users.login.email_login_disabled'); } else { $authError = User::attemptLogin($user, $password, $ip); diff --git a/app/Http/Controllers/Store/Controller.php b/app/Http/Controllers/Store/Controller.php index a7bc498ceba..1da52d50e1c 100644 --- a/app/Http/Controllers/Store/Controller.php +++ b/app/Http/Controllers/Store/Controller.php @@ -32,6 +32,6 @@ protected function userCart() protected function isAllowRestrictedUsers() { - return config('store.allow_restricted_users'); + return $GLOBALS['cfg']['store']['allow_restricted_users']; } } diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index d772a59285e..b92a8bd65e1 100644 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -116,7 +116,7 @@ public function card($id) public function create() { - if (config('osu.user.registration_mode') !== 'web') { + if ($GLOBALS['cfg']['osu']['user']['registration_mode'] !== 'web') { return abort(403, osu_trans('users.store.from_client')); } @@ -210,14 +210,14 @@ public function extraPages($_id, $page) public function store() { - if (config('osu.user.registration_mode') !== 'client') { + if ($GLOBALS['cfg']['osu']['user']['registration_mode'] !== 'client') { return response([ 'error' => osu_trans('users.store.from_web'), 'url' => route('users.create'), ], 403); } - if (!starts_with(Request::header('User-Agent'), config('osu.client.user_agent'))) { + if (!starts_with(Request::header('User-Agent'), $GLOBALS['cfg']['osu']['client']['user_agent'])) { return error_popup(osu_trans('users.store.from_client'), 403); } @@ -226,7 +226,7 @@ public function store() public function storeWeb() { - if (config('osu.user.registration_mode') !== 'web') { + if ($GLOBALS['cfg']['osu']['user']['registration_mode'] !== 'web') { return error_popup(osu_trans('users.store.from_client'), 403); } @@ -650,7 +650,7 @@ public function show($id, $mode = null) $initialData = [ 'achievements' => $achievements, 'current_mode' => $currentMode, - 'scores_notice' => config('osu.user.profile_scores_notice'), + 'scores_notice' => $GLOBALS['cfg']['osu']['user']['profile_scores_notice'], 'user' => $userArray, ]; @@ -931,7 +931,7 @@ private function fillDeprecatedDuplicateFields(array $userJson): array private function storeUser(array $rawParams) { - if (!config('osu.user.allow_registration')) { + if (!$GLOBALS['cfg']['osu']['user']['allow_registration']) { return abort(403, 'User registration is currently disabled'); } @@ -982,7 +982,7 @@ private function storeUser(array $rawParams) ); } - if (config('osu.user.registration_mode') === 'web') { + if ($GLOBALS['cfg']['osu']['user']['registration_mode'] === 'web') { $this->login($user); session()->flash('popup', osu_trans('users.store.saved')); diff --git a/app/Http/Middleware/DatadogMetrics.php b/app/Http/Middleware/DatadogMetrics.php index 68a8f1f710f..801d6ff8a5d 100644 --- a/app/Http/Middleware/DatadogMetrics.php +++ b/app/Http/Middleware/DatadogMetrics.php @@ -43,6 +43,6 @@ protected static function logDuration(Request $request, Response $response, $sta $tags = array_merge($tags, app('route-section')->getOriginal()); - Datadog::timing(config('datadog-helper.prefix_web').'.request_time', $duration, 1, $tags); + Datadog::timing($GLOBALS['cfg']['datadog-helper']['prefix_web'].'.request_time', $duration, 1, $tags); } } diff --git a/app/Http/Middleware/LegacyInterOpAuth.php b/app/Http/Middleware/LegacyInterOpAuth.php index 49bff537974..47ca0ae4333 100644 --- a/app/Http/Middleware/LegacyInterOpAuth.php +++ b/app/Http/Middleware/LegacyInterOpAuth.php @@ -25,7 +25,7 @@ public function handle($request, Closure $next) $signature = $request->header('X-LIO-Signature'); // don't use $request->fullUrl() because it returns normalised url. $fullUrl = $request->getSchemeAndHttpHost().$request->getRequestUri(); - $expected = hash_hmac('sha1', $fullUrl, config('osu.legacy.shared_interop_secret')); + $expected = hash_hmac('sha1', $fullUrl, $GLOBALS['cfg']['osu']['legacy']['shared_interop_secret']); if (!present($signature) || !present($timestamp) || $diff > 300 || !hash_equals($expected, $signature)) { $reason = match (true) { diff --git a/app/Http/Middleware/SetLocale.php b/app/Http/Middleware/SetLocale.php index 2fc3ed7bded..7a5a01a2356 100644 --- a/app/Http/Middleware/SetLocale.php +++ b/app/Http/Middleware/SetLocale.php @@ -47,6 +47,6 @@ protected function setLocale(?string $locale, Request $request): void private function localeFromHeader(Request $request): string { return (new Parser())->languageRegionCompatibleFor($request->server('HTTP_ACCEPT_LANGUAGE')) - ?? config('app.fallback_locale'); + ?? $GLOBALS['cfg']['app']['fallback_locale']; } } diff --git a/app/Http/Middleware/ThrottleRequests.php b/app/Http/Middleware/ThrottleRequests.php index 646c42dd008..6395918c6fa 100644 --- a/app/Http/Middleware/ThrottleRequests.php +++ b/app/Http/Middleware/ThrottleRequests.php @@ -18,7 +18,7 @@ public function __construct(RateLimiter $limiter) public static function getApiThrottle($group = 'global') { - return 'throttle:'.config("osu.api.throttle.{$group}").':'; + return 'throttle:'.$GLOBALS['cfg']['osu']['api']['throttle'][$group].':'; } protected function handleRequest($request, Closure $next, array $limits) diff --git a/app/Http/Middleware/VerifyUserAlways.php b/app/Http/Middleware/VerifyUserAlways.php index 8c11efb829b..992d3ce3b7e 100644 --- a/app/Http/Middleware/VerifyUserAlways.php +++ b/app/Http/Middleware/VerifyUserAlways.php @@ -21,7 +21,7 @@ public static function isRequired($user) public function requiresVerification($request) { $method = $request->getMethod(); - $isPostAction = config('osu.user.post_action_verification') + $isPostAction = $GLOBALS['cfg']['osu']['user']['post_action_verification'] ? !isset(static::GET_ACTION_METHODS[$method]) : false; diff --git a/app/Jobs/EsDocument.php b/app/Jobs/EsDocument.php index 141682d56c9..abde72d4860 100644 --- a/app/Jobs/EsDocument.php +++ b/app/Jobs/EsDocument.php @@ -74,7 +74,7 @@ public function handle(): void private function incrementStat(string $action): void { Datadog::increment( - config('datadog-helper.prefix_web').'.es_document', + $GLOBALS['cfg']['datadog-helper']['prefix_web'].'.es_document', 1, [ 'action' => $action, diff --git a/app/Jobs/RegenerateBeatmapsetCover.php b/app/Jobs/RegenerateBeatmapsetCover.php index 2d92e047e21..b2f808c497b 100644 --- a/app/Jobs/RegenerateBeatmapsetCover.php +++ b/app/Jobs/RegenerateBeatmapsetCover.php @@ -57,8 +57,8 @@ public function handle() } catch (Exception $e) { Datadog::increment(['thumbdonger.processed', 'thumbdonger.error']); Log::warning("[beatmapset_id: {$this->beatmapset->beatmapset_id}] Cover regeneration FAILED."); - if (config('osu.beatmap_processor.sentry')) { - $client = ClientBuilder::create(['dsn' => config('osu.beatmap_processor.sentry')])->getClient(); + if ($GLOBALS['cfg']['osu']['beatmap_processor']['sentry']) { + $client = ClientBuilder::create(['dsn' => $GLOBALS['cfg']['osu']['beatmap_processor']['sentry']])->getClient(); $scope = (new Scope())->setTag('beatmapset_id', (string) $this->beatmapset->beatmapset_id); $client->captureException($e, $scope); throw new SilencedException('Silenced Exception: ['.get_class($e).'] '.$e->getMessage()); diff --git a/app/Jobs/RemoveBeatmapsetBestScores.php b/app/Jobs/RemoveBeatmapsetBestScores.php index 4848fe7ba3a..0e1b85fe53e 100644 --- a/app/Jobs/RemoveBeatmapsetBestScores.php +++ b/app/Jobs/RemoveBeatmapsetBestScores.php @@ -52,7 +52,7 @@ public function handle() // TODO: do something with response? Es::getClient('scores')->deleteByQuery([ - 'index' => config('osu.elasticsearch.prefix')."high_scores_{$mode}", + 'index' => $GLOBALS['cfg']['osu']['elasticsearch']['prefix']."high_scores_{$mode}", 'body' => ['query' => $query->toArray()], 'client' => ['ignore' => 404], ]); diff --git a/app/Jobs/UserNotificationDigest.php b/app/Jobs/UserNotificationDigest.php index 57606b56d2c..0bc1fe115d4 100644 --- a/app/Jobs/UserNotificationDigest.php +++ b/app/Jobs/UserNotificationDigest.php @@ -52,7 +52,7 @@ public function handle() // TODO: catch and log errors? Mail::to($this->user)->send(new UserNotificationDigestMail($notifications, $this->user)); - Datadog::increment(config('datadog-helper.prefix_web').'.user_notification_digest.mail', 1); + Datadog::increment($GLOBALS['cfg']['datadog-helper']['prefix_web'].'.user_notification_digest.mail', 1); } private function filterNotifications(Collection $notifications) diff --git a/app/Libraries/AcceptHttpLanguage/Parser.php b/app/Libraries/AcceptHttpLanguage/Parser.php index b1ec30bf749..643de29936c 100644 --- a/app/Libraries/AcceptHttpLanguage/Parser.php +++ b/app/Libraries/AcceptHttpLanguage/Parser.php @@ -52,7 +52,7 @@ public static function parseHeader(?string $header): array public function __construct(?array $availableLanguages = null) { - $this->availableLanguages = $availableLanguages ?? config('app.available_locales'); + $this->availableLanguages = $availableLanguages ?? $GLOBALS['cfg']['app']['available_locales']; } /** diff --git a/app/Libraries/BBCodeForDB.php b/app/Libraries/BBCodeForDB.php index 88d7a8445ed..7e315762258 100644 --- a/app/Libraries/BBCodeForDB.php +++ b/app/Libraries/BBCodeForDB.php @@ -42,7 +42,7 @@ public static function extraUnescape(string $text): string public function __construct($text = '') { $this->text = $text; - $this->uid = config('osu.bbcode.uid'); + $this->uid = $GLOBALS['cfg']['osu']['bbcode']['uid']; } public function parseAudio($text) @@ -175,7 +175,7 @@ public function parseInlineSimple(string $text): string public function parseLinks($text) { $spaces = ['(^|\[.+?\]|\s(?:<|[.:([])*)', "((?:\[.+?\]|>|[.:)\]])*(?:$|\s|\n|\r))"]; - $internalUrl = rtrim(preg_quote(config('app.url'), '#'), '/'); + $internalUrl = rtrim(preg_quote($GLOBALS['cfg']['app']['url'], '#'), '/'); // internal url $text = preg_replace( diff --git a/app/Libraries/BBCodeFromDB.php b/app/Libraries/BBCodeFromDB.php index 7bfde54fb68..1abe791a85c 100644 --- a/app/Libraries/BBCodeFromDB.php +++ b/app/Libraries/BBCodeFromDB.php @@ -30,7 +30,7 @@ public function __construct($text, $uid = '', $options = []) ]; $this->text = $text; - $this->uid = presence($uid) ?? config('osu.bbcode.uid'); + $this->uid = presence($uid) ?? $GLOBALS['cfg']['osu']['bbcode']['uid']; $this->options = array_merge($defaultOptions, $options); if ($this->options['withGallery']) { diff --git a/app/Libraries/BeatmapDifficultyAttributes.php b/app/Libraries/BeatmapDifficultyAttributes.php index b6fd39856cd..271d0d82b88 100644 --- a/app/Libraries/BeatmapDifficultyAttributes.php +++ b/app/Libraries/BeatmapDifficultyAttributes.php @@ -11,7 +11,7 @@ class BeatmapDifficultyAttributes { public static function get(int $beatmapId, int $rulesetId, array $mods) { - $response = (new Client(['base_uri' => config('osu.beatmaps.difficulty_cache.server_url')])) + $response = (new Client(['base_uri' => $GLOBALS['cfg']['osu']['beatmaps']['difficulty_cache']['server_url']])) ->request('POST', 'attributes', [ 'connect_timeout' => 1, 'json' => [ diff --git a/app/Libraries/BeatmapsetDiscussion/Review.php b/app/Libraries/BeatmapsetDiscussion/Review.php index aabe94ca239..9430779d723 100644 --- a/app/Libraries/BeatmapsetDiscussion/Review.php +++ b/app/Libraries/BeatmapsetDiscussion/Review.php @@ -37,7 +37,7 @@ private function __construct( public static function config() { return [ - 'max_blocks' => config('osu.beatmapset.discussion_review_max_blocks'), + 'max_blocks' => $GLOBALS['cfg']['osu']['beatmapset']['discussion_review_max_blocks'], ]; } @@ -178,12 +178,12 @@ private function parseDocument() $childIds = array_values(array_filter(array_pluck($output, 'discussion_id'))); - $minIssues = config('osu.beatmapset.discussion_review_min_issues'); + $minIssues = $GLOBALS['cfg']['osu']['beatmapset']['discussion_review_min_issues']; if (empty($childIds) || count($childIds) < $minIssues) { throw new InvariantException(osu_trans_choice('beatmap_discussions.review.validation.minimum_issues', $minIssues)); } - $maxBlocks = config('osu.beatmapset.discussion_review_max_blocks'); + $maxBlocks = $GLOBALS['cfg']['osu']['beatmapset']['discussion_review_max_blocks']; $blockCount = count($this->document); if ($blockCount > $maxBlocks) { throw new InvariantException(osu_trans_choice('beatmap_discussions.review.validation.too_many_blocks', $maxBlocks)); diff --git a/app/Libraries/ClientCheck.php b/app/Libraries/ClientCheck.php index fd75549f7ad..f195067fd4c 100644 --- a/app/Libraries/ClientCheck.php +++ b/app/Libraries/ClientCheck.php @@ -11,7 +11,7 @@ class ClientCheck { public static function findBuild($user, $params): ?Build { - $assertValid = config('osu.client.check_version') && $user->findUserGroup(app('groups')->byIdentifier('admin'), true) === null; + $assertValid = $GLOBALS['cfg']['osu']['client']['check_version'] && $user->findUserGroup(app('groups')->byIdentifier('admin'), true) === null; $clientHash = presence(get_string($params['version_hash'] ?? null)); if ($clientHash === null) { diff --git a/app/Libraries/CommentBundle.php b/app/Libraries/CommentBundle.php index 359d3380cec..997e9b57b7e 100644 --- a/app/Libraries/CommentBundle.php +++ b/app/Libraries/CommentBundle.php @@ -164,7 +164,7 @@ public function countForPaginator() if (!$this->includeDeleted) { $query->withoutTrashed(); } - $query->select('id')->limit(config('osu.pagination.max_count'))->unorder(); + $query->select('id')->limit($GLOBALS['cfg']['osu']['pagination']['max_count'])->unorder(); return Comment::from($query)->count(); } diff --git a/app/Libraries/Elasticsearch/Es.php b/app/Libraries/Elasticsearch/Es.php index ad952de69c0..4eb27596a75 100644 --- a/app/Libraries/Elasticsearch/Es.php +++ b/app/Libraries/Elasticsearch/Es.php @@ -40,6 +40,6 @@ public static function getClient(string $name = 'default'): Client { static $clients = []; - return $clients[$name] ??= ClientBuilder::fromConfig(config("elasticsearch.connections.{$name}")); + return $clients[$name] ??= ClientBuilder::fromConfig($GLOBALS['cfg']['elasticsearch']['connections'][$name]); } } diff --git a/app/Libraries/Elasticsearch/Search.php b/app/Libraries/Elasticsearch/Search.php index 01c9277a1b3..2f507589456 100644 --- a/app/Libraries/Elasticsearch/Search.php +++ b/app/Libraries/Elasticsearch/Search.php @@ -207,7 +207,7 @@ public function toArray(): array 'sort' => array_map(function ($sort) { return $sort->toArray(); }, $this->params->sorts), - 'timeout' => config('osu.elasticsearch.search_timeout'), + 'timeout' => $GLOBALS['cfg']['osu']['elasticsearch']['search_timeout'], ]; if (isset($this->params->searchAfter)) { @@ -289,7 +289,7 @@ private function handleError(ElasticsearchException $e, string $operation) } Datadog::increment( - config('datadog-helper.prefix_web').'.search.errors', + $GLOBALS['cfg']['datadog-helper']['prefix_web'].'.search.errors', 1, $tags ); @@ -328,7 +328,7 @@ private function runQuery(string $operation, callable $callable) try { return datadog_timing( $callable, - config('datadog-helper.prefix_web').'.search.'.$operation, + $GLOBALS['cfg']['datadog-helper']['prefix_web'].'.search.'.$operation, $this->getDatadogTags() ); } catch (ElasticsearchException $e) { diff --git a/app/Libraries/Elasticsearch/SearchParams.php b/app/Libraries/Elasticsearch/SearchParams.php index 91828791aa6..dd9c4c30a0c 100644 --- a/app/Libraries/Elasticsearch/SearchParams.php +++ b/app/Libraries/Elasticsearch/SearchParams.php @@ -69,7 +69,7 @@ public function blockedUserIds() public function isQueryStringTooShort() { - return mb_strlen($this->queryString) < config('osu.search.minimum_length'); + return mb_strlen($this->queryString) < $GLOBALS['cfg']['osu']['search']['minimum_length']; } public function isLoginRequired(): bool diff --git a/app/Libraries/ImageProcessorService.php b/app/Libraries/ImageProcessorService.php index 846c22a7ba3..bbc52d9290a 100644 --- a/app/Libraries/ImageProcessorService.php +++ b/app/Libraries/ImageProcessorService.php @@ -14,7 +14,7 @@ class ImageProcessorService public function __construct(?string $endpoint = null) { - $this->endpoint = $endpoint ?? config('osu.beatmap_processor.thumbnailer'); + $this->endpoint = $endpoint ?? $GLOBALS['cfg']['osu']['beatmap_processor']['thumbnailer']; } private static function isValidFormat($size) diff --git a/app/Libraries/LocalCacheManager.php b/app/Libraries/LocalCacheManager.php index 8b87a30596e..f315cc70edd 100644 --- a/app/Libraries/LocalCacheManager.php +++ b/app/Libraries/LocalCacheManager.php @@ -16,7 +16,7 @@ class LocalCacheManager public function incrementResetTicker(): void { $this->resetTicker++; - $this->resetTickerLimit ??= config('osu.octane.local_cache_reset_requests'); + $this->resetTickerLimit ??= $GLOBALS['cfg']['osu']['octane']['local_cache_reset_requests']; if ($this->resetTicker > $this->resetTickerLimit) { $this->resetTicker = 0; diff --git a/app/Libraries/Markdown/Osu/DocumentProcessor.php b/app/Libraries/Markdown/Osu/DocumentProcessor.php index de290acc677..cccd53aa6f3 100644 --- a/app/Libraries/Markdown/Osu/DocumentProcessor.php +++ b/app/Libraries/Markdown/Osu/DocumentProcessor.php @@ -194,7 +194,7 @@ private function parseFigure($withGallery = false) $imageUrl = $image->getUrl(); if (starts_with($imageUrl, route('wiki.show', [], false))) { - $imageUrl = config('app.url').$imageUrl; + $imageUrl = $GLOBALS['cfg']['app']['url'].$imageUrl; } $imageSize = fast_imagesize($imageUrl); @@ -236,7 +236,7 @@ private function fixWikiUrl() if (OsuWiki::isImage($path)) { $url = wiki_image_url($path, false); } else { - $locale ??= $this->wikiLocale ?? config('app.fallback_locale'); + $locale ??= $this->wikiLocale ?? $GLOBALS['cfg']['app']['fallback_locale']; $url = wiki_url($path, $locale, false, false); if (starts_with($url, $this->wikiAbsoluteRootPath)) { diff --git a/app/Libraries/OrderCheckout.php b/app/Libraries/OrderCheckout.php index 0f1b4e1183a..8a671d77268 100644 --- a/app/Libraries/OrderCheckout.php +++ b/app/Libraries/OrderCheckout.php @@ -84,14 +84,14 @@ public function allowedCheckoutProviders() public function getCentiliPaymentLink() { $params = [ - 'apikey' => config('payments.centili.api_key'), + 'apikey' => $GLOBALS['cfg']['payments']['centili']['api_key'], 'country' => 'jp', 'countrylock' => 'true', 'reference' => $this->order->getOrderNumber(), - 'price' => $this->order->getTotal() * config('payments.centili.conversion_rate'), + 'price' => $this->order->getTotal() * $GLOBALS['cfg']['payments']['centili']['conversion_rate'], ]; - return config('payments.centili.widget_url').'?'.http_build_query($params); + return $GLOBALS['cfg']['payments']['centili']['widget_url'].'?'.http_build_query($params); } public function beginCheckout() @@ -224,7 +224,7 @@ public static function for(?string $orderNumber): self */ private function allowCentiliPayment() { - return config('payments.centili.enabled') + return $GLOBALS['cfg']['payments']['centili']['enabled'] && strcasecmp(request_country(), 'JP') === 0 && !$this->order->requiresShipping() && Request::input('intl') !== '1'; diff --git a/app/Libraries/OsuAuthorize.php b/app/Libraries/OsuAuthorize.php index 2ed38bad822..34ac87e11ce 100644 --- a/app/Libraries/OsuAuthorize.php +++ b/app/Libraries/OsuAuthorize.php @@ -538,7 +538,7 @@ public function checkBeatmapDiscussionPostShow(?User $user, BeatmapDiscussionPos */ public function checkBeatmapsetAdvancedSearch(?User $user): string { - if (oauth_token() === null && !config('osu.beatmapset.guest_advanced_search')) { + if (oauth_token() === null && !$GLOBALS['cfg']['osu']['beatmapset']['guest_advanced_search']) { $this->ensureLoggedIn($user); } @@ -671,7 +671,7 @@ public function checkBeatmapsetNominate(?User $user, Beatmapset $beatmapset): st return $prefix.'set_metadata'; } - if ($user->beatmapsetNominationsToday() >= config('osu.beatmapset.user_daily_nominations')) { + if ($user->beatmapsetNominationsToday() >= $GLOBALS['cfg']['osu']['beatmapset']['user_daily_nominations']) { return $prefix.'exhausted'; } @@ -938,7 +938,7 @@ public function checkChatChannelCanMessage(?User $user, Channel $channel): strin $this->ensureLoggedIn($user); $this->ensureCleanRecord($user, $prefix); - if (!config('osu.user.min_plays_allow_verified_bypass')) { + if (!$GLOBALS['cfg']['osu']['user']['min_plays_allow_verified_bypass']) { $this->ensureHasPlayed($user); } @@ -987,7 +987,7 @@ public function checkChatPmStart(?User $user, User $target): string $this->ensureLoggedIn($user); $this->ensureCleanRecord($user, $prefix); - if (!config('osu.user.min_plays_allow_verified_bypass')) { + if (!$GLOBALS['cfg']['osu']['user']['min_plays_allow_verified_bypass']) { $this->ensureHasPlayed($user); } @@ -1381,7 +1381,7 @@ public function checkForumView(?User $user, Forum $forum): string return 'ok'; } - if ($forum->categoryId() !== config('osu.forum.admin_forum_id')) { + if ($forum->categoryId() !== $GLOBALS['cfg']['osu']['forum']['admin_forum_id']) { return 'ok'; } @@ -1486,14 +1486,14 @@ public function checkForumPostStore(?User $user, Forum $forum): string if (!$user->isBot()) { $plays = $user->playCount(); $posts = $user->user_posts; - $forInitialHelpForum = in_array($forum->forum_id, config('osu.forum.initial_help_forum_ids'), true); + $forInitialHelpForum = in_array($forum->forum_id, $GLOBALS['cfg']['osu']['forum']['initial_help_forum_ids'], true); if ($forInitialHelpForum) { if ($plays < 10 && $posts > 10) { return $prefix.'too_many_help_posts'; } } else { - if ($plays < config('osu.forum.minimum_plays') && $plays < $posts + 1) { + if ($plays < $GLOBALS['cfg']['osu']['forum']['minimum_plays'] && $plays < $posts + 1) { return $prefix.'play_more'; } @@ -1756,7 +1756,7 @@ public function checkForumTopicVote(?User $user, Topic $topic): string } $plays = $user->playCount(); - if ($plays < config('osu.forum.minimum_plays')) { + if ($plays < $GLOBALS['cfg']['osu']['forum']['minimum_plays']) { return $prefix.'play_more'; } @@ -1903,7 +1903,7 @@ public function checkScorePin(?User $user, ScoreBest|Solo\Score $score): string return $prefix.'not_owner'; } - if ($score instanceof Solo\Score && config('osu.user.hide_pinned_solo_scores')) { + if ($score instanceof Solo\Score && $GLOBALS['cfg']['osu']['user']['hide_pinned_solo_scores']) { return $prefix.'disabled_type'; } @@ -2115,13 +2115,13 @@ public function ensureHasPlayed(?User $user): void return; } - $minPlays = config('osu.user.min_plays_for_posting'); + $minPlays = $GLOBALS['cfg']['osu']['user']['min_plays_for_posting']; if ($user->playCount() >= $minPlays) { return; } - if (config('osu.user.min_plays_allow_verified_bypass')) { + if ($GLOBALS['cfg']['osu']['user']['min_plays_allow_verified_bypass']) { if ($user->isSessionVerified()) { return; } diff --git a/app/Libraries/OsuWiki.php b/app/Libraries/OsuWiki.php index 59bbd47851a..f803530a7ce 100644 --- a/app/Libraries/OsuWiki.php +++ b/app/Libraries/OsuWiki.php @@ -128,17 +128,17 @@ public static function isImage($path) public static function branch() { - return config('osu.wiki.branch'); + return $GLOBALS['cfg']['osu']['wiki']['branch']; } public static function repository() { - return config('osu.wiki.repository'); + return $GLOBALS['cfg']['osu']['wiki']['repository']; } public static function user() { - return config('osu.wiki.user'); + return $GLOBALS['cfg']['osu']['wiki']['user']; } public function __construct($path) diff --git a/app/Libraries/Payments/CentiliPaymentProcessor.php b/app/Libraries/Payments/CentiliPaymentProcessor.php index d6f8d46ecfa..454fbb1588d 100644 --- a/app/Libraries/Payments/CentiliPaymentProcessor.php +++ b/app/Libraries/Payments/CentiliPaymentProcessor.php @@ -34,7 +34,7 @@ public function getPaymentTransactionId() public function getPaymentAmount() { // TODO: less floaty - return $this['enduserprice'] / config('payments.centili.conversion_rate'); + return $this['enduserprice'] / $GLOBALS['cfg']['payments']['centili']['conversion_rate']; } public function getPaymentDate() @@ -76,7 +76,7 @@ public function validateTransaction() return false; } - if ($this['service'] !== config('payments.centili.api_key')) { + if ($this['service'] !== $GLOBALS['cfg']['payments']['centili']['api_key']) { $this->validationErrors()->add('service', '.param.invalid', ['param' => 'service']); } diff --git a/app/Libraries/Payments/CentiliSignature.php b/app/Libraries/Payments/CentiliSignature.php index 40fe36bad83..db037eaed65 100644 --- a/app/Libraries/Payments/CentiliSignature.php +++ b/app/Libraries/Payments/CentiliSignature.php @@ -29,7 +29,7 @@ public static function calculateSignature(array $params) // Centili signature is a HMAC of the concatenation of all params values sorted alphabetically by key name. $content = static::stringifyInput($params); - return hash_hmac('sha1', $content, config('payments.centili.secret_key'), false); + return hash_hmac('sha1', $content, $GLOBALS['cfg']['payments']['centili']['secret_key'], false); } public static function stringifyInput(array $input) diff --git a/app/Libraries/Payments/PaymentProcessor.php b/app/Libraries/Payments/PaymentProcessor.php index c33b8fd92cc..680cc4bbffa 100644 --- a/app/Libraries/Payments/PaymentProcessor.php +++ b/app/Libraries/Payments/PaymentProcessor.php @@ -153,7 +153,7 @@ public function run() } Datadog::increment( - config('datadog-helper.prefix_web').'.payment_processor.run', + $GLOBALS['cfg']['datadog-helper']['prefix_web'].'.payment_processor.run', 1, ['provider' => $this->getPaymentProvider(), 'type' => $type] ); @@ -400,7 +400,7 @@ private function dispatchErrorEvent($exception, $order) private function sandboxAssertion() { - if ($this->isTest() && !config('payments.sandbox')) { + if ($this->isTest() && !$GLOBALS['cfg']['payments']['sandbox']) { throw new SandboxException('Trying to run a test transaction in a non-sanboxed environment.'); } } diff --git a/app/Libraries/Payments/PaypalApiContext.php b/app/Libraries/Payments/PaypalApiContext.php index a50179eeb4b..91667a61f5b 100644 --- a/app/Libraries/Payments/PaypalApiContext.php +++ b/app/Libraries/Payments/PaypalApiContext.php @@ -13,10 +13,10 @@ class PaypalApiContext { public static function client() { - $clientId = config('payments.paypal.client_id'); - $clientSecret = config('payments.paypal.client_secret'); + $clientId = $GLOBALS['cfg']['payments']['paypal']['client_id']; + $clientSecret = $GLOBALS['cfg']['payments']['paypal']['client_secret']; - $environment = config('payments.sandbox') === true + $environment = $GLOBALS['cfg']['payments']['sandbox'] === true ? new SandboxEnvironment($clientId, $clientSecret) : new ProductionEnvironment($clientId, $clientSecret); diff --git a/app/Libraries/Payments/PaypalPaymentProcessor.php b/app/Libraries/Payments/PaypalPaymentProcessor.php index 8ec4ef769d0..83791d3e8a5 100644 --- a/app/Libraries/Payments/PaypalPaymentProcessor.php +++ b/app/Libraries/Payments/PaypalPaymentProcessor.php @@ -102,7 +102,7 @@ public function validateTransaction() return false; } - if ($this['receiver_id'] !== config('payments.paypal.merchant_id')) { + if ($this['receiver_id'] !== $GLOBALS['cfg']['payments']['paypal']['merchant_id']) { $this->validationErrors()->add('receiver_id', '.param.invalid', ['param' => 'receiver_id']); } diff --git a/app/Libraries/Payments/PaypalSignature.php b/app/Libraries/Payments/PaypalSignature.php index ce58d547fd6..5c514253d1f 100644 --- a/app/Libraries/Payments/PaypalSignature.php +++ b/app/Libraries/Payments/PaypalSignature.php @@ -23,7 +23,7 @@ public function isValid() } $client = new Client(); - $response = $client->request('POST', config('payments.paypal.url'), [ + $response = $client->request('POST', $GLOBALS['cfg']['payments']['paypal']['url'], [ 'allow_redirects' => false, 'form_params' => $this->calculatedSignature(), ]); diff --git a/app/Libraries/Payments/ShopifySignature.php b/app/Libraries/Payments/ShopifySignature.php index 77cc7f09c30..38c379912c1 100644 --- a/app/Libraries/Payments/ShopifySignature.php +++ b/app/Libraries/Payments/ShopifySignature.php @@ -29,7 +29,7 @@ public function isValid() public static function calculateSignature(string $content) { - return base64_encode(hash_hmac('sha256', $content, config('payments.shopify.webhook_key'), true)); + return base64_encode(hash_hmac('sha256', $content, $GLOBALS['cfg']['payments']['shopify']['webhook_key'], true)); } private function receivedSignature() diff --git a/app/Libraries/Payments/XsollaSignature.php b/app/Libraries/Payments/XsollaSignature.php index 7d85a2e77d8..3b4a3d40f04 100644 --- a/app/Libraries/Payments/XsollaSignature.php +++ b/app/Libraries/Payments/XsollaSignature.php @@ -25,7 +25,7 @@ public function isValid() public static function calculateSignature(string $content) { - return sha1($content.config('payments.xsolla.secret_key')); + return sha1($content.$GLOBALS['cfg']['payments']['xsolla']['secret_key']); } private function receivedSignature() diff --git a/app/Libraries/ProfileCover.php b/app/Libraries/ProfileCover.php index 1191a7e1789..6fa89c18f6c 100644 --- a/app/Libraries/ProfileCover.php +++ b/app/Libraries/ProfileCover.php @@ -97,7 +97,7 @@ public function url() $id = $this->id(); if ($id !== null) { - return config('app.url').'/images/headers/profile-covers/c'.$id.'.jpg'; + return $GLOBALS['cfg']['app']['url'].'/images/headers/profile-covers/c'.$id.'.jpg'; } } } diff --git a/app/Libraries/ReplayFile.php b/app/Libraries/ReplayFile.php index 71c15b28dfd..37f62e0957f 100644 --- a/app/Libraries/ReplayFile.php +++ b/app/Libraries/ReplayFile.php @@ -110,7 +110,7 @@ private function path(): string private function storage(): Filesystem { - $disk = 'replays.'.$this->score->getMode().'.'.config('osu.score_replays.storage'); + $disk = "replays.{$this->score->getMode()}.{$GLOBALS['cfg']['osu']['score_replays']['storage']}"; return \Storage::disk($disk); } diff --git a/app/Libraries/Score/BeatmapScores.php b/app/Libraries/Score/BeatmapScores.php index b8ff81857a4..4c9048b704e 100644 --- a/app/Libraries/Score/BeatmapScores.php +++ b/app/Libraries/Score/BeatmapScores.php @@ -19,7 +19,7 @@ class BeatmapScores public function __construct(private array $rawParams) { - $rawParams['limit'] = clamp($rawParams['limit'] ?? 50, 1, config('osu.beatmaps.max_scores')); + $rawParams['limit'] = clamp($rawParams['limit'] ?? 50, 1, $GLOBALS['cfg']['osu']['beatmaps']['max_scores']); $rawParams['sort'] ??= 'score_desc'; $this->baseParams = ScoreSearchParams::fromArray($rawParams); } diff --git a/app/Libraries/Score/UserRankCache.php b/app/Libraries/Score/UserRankCache.php index 1645cfbb4b1..1f88bc23e74 100644 --- a/app/Libraries/Score/UserRankCache.php +++ b/app/Libraries/Score/UserRankCache.php @@ -16,9 +16,9 @@ class UserRankCache { public static function fetch(array $options, int $beatmapId, int $rulesetId, int $score): ?int { - $ddPrefix = config('datadog-helper.prefix_web').'.user_rank_cached_lookup'; + $ddPrefix = $GLOBALS['cfg']['datadog-helper']['prefix_web'].'.user_rank_cached_lookup'; - $server = config('osu.scores.rank_cache.server_url'); + $server = $GLOBALS['cfg']['osu']['scores']['rank_cache']['server_url']; if ($server === null || !empty($options['mods']) || ($options['type'] ?? 'global') !== 'global') { Datadog::increment("{$ddPrefix}.miss", 1, ['reason' => 'unsupported_mode']); @@ -37,7 +37,7 @@ public static function fetch(array $options, int $beatmapId, int $rulesetId, int return null; } - if ($stats->unique_users < config('osu.scores.rank_cache.min_users')) { + if ($stats->unique_users < $GLOBALS['cfg']['osu']['scores']['rank_cache']['min_users']) { Datadog::increment("{$ddPrefix}.miss", 1, ['reason' => 'not_enough_unique_users']); return null; @@ -47,7 +47,7 @@ public static function fetch(array $options, int $beatmapId, int $rulesetId, int $response = (new Client(['base_uri' => $server])) ->request('GET', 'rankLookup', [ 'connect_timeout' => 1, - 'timeout' => config('osu.scores.rank_cache.timeout'), + 'timeout' => $GLOBALS['cfg']['osu']['scores']['rank_cache']['timeout'], 'query' => compact('beatmapId', 'rulesetId', 'score'), ]) ->getBody() diff --git a/app/Libraries/Search/BeatmapsetSearch.php b/app/Libraries/Search/BeatmapsetSearch.php index 08b888acf52..ec69b4ec3c2 100644 --- a/app/Libraries/Search/BeatmapsetSearch.php +++ b/app/Libraries/Search/BeatmapsetSearch.php @@ -128,7 +128,7 @@ private function addBlacklistFilter($query) { static $fields = ['artist', 'source', 'tags']; $params = [ - 'index' => config('osu.elasticsearch.prefix').'blacklist', + 'index' => $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'blacklist', 'id' => 'beatmapsets', // can be changed to per-field blacklist as different fields should probably have different restrictions. 'path' => 'keywords', diff --git a/app/Libraries/Search/BeatmapsetSearchCached.php b/app/Libraries/Search/BeatmapsetSearchCached.php index b7cc58999b2..0bca5be6f7c 100644 --- a/app/Libraries/Search/BeatmapsetSearchCached.php +++ b/app/Libraries/Search/BeatmapsetSearchCached.php @@ -31,7 +31,7 @@ public function response(): SearchResponse $value = parent::response(); if ($this->getError() === null) { - Cache::put($key, $value, config('osu.beatmapset.es_cache_duration')); + Cache::put($key, $value, $GLOBALS['cfg']['osu']['beatmapset']['es_cache_duration']); } return $value; diff --git a/app/Libraries/Search/BeatmapsetSearchParams.php b/app/Libraries/Search/BeatmapsetSearchParams.php index 3dd28c822e4..3dcb7a085d8 100644 --- a/app/Libraries/Search/BeatmapsetSearchParams.php +++ b/app/Libraries/Search/BeatmapsetSearchParams.php @@ -53,7 +53,7 @@ public function __construct() { parent::__construct(); - $this->size = config('osu.beatmaps.max'); + $this->size = $GLOBALS['cfg']['osu']['beatmaps']['max']; } /** diff --git a/app/Libraries/Search/ScoreSearch.php b/app/Libraries/Search/ScoreSearch.php index 5e6aa6d490c..7a4668a9a34 100644 --- a/app/Libraries/Search/ScoreSearch.php +++ b/app/Libraries/Search/ScoreSearch.php @@ -21,7 +21,7 @@ class ScoreSearch extends RecordSearch public function __construct(?ScoreSearchParams $params = null) { parent::__construct( - config('osu.elasticsearch.prefix').'solo_scores', + $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'solo_scores', $params ?? new ScoreSearchParams(), Score::class ); @@ -29,7 +29,7 @@ public function __construct(?ScoreSearchParams $params = null) public function getActiveSchemas(): array { - return LaravelRedis::smembers('osu-queue:score-index:'.config('osu.elasticsearch.prefix').'active-schemas'); + return LaravelRedis::smembers('osu-queue:score-index:'.$GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'active-schemas'); } public function getQuery(): BoolQuery @@ -126,7 +126,7 @@ public function queueForIndex(?array $schemas, array $ids): void public function setSchema(string $schema): void { - LaravelRedis::set('osu-queue:score-index:'.config('osu.elasticsearch.prefix').'schema', $schema); + LaravelRedis::set('osu-queue:score-index:'.$GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'schema', $schema); } private function addModsFilter(BoolQuery $query): void diff --git a/app/Libraries/Search/UserSearch.php b/app/Libraries/Search/UserSearch.php index cb210caaf75..18e8fbaddf8 100644 --- a/app/Libraries/Search/UserSearch.php +++ b/app/Libraries/Search/UserSearch.php @@ -73,6 +73,6 @@ public function getQuery() protected function maxResults(): int { - return config('osu.search.max.user'); + return $GLOBALS['cfg']['osu']['search']['max']['user']; } } diff --git a/app/Libraries/Search/WikiSearch.php b/app/Libraries/Search/WikiSearch.php index e290c853fe3..fa2ee3029d6 100644 --- a/app/Libraries/Search/WikiSearch.php +++ b/app/Libraries/Search/WikiSearch.php @@ -65,7 +65,7 @@ public function getQuery() ->should(['constant_score' => [ 'filter' => [ 'match' => [ - 'locale' => config('app.fallback_locale'), + 'locale' => $GLOBALS['cfg']['app']['fallback_locale'], ], ], ]]); diff --git a/app/Libraries/Search/WikiSuggestions.php b/app/Libraries/Search/WikiSuggestions.php index c4c00135361..32e03c84be9 100644 --- a/app/Libraries/Search/WikiSuggestions.php +++ b/app/Libraries/Search/WikiSuggestions.php @@ -50,7 +50,7 @@ public function getQuery() ->should(['constant_score' => [ 'filter' => [ 'match' => [ - 'locale' => config('app.fallback_locale'), + 'locale' => $GLOBALS['cfg']['app']['fallback_locale'], ], ], ]]); diff --git a/app/Libraries/Session/SessionManager.php b/app/Libraries/Session/SessionManager.php index 0fab6219109..2ad89ab2bc5 100644 --- a/app/Libraries/Session/SessionManager.php +++ b/app/Libraries/Session/SessionManager.php @@ -17,17 +17,17 @@ class SessionManager extends \Illuminate\Session\SessionManager */ protected function buildSession($handler) { - return new Store($this->config->get('session.cookie'), $handler); + return new Store($GLOBALS['cfg']['session']['cookie'], $handler); } // copied from upstream but with custom CacheBasedSessionHandler protected function createCacheHandler($driver) { - $store = $this->config->get('session.store') ?: $driver; + $store = $GLOBALS['cfg']['session']['store'] ?: $driver; return new CacheBasedSessionHandler( clone $this->container->make('cache')->store($store), - $this->config->get('session.lifetime') + $GLOBALS['cfg']['session']['lifetime'], ); } } diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 04a0d82cd4c..043b86e6273 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -149,7 +149,7 @@ private static function listKey(int $userId): string private static function redis(): PhpRedisConnection { - return \LaravelRedis::connection(\Config::get('session.connection')); + return \LaravelRedis::connection($GLOBALS['cfg']['session']['connection']); } public function delete(): void @@ -206,7 +206,7 @@ public function save() $userId = $this->userId(); if ($this->handler instanceof CacheBasedSessionHandler) { - $this->handler->setMinutes($userId === null ? 120 : config('session.lifetime')); + $this->handler->setMinutes($userId === null ? 120 : $GLOBALS['cfg']['session']['lifetime']); } parent::save(); diff --git a/app/Libraries/StorageUrl.php b/app/Libraries/StorageUrl.php index 2f467a236f8..013ae323d35 100644 --- a/app/Libraries/StorageUrl.php +++ b/app/Libraries/StorageUrl.php @@ -11,8 +11,8 @@ class StorageUrl { public static function make(?string $diskName, string $path): string { - $diskName ??= \Config::get('filesystems.default'); - $baseUrl = \Config::get("filesystems.disks.{$diskName}.base_url"); + $diskName ??= $GLOBALS['cfg']['filesystems']['default']; + $baseUrl = $GLOBALS['cfg']['filesystems']['disks'][$diskName]['base_url']; return "{$baseUrl}/{$path}"; } diff --git a/app/Libraries/User/AvatarHelper.php b/app/Libraries/User/AvatarHelper.php index 6b4919dc507..41ea193787d 100644 --- a/app/Libraries/User/AvatarHelper.php +++ b/app/Libraries/User/AvatarHelper.php @@ -40,24 +40,24 @@ public static function url(User $user): string return present($value) ? StorageUrl::make(static::disk(), strtr($value, '_', '?')) - : \Config::get('osu.avatar.default'); + : $GLOBALS['cfg']['osu']['avatar']['default']; } private static function disk(): string { - return \Config::get('osu.avatar.storage'); + return $GLOBALS['cfg']['osu']['avatar']['storage']; } private static function purgeCache(int $id): void { - $prefix = presence(\Config::get('osu.avatar.cache_purge_prefix')); + $prefix = presence($GLOBALS['cfg']['osu']['avatar']['cache_purge_prefix']); if ($prefix === null) { return; } - $method = \Config::get('osu.avatar.cache_purge_method') ?? 'GET'; - $auth = \Config::get('osu.avatar.cache_purge_authorization_key'); + $method = $GLOBALS['cfg']['osu']['avatar']['cache_purge_method'] ?? 'GET'; + $auth = $GLOBALS['cfg']['osu']['avatar']['cache_purge_authorization_key']; $ctx = [ 'http' => [ 'method' => $method, diff --git a/app/Libraries/User/CountryChangeTarget.php b/app/Libraries/User/CountryChangeTarget.php index 7d71ee86ff3..4ef8f32797c 100644 --- a/app/Libraries/User/CountryChangeTarget.php +++ b/app/Libraries/User/CountryChangeTarget.php @@ -90,12 +90,12 @@ public static function get(User $user): ?string public static function maxMixedMonths(): int { - return config('osu.user.country_change.max_mixed_months'); + return $GLOBALS['cfg']['osu']['user']['country_change']['max_mixed_months']; } public static function minMonths(): int { - return config('osu.user.country_change.min_months'); + return $GLOBALS['cfg']['osu']['user']['country_change']['min_months']; } private static function isUserInTournament(User $user): bool diff --git a/app/Libraries/User/DatadogLoginAttempt.php b/app/Libraries/User/DatadogLoginAttempt.php index ac0e126939e..2f18c74838f 100644 --- a/app/Libraries/User/DatadogLoginAttempt.php +++ b/app/Libraries/User/DatadogLoginAttempt.php @@ -13,7 +13,7 @@ public static function log($failReasonOrNull) { $success = $failReasonOrNull === null; - Datadog::increment(config('datadog-helper.prefix_web').'.login_attempts', 1, [ + Datadog::increment($GLOBALS['cfg']['datadog-helper']['prefix_web'].'.login_attempts', 1, [ 'success' => (int) $success, 'reason' => $failReasonOrNull, ]); diff --git a/app/Libraries/User/PasswordResetData.php b/app/Libraries/User/PasswordResetData.php index bc24ee3afd8..9f2ba49fc52 100644 --- a/app/Libraries/User/PasswordResetData.php +++ b/app/Libraries/User/PasswordResetData.php @@ -38,8 +38,8 @@ public static function create(?User $user, string $username): ?string $data = new static([ 'authHash' => static::authHash($user), 'canResendMailAfter' => $now - 1, - 'key' => bin2hex(random_bytes(config('osu.user.password_reset.key_length') / 2)), - 'expiresAt' => $now + config('osu.user.password_reset.expires_hour') * 3600, + 'key' => bin2hex(random_bytes($GLOBALS['cfg']['osu']['user']['password_reset']['key_length'] / 2)), + 'expiresAt' => $now + $GLOBALS['cfg']['osu']['user']['password_reset']['expires_hour'] * 3600, 'tries' => 0, ], $user, $username); $data->sendMail(); @@ -92,7 +92,7 @@ public function delete(): void public function hasMoreTries(): bool { - return $this->attrs['tries'] < config('osu.user.password_reset.tries'); + return $this->attrs['tries'] < $GLOBALS['cfg']['osu']['user']['password_reset']['tries']; } public function isActive(): bool diff --git a/app/Libraries/UserBestScoresCheck.php b/app/Libraries/UserBestScoresCheck.php index bebc659069f..6f7c4b41db1 100644 --- a/app/Libraries/UserBestScoresCheck.php +++ b/app/Libraries/UserBestScoresCheck.php @@ -85,7 +85,7 @@ public function check(string $mode) public function removeFromEs(string $mode, array $ids) { return Es::getClient('scores')->deleteByQuery([ - 'index' => config('osu.elasticsearch.prefix')."high_scores_{$mode}", + 'index' => $GLOBALS['cfg']['osu']['elasticsearch']['prefix']."high_scores_{$mode}", 'body' => ['query' => ['terms' => ['score_id' => $ids]]], ]); } @@ -103,7 +103,7 @@ public function run(string $mode) private function newSearch(string $mode): Search { - $index = config('osu.elasticsearch.prefix')."high_scores_{$mode}"; + $index = $GLOBALS['cfg']['osu']['elasticsearch']['prefix']."high_scores_{$mode}"; $search = new BasicSearch($index, "user_best_scores_check_{$mode}"); $search->connectionName = 'scores'; diff --git a/app/Libraries/UserChannelList.php b/app/Libraries/UserChannelList.php index 5103c90d37a..edfb7664b77 100644 --- a/app/Libraries/UserChannelList.php +++ b/app/Libraries/UserChannelList.php @@ -48,7 +48,7 @@ private function loadChannels() ->where('hidden', false) ->whereHas('channel') ->with('channel') - ->limit(config('osu.chat.channel_limit')) + ->limit($GLOBALS['cfg']['osu']['chat']['channel_limit']) ->get(); foreach ($userChannels as $userChannel) { diff --git a/app/Libraries/UserVerification.php b/app/Libraries/UserVerification.php index 14d370f6666..777e62aa612 100644 --- a/app/Libraries/UserVerification.php +++ b/app/Libraries/UserVerification.php @@ -39,7 +39,7 @@ public static function fromCurrentRequest() public static function logAttempt(string $source, string $type, string $reason = null): void { Datadog::increment( - config('datadog-helper.prefix_web').'.verification.attempts', + $GLOBALS['cfg']['datadog-helper']['prefix_web'].'.verification.attempts', 1, compact('reason', 'source', 'type') ); diff --git a/app/Libraries/UserVerificationState.php b/app/Libraries/UserVerificationState.php index ff1d99eac84..43bd3148b6b 100644 --- a/app/Libraries/UserVerificationState.php +++ b/app/Libraries/UserVerificationState.php @@ -64,7 +64,7 @@ public function issue() } // 1 byte = 2^8 bits = 16^2 bits = 2 hex characters - $key = bin2hex(random_bytes(config('osu.user.verification_key_length_hex') / 2)); + $key = bin2hex(random_bytes($GLOBALS['cfg']['osu']['user']['verification_key_length_hex'] / 2)); $linkKey = SignedRandomString::create(32); $expires = now()->addHours(5); @@ -129,7 +129,7 @@ public function verify($inputKey) throw new UserVerificationException('expired', true); } - if ($tries > config('osu.user.verification_key_tries_limit')) { + if ($tries > $GLOBALS['cfg']['osu']['user']['verification_key_tries_limit']) { throw new UserVerificationException('retries_exceeded', true); } diff --git a/app/Libraries/Wiki/WikiSitemap.php b/app/Libraries/Wiki/WikiSitemap.php index 6418b7349a0..9c1e8f2849d 100644 --- a/app/Libraries/Wiki/WikiSitemap.php +++ b/app/Libraries/Wiki/WikiSitemap.php @@ -93,7 +93,7 @@ private function parse(Hit $hit) $this->titles[$key] = $page->title(); - if ($page->locale === config('app.fallback_locale')) { + if ($page->locale === $GLOBALS['cfg']['app']['fallback_locale']) { static::arraySet($this->sitemap, $page->path, null); } } diff --git a/app/Mail/DonationThanks.php b/app/Mail/DonationThanks.php index 50d1752c37c..a0523f0fdf9 100644 --- a/app/Mail/DonationThanks.php +++ b/app/Mail/DonationThanks.php @@ -31,7 +31,7 @@ public function __construct($donor, $length, $amount, $isGift, $continued) 'duration' => $length, 'amount' => $amount, 'isGift' => $isGift, - 'minutes' => round($amount / config('payments.running_cost') * 525949, 1), // 365.2425 days + 'minutes' => round($amount / $GLOBALS['cfg']['payments']['running_cost'] * 525949, 1), // 365.2425 days ]; } @@ -45,8 +45,8 @@ public function build() return $this->text('emails.store.donation_thanks') ->with($this->params) ->from( - config('store.mail.donation_thanks.sender_address'), - config('store.mail.donation_thanks.sender_name') + $GLOBALS['cfg']['store']['mail']['donation_thanks']['sender_address'], + $GLOBALS['cfg']['store']['mail']['donation_thanks']['sender_name'] ) ->subject(osu_trans('mail.donation_thanks.subject')); } diff --git a/app/Models/Achievement.php b/app/Models/Achievement.php index 73babae7127..d28287e82f5 100644 --- a/app/Models/Achievement.php +++ b/app/Models/Achievement.php @@ -40,7 +40,7 @@ public function scopeAchievable($query) public function iconUrl() { - return config('osu.achievement.icon_prefix').e($this->slug).'.png'; + return $GLOBALS['cfg']['osu']['achievement']['icon_prefix'].e($this->slug).'.png'; } public function getAttribute($key) diff --git a/app/Models/BeatmapDiscussion.php b/app/Models/BeatmapDiscussion.php index 7245e01f0e5..a45626be214 100644 --- a/app/Models/BeatmapDiscussion.php +++ b/app/Models/BeatmapDiscussion.php @@ -302,7 +302,7 @@ public function refreshKudosu($event, $eventExtraData = []) ->select('id') )->sum('amount'); - $availableKudosu = config('osu.beatmapset.discussion_kudosu_per_user') - $beatmapsetKudosuGranted; + $availableKudosu = $GLOBALS['cfg']['osu']['beatmapset']['discussion_kudosu_per_user'] - $beatmapsetKudosuGranted; $maxChange = $targetKudosu - $kudosuGranted; $change = min($availableKudosu, $maxChange); diff --git a/app/Models/Beatmapset.php b/app/Models/Beatmapset.php index 4a04566ec7f..0c4d19984fa 100644 --- a/app/Models/Beatmapset.php +++ b/app/Models/Beatmapset.php @@ -349,7 +349,7 @@ public function scopeToBeRanked(Builder $query, Ruleset $ruleset) return $query->qualified() ->withoutTrashed() ->withModesForRanking($ruleset->value) - ->where('queued_at', '<', now()->subDays(config('osu.beatmapset.minimum_days_for_rank'))) + ->where('queued_at', '<', now()->subDays($GLOBALS['cfg']['osu']['beatmapset']['minimum_days_for_rank'])) ->whereDoesntHave('beatmapDiscussions', fn ($q) => $q->openIssues()); } @@ -467,7 +467,7 @@ public function removeCovers() public function fetchBeatmapsetArchive() { $oszFile = tmpfile(); - $mirrorsToUse = config('osu.beatmap_processor.mirrors_to_use'); + $mirrorsToUse = $GLOBALS['cfg']['osu']['beatmap_processor']['mirrors_to_use']; $url = BeatmapMirror::getRandomFromList($mirrorsToUse)->generateURL($this, true); if ($url === false) { @@ -584,7 +584,7 @@ public function setApproved($state, $user, ?array $beatmapIds = null) $this->previous_queue_duration = ($this->queued_at ?? $this->approved_date)->diffinSeconds(); $this->queued_at = null; } elseif ($this->isPending() && $state === 'qualified') { - $maxAdjustment = (config('osu.beatmapset.minimum_days_for_rank') - 1) * 24 * 3600; + $maxAdjustment = ($GLOBALS['cfg']['osu']['beatmapset']['minimum_days_for_rank'] - 1) * 24 * 3600; $adjustment = min($this->previous_queue_duration, $maxAdjustment); $this->queued_at = $currentTime->copy()->subSeconds($adjustment); } @@ -1071,7 +1071,7 @@ public function getAttribute($key) public function requiredHype() { - return config('osu.beatmapset.required_hype'); + return $GLOBALS['cfg']['osu']['beatmapset']['required_hype']; } public function commentLocked(): bool @@ -1130,8 +1130,8 @@ public function requiredNominationCount($summary = false) { $playmodeCount = $this->playmodeCount(); $baseRequirement = $playmodeCount === 1 - ? config('osu.beatmapset.required_nominations') - : config('osu.beatmapset.required_nominations_hybrid'); + ? $GLOBALS['cfg']['osu']['beatmapset']['required_nominations'] + : $GLOBALS['cfg']['osu']['beatmapset']['required_nominations_hybrid']; if ($summary || $this->isLegacyNominationMode()) { return $playmodeCount * $baseRequirement; @@ -1240,9 +1240,9 @@ public function rankingQueueStatus() ->withModesForRanking($modes) ->where('queued_at', '<', $this->queued_at) ->count(); - $days = ceil($queueSize / config('osu.beatmapset.rank_per_day')); + $days = ceil($queueSize / $GLOBALS['cfg']['osu']['beatmapset']['rank_per_day']); - $minDays = config('osu.beatmapset.minimum_days_for_rank') - $this->queued_at->diffInDays(); + $minDays = $GLOBALS['cfg']['osu']['beatmapset']['minimum_days_for_rank'] - $this->queued_at->diffInDays(); $days = max($minDays, $days); return [ diff --git a/app/Models/Build.php b/app/Models/Build.php index 5fcbcf076c1..6b02a3fdbb5 100644 --- a/app/Models/Build.php +++ b/app/Models/Build.php @@ -117,7 +117,7 @@ public function defaultChangelogEntries() public function scopeDefault($query) { - $query->whereIn('stream_id', config('osu.changelog.update_streams')); + $query->whereIn('stream_id', $GLOBALS['cfg']['osu']['changelog']['update_streams']); } public function propagationHistories() diff --git a/app/Models/BuildPropagationHistory.php b/app/Models/BuildPropagationHistory.php index f0758933574..7bb60549405 100644 --- a/app/Models/BuildPropagationHistory.php +++ b/app/Models/BuildPropagationHistory.php @@ -32,7 +32,7 @@ public function scopeChangelog($query, $streamId, $days) { $buildsTable = (new Build())->getTable(); $propagationTable = (new self())->getTable(); - $streamsTable = config('database.connections.mysql-updates.database').'.'.(new UpdateStream())->getTable(); + $streamsTable = $GLOBALS['cfg']['database']['connections']['mysql-updates']['database'].'.'.(new UpdateStream())->getTable(); $query->join($buildsTable, "{$buildsTable}.build_id", '=', "{$propagationTable}.build_id") ->select('created_at') @@ -46,7 +46,7 @@ public function scopeChangelog($query, $streamId, $days) $query->join($streamsTable, "{$streamsTable}.stream_id", '=', "{$buildsTable}.stream_id") // casting to integer here as the sum aggregate returns a string ->addSelect(DB::raw('cast(sum(user_count) as signed) as user_count, pretty_name as label')) - ->whereIn("{$buildsTable}.stream_id", config('osu.changelog.update_streams')) + ->whereIn("{$buildsTable}.stream_id", $GLOBALS['cfg']['osu']['changelog']['update_streams']) ->groupBy(['created_at', 'pretty_name']); } } diff --git a/app/Models/Changelog.php b/app/Models/Changelog.php index b534006493c..ec05344436f 100644 --- a/app/Models/Changelog.php +++ b/app/Models/Changelog.php @@ -52,7 +52,7 @@ public function scopeDefault($query) public function scopeListing($query, $offset = 20) { - $limit = config('osu.changelog.max', 20); + $limit = $GLOBALS['cfg']['osu']['changelog']['max'] ?? 20; return $query ->where('private', 0) diff --git a/app/Models/Chat/Channel.php b/app/Models/Chat/Channel.php index adab21408ee..6476f7be9b3 100644 --- a/app/Models/Chat/Channel.php +++ b/app/Models/Chat/Channel.php @@ -393,7 +393,7 @@ public function messageLengthLimit(): int { return $this->isAnnouncement() ? static::ANNOUNCE_MESSAGE_LENGTH_LIMIT - : config('osu.chat.message_length_limit'); + : $GLOBALS['cfg']['osu']['chat']['message_length_limit']; } public function multiplayerMatch() @@ -430,12 +430,12 @@ public function receiveMessage(User $sender, ?string $content, bool $isAction = } if ($this->isPM()) { - $limit = config('osu.chat.rate_limits.private.limit'); - $window = config('osu.chat.rate_limits.private.window'); + $limit = $GLOBALS['cfg']['osu']['chat']['rate_limits']['private']['limit']; + $window = $GLOBALS['cfg']['osu']['chat']['rate_limits']['private']['window']; $keySuffix = 'PM'; } else { - $limit = config('osu.chat.rate_limits.public.limit'); - $window = config('osu.chat.rate_limits.public.window'); + $limit = $GLOBALS['cfg']['osu']['chat']['rate_limits']['public']['limit']; + $window = $GLOBALS['cfg']['osu']['chat']['rate_limits']['public']['window']; $keySuffix = 'PUBLIC'; } diff --git a/app/Models/Chat/Message.php b/app/Models/Chat/Message.php index ac4fe2dcd36..3e4f9409c29 100644 --- a/app/Models/Chat/Message.php +++ b/app/Models/Chat/Message.php @@ -31,7 +31,7 @@ public static function filterBacklogs(Channel $channel, Collection $messages): C return $messages; } - $minTimestamp = json_time(Carbon::now()->subHours(config('osu.chat.public_backlog_limit'))); + $minTimestamp = json_time(Carbon::now()->subHours($GLOBALS['cfg']['osu']['chat']['public_backlog_limit'])); $ret = []; foreach ($messages as $message) { diff --git a/app/Models/Count.php b/app/Models/Count.php index ddec53453c2..54ab25dc60d 100644 --- a/app/Models/Count.php +++ b/app/Models/Count.php @@ -21,7 +21,7 @@ class Count extends Model public static function currentRankStartName(string $ruleset): string { - return config('osu.scores.experimental_rank_as_default') + return $GLOBALS['cfg']['osu']['scores']['experimental_rank_as_default'] ? "pp_rank_column_exp_{$ruleset}" : "pp_rank_column_{$ruleset}"; } diff --git a/app/Models/Event.php b/app/Models/Event.php index 4a67686f2e0..b7e48085928 100644 --- a/app/Models/Event.php +++ b/app/Models/Event.php @@ -95,8 +95,8 @@ public static function generate($type, $options) $userUrl = e(route('users.show', $beatmapset->user, false)); $approval = e($beatmapset->status()); - $textCleanBeatmapsetUrl = config('app.url').$beatmapsetUrl; - $textCleanUserUrl = config('app.url').$userUrl; + $textCleanBeatmapsetUrl = $GLOBALS['cfg']['app']['url'].$beatmapsetUrl; + $textCleanUserUrl = $GLOBALS['cfg']['app']['url'].$userUrl; $textClean = "[{$textCleanBeatmapsetUrl} {$beatmapsetTitle}] by [{$textCleanUserUrl} {$userName}] has just been {$approval}!"; $params = [ diff --git a/app/Models/Forum/Forum.php b/app/Models/Forum/Forum.php index 82a24493270..d8875ba8ec6 100644 --- a/app/Models/Forum/Forum.php +++ b/app/Models/Forum/Forum.php @@ -255,14 +255,14 @@ public function setForumLastPostTimeAttribute($value) // feature forum shall have extra features like sorting and voting public function isFeatureForum() { - $id = config('osu.forum.feature_forum_id'); + $id = $GLOBALS['cfg']['osu']['forum']['feature_forum_id']; return $this->forum_id === $id || isset($this->forum_parents[$id]); } public function isHelpForum() { - return $this->forum_id === config('osu.forum.help_forum_id'); + return $this->forum_id === $GLOBALS['cfg']['osu']['forum']['help_forum_id']; } public function topicsAdded($count) diff --git a/app/Models/Forum/Post.php b/app/Models/Forum/Post.php index b3496367c28..3f1c04ee3cc 100644 --- a/app/Models/Forum/Post.php +++ b/app/Models/Forum/Post.php @@ -355,7 +355,7 @@ public function isValid() } } - $this->validateDbFieldLength(config('osu.forum.max_post_length'), 'post_text', 'body_raw'); + $this->validateDbFieldLength($GLOBALS['cfg']['osu']['forum']['max_post_length'], 'post_text', 'body_raw'); if (!$this->skipBeatmapPostRestrictions) { // don't forget to sync with views.forum.topics._posts diff --git a/app/Models/Forum/Topic.php b/app/Models/Forum/Topic.php index ea0d9c426f9..8734c315574 100644 --- a/app/Models/Forum/Topic.php +++ b/app/Models/Forum/Topic.php @@ -489,7 +489,7 @@ public function isOld() return false; } - return $this->topic_last_post_time < Carbon::now()->subMonths(config('osu.forum.old_months')); + return $this->topic_last_post_time < Carbon::now()->subMonths($GLOBALS['cfg']['osu']['forum']['old_months']); } public function isLocked() @@ -501,7 +501,7 @@ public function isLocked() public function isActive() { - return $this->topic_last_post_time > Carbon::now()->subMonths(config('osu.forum.necropost_months')); + return $this->topic_last_post_time > Carbon::now()->subMonths($GLOBALS['cfg']['osu']['forum']['necropost_months']); } public function markRead($user, $markTime) @@ -557,7 +557,7 @@ public function markRead($user, $markTime) public function isIssue() { - return in_array($this->forum_id, config('osu.forum.issue_forum_ids'), true); + return in_array($this->forum_id, $GLOBALS['cfg']['osu']['forum']['issue_forum_ids'], true); } public function delete() @@ -756,7 +756,7 @@ public function deleteWithDependencies() public function allowsDoublePosting(): bool { - return in_array($this->forum_id, config('osu.forum.double_post_allowed_forum_ids'), true); + return in_array($this->forum_id, $GLOBALS['cfg']['osu']['forum']['double_post_allowed_forum_ids'], true); } public function isDoublePostBy(User $user) @@ -768,9 +768,9 @@ public function isDoublePostBy(User $user) return false; } if ($user->user_id === $this->topic_poster) { - $minHours = config('osu.forum.double_post_time.author'); + $minHours = $GLOBALS['cfg']['osu']['forum']['double_post_time']['author']; } else { - $minHours = config('osu.forum.double_post_time.normal'); + $minHours = $GLOBALS['cfg']['osu']['forum']['double_post_time']['normal']; } return $this->topic_last_post_time > Carbon::now()->subHours($minHours); diff --git a/app/Models/Forum/TopicPoll.php b/app/Models/Forum/TopicPoll.php index 3538b75e6a5..fc0e432f1b5 100644 --- a/app/Models/Forum/TopicPoll.php +++ b/app/Models/Forum/TopicPoll.php @@ -32,7 +32,7 @@ public function __get(string $field) public function canEdit() { - return $this->topic->topic_time > Carbon::now()->subHours(config('osu.forum.poll_edit_hours')); + return $this->topic->topic_time > Carbon::now()->subHours($GLOBALS['cfg']['osu']['forum']['poll_edit_hours']); } public function exists() @@ -100,7 +100,7 @@ public function isValid($revalidate = false) $this->validationErrors()->add( 'edit', '.grace_period_expired', - ['limit' => config('osu.forum.poll_edit_hours')] + ['limit' => $GLOBALS['cfg']['osu']['forum']['poll_edit_hours']] ); } } diff --git a/app/Models/GithubUser.php b/app/Models/GithubUser.php index c281f877dcb..ea4e4b3c27d 100644 --- a/app/Models/GithubUser.php +++ b/app/Models/GithubUser.php @@ -32,8 +32,8 @@ class GithubUser extends Model */ public static function canAuthenticate(): bool { - return config('osu.github.client_id') !== null - && config('osu.github.client_secret') !== null; + return $GLOBALS['cfg']['osu']['github']['client_id'] !== null + && $GLOBALS['cfg']['osu']['github']['client_secret'] !== null; } /** diff --git a/app/Models/LivestreamCollection.php b/app/Models/LivestreamCollection.php index c21a82dd241..c0be3a02232 100644 --- a/app/Models/LivestreamCollection.php +++ b/app/Models/LivestreamCollection.php @@ -41,7 +41,7 @@ public function downloadStreams() public function download($api) { - $clientId = config('osu.twitch_client_id'); + $clientId = $GLOBALS['cfg']['osu']['twitch_client_id']; if ($clientId === null) { return; } @@ -89,8 +89,8 @@ public function token() try { $response = (new Client(['base_uri' => 'https://id.twitch.tv'])) ->request('POST', '/oauth2/token', ['query' => [ - 'client_id' => config('osu.twitch_client_id'), - 'client_secret' => config('osu.twitch_client_secret'), + 'client_id' => $GLOBALS['cfg']['osu']['twitch_client_id'], + 'client_secret' => $GLOBALS['cfg']['osu']['twitch_client_secret'], 'grant_type' => 'client_credentials', ]]) ->getBody() diff --git a/app/Models/LoginAttempt.php b/app/Models/LoginAttempt.php index f39cb6e64be..7201cdae5ba 100644 --- a/app/Models/LoginAttempt.php +++ b/app/Models/LoginAttempt.php @@ -76,7 +76,7 @@ public static function isLocked($ip) return true; } - return $record->failed_attempts > config('osu.user.max_login_attempts'); + return $record->failed_attempts > $GLOBALS['cfg']['osu']['user']['max_login_attempts']; } public static function logAttempt($ip, $user, $type, $password = null) diff --git a/app/Models/Model.php b/app/Models/Model.php index 441ac65ed74..8e54716b6b7 100644 --- a/app/Models/Model.php +++ b/app/Models/Model.php @@ -118,7 +118,7 @@ public function macroRealCount() $query->getQuery()->offset = null; $query->limit(null); - return min($query->count(), config('osu.pagination.max_count')); + return min($query->count(), $GLOBALS['cfg']['osu']['pagination']['max_count']); }; } @@ -224,9 +224,9 @@ public function saveOrExplode($options = []) public function dbName() { - $connection = $this->connection ?? config('database.default'); + $connection = $this->connection ?? $GLOBALS['cfg']['database']['default']; - return config("database.connections.{$connection}.database"); + return $GLOBALS['cfg']['database']['connections'][$connection]['database']; } public function tableName(bool $includeDbPrefix = false) diff --git a/app/Models/Multiplayer/PlaylistItem.php b/app/Models/Multiplayer/PlaylistItem.php index 6fc8a4cc8b4..8d636286af5 100644 --- a/app/Models/Multiplayer/PlaylistItem.php +++ b/app/Models/Multiplayer/PlaylistItem.php @@ -122,7 +122,7 @@ private function assertValidMaxAttempts() return; } - $maxAttemptsLimit = config('osu.multiplayer.max_attempts_limit'); + $maxAttemptsLimit = $GLOBALS['cfg']['osu']['multiplayer']['max_attempts_limit']; if ($this->max_attempts < 1 || $this->max_attempts > $maxAttemptsLimit) { throw new InvariantException("field 'max_attempts' must be between 1 and {$maxAttemptsLimit}"); } diff --git a/app/Models/Multiplayer/Room.php b/app/Models/Multiplayer/Room.php index 1ff21d1f63a..2ac7f0bbd2a 100644 --- a/app/Models/Multiplayer/Room.php +++ b/app/Models/Multiplayer/Room.php @@ -672,7 +672,7 @@ private function assertValidStartGame() } if ($this->max_attempts !== null) { - $maxAttemptsLimit = config('osu.multiplayer.max_attempts_limit'); + $maxAttemptsLimit = $GLOBALS['cfg']['osu']['multiplayer']['max_attempts_limit']; if ($this->max_attempts < 1 || $this->max_attempts > $maxAttemptsLimit) { throw new InvariantException("field 'max_attempts' must be between 1 and {$maxAttemptsLimit}"); } diff --git a/app/Models/NewsPost.php b/app/Models/NewsPost.php index 66d83085ac4..213a1f16113 100644 --- a/app/Models/NewsPost.php +++ b/app/Models/NewsPost.php @@ -257,7 +257,7 @@ public function firstImage($absolute = false) if ($absolute && !starts_with($url, ['https://', 'http://'])) { if ($url[0] === '/') { - $url = config('app.url').$url; + $url = $GLOBALS['cfg']['app']['url'].$url; } else { $url = "{$this->url()}/{$url}"; } diff --git a/app/Models/OAuth/Client.php b/app/Models/OAuth/Client.php index a9b037d0035..a639f9e63eb 100644 --- a/app/Models/OAuth/Client.php +++ b/app/Models/OAuth/Client.php @@ -85,7 +85,7 @@ public function isValid() $this->validationErrors()->reset(); if (!$this->exists && $this->user !== null) { - $max = config('osu.oauth.max_user_clients'); + $max = $GLOBALS['cfg']['osu']['oauth']['max_user_clients']; if ($this->user->oauthClients()->thirdParty()->where('revoked', false)->count() >= $max) { $this->validationErrors()->add('user.oauthClients.count', '.too_many'); } diff --git a/app/Models/ProfileBanner.php b/app/Models/ProfileBanner.php index 366b9acd0b1..ab32100b4c9 100644 --- a/app/Models/ProfileBanner.php +++ b/app/Models/ProfileBanner.php @@ -51,17 +51,17 @@ public function macroActive() public function scopeActiveOnly(Builder $query): Builder { - $currentTournamentId = config('osu.tournament_banner.current.id'); + $currentTournamentId = $GLOBALS['cfg']['osu']['tournament_banner']['current']['id']; if ($currentTournamentId !== null) { $mayHaveTournamentBanner = true; $query->where('tournament_id', $currentTournamentId); } - $previousTournamentId = config('osu.tournament_banner.previous.id'); + $previousTournamentId = $GLOBALS['cfg']['osu']['tournament_banner']['previous']['id']; if ($previousTournamentId !== null) { $mayHaveTournamentBanner = true; $query->orWhere(fn ($q) => $q->where([ 'tournament_id' => $previousTournamentId, - 'country_acronym' => config('osu.tournament_banner.previous.winner_id'), + 'country_acronym' => $GLOBALS['cfg']['osu']['tournament_banner']['previous']['winner_id'], ])); } @@ -75,7 +75,7 @@ public function image() $period = $this->period(); if ($period !== null) { - $prefix = config("osu.tournament_banner.{$period}.prefix"); + $prefix = $GLOBALS['cfg']['osu']['tournament_banner'][$period]['prefix']; return "{$prefix}{$this->country_acronym}.jpg"; } @@ -86,15 +86,15 @@ public function isActive() $period = $this->period(); return $period === 'current' || - ($period === 'previous' && $this->country_acronym === config('osu.tournament_banner.previous.winner_id')); + ($period === 'previous' && $this->country_acronym === $GLOBALS['cfg']['osu']['tournament_banner']['previous']['winner_id']); } public function period() { switch ($this->tournament_id) { - case config('osu.tournament_banner.current.id'): + case $GLOBALS['cfg']['osu']['tournament_banner']['current']['id']: return 'current'; - case config('osu.tournament_banner.previous.id'): + case $GLOBALS['cfg']['osu']['tournament_banner']['previous']['id']: return 'previous'; } } diff --git a/app/Models/RankHistory.php b/app/Models/RankHistory.php index 6c59dd179dd..838dd4530ef 100644 --- a/app/Models/RankHistory.php +++ b/app/Models/RankHistory.php @@ -111,7 +111,7 @@ class RankHistory extends Model public function __construct(array $attributes = []) { - if (config('osu.scores.experimental_rank_as_default')) { + if ($GLOBALS['cfg']['osu']['scores']['experimental_rank_as_default']) { $this->table = 'osu_user_performance_rank_exp'; } diff --git a/app/Models/Repository.php b/app/Models/Repository.php index 7d8aab26615..69cd7dc5fda 100644 --- a/app/Models/Repository.php +++ b/app/Models/Repository.php @@ -34,7 +34,7 @@ public function mainUpdateStream() public function updateStreams() { - $bridgeTable = config('database.connections.mysql.database').'.repository_update_stream'; + $bridgeTable = $GLOBALS['cfg']['database']['connections']['mysql']['database'].'.repository_update_stream'; return $this->belongsToMany(UpdateStream::class, $bridgeTable, null, 'stream_id'); } diff --git a/app/Models/Score/Best/Model.php b/app/Models/Score/Best/Model.php index 645d2689bfb..b656d04067b 100644 --- a/app/Models/Score/Best/Model.php +++ b/app/Models/Score/Best/Model.php @@ -107,7 +107,7 @@ public function getReplayFile(): ?string public function macroForListing() { return function ($query, $limit) { - $limit = clamp($limit ?? 50, 1, config('osu.beatmaps.max_scores')); + $limit = clamp($limit ?? 50, 1, $GLOBALS['cfg']['osu']['beatmaps']['max_scores']); $newQuery = (clone $query)->with('user')->limit($limit + 100); $result = []; diff --git a/app/Models/ScorePin.php b/app/Models/ScorePin.php index 047eb07a836..5ac30be41fb 100644 --- a/app/Models/ScorePin.php +++ b/app/Models/ScorePin.php @@ -47,7 +47,7 @@ public function scopeWithVisibleScore($query): Builder { $scoreModels = static::SCORES; - if (config('osu.user.hide_pinned_solo_scores')) { + if ($GLOBALS['cfg']['osu']['user']['hide_pinned_solo_scores']) { $soloScoreIndex = array_search_null(MorphMap::MAP[Solo\Score::class], $scoreModels); array_splice($scoreModels, $soloScoreIndex, 1); } diff --git a/app/Models/Solo/Score.php b/app/Models/Solo/Score.php index 65507e4ad8c..544966b3bf3 100644 --- a/app/Models/Solo/Score.php +++ b/app/Models/Solo/Score.php @@ -184,7 +184,7 @@ public function getMode(): string public function getReplayFile(): ?string { - return Storage::disk(config('osu.score_replays.storage').'-solo-replay') + return Storage::disk($GLOBALS['cfg']['osu']['score_replays']['storage'].'-solo-replay') ->get($this->getKey()); } diff --git a/app/Models/Store/Order.php b/app/Models/Store/Order.php index 8662594f1f7..c91be16e98c 100644 --- a/app/Models/Store/Order.php +++ b/app/Models/Store/Order.php @@ -142,7 +142,7 @@ public function scopePaymentRequested($query) public function scopeStale($query) { - return $query->where('updated_at', '<', Carbon::now()->subDays(config('store.order.stale_days'))); + return $query->where('updated_at', '<', Carbon::now()->subDays($GLOBALS['cfg']['store']['order']['stale_days'])); } public function scopeWhereHasInvoice($query) @@ -154,7 +154,7 @@ public function scopeWhereOrderNumber($query, $orderNumber) { if ( !preg_match(static::ORDER_NUMBER_REGEX, $orderNumber, $matches) - || config('store.order.prefix') !== $matches['prefix'] + || $GLOBALS['cfg']['store']['order']['prefix'] !== $matches['prefix'] ) { // hope there's no order_id 0 :D return $query->where('order_id', '=', 0); @@ -208,7 +208,7 @@ public function getOrderName() public function getOrderNumber() { - return config('store.order.prefix')."-{$this->user_id}-{$this->order_id}"; + return $GLOBALS['cfg']['store']['order']['prefix']."-{$this->user_id}-{$this->order_id}"; } public function getPaymentProvider() diff --git a/app/Models/Traits/Es/BaseDbIndexable.php b/app/Models/Traits/Es/BaseDbIndexable.php index ec4cad92fdc..91101009381 100644 --- a/app/Models/Traits/Es/BaseDbIndexable.php +++ b/app/Models/Traits/Es/BaseDbIndexable.php @@ -31,7 +31,7 @@ public static function esIndexIntoNew($batchSize = 1000, $name = null, callable public static function esIndexName() { - return config('osu.elasticsearch.prefix').(new static())->getTable(); + return $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].(new static())->getTable(); } public static function esSchemaFile() diff --git a/app/Models/Traits/Es/BeatmapsetSearch.php b/app/Models/Traits/Es/BeatmapsetSearch.php index 1ea1ceb5763..0037776f7fa 100644 --- a/app/Models/Traits/Es/BeatmapsetSearch.php +++ b/app/Models/Traits/Es/BeatmapsetSearch.php @@ -14,7 +14,7 @@ trait BeatmapsetSearch public static function esIndexName() { - return config('osu.elasticsearch.prefix').'beatmaps'; + return $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'beatmaps'; } public static function esIndexingQuery() diff --git a/app/Models/Traits/Es/ForumPostSearch.php b/app/Models/Traits/Es/ForumPostSearch.php index 621377cc1f5..237015e2228 100644 --- a/app/Models/Traits/Es/ForumPostSearch.php +++ b/app/Models/Traits/Es/ForumPostSearch.php @@ -14,7 +14,7 @@ trait ForumPostSearch public static function esIndexName() { - return config('osu.elasticsearch.prefix').'posts'; + return $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'posts'; } public static function esIndexingQuery() diff --git a/app/Models/Traits/Es/UserSearch.php b/app/Models/Traits/Es/UserSearch.php index 52cd3e96c14..116184b5b9d 100644 --- a/app/Models/Traits/Es/UserSearch.php +++ b/app/Models/Traits/Es/UserSearch.php @@ -13,7 +13,7 @@ trait UserSearch public static function esIndexName() { - return config('osu.elasticsearch.prefix').'users'; + return $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'users'; } public static function esIndexingQuery() diff --git a/app/Models/Traits/Es/WikiPageSearch.php b/app/Models/Traits/Es/WikiPageSearch.php index 9ae494cf5c0..027ae63ff96 100644 --- a/app/Models/Traits/Es/WikiPageSearch.php +++ b/app/Models/Traits/Es/WikiPageSearch.php @@ -11,7 +11,7 @@ trait WikiPageSearch public static function esIndexName() { - return config('osu.elasticsearch.prefix').'wiki_pages'; + return $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'wiki_pages'; } public static function esSchemaFile() diff --git a/app/Models/Traits/UserScoreable.php b/app/Models/Traits/UserScoreable.php index 54761f9e121..e04a9bacccf 100644 --- a/app/Models/Traits/UserScoreable.php +++ b/app/Models/Traits/UserScoreable.php @@ -16,7 +16,7 @@ trait UserScoreable public function aggregatedScoresBest(string $mode, int $size): SearchResponse { - $index = config('osu.elasticsearch.prefix')."high_scores_{$mode}"; + $index = $GLOBALS['cfg']['osu']['elasticsearch']['prefix']."high_scores_{$mode}"; $search = new BasicSearch($index, "aggregatedScoresBest_{$mode}"); $search->connectionName = 'scores'; @@ -61,7 +61,7 @@ public function beatmapBestScoreIds(string $mode) // always fetching 100 to cache; we're not supporting beyond 100, either. $this->beatmapBestScoreIds[$mode] = cache_remember_mutexed( "search-cache:beatmapBestScores:{$this->getKey()}:{$mode}", - config('osu.scores.es_cache_duration'), + $GLOBALS['cfg']['osu']['scores']['es_cache_duration'], [], function () use ($mode) { // FIXME: should return some sort of error on error diff --git a/app/Models/UpdateStream.php b/app/Models/UpdateStream.php index 2a96c967cbd..fb74e983470 100644 --- a/app/Models/UpdateStream.php +++ b/app/Models/UpdateStream.php @@ -82,6 +82,6 @@ public function userCount() public function isFeatured() { - return $this->getKey() === config('osu.changelog.featured_stream'); + return $this->getKey() === $GLOBALS['cfg']['osu']['changelog']['featured_stream']; } } diff --git a/app/Models/User.php b/app/Models/User.php index 45a5c87c985..ce03568fcb7 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -449,7 +449,7 @@ public function getUsernameAvailableAt(): Carbon $allGroupIds = array_merge([$this->group_id], $this->groupIds()['active']); $allowedGroupIds = array_map(function ($groupIdentifier) { return app('groups')->byIdentifier($groupIdentifier)->getKey(); - }, config('osu.user.allowed_rename_groups')); + }, $GLOBALS['cfg']['osu']['user']['allowed_rename_groups']); // only users which groups are all in the whitelist can be renamed if (count(array_diff($allGroupIds, $allowedGroupIds)) > 0) { @@ -1051,13 +1051,13 @@ public function isActive() */ public function isInactive(): bool { - return time() - $this->getRawAttribute('user_lastvisit') > config('osu.user.inactive_seconds_verification'); + return time() - $this->getRawAttribute('user_lastvisit') > $GLOBALS['cfg']['osu']['user']['inactive_seconds_verification']; } public function isOnline() { return !$this->hide_presence - && time() - $this->getRawAttribute('user_lastvisit') < config('osu.user.online_window'); + && time() - $this->getRawAttribute('user_lastvisit') < $GLOBALS['cfg']['osu']['user']['online_window']; } public function isPrivileged() @@ -1292,7 +1292,7 @@ public function rank() public function rankHighests(): HasMany { - return config('osu.scores.experimental_rank_as_default') + return $GLOBALS['cfg']['osu']['scores']['experimental_rank_as_default'] ? $this->hasMany(RankHighest::class, null, 'nonexistent') : $this->hasMany(RankHighest::class); } @@ -1541,32 +1541,32 @@ public function maxBlocks() public function maxFriends() { - return $this->isSupporter() ? config('osu.user.max_friends_supporter') : config('osu.user.max_friends'); + return $this->isSupporter() ? $GLOBALS['cfg']['osu']['user']['max_friends_supporter'] : $GLOBALS['cfg']['osu']['user']['max_friends']; } public function maxMultiplayerDuration() { - return $this->isSupporter() ? config('osu.user.max_multiplayer_duration_supporter') : config('osu.user.max_multiplayer_duration'); + return $this->isSupporter() ? $GLOBALS['cfg']['osu']['user']['max_multiplayer_duration_supporter'] : $GLOBALS['cfg']['osu']['user']['max_multiplayer_duration']; } public function maxMultiplayerRooms() { - return $this->isSupporter() ? config('osu.user.max_multiplayer_rooms_supporter') : config('osu.user.max_multiplayer_rooms'); + return $this->isSupporter() ? $GLOBALS['cfg']['osu']['user']['max_multiplayer_rooms_supporter'] : $GLOBALS['cfg']['osu']['user']['max_multiplayer_rooms']; } public function maxScorePins() { - return $this->isSupporter() ? config('osu.user.max_score_pins_supporter') : config('osu.user.max_score_pins'); + return $this->isSupporter() ? $GLOBALS['cfg']['osu']['user']['max_score_pins_supporter'] : $GLOBALS['cfg']['osu']['user']['max_score_pins']; } public function beatmapsetDownloadAllowance() { - return $this->isSupporter() ? config('osu.beatmapset.download_limit_supporter') : config('osu.beatmapset.download_limit'); + return $this->isSupporter() ? $GLOBALS['cfg']['osu']['beatmapset']['download_limit_supporter'] : $GLOBALS['cfg']['osu']['beatmapset']['download_limit']; } public function beatmapsetFavouriteAllowance() { - return $this->isSupporter() ? config('osu.beatmapset.favourite_limit_supporter') : config('osu.beatmapset.favourite_limit'); + return $this->isSupporter() ? $GLOBALS['cfg']['osu']['beatmapset']['favourite_limit_supporter'] : $GLOBALS['cfg']['osu']['beatmapset']['favourite_limit']; } public function uncachedFollowerCount() @@ -1772,7 +1772,7 @@ public function remainingHype() ->where('created_at', '>', Carbon::now()->subWeeks()) ->count(); - return config('osu.beatmapset.user_weekly_hype') - $hyped; + return $GLOBALS['cfg']['osu']['beatmapset']['user_weekly_hype'] - $hyped; }); } @@ -1840,7 +1840,7 @@ public function updatePage($text) if ($this->userPage === null) { DB::transaction(function () use ($text) { $topic = Forum\Topic::createNew( - Forum\Forum::find(config('osu.user.user_page_forum_id')), + Forum\Forum::find($GLOBALS['cfg']['osu']['user']['user_page_forum_id']), [ 'title' => "{$this->username}'s user page", 'user' => $this, @@ -1982,7 +1982,7 @@ public function scopeOnline($query) { return $query ->where('user_allow_viewonline', true) - ->where('user_lastvisit', '>', time() - config('osu.user.online_window')); + ->where('user_lastvisit', '>', time() - $GLOBALS['cfg']['osu']['user']['online_window']); } public function scopeEagerloadForListing($query) @@ -2090,7 +2090,7 @@ public static function findForLogin($username, $allowEmail = false) $query = static::where('username', $username); - if (config('osu.user.allow_email_login') || $allowEmail) { + if ($GLOBALS['cfg']['osu']['user']['allow_email_login'] || $allowEmail) { $query->orWhere('user_email', strtolower($username)); } diff --git a/app/Models/UserAccountHistory.php b/app/Models/UserAccountHistory.php index d42b1c394f3..8967b982118 100644 --- a/app/Models/UserAccountHistory.php +++ b/app/Models/UserAccountHistory.php @@ -84,7 +84,7 @@ public function scopeDefault($query) public function scopeRecent($query) { return $query - ->where('timestamp', '>', Carbon::now()->subDays(config('osu.user.ban_persist_days'))) + ->where('timestamp', '>', Carbon::now()->subDays($GLOBALS['cfg']['osu']['user']['ban_persist_days'])) ->orWhere('permanent', true) ->orderBy('timestamp', 'desc'); } diff --git a/app/Models/UserRelation.php b/app/Models/UserRelation.php index 70cf03e8dc2..7fd6d2560b9 100644 --- a/app/Models/UserRelation.php +++ b/app/Models/UserRelation.php @@ -71,8 +71,8 @@ public function scopeWithMutual($query) AND z.friend = 1 ), 0)'; - if (count(config('osu.user.super_friendly')) > 0) { - $friendlyIds = implode(',', config('osu.user.super_friendly')); + if (count($GLOBALS['cfg']['osu']['user']['super_friendly']) > 0) { + $friendlyIds = implode(',', $GLOBALS['cfg']['osu']['user']['super_friendly']); $raw = DB::raw( "CASE WHEN phpbb_zebra.zebra_id IN ({$friendlyIds}) THEN 1 diff --git a/app/Models/UserReport.php b/app/Models/UserReport.php index c283bcb98bf..61b059f07c6 100644 --- a/app/Models/UserReport.php +++ b/app/Models/UserReport.php @@ -82,7 +82,7 @@ public function routeNotificationForSlack(?Notification $_notification): ?string || $reportableModel instanceof BestModel || $reportableModel instanceof Solo\Score ) { - return config('osu.user_report_notification.endpoint_cheating'); + return $GLOBALS['cfg']['osu']['user_report_notification']['endpoint_cheating']; } else { $type = match ($reportableModel::class) { BeatmapDiscussionPost::class => 'beatmapset_discussion', @@ -93,8 +93,8 @@ public function routeNotificationForSlack(?Notification $_notification): ?string User::class => 'user', }; - return config("osu.user_report_notification.endpoint.{$type}") - ?? config('osu.user_report_notification.endpoint_moderation'); + return $GLOBALS['cfg']['osu']['user_report_notification']['endpoint'][$type] + ?? $GLOBALS['cfg']['osu']['user_report_notification']['endpoint_moderation']; } } diff --git a/app/Models/UserStatistics/Model.php b/app/Models/UserStatistics/Model.php index 6e40322f3b4..010a3c6fde4 100644 --- a/app/Models/UserStatistics/Model.php +++ b/app/Models/UserStatistics/Model.php @@ -24,7 +24,7 @@ public static function ppColumn() { static $ret; - return $ret ??= config('osu.scores.experimental_rank_as_default') + return $ret ??= $GLOBALS['cfg']['osu']['scores']['experimental_rank_as_default'] ? 'rank_score_exp' : 'rank_score'; } @@ -185,7 +185,7 @@ public function countryRank() public function globalRank(): ?int { - $column = config('osu.scores.experimental_rank_as_default') + $column = $GLOBALS['cfg']['osu']['scores']['experimental_rank_as_default'] ? 'rank_score_index_exp' : 'rank_score_index'; diff --git a/app/Models/Wiki/Page.php b/app/Models/Wiki/Page.php index d0b7bd29129..8eca5f8fb3b 100644 --- a/app/Models/Wiki/Page.php +++ b/app/Models/Wiki/Page.php @@ -87,7 +87,7 @@ public static function lookupForController($path, $locale) $page = static::lookup($path, $locale)->sync(); if (!$page->isVisible() && $page->isTranslation()) { - $page = static::lookup($path, config('app.fallback_locale'), $locale)->sync(); + $page = static::lookup($path, $GLOBALS['cfg']['app']['fallback_locale'], $locale)->sync(); } return $page; @@ -122,7 +122,7 @@ public static function searchPath($path, $locale) ['constant_score' => [ 'filter' => [ 'match' => [ - 'locale' => config('app.fallback_locale'), + 'locale' => $GLOBALS['cfg']['app']['fallback_locale'], ], ], ]]; @@ -311,7 +311,7 @@ public function isStub(): bool public function isTranslation(): bool { - return $this->locale !== config('app.fallback_locale'); + return $this->locale !== $GLOBALS['cfg']['app']['fallback_locale']; } public function isVisible() diff --git a/app/Notifications/Store/ErrorMessage.php b/app/Notifications/Store/ErrorMessage.php index 72203313843..b4219cf5f66 100644 --- a/app/Notifications/Store/ErrorMessage.php +++ b/app/Notifications/Store/ErrorMessage.php @@ -41,7 +41,7 @@ public function toSlack($notifiable) return (new SlackMessage()) ->http(static::HTTP_OPTIONS) - ->to(config('payments.notification_channel')) + ->to($GLOBALS['cfg']['payments']['notification_channel']) ->error() ->content($content) ->attachment(function ($attachment) { diff --git a/app/Notifications/Store/Message.php b/app/Notifications/Store/Message.php index ef4448fb36e..9fa8ce0cdfe 100644 --- a/app/Notifications/Store/Message.php +++ b/app/Notifications/Store/Message.php @@ -24,7 +24,7 @@ abstract class Message extends Notification implements ShouldQueue public function __construct() { - $this->queue = config('store.queue.notifications'); + $this->queue = $GLOBALS['cfg']['store']['queue']['notifications']; $this->notified_at = Carbon::now(); } @@ -38,7 +38,7 @@ public function via($notifiable) { // FIXME: remove this after adding the right checks to the tests if ( - config('app.env') === 'testing' + $GLOBALS['cfg']['app']['env'] === 'testing' && presence(env('STORE_NOTIFICATION_TESTS'), false) === false ) { return []; diff --git a/app/Notifications/Store/OrderMessage.php b/app/Notifications/Store/OrderMessage.php index 095d827ef10..d820a387189 100644 --- a/app/Notifications/Store/OrderMessage.php +++ b/app/Notifications/Store/OrderMessage.php @@ -32,7 +32,7 @@ public function toSlack($notifiable) return (new SlackMessage()) ->http(static::HTTP_OPTIONS) - ->to(config('payments.notification_channel')) + ->to($GLOBALS['cfg']['payments']['notification_channel']) ->content($content); } diff --git a/app/Notifications/Store/StoreMessage.php b/app/Notifications/Store/StoreMessage.php index 08e6acf6f54..6afcae7eee9 100644 --- a/app/Notifications/Store/StoreMessage.php +++ b/app/Notifications/Store/StoreMessage.php @@ -30,7 +30,7 @@ public function toSlack($notifiable) return (new SlackMessage()) ->http(static::HTTP_OPTIONS) - ->to(config('payments.notification_channel')) + ->to($GLOBALS['cfg']['payments']['notification_channel']) ->content($content); } diff --git a/app/Notifications/Store/ValidationMessage.php b/app/Notifications/Store/ValidationMessage.php index 7d6bb7ebb73..acfc1687854 100644 --- a/app/Notifications/Store/ValidationMessage.php +++ b/app/Notifications/Store/ValidationMessage.php @@ -35,7 +35,7 @@ public function toSlack($notifiable) return (new SlackMessage()) ->http(static::HTTP_OPTIONS) - ->to(config('payments.notification_channel')) + ->to($GLOBALS['cfg']['payments']['notification_channel']) ->warning() ->content($content) ->attachment(function ($attachment) { diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 8dc6a20424d..d7f52a0bd0b 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -67,12 +67,14 @@ public function boot() { Relation::morphMap(MorphMap::flippedMap()); + $GLOBALS['cfg'] = \Config::all(); + Queue::after(function (JobProcessed $event) { app('OsuAuthorize')->resetCache(); app('local-cache-manager')->incrementResetTicker(); Datadog::increment( - config('datadog-helper.prefix_web').'.queue.run', + $GLOBALS['cfg']['datadog-helper']['prefix_web'].'.queue.run', 1, [ 'job' => $event->job->resolveName(), @@ -83,9 +85,9 @@ public function boot() $this->app->make('translator')->setSelector(new OsuMessageSelector()); - app('url')->forceScheme(substr(config('app.url'), 0, 5) === 'https' ? 'https' : 'http'); + app('url')->forceScheme(substr($GLOBALS['cfg']['app']['url'], 0, 5) === 'https' ? 'https' : 'http'); - Request::setTrustedProxies(config('trustedproxy.proxies'), config('trustedproxy.headers')); + Request::setTrustedProxies($GLOBALS['cfg']['trustedproxy']['proxies'], $GLOBALS['cfg']['trustedproxy']['headers']); // newest scribe tries to rename {modelName} parameters to {id} // but it kind of doesn't work with our route handlers. @@ -119,7 +121,7 @@ public function register() }); $this->app->singleton('cookie', function ($app) { - $config = $app->make('config')->get('session'); + $config = $GLOBALS['cfg']['session']; return (new OsuCookieJar())->setDefaultPathAndDomain( $config['path'], diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 719bcb38c75..9b0f0c3256d 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -34,7 +34,7 @@ public function register() // AuthorizationController class. $this->app->when(AuthorizationController::class) ->needs(StatefulGuard::class) - ->give(fn () => Auth::guard(config('passport.guard', null))); + ->give(fn () => Auth::guard($GLOBALS['cfg']['passport']['guard'])); } public function boot() @@ -45,7 +45,7 @@ public function boot() Passport::useTokenModel(Token::class); Passport::useClientModel(Client::class); - if ($path = config('services.passport.path')) { + if ($path = $GLOBALS['cfg']['services']['passport']['path']) { Passport::keyPath($path); } diff --git a/app/Traits/NotificationQueue.php b/app/Traits/NotificationQueue.php index 202ba0c2ea4..3ff6c8608eb 100644 --- a/app/Traits/NotificationQueue.php +++ b/app/Traits/NotificationQueue.php @@ -9,6 +9,6 @@ trait NotificationQueue { public function dispatch() { - return dispatch($this->onQueue(config('osu.notification.queue_name'))); + return dispatch($this->onQueue($GLOBALS['cfg']['osu']['notification']['queue_name'])); } } diff --git a/app/Traits/StoreNotifiable.php b/app/Traits/StoreNotifiable.php index af31cc720a1..445ed0c3b22 100644 --- a/app/Traits/StoreNotifiable.php +++ b/app/Traits/StoreNotifiable.php @@ -20,7 +20,7 @@ trait StoreNotifiable public function routeNotificationForSlack() { - return config('slack.endpoint'); + return $GLOBALS['cfg']['slack']['endpoint']; } public function notifyText($text, $eventName = null) diff --git a/app/Transformers/UserStatisticsTransformer.php b/app/Transformers/UserStatisticsTransformer.php index a9b7260a367..e12989f179a 100644 --- a/app/Transformers/UserStatisticsTransformer.php +++ b/app/Transformers/UserStatisticsTransformer.php @@ -23,7 +23,7 @@ public function transform(UserStatistics\Model $stats = null) $stats = new UserStatistics\Osu(); } - if (!config('osu.scores.experimental_rank_as_default') && config('osu.scores.experimental_rank_as_extra')) { + if (!$GLOBALS['cfg']['osu']['scores']['experimental_rank_as_default'] && $GLOBALS['cfg']['osu']['scores']['experimental_rank_as_extra']) { $globalRankExp = $stats->globalRankExp(); $ppExp = $stats->rank_score_exp; } diff --git a/app/helpers.php b/app/helpers.php index 218d0c9bc1d..4929b170b43 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -185,7 +185,7 @@ function cache_forget_with_fallback($key) function captcha_enabled() { - return config('captcha.sitekey') !== '' && config('captcha.secret') !== ''; + return $GLOBALS['cfg']['captcha']['sitekey'] !== '' && $GLOBALS['cfg']['captcha']['secret'] !== ''; } function captcha_login_triggered() @@ -194,11 +194,11 @@ function captcha_login_triggered() return false; } - if (config('captcha.threshold') === 0) { + if ($GLOBALS['cfg']['captcha']['threshold'] === 0) { $triggered = true; } else { $loginAttempts = LoginAttempt::find(request()->getClientIp()); - $triggered = $loginAttempts && $loginAttempts->failed_attempts >= config('captcha.threshold'); + $triggered = $loginAttempts && $loginAttempts->failed_attempts >= $GLOBALS['cfg']['captcha']['threshold']; } return $triggered; @@ -264,7 +264,7 @@ function cleanup_cookies() } // remove duplicates and current session domain - $sessionDomain = presence(ltrim(config('session.domain'), '.')) ?? ''; + $sessionDomain = presence(ltrim($GLOBALS['cfg']['session']['domain'], '.')) ?? ''; $domains = array_diff(array_unique($domains), [$sessionDomain]); foreach (['locale', 'osu_session', 'XSRF-TOKEN'] as $key) { @@ -274,6 +274,12 @@ function cleanup_cookies() } } +function config_set(string $key, $value): void +{ + Config::set($key, $value); + $GLOBALS['cfg'] = Config::all(); +} + function css_group_colour($group) { return '--group-colour: '.(optional($group)->colour ?? 'initial'); @@ -394,7 +400,7 @@ function format_rank(?int $rank): string function get_valid_locale($requestedLocale) { - if (in_array($requestedLocale, config('app.available_locales'), true)) { + if (in_array($requestedLocale, $GLOBALS['cfg']['app']['available_locales'], true)) { return $requestedLocale; } } @@ -457,7 +463,7 @@ function log_error($exception) { Log::error($exception); - if (config('sentry.dsn')) { + if ($GLOBALS['cfg']['sentry']['dsn']) { Sentry::captureException($exception); } } @@ -523,7 +529,7 @@ function max_offset($page, $limit) { $offset = ($page - 1) * $limit; - return max(0, min($offset, config('osu.pagination.max_count') - $limit)); + return max(0, min($offset, $GLOBALS['cfg']['osu']['pagination']['max_count'] - $limit)); } function mysql_escape_like($string) @@ -545,7 +551,7 @@ function osu_trans($key = null, $replace = [], $locale = null) } if (!trans_exists($key, $locale)) { - $locale = config('app.fallback_locale'); + $locale = $GLOBALS['cfg']['app']['fallback_locale']; } return $translator->get($key, $replace, $locale, false); @@ -554,7 +560,7 @@ function osu_trans($key = null, $replace = [], $locale = null) function osu_trans_choice($key, $number, array $replace = [], $locale = null) { if (!trans_exists($key, $locale)) { - $locale = config('app.fallback_locale'); + $locale = $GLOBALS['cfg']['app']['fallback_locale']; } if (is_array($number) || $number instanceof Countable) { @@ -568,12 +574,12 @@ function osu_trans_choice($key, $number, array $replace = [], $locale = null) return app('translator')->choice($key, $number, $replace, $locale); } -function osu_url($key) +function osu_url(string $key): ?string { - $url = config("osu.urls.{$key}"); + $url = $GLOBALS['cfg']['osu']['urls'][$key] ?? null; if (($url[0] ?? null) === '/') { - $url = config('osu.urls.base').$url; + $url = $GLOBALS['cfg']['osu']['urls']['base'].$url; } return $url; @@ -765,7 +771,7 @@ function from_app_url() // Add trailing slash so people can't just use https://osu.web.domain.com // to bypass https://osu.web referrer check. // This assumes app.url doesn't contain trailing slash. - return starts_with(request()->headers->get('referer'), config('app.url').'/'); + return starts_with(request()->headers->get('referer'), $GLOBALS['cfg']['app']['url'].'/'); } function forum_user_link(int $id, string $username, string|null $colour, int|null $currentUserId): string @@ -837,7 +843,7 @@ function page_description($extra) function page_title() { $currentRoute = app('route-section')->getCurrent(); - $checkLocale = config('app.fallback_locale'); + $checkLocale = $GLOBALS['cfg']['app']['fallback_locale']; $actionKey = "{$currentRoute['namespace']}.{$currentRoute['controller']}.{$currentRoute['action']}"; $actionKey = match ($actionKey) { @@ -1044,11 +1050,11 @@ function proxy_media($url) $url = html_entity_decode_better($url); - if (config('osu.camo.key') === null) { + if ($GLOBALS['cfg']['osu']['camo']['key'] === null) { return $url; } - $isProxied = starts_with($url, config('osu.camo.prefix')); + $isProxied = starts_with($url, $GLOBALS['cfg']['osu']['camo']['prefix']); if ($isProxied) { return $url; @@ -1060,14 +1066,14 @@ function proxy_media($url) if ($url[0] !== '/') { $url = "/{$url}"; } - $url = config('app.url').$url; + $url = $GLOBALS['cfg']['app']['url'].$url; } $hexUrl = bin2hex($url); - $secret = hash_hmac('sha1', $url, config('osu.camo.key')); + $secret = hash_hmac('sha1', $url, $GLOBALS['cfg']['osu']['camo']['key']); - return config('osu.camo.prefix')."{$secret}/{$hexUrl}"; + return $GLOBALS['cfg']['osu']['camo']['prefix']."{$secret}/{$hexUrl}"; } function lazy_load_image($url, $class = '', $alt = '') @@ -1748,7 +1754,7 @@ function check_url(string $url): bool function mini_asset(string $url): string { - return str_replace(config('filesystems.disks.s3.base_url'), config('filesystems.disks.s3.mini_url'), $url); + return str_replace($GLOBALS['cfg']['filesystems']['disks']['s3']['base_url'], $GLOBALS['cfg']['filesystems']['disks']['s3']['mini_url'], $url); } function section_to_hue_map($section): int diff --git a/config/osu.php b/config/osu.php index fe74aab750e..33af7ae8d4a 100644 --- a/config/osu.php +++ b/config/osu.php @@ -208,33 +208,24 @@ 'experimental_host' => presence(env('OSU_EXPERIMENTAL_HOST')), 'installer' => 'https://m1.ppy.sh/r/osu!install.exe', 'installer-mirror' => 'https://m2.ppy.sh/r/osu!install.exe', + 'lazer_dl.android' => presence(env('OSU_URL_LAZER_ANDROID')) ?? 'https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk', + 'lazer_dl.ios' => presence(env('OSU_URL_LAZER_IOS')) ?? '/home/testflight', + 'lazer_dl.linux_x64' => presence(env('OSU_URL_LAZER_LINUX_X64')) ?? 'https://github.com/ppy/osu/releases/latest/download/osu.AppImage', + 'lazer_dl.macos_as' => presence(env('OSU_URL_LAZER_MACOS_AS')) ?? 'https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip', + 'lazer_dl.windows_x64' => presence(env('OSU_URL_LAZER_WINDOWS_X64')) ?? 'https://github.com/ppy/osu/releases/latest/download/install.exe', 'lazer_dl_other' => presence(env('OSU_URL_LAZER_OTHER')) ?? 'https://github.com/ppy/osu/#running-osu', 'lazer_info' => presence(env('OSU_URL_LAZER_INFO')), 'osx' => 'https://osx.ppy.sh', 'server_status' => 'https://status.ppy.sh', 'smilies' => '/forum/images/smilies', + 'social.twitter' => '/wiki/Twitter', 'source_code' => 'https://github.com/ppy', + 'testflight.public' => env('TESTFLIGHT_LINK'), + 'testflight.supporter' => env('TESTFLIGHT_LINK_SUPPORTER'), + 'user.recover' => '/wiki/Help_centre/Account#sign-in', + 'user.restriction' => presence(env('OSU_URL_USER_RESTRICTION')) ?? '/wiki/Help_centre/Account_restrictions', + 'user.rules' => '/wiki/Osu!:Rules', 'youtube-tutorial-playlist' => 'PLmWVQsxi34bMYwAawZtzuptfMmszUa_tl', - - 'lazer_dl' => [ - 'android' => presence(env('OSU_URL_LAZER_ANDROID')) ?? 'https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk', - 'ios' => presence(env('OSU_URL_LAZER_IOS')) ?? '/home/testflight', - 'linux_x64' => presence(env('OSU_URL_LAZER_LINUX_X64')) ?? 'https://github.com/ppy/osu/releases/latest/download/osu.AppImage', - 'macos_as' => presence(env('OSU_URL_LAZER_MACOS_AS')) ?? 'https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip', - 'windows_x64' => presence(env('OSU_URL_LAZER_WINDOWS_X64')) ?? 'https://github.com/ppy/osu/releases/latest/download/install.exe', - ], - 'social' => [ - 'twitter' => '/wiki/Twitter', - ], - 'user' => [ - 'recover' => '/wiki/Help_centre/Account#sign-in', - 'restriction' => presence(env('OSU_URL_USER_RESTRICTION')) ?? '/wiki/Help_centre/Account_restrictions', - 'rules' => '/wiki/Osu!:Rules', - ], - 'testflight' => [ - 'public' => env('TESTFLIGHT_LINK'), - 'supporter' => env('TESTFLIGHT_LINK_SUPPORTER'), - ], ], 'user' => [ 'allow_email_login' => get_bool(env('USER_ALLOW_EMAIL_LOGIN')) ?? true, diff --git a/config/scribe.php b/config/scribe.php index 6bf080358dc..38ea83d10ad 100644 --- a/config/scribe.php +++ b/config/scribe.php @@ -5,7 +5,7 @@ return [ /* - * The HTML for the generated documentation. If this is empty, Scribe will infer it from config('app.name'). + * The HTML <title> for the generated documentation. If this is empty, Scribe will infer it from $GLOBALS['cfg']['app']['name']. */ 'title' => null, @@ -242,7 +242,7 @@ ], /* - * The base URL to be used in examples. If this is empty, Scribe will use the value of config('app.url'). + * The base URL to be used in examples. If this is empty, Scribe will use the value of $GLOBALS['cfg']['app']['url']. */ 'base_url' => null, @@ -351,7 +351,7 @@ * For response calls, api resource responses and transformer responses, Scribe will try to start database transactions, so no changes are persisted to your database. * Tell Scribe which connections should be transacted here. If you only use the default db connection, you can leave this as is. */ - 'database_connections_to_transact' => [config('database.default')], + 'database_connections_to_transact' => [], 'theme' => 'osu', 'try_it_out' => [ /** diff --git a/config/sentry.php b/config/sentry.php index 704997686ec..be0a835b7e8 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -1,10 +1,12 @@ <?php +$configOsu = include __DIR__.'/osu.php'; + return [ 'dsn' => env('APP_SENTRY'), // capture release as git sha - 'release' => config('osu.git-sha'), + 'release' => $configOsu['git-sha'], // When left empty or `null` the Laravel environment will be used 'environment' => env('APP_SENTRY_ENVIRONMENT'), diff --git a/database/factories/BeatmapMirrorFactory.php b/database/factories/BeatmapMirrorFactory.php index 86ed3daf5f8..37aa26dc9cb 100644 --- a/database/factories/BeatmapMirrorFactory.php +++ b/database/factories/BeatmapMirrorFactory.php @@ -16,7 +16,7 @@ class BeatmapMirrorFactory extends Factory public function default(): static { return $this->state([ - 'mirror_id' => config('osu.beatmap_processor.mirrors_to_use')[0], + 'mirror_id' => $GLOBALS['cfg']['osu']['beatmap_processor']['mirrors_to_use'][0], ]); } diff --git a/database/factories/BeatmapsetFactory.php b/database/factories/BeatmapsetFactory.php index c25f2b44840..f3ec0b08d21 100644 --- a/database/factories/BeatmapsetFactory.php +++ b/database/factories/BeatmapsetFactory.php @@ -105,7 +105,7 @@ public function withDiscussion() public function withNominations() { - $count = config('osu.beatmapset.required_nominations'); + $count = $GLOBALS['cfg']['osu']['beatmapset']['required_nominations']; return $this ->has(BeatmapsetNomination::factory() diff --git a/database/factories/BuildFactory.php b/database/factories/BuildFactory.php index 5ec1e3446e5..2bf74f338c1 100644 --- a/database/factories/BuildFactory.php +++ b/database/factories/BuildFactory.php @@ -17,7 +17,7 @@ public function definition(): array return [ 'date' => fn () => $this->faker->dateTimeBetween('-5 years'), 'hash' => fn () => md5($this->faker->word(), true), - 'stream_id' => fn () => array_rand_val(config('osu.changelog.update_streams')), + 'stream_id' => fn () => array_rand_val($GLOBALS['cfg']['osu']['changelog']['update_streams']), 'users' => rand(100, 10000), // the default depends on date diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index ce517ee827f..d930cc4d8d6 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -142,7 +142,7 @@ public function withNote() public function withPlays(?int $count = null, ?string $ruleset = 'osu'): static { $state = [ - 'playcount' => $count ?? config('osu.user.min_plays_for_posting'), + 'playcount' => $count ?? $GLOBALS['cfg']['osu']['user']['min_plays_for_posting'], ]; $ret = $this->has( diff --git a/database/seeders/ModelSeeders/ForumSeeder.php b/database/seeders/ModelSeeders/ForumSeeder.php index 6c39c36e7b6..e0de7854779 100644 --- a/database/seeders/ModelSeeders/ForumSeeder.php +++ b/database/seeders/ModelSeeders/ForumSeeder.php @@ -24,7 +24,7 @@ public function run(): void ->has( Forum::factory()->state([ 'forum_desc' => 'The place to go when you have a problem to report or a question to ask.', - 'forum_id' => config('osu.forum.help_forum_id'), + 'forum_id' => $GLOBALS['cfg']['osu']['forum']['help_forum_id'], 'forum_name' => 'Help', ]), 'subforums', @@ -32,7 +32,7 @@ public function run(): void ->has( Forum::factory()->state([ 'forum_desc' => 'Suggest what you would like to see in osu!.', - 'forum_id' => config('osu.forum.feature_forum_id'), + 'forum_id' => $GLOBALS['cfg']['osu']['forum']['feature_forum_id'], 'forum_name' => 'Feature Requests', ]), 'subforums', @@ -53,14 +53,14 @@ public function run(): void ->has( Forum::factory()->state([ 'forum_desc' => '', - 'forum_id' => config('osu.user.user_page_forum_id'), + 'forum_id' => $GLOBALS['cfg']['osu']['user']['user_page_forum_id'], 'forum_name' => 'User Pages', ]), 'subforums', ) ->create([ 'forum_desc' => '', - 'forum_id' => config('osu.forum.admin_forum_id'), + 'forum_id' => $GLOBALS['cfg']['osu']['forum']['admin_forum_id'], 'forum_name' => 'Management', ]); @@ -81,7 +81,7 @@ public function run(): void // Forums to be populated, i.e. all open forums except "User Pages" $forums = Forum::where('forum_type', 1) - ->where('forum_id', '<>', config('osu.user.user_page_forum_id')) + ->where('forum_id', '<>', $GLOBALS['cfg']['osu']['user']['user_page_forum_id']) ->get(); // Topics and posts diff --git a/resources/views/accounts/_edit_email.blade.php b/resources/views/accounts/_edit_email.blade.php index 9f84194691a..25c21fb501c 100644 --- a/resources/views/accounts/_edit_email.blade.php +++ b/resources/views/accounts/_edit_email.blade.php @@ -23,7 +23,7 @@ class="js-form-error js-form-clear js-account-edit account-edit" <div class="account-edit-entry account-edit-entry--no-label"> <div>{!! osu_trans('accounts.edit.email.locked._', [ 'accounts' => link_to( - 'mailto:'.config('osu.emails.account'), + "mailto:{$GLOBALS['cfg']['osu']['emails']['account']}", osu_trans('accounts.edit.email.locked.accounts') ) ]) !!}</div> diff --git a/resources/views/docs/auth.blade.php b/resources/views/docs/auth.blade.php index 8393390d6c7..aa4530d66e6 100644 --- a/resources/views/docs/auth.blade.php +++ b/resources/views/docs/auth.blade.php @@ -6,7 +6,7 @@ use App\Libraries\ApidocRouteHelper; use Knuckles\Camel\Output\OutputEndpointData; - $baseUrl = config('app.url'); + $baseUrl = $GLOBALS['cfg']['app']['url']; $wikiUrl = wiki_url('Bot_account', null, false); $defaultHeaders = [ @@ -428,14 +428,14 @@ <div class="bash-example"> <pre><code class="language-bash" ># With shell, you can just pass the correct header with each request -curl "{{ config('app.url') }}/api/[version]/[endpoint]" +curl "{{ $GLOBALS['cfg']['app']['url'] }}/api/[version]/[endpoint]" -H "Authorization: Bearer @{{token}}"</code><pre> </div> <div class="javascript-example"> <pre><code class="language-javascript" >// This javascript example uses fetch() -fetch("{{ config('app.url') }}/api/[version]/[endpoint]", { +fetch("{{ $GLOBALS['cfg']['app']['url'] }}/api/[version]/[endpoint]", { headers: { Authorization: 'Bearer @{{token}}' } diff --git a/resources/views/docs/endpoint.blade.php b/resources/views/docs/endpoint.blade.php index 845479d80aa..9e5ffd126b9 100644 --- a/resources/views/docs/endpoint.blade.php +++ b/resources/views/docs/endpoint.blade.php @@ -15,7 +15,7 @@ $isApiUri = substr($uri, 0, 6) === 'api/v2'; // either remove api/v2 prefix or add full url - $displayUri = $isApiUri ? substr($uri, 6) : config('app.url').$uri; + $displayUri = $isApiUri ? substr($uri, 6) : $GLOBALS['cfg']['app']['url'].$uri; $helper = ApidocRouteHelper::instance(); @endphp diff --git a/resources/views/docs/info.md.blade.php b/resources/views/docs/info.md.blade.php index 97c38cd9147..5a1ca0a9644 100644 --- a/resources/views/docs/info.md.blade.php +++ b/resources/views/docs/info.md.blade.php @@ -110,7 +110,7 @@ ## Base URL -The base URL is: `{{ config('app.url') }}/api/[version]/` +The base URL is: `{{ $GLOBALS['cfg']['app']['url'] }}/api/[version]/` ## API Versions diff --git a/resources/views/emails/_signature.blade.php b/resources/views/emails/_signature.blade.php index 193717f5810..c5f0b4990c4 100644 --- a/resources/views/emails/_signature.blade.php +++ b/resources/views/emails/_signature.blade.php @@ -3,4 +3,4 @@ See the LICENCE file in the repository root for full licence text. --}} -- -osu! | {{ config('app.url') }} +osu! | {{ $GLOBALS['cfg']['app']['url'] }} diff --git a/resources/views/forum/topics/_feature_vote.blade.php b/resources/views/forum/topics/_feature_vote.blade.php index 91932a1e681..636a933a65d 100644 --- a/resources/views/forum/topics/_feature_vote.blade.php +++ b/resources/views/forum/topics/_feature_vote.blade.php @@ -16,7 +16,7 @@ <div class=" forum-topic-feature-vote__votes - {{ $topic->osu_starpriority > config('osu.forum.feature_topic_small_star_min') ? 'forum-topic-feature-vote__votes--small' : '' }} + {{ $topic->osu_starpriority > $GLOBALS['cfg']['osu']['forum']['feature_topic_small_star_min'] ? 'forum-topic-feature-vote__votes--small' : '' }} " > @foreach ($featureVotes as $username => $votes) diff --git a/resources/views/home/_landing_locales.blade.php b/resources/views/home/_landing_locales.blade.php index f58436274a1..8c2b8bdde4b 100644 --- a/resources/views/home/_landing_locales.blade.php +++ b/resources/views/home/_landing_locales.blade.php @@ -18,7 +18,7 @@ class="js-menu landing-nav__locale-menu" data-menu-id="landing--locale" data-visibility="hidden" > - @foreach (config('app.available_locales') as $locale) + @foreach ($GLOBALS['cfg']['app']['available_locales'] as $locale) @php $localeMeta = locale_meta($locale); @endphp diff --git a/resources/views/home/_search_results.blade.php b/resources/views/home/_search_results.blade.php index f7777e042e3..9bc1955225a 100644 --- a/resources/views/home/_search_results.blade.php +++ b/resources/views/home/_search_results.blade.php @@ -41,7 +41,7 @@ class="search-result__row search-result__row--more" @else @if ($allSearch->getMode() === 'user' && $search->overLimit()) <div class="search-result__row search-result__row--notice"> - {{ osu_trans("home.search.user.more_hidden", ['max' => config("osu.search.max.user")]) }} + {{ osu_trans("home.search.user.more_hidden", ['max' => $GLOBALS['cfg']['osu']['search']['max']['user']]) }} </div> @endif <div class="search-result__row search-result__row--paginator"> diff --git a/resources/views/home/download.blade.php b/resources/views/home/download.blade.php index 185857232a4..cc4f02fc7f8 100644 --- a/resources/views/home/download.blade.php +++ b/resources/views/home/download.blade.php @@ -21,17 +21,17 @@ </div> <div> - <a class="btn-osu-big btn-osu-big--download" href="{{ config('osu.urls.installer') }}"> + <a class="btn-osu-big btn-osu-big--download" href="{{ osu_url('installer') }}"> <span class="btn-osu-big__text-top">{{ osu_trans('home.download.action') }}</span> <span class="btn-osu-big__text-bottom">{{ osu_trans('home.download.os.windows') }}</span> </a> <div class="download-page-header__extra-links"> - <a class="download-page-header__extra-link" href="{{ config('osu.urls.installer-mirror') }}"> + <a class="download-page-header__extra-link" href="{{ osu_url('installer-mirror') }}"> {{ osu_trans('home.download.mirror') }} </a> <span class="download-page-header__extra-link download-page-header__extra-link--separator"></span> - <a class="download-page-header__extra-link" href="{{ config('osu.urls.osx') }}"> + <a class="download-page-header__extra-link" href="{{ osu_url('osx') }}"> {{ osu_trans('home.download.macos-fallback') }} </a> </div> @@ -48,7 +48,7 @@ <div> {{ osu_trans('home.download.action_lazer_description') }} </div> - @if (($lazerInfoUrl = config('osu.urls.lazer_info')) !== null) + @if (($lazerInfoUrl = osu_url('lazer_info')) !== null) <a href="{{ $lazerInfoUrl }}"> {{ osu_trans('home.download.action_lazer_info') }} </a> @@ -69,7 +69,7 @@ class="btn-osu-big btn-osu-big--download btn-osu-big--download-lazer" </a> <div class="download-page-header__extra-links"> - <a class="download-page-header__extra-link" href="{{ config('osu.urls.lazer_dl_other') }}"> + <a class="download-page-header__extra-link" href="{{ osu_url('lazer_dl_other') }}"> {{ osu_trans('home.download.other_os') }} </a> </div> @@ -121,7 +121,7 @@ class="btn-osu-big btn-osu-big--download btn-osu-big--download-lazer" </div> </div> - @if (config('services.enchant.id') !== null) + @if ($GLOBALS['cfg']['services']['enchant']['id'] !== null) <div class="download-page__help"> {!! osu_trans('home.download.help._', [ 'support_button' => link_to( @@ -133,7 +133,7 @@ class="btn-osu-big btn-osu-big--download btn-osu-big--download-lazer" ], ), 'help_forum_link' => link_to( - route('forum.forums.show', ['forum' => config('osu.forum.help_forum_id')]), + route('forum.forums.show', ['forum' => $GLOBALS['cfg']['osu']['forum']['help_forum_id']]), osu_trans('home.download.help.help_forum_link') ) ]) !!} @@ -150,7 +150,7 @@ class="btn-osu-big btn-osu-big--download btn-osu-big--download-lazer" </h2> <iframe class="u-embed-wide" - src="https://youtube.com/embed/videoseries?list={{ config('osu.urls.youtube-tutorial-playlist') }}" + src="https://youtube.com/embed/videoseries?list={{ $GLOBALS['cfg']['osu']['urls']['youtube-tutorial-playlist'] }}" ></iframe> </div> </div> diff --git a/resources/views/home/landing.blade.php b/resources/views/home/landing.blade.php index 561301a868f..593d61eac3d 100644 --- a/resources/views/home/landing.blade.php +++ b/resources/views/home/landing.blade.php @@ -62,7 +62,7 @@ class="landing-hero__bg" loop muted playsinline - src="{{ config('osu.landing.video_url') }}" + src="{{ $GLOBALS['cfg']['osu']['landing']['video_url'] }}" ></video> </div> @@ -145,7 +145,7 @@ class="landing-hero__bg" <a href="{{ route('support-the-game') }}" class="landing-footer-social__icon landing-footer-social__icon--support"> <span class="fas fa-heart"></span> </a> - <a href="{{ osu_url("social.twitter") }}" class="landing-footer-social__icon landing-footer-social__icon--twitter"> + <a href="{{ osu_url('social.twitter') }}" class="landing-footer-social__icon landing-footer-social__icon--twitter"> <span class="fab fa-twitter"></span> </a> </div> diff --git a/resources/views/home/opensearch.blade.php b/resources/views/home/opensearch.blade.php index 81e7a12b1cb..1468fc0b93e 100644 --- a/resources/views/home/opensearch.blade.php +++ b/resources/views/home/opensearch.blade.php @@ -3,7 +3,7 @@ See the LICENCE file in the repository root for full licence text. --}} @php - $appUrl = config('app.url'); + $appUrl = $GLOBALS['cfg']['app']['url']; $searchUrl = route('search'); @endphp <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/"> diff --git a/resources/views/home/testflight.blade.php b/resources/views/home/testflight.blade.php index 428e5177dfd..a8eec73a25f 100644 --- a/resources/views/home/testflight.blade.php +++ b/resources/views/home/testflight.blade.php @@ -4,26 +4,31 @@ --}} @extends('master') +@php + $user = Auth::user(); + $isSupporter = $user?->isSupporter() ?? false; + $url = $isSupporter + ? osu_url('testflight.supporter') + : osu_url('testflight.public'); +@endphp @section('content') @include('layout._page_header_v4', ['params' => [ 'theme' => 'home', ]]) <div class="osu-page osu-page--generic"> - @if (Auth::user() && Auth::user()->isSupporter()) - <p> + <p> + @if ($isSupporter) This is a private link for osu!supporters. <strong>Please do not share it.</strong><br /> If you want to share access to the iOS beta with other users, link them to <a href="{{route('testflight')}}">this page</a> instead. - </p> - <center><a href="{{config('osu.urls.testflight.supporter')}}" rel="nofollow noreferrer">{{config('osu.urls.testflight.supporter')}}</a></center> - @else - <p> + @else Note that we may reset this link every few months to allow new users to test.<br/> (because Apple has a limit on how many testers can be added)<br/> - @if (!Auth::user()) + @if ($user === null) If you are an osu!supporter, please login for a more permanent link. @endif - </p> - <center><a href="{{config('osu.urls.testflight.public')}}" rel="nofollow noreferrer">{{config('osu.urls.testflight.public')}}</a></center> - @endif + @endif + </p> + + <center><a href="{{ $url }}" rel="nofollow noreferrer">{{ $url }}</a></center> </div> @endsection diff --git a/resources/views/layout/header_mobile/_locales.blade.php b/resources/views/layout/header_mobile/_locales.blade.php index 1f29cd129ca..9f5715111b1 100644 --- a/resources/views/layout/header_mobile/_locales.blade.php +++ b/resources/views/layout/header_mobile/_locales.blade.php @@ -26,7 +26,7 @@ class="navbar-mobile-item__main js-click-menu" </button> <ul class="navbar-mobile-item__submenu js-click-menu" data-click-menu-id="nav-mobile-locale"> - @foreach (config('app.available_locales') as $locale) + @foreach ($GLOBALS['cfg']['app']['available_locales'] as $locale) @php $localeMeta = locale_meta($locale); @endphp diff --git a/resources/views/layout/metadata.blade.php b/resources/views/layout/metadata.blade.php index ef0937c3d7e..44e67b556ab 100644 --- a/resources/views/layout/metadata.blade.php +++ b/resources/views/layout/metadata.blade.php @@ -3,9 +3,9 @@ See the LICENCE file in the repository root for full licence text. --}} @php - $appUrl = config('app.url'); + $appUrl = $GLOBALS['cfg']['app']['url']; $currentLocale = App::getLocale(); - $fallbackLocale = config('app.fallback_locale'); + $fallbackLocale = $GLOBALS['cfg']['app']['fallback_locale']; $opengraph = Request::instance()->attributes->get('opengraph'); $opengraph['description'] ??= $pageDescription ?? null; @@ -23,7 +23,7 @@ <meta name="keywords" content="osu, peppy, ouendan, elite, beat, agents, ds, windows, game, taiko, tatsujin, simulator, sim, xna, ddr, beatmania, osu!, osume"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> -<link rel="search" type="application/opensearchdescription+xml" title="osu! search" href="{{ config('app.url') }}/opensearch.xml"> +<link rel="search" type="application/opensearchdescription+xml" title="osu! search" href="{{ $appUrl }}/opensearch.xml"> <meta property="og:site_name" content="osu!"> <meta property="og:type" content="website"> @@ -89,18 +89,18 @@ <script> var currentLocale = {!! json_encode($currentLocale) !!}; var fallbackLocale = {!! json_encode($fallbackLocale) !!}; - var experimentalHost = {!! json_encode(config('osu.urls.experimental_host')) !!} + var experimentalHost = {!! json_encode(osu_url('experimental_host')) !!} </script> <script src="{{ unmix('js/runtime.js') }}" data-turbolinks-track="reload"></script> <script src="{{ unmix('js/vendor.js') }}" data-turbolinks-track="reload"></script> -@if(config('services.sentry.public_dsn') !== '') +@if($GLOBALS['cfg']['services']['sentry']['public_dsn'] !== '') <script src="https://browser.sentry-cdn.com/5.1.0/bundle.min.js" crossorigin="anonymous"></script> <script> typeof Sentry !== 'undefined' && Sentry.init({ - debug: {!! json_encode(config('app.debug')) !!}, - dsn: {!! json_encode(config('services.sentry.public_dsn')) !!}, + debug: {!! json_encode($GLOBALS['cfg']['app']['debug']) !!}, + dsn: {!! json_encode($GLOBALS['cfg']['services']['sentry']['public_dsn']) !!}, ignoreErrors: [ // Random plugins/extensions 'top.GLOBALS', @@ -114,7 +114,7 @@ // Errors caused by spyware/adware junk /^\/loaders\//i ], - release: {!! json_encode(config('osu.git-sha')) !!}, + release: {!! json_encode($GLOBALS['cfg']['osu']['git-sha']) !!}, whitelistUrls: [/^{!! preg_quote($appUrl, '/') !!}\/.*\.js(?:\?.*)?$/], }); </script> diff --git a/resources/views/layout/nav2/_locales.blade.php b/resources/views/layout/nav2/_locales.blade.php index 6ebe3cd5110..da75bbf895b 100644 --- a/resources/views/layout/nav2/_locales.blade.php +++ b/resources/views/layout/nav2/_locales.blade.php @@ -19,7 +19,7 @@ class="simple-menu simple-menu--nav2 simple-menu--nav2-locales js-click-menu js- data-visibility="hidden" > <div class="simple-menu__content"> - @foreach (config('app.available_locales') as $locale) + @foreach ($GLOBALS['cfg']['app']['available_locales'] as $locale) @php $localeMeta = locale_meta($locale); @endphp diff --git a/resources/views/master.blade.php b/resources/views/master.blade.php index d27b7e3cd4c..a16912d30f9 100644 --- a/resources/views/master.blade.php +++ b/resources/views/master.blade.php @@ -71,7 +71,7 @@ class=" 'title' => osu_trans('users.restricted_banner.title'), 'message' => osu_trans('users.restricted_banner.message', [ 'link' => link_to( - config('osu.urls.user.restriction'), + osu_url('user.restriction'), osu_trans('users.restricted_banner.message_link') ), ]), @@ -109,7 +109,7 @@ class="js-permanent-fixed-footer > @yield('permanent-fixed-footer') - @if (config('osu.is_development_deploy')) + @if ($GLOBALS['cfg']['osu']['is_development_deploy']) <div class="development-deploy-footer"> This is a development instance of the <a href="https://osu.ppy.sh" class="development-deploy-footer__link">osu! website</a>. Please do not login with your osu! credentials. </div> diff --git a/resources/views/news/index-atom.blade.php b/resources/views/news/index-atom.blade.php index 7a10ebfaea5..6814f15984c 100644 --- a/resources/views/news/index-atom.blade.php +++ b/resources/views/news/index-atom.blade.php @@ -11,7 +11,7 @@ <link rel="self" type="application/atom+xml" href="{{ request()->fullUrl() }}" /> <title>osu!news - {{ config('app.url') }}/apple-touch-icon.png + {{ $GLOBALS['cfg']['app']['url'] }}/apple-touch-icon.png {{ json_time(optional($posts->last())->published_at ?? now()) }} diff --git a/resources/views/objects/_captcha_script.blade.php b/resources/views/objects/_captcha_script.blade.php index b94189ed4f2..99581131560 100644 --- a/resources/views/objects/_captcha_script.blade.php +++ b/resources/views/objects/_captcha_script.blade.php @@ -8,5 +8,5 @@ --}} diff --git a/resources/views/objects/_enchant.blade.php b/resources/views/objects/_enchant.blade.php index 170fe0a7b56..94ca0e9688d 100644 --- a/resources/views/objects/_enchant.blade.php +++ b/resources/views/objects/_enchant.blade.php @@ -2,6 +2,6 @@ Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. See the LICENCE file in the repository root for full licence text. --}} -@if (config('services.enchant.id') !== null) -
+@if ($GLOBALS['cfg']['services']['enchant']['id'] !== null) +
@endif diff --git a/resources/views/password_reset/index.blade.php b/resources/views/password_reset/index.blade.php index 19f8398657d..d114b721e19 100644 --- a/resources/views/password_reset/index.blade.php +++ b/resources/views/password_reset/index.blade.php @@ -32,7 +32,7 @@ class="password-reset js-form-error" - @if (config('services.enchant.id') !== null) + @if ($GLOBALS['cfg']['services']['enchant']['id'] !== null)
{!! osu_trans('password_reset.starting.support._', ['button' => link_to( '#', diff --git a/resources/views/store/header.blade.php b/resources/views/store/header.blade.php index c52bd61b6be..ce3302700d9 100644 --- a/resources/views/store/header.blade.php +++ b/resources/views/store/header.blade.php @@ -78,13 +78,13 @@ @endcomponent
- @if (config('osu.store.notice') !== null) + @if ($GLOBALS['cfg']['osu']['store']['notice'] !== null)

{{ osu_trans('common.title.notice') }}

- {!! markdown(config('osu.store.notice')) !!} + {!! markdown($GLOBALS['cfg']['osu']['store']['notice']) !!}
@endif diff --git a/resources/views/store/layout.blade.php b/resources/views/store/layout.blade.php index 888d1994c67..1e8aa55d577 100644 --- a/resources/views/store/layout.blade.php +++ b/resources/views/store/layout.blade.php @@ -7,8 +7,8 @@ @section('script') diff --git a/resources/views/users/_verify_box.blade.php b/resources/views/users/_verify_box.blade.php index 82dae27fd4d..aa514e44794 100644 --- a/resources/views/users/_verify_box.blade.php +++ b/resources/views/users/_verify_box.blade.php @@ -13,7 +13,7 @@
diff --git a/resources/views/users/disabled.blade.php b/resources/views/users/disabled.blade.php index fa29755b226..4f99d2f3bec 100644 --- a/resources/views/users/disabled.blade.php +++ b/resources/views/users/disabled.blade.php @@ -39,7 +39,7 @@

{!! osu_trans('users.disabled.if_mistake._', [ 'email' => link_to( - 'mailto:'.config('osu.emails.account'), + "mailto:{$GLOBALS['cfg']['osu']['emails']['account']}", osu_trans('users.disabled.if_mistake.email')) ]) !!}

diff --git a/resources/views/wiki/_notice.blade.php b/resources/views/wiki/_notice.blade.php index f7ba57e4028..bc69a8930eb 100644 --- a/resources/views/wiki/_notice.blade.php +++ b/resources/views/wiki/_notice.blade.php @@ -11,7 +11,7 @@ @if ($page->isLegalTranslation())
{!! osu_trans('wiki.show.translation.legal', [ - 'default' => ''.e(osu_trans('wiki.show.translation.default')).'', + 'default' => ''.e(osu_trans('wiki.show.translation.default')).'', ]) !!}
@endif @@ -19,7 +19,7 @@ @if ($page->isOutdatedTranslation())
{!! osu_trans('wiki.show.translation.outdated', [ - 'default' => ''.e(osu_trans('wiki.show.translation.default')).'', + 'default' => ''.e(osu_trans('wiki.show.translation.default')).'', ]) !!}
@endif diff --git a/resources/views/wiki/_sitemap_section.blade.php b/resources/views/wiki/_sitemap_section.blade.php index eb7467c3785..fd77e06f3eb 100644 --- a/resources/views/wiki/_sitemap_section.blade.php +++ b/resources/views/wiki/_sitemap_section.blade.php @@ -8,7 +8,7 @@ @php $currentSection = concat_path([$section ?? null, $childSection]); $title = $titles["{$locale}/{$currentSection}"] - ?? $titles[config('app.fallback_locale').'/'.$currentSection] + ?? $titles[$GLOBALS['cfg']['app']['fallback_locale'].'/'.$currentSection] ?? null; @endphp diff --git a/resources/views/wiki/sitemap.blade.php b/resources/views/wiki/sitemap.blade.php index 07775e7e4ed..ce96772e63a 100644 --- a/resources/views/wiki/sitemap.blade.php +++ b/resources/views/wiki/sitemap.blade.php @@ -5,7 +5,7 @@ @php $urlFn = fn (string $locale): string => route('wiki.sitemap', compact('locale')); $sitemapUrl = $urlFn($locale); - $availableLocales = new Ds\Set(config('app.available_locales')); + $availableLocales = new Ds\Set($GLOBALS['cfg']['app']['available_locales']); @endphp @extends('wiki.layout', [ diff --git a/routes/web.php b/routes/web.php index f91342a5d7b..cdf21216f54 100644 --- a/routes/web.php +++ b/routes/web.php @@ -378,7 +378,7 @@ route_redirect('/', 'home'); - if (config('osu.scores.rank_cache.local_server')) { + if ($GLOBALS['cfg']['osu']['scores']['rank_cache']['local_server']) { Route::get('rankLookup', 'ScoresController@userRankLookup'); } diff --git a/tests/BeatmapsetEventNominationResetTest.php b/tests/BeatmapsetEventNominationResetTest.php index 6cde9fc78f8..eaecba4bab5 100644 --- a/tests/BeatmapsetEventNominationResetTest.php +++ b/tests/BeatmapsetEventNominationResetTest.php @@ -64,7 +64,7 @@ public function testInterOpDisqualify() { $this->createBeatmapsetWithNominators('qualified'); $banchoBotUser = User::factory()->create([ - 'user_id' => config('osu.legacy.bancho_bot_user_id'), + 'user_id' => $GLOBALS['cfg']['osu']['legacy']['bancho_bot_user_id'], ]); $disqualifyCount = BeatmapsetEvent::disqualifications()->count(); @@ -103,7 +103,7 @@ protected function setUp(): void { parent::setUp(); - config()->set('osu.beatmapset.required_nominations', 2); + config_set('osu.beatmapset.required_nominations', 2); Queue::fake(); @@ -115,7 +115,7 @@ private function createBeatmapsetWithNominators($state) $this->beatmapset = Beatmapset::factory()->owner()->$state()->withDiscussion()->create(); $modes = $this->beatmapset->beatmaps->map->mode->all(); - $nominatorCount = config('osu.beatmapset.required_nominations'); + $nominatorCount = $GLOBALS['cfg']['osu']['beatmapset']['required_nominations']; $this->nominators = []; diff --git a/tests/Browser/SanityTest.php b/tests/Browser/SanityTest.php index 6b3bfc836b4..8f987d22a16 100644 --- a/tests/Browser/SanityTest.php +++ b/tests/Browser/SanityTest.php @@ -193,7 +193,7 @@ private static function createScaffolding() // satisfy minimum playcount for forum posting UserStatistics\Osu::factory()->create([ - 'playcount' => config('osu.forum.minimum_plays'), + 'playcount' => $GLOBALS['cfg']['osu']['forum']['minimum_plays'], 'user_id' => self::$scaffolding['user'], ]); @@ -258,7 +258,7 @@ private static function createScaffolding() private static function filterLog(array $log) { - $appUrl = config('app.url'); + $appUrl = $GLOBALS['cfg']['app']['url']; $return = []; foreach ($log as $line) { @@ -474,7 +474,7 @@ private function bindParams(LaravelRoute $route) } } - $url = str_replace(config('app.url'), '', route($route->getName(), $params)); + $url = str_replace($GLOBALS['cfg']['app']['url'], '', route($route->getName(), $params)); return $url; } diff --git a/tests/Commands/ModdingRankCommandTest.php b/tests/Commands/ModdingRankCommandTest.php index 2aa7ad92f74..be85bfe995a 100644 --- a/tests/Commands/ModdingRankCommandTest.php +++ b/tests/Commands/ModdingRankCommandTest.php @@ -135,8 +135,8 @@ protected function setUp(): void { parent::setUp(); - config()->set('osu.beatmapset.minimum_days_for_rank', 1); - config()->set('osu.beatmapset.rank_per_day', 2); + config_set('osu.beatmapset.minimum_days_for_rank', 1); + config_set('osu.beatmapset.rank_per_day', 2); Bus::fake([BeatmapsetRank::class, CheckBeatmapsetCovers::class]); } diff --git a/tests/Commands/OAuthDeleteExpiredTokensTest.php b/tests/Commands/OAuthDeleteExpiredTokensTest.php index fc0a5426f7b..2567d489611 100644 --- a/tests/Commands/OAuthDeleteExpiredTokensTest.php +++ b/tests/Commands/OAuthDeleteExpiredTokensTest.php @@ -14,7 +14,7 @@ class OAuthDeleteExpiredTokensTest extends TestCase { public function testDeleteAccessTokens() { - config()->set('osu.oauth.retain_expired_tokens_days', 0); + config_set('osu.oauth.retain_expired_tokens_days', 0); $user = User::factory()->create(); $tokenAttributes = [ diff --git a/tests/Controllers/CommentsControllerTest.php b/tests/Controllers/CommentsControllerTest.php index e7a9e9bd281..c3efd249999 100644 --- a/tests/Controllers/CommentsControllerTest.php +++ b/tests/Controllers/CommentsControllerTest.php @@ -314,8 +314,8 @@ public static function pinPermissionsDataProvider(): array private function prepareForStore() { - config()->set('osu.user.post_action_verification', false); - $this->minPlays = config('osu.user.min_plays_for_posting'); + config_set('osu.user.post_action_verification', false); + $this->minPlays = $GLOBALS['cfg']['osu']['user']['min_plays_for_posting']; $this->user = User::factory()->withPlays()->create(); diff --git a/tests/Controllers/ForumTopicsControllerTest.php b/tests/Controllers/ForumTopicsControllerTest.php index 4ea9b0f18e1..594fc67823f 100644 --- a/tests/Controllers/ForumTopicsControllerTest.php +++ b/tests/Controllers/ForumTopicsControllerTest.php @@ -84,7 +84,7 @@ public function testPin(): void public function testReply(): void { $topic = Topic::factory()->create(); - $user = User::factory()->withPlays(config('osu.forum.minimum_plays'))->create(); + $user = User::factory()->withPlays($GLOBALS['cfg']['osu']['forum']['minimum_plays'])->create(); Authorize::factory()->reply()->create([ 'forum_id' => $topic->forum_id, 'group_id' => app('groups')->byIdentifier('default'), @@ -204,7 +204,7 @@ public function testShowNewUser(): void public function testStore(): void { $forum = Forum::factory()->create(); - $user = User::factory()->withPlays(config('osu.forum.minimum_plays'))->create(); + $user = User::factory()->withPlays($GLOBALS['cfg']['osu']['forum']['minimum_plays'])->create(); Authorize::factory()->post()->create([ 'forum_id' => $forum, 'group_id' => app('groups')->byIdentifier('default'), diff --git a/tests/Controllers/InterOp/BeatmapsetsControllerTest.php b/tests/Controllers/InterOp/BeatmapsetsControllerTest.php index db70673447f..462d79f3b46 100644 --- a/tests/Controllers/InterOp/BeatmapsetsControllerTest.php +++ b/tests/Controllers/InterOp/BeatmapsetsControllerTest.php @@ -65,7 +65,7 @@ public function testDestroy() ]); $banchoBotUser = User::factory()->create(); - config()->set('osu.legacy.bancho_bot_user_id', $banchoBotUser->getKey()); + config_set('osu.legacy.bancho_bot_user_id', $banchoBotUser->getKey()); $url = route('interop.beatmapsets.destroy', [ 'beatmapset' => $beatmapset->getKey(), diff --git a/tests/Controllers/Passport/AuthorizationControllerTest.php b/tests/Controllers/Passport/AuthorizationControllerTest.php index 43f890f5820..d4172320278 100644 --- a/tests/Controllers/Passport/AuthorizationControllerTest.php +++ b/tests/Controllers/Passport/AuthorizationControllerTest.php @@ -23,7 +23,7 @@ public function testAuthorizeNormalizes() $client = Client::factory()->create(); $request = (new Psr17Factory()) - ->createServerRequest('GET', config('app.url').'/oauth/authorize') + ->createServerRequest('GET', $GLOBALS['cfg']['app']['url'].'/oauth/authorize') ->withQueryParams(['client_id' => $client->getKey(), 'scope' => 'one two three']); $actual = $this->invokeMethod($this->controller, 'normalizeRequestScopes', [$request])->getQueryParams()['scope']; diff --git a/tests/Controllers/Payments/CentiliControllerTest.php b/tests/Controllers/Payments/CentiliControllerTest.php index 919cde747fb..5de778337b7 100644 --- a/tests/Controllers/Payments/CentiliControllerTest.php +++ b/tests/Controllers/Payments/CentiliControllerTest.php @@ -8,7 +8,6 @@ use App\Libraries\Payments\CentiliSignature; use App\Models\Store\Order; use App\Models\Store\OrderItem; -use Config; use Tests\TestCase; class CentiliControllerTest extends TestCase @@ -44,9 +43,9 @@ public function testWhenPaymentIsInsufficient() protected function setUp(): void { parent::setUp(); - Config::set('payments.centili.secret_key', 'secret_key'); - Config::set('payments.centili.api_key', 'api_key'); - Config::set('payments.centili.conversion_rate', 120.00); + config_set('payments.centili.secret_key', 'secret_key'); + config_set('payments.centili.api_key', 'api_key'); + config_set('payments.centili.conversion_rate', 120.00); $this->order = Order::factory()->checkout()->create(); } @@ -55,13 +54,13 @@ private function getPostData(array $overrides = []) $base = [ 'reference' => $this->order->getOrderNumber(), 'country' => 'jp', - 'enduserprice' => $this->order->getTotal() * config('payments.centili.conversion_rate'), + 'enduserprice' => $this->order->getTotal() * $GLOBALS['cfg']['payments']['centili']['conversion_rate'], 'event_type' => 'one_off', 'mnocode' => 'BADDOG', 'phone' => 'test@example.org', 'revenue' => '4.34', 'revenuecurrency' => 'MONOPOLY', - 'service' => config('payments.centili.api_key'), + 'service' => $GLOBALS['cfg']['payments']['centili']['api_key'], 'status' => 'success', 'transactionid' => '111222333', ]; diff --git a/tests/Controllers/Payments/ShopifyControllerTest.php b/tests/Controllers/Payments/ShopifyControllerTest.php index 9d611a5ebde..e01fc3b4db3 100644 --- a/tests/Controllers/Payments/ShopifyControllerTest.php +++ b/tests/Controllers/Payments/ShopifyControllerTest.php @@ -123,7 +123,7 @@ public function testReplacementOrdersCreatedByDuplicatingShopifyOrderShouldBeIgn protected function setUp(): void { parent::setUp(); - config()->set('payments.shopify.webhook_key', 'magic'); + config_set('payments.shopify.webhook_key', 'magic'); $this->url = route('payments.shopify.callback'); } diff --git a/tests/Controllers/Payments/XsollaControllerTest.php b/tests/Controllers/Payments/XsollaControllerTest.php index 7ef0e2e762a..7bfafc53dbc 100644 --- a/tests/Controllers/Payments/XsollaControllerTest.php +++ b/tests/Controllers/Payments/XsollaControllerTest.php @@ -7,7 +7,6 @@ use App\Libraries\Payments\XsollaSignature; use App\Models\Store\Order; -use Config; use Tests\TestCase; class XsollaControllerTest extends TestCase @@ -65,7 +64,7 @@ public function testValidationSignatureNotMatch() protected function setUp(): void { parent::setUp(); - Config::set('payments.xsolla.secret_key', 'magic'); + config_set('payments.xsolla.secret_key', 'magic'); $this->order = Order::factory()->checkout()->create(); } diff --git a/tests/Controllers/ScorePinsControllerTest.php b/tests/Controllers/ScorePinsControllerTest.php index c29eebc6fe2..3b4b043e28f 100644 --- a/tests/Controllers/ScorePinsControllerTest.php +++ b/tests/Controllers/ScorePinsControllerTest.php @@ -245,7 +245,7 @@ public function testStoreInvalidScoreMode() public function testStoreLimit() { - config()->set('osu.user.max_score_pins', 1); + config_set('osu.user.max_score_pins', 1); $user = User::factory()->create([ 'osu_subscriber' => false, @@ -267,7 +267,7 @@ public function testStoreLimit() public function testStoreLimitDifferentMode() { - config()->set('osu.user.max_score_pins', 1); + config_set('osu.user.max_score_pins', 1); $user = User::factory()->create([ 'osu_subscriber' => false, diff --git a/tests/Controllers/ScoresControllerTest.php b/tests/Controllers/ScoresControllerTest.php index 3e4efdf0910..ec4a585a24f 100644 --- a/tests/Controllers/ScoresControllerTest.php +++ b/tests/Controllers/ScoresControllerTest.php @@ -22,7 +22,7 @@ public function testDownload() { $this ->actingAs($this->user) - ->withHeaders(['HTTP_REFERER' => config('app.url').'/']) + ->withHeaders(['HTTP_REFERER' => $GLOBALS['cfg']['app']['url'].'/']) ->json( 'GET', route('scores.download-legacy', $this->params()) @@ -41,7 +41,7 @@ public function testDownloadSoloScore() $this ->actingAs($this->user) - ->withHeaders(['HTTP_REFERER' => config('app.url').'/']) + ->withHeaders(['HTTP_REFERER' => $GLOBALS['cfg']['app']['url'].'/']) ->json( 'GET', route('scores.download', $soloScore) @@ -55,7 +55,7 @@ public function testDownloadDeletedBeatmap() $this ->actingAs($this->user) - ->withHeaders(['HTTP_REFERER' => config('app.url').'/']) + ->withHeaders(['HTTP_REFERER' => $GLOBALS['cfg']['app']['url'].'/']) ->get(route('scores.download-legacy', $this->params())) ->assertSuccessful(); } @@ -66,7 +66,7 @@ public function testDownloadMissingBeatmap() $this ->actingAs($this->user) - ->withHeaders(['HTTP_REFERER' => config('app.url').'/']) + ->withHeaders(['HTTP_REFERER' => $GLOBALS['cfg']['app']['url'].'/']) ->get(route('scores.download-legacy', $this->params())) ->assertStatus(422); } @@ -77,7 +77,7 @@ public function testDownloadMissingUser() $this ->actingAs($this->user) - ->withHeaders(['HTTP_REFERER' => config('app.url').'/']) + ->withHeaders(['HTTP_REFERER' => $GLOBALS['cfg']['app']['url'].'/']) ->get(route('scores.download-legacy', $this->params())) ->assertStatus(422); } @@ -94,7 +94,7 @@ public function testDownloadInvalidReferer() $this ->actingAs($this->user) - ->withHeaders(['HTTP_REFERER' => rtrim(config('app.url'), '/').'.example.com']) + ->withHeaders(['HTTP_REFERER' => rtrim($GLOBALS['cfg']['app']['url'], '/').'.example.com']) ->json( 'GET', route('scores.download-legacy', $this->params()) @@ -119,8 +119,8 @@ protected function setUp(): void // fake all the replay disks $disks = []; - foreach (array_keys(config('filesystems.disks.replays')) as $key) { - foreach (array_keys(config("filesystems.disks.replays.{$key}")) as $type) { + foreach (array_keys($GLOBALS['cfg']['filesystems']['disks']['replays']) as $key) { + foreach (array_keys($GLOBALS['cfg']['filesystems']['disks']['replays'][$key]) as $type) { $disk = "replays.{$key}.{$type}"; $disks[] = $disk; Storage::fake($disk); diff --git a/tests/Controllers/SessionsControllerTest.php b/tests/Controllers/SessionsControllerTest.php index c8925bf52ba..29000ee7f21 100644 --- a/tests/Controllers/SessionsControllerTest.php +++ b/tests/Controllers/SessionsControllerTest.php @@ -30,7 +30,7 @@ public function testLoginInactiveUser() $password = 'password1'; $countryAcronym = (Country::first() ?? Country::factory()->create())->getKey(); $user = User::factory()->create(['password' => $password, 'country_acronym' => $countryAcronym]); - $user->update(['user_lastvisit' => time() - config('osu.user.inactive_seconds_verification') - 1]); + $user->update(['user_lastvisit' => time() - $GLOBALS['cfg']['osu']['user']['inactive_seconds_verification'] - 1]); $this->post(route('login'), [ 'username' => $user->username, @@ -48,7 +48,7 @@ public function testLoginInactiveUserDifferentCountry() { $password = 'password1'; $user = User::factory()->create(compact('password')); - $user->update(['user_lastvisit' => time() - config('osu.user.inactive_seconds_verification') - 1]); + $user->update(['user_lastvisit' => time() - $GLOBALS['cfg']['osu']['user']['inactive_seconds_verification'] - 1]); $this->assertNotSame('', $user->fresh()->user_password); diff --git a/tests/Controllers/UsersControllerTest.php b/tests/Controllers/UsersControllerTest.php index b436451cce7..43670ca2d38 100644 --- a/tests/Controllers/UsersControllerTest.php +++ b/tests/Controllers/UsersControllerTest.php @@ -41,7 +41,7 @@ public function testStore() 'password' => 'hunter22', ], ], [ - 'HTTP_USER_AGENT' => config('osu.client.user_agent'), + 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], ])->assertJsonFragment([ 'username' => 'user1', 'country_code' => Country::UNKNOWN, @@ -52,7 +52,7 @@ public function testStore() public function testStoreRegModeWeb() { - config()->set('osu.user.registration_mode', 'web'); + config_set('osu.user.registration_mode', 'web'); $this->expectCountChange(fn () => User::count(), 0); $this @@ -63,7 +63,7 @@ public function testStoreRegModeWeb() 'password' => 'hunter22', ], ], [ - 'HTTP_USER_AGENT' => config('osu.client.user_agent'), + 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], ])->assertStatus(403) ->assertJsonFragment([ 'error' => osu_trans('users.store.from_web'), @@ -86,7 +86,7 @@ public function testStoreDryRunValid() 'password' => 'hunter22', ], ], [ - 'HTTP_USER_AGENT' => config('osu.client.user_agent'), + 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], ])->assertSuccessful(); $this->assertSame($previousCount, User::count()); @@ -108,7 +108,7 @@ public function testStoreInvalid() 'password' => 'hunter22', ], ], [ - 'HTTP_USER_AGENT' => config('osu.client.user_agent'), + 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], ])->assertStatus(422) ->assertJsonFragment([ 'form_error' => ['user' => ['username' => ['Username is required.']]], @@ -122,7 +122,7 @@ public function testStoreInvalid() 'password' => 'hunter22', ], ], [ - 'HTTP_USER_AGENT' => config('osu.client.user_agent'), + 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], ])->assertStatus(422) ->assertJsonFragment([ 'form_error' => ['user' => ['username' => ['Username is required.']]], @@ -149,7 +149,7 @@ public function testStoreWebRegModeClient() public function testStoreWeb(): void { - config()->set('osu.user.registration_mode', 'web'); + config_set('osu.user.registration_mode', 'web'); $this->expectCountChange(fn () => User::count(), 1); $this->post(route('users.store-web'), [ @@ -168,7 +168,7 @@ public function testStoreWeb(): void */ public function testStoreWebInvalidParams($username, $email, $emailConfirmation, $password, $passwordConfirmation): void { - config()->set('osu.user.registration_mode', 'web'); + config_set('osu.user.registration_mode', 'web'); $this->expectCountChange(fn () => User::count(), 0); $this->post(route('users.store-web'), [ @@ -184,7 +184,7 @@ public function testStoreWebInvalidParams($username, $email, $emailConfirmation, public function testStoreWebLoggedIn(): void { - config()->set('osu.user.registration_mode', 'web'); + config_set('osu.user.registration_mode', 'web'); $user = User::factory()->create(); $this->expectCountChange(fn () => User::count(), 0); @@ -214,7 +214,7 @@ public function testStoreWithCountry() 'password' => 'hunter22', ], ], [ - 'HTTP_USER_AGENT' => config('osu.client.user_agent'), + 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], 'HTTP_CF_IPCOUNTRY' => $country->getKey(), ])->assertJsonFragment([ 'username' => 'user1', @@ -245,7 +245,7 @@ public function testStoreLoggedIn() 'password' => 'hunter22', ], ], [ - 'HTTP_USER_AGENT' => config('osu.client.user_agent'), + 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], ])->assertStatus(302); $this->assertSame($previousCount, User::count()); diff --git a/tests/Jobs/UpdateUserForumTopicFollowsTest.php b/tests/Jobs/UpdateUserForumTopicFollowsTest.php index 5d47fe5cefb..200e8ec3ec8 100644 --- a/tests/Jobs/UpdateUserForumTopicFollowsTest.php +++ b/tests/Jobs/UpdateUserForumTopicFollowsTest.php @@ -20,7 +20,7 @@ class UpdateUserForumTopicFollowsTest extends TestCase public function testRemoveUserWithNoWatchPermission(): void { $adminForum = Forum::factory()->create(); - config()->set('osu.forum.admin_forum_id', $adminForum->getKey()); + config_set('osu.forum.admin_forum_id', $adminForum->getKey()); $normalForum = Forum::factory()->create(); $topic = Topic::factory()->create(); $user = User::factory()->create(); diff --git a/tests/Libraries/BBCodeForDBTest.php b/tests/Libraries/BBCodeForDBTest.php index 7921906aabf..1ef31ae2cf9 100644 --- a/tests/Libraries/BBCodeForDBTest.php +++ b/tests/Libraries/BBCodeForDBTest.php @@ -81,6 +81,6 @@ protected function setUp(): void { parent::setUp(); - config()->set('osu.bbcode.uid', '1'); + config_set('osu.bbcode.uid', '1'); } } diff --git a/tests/Libraries/BBCodeFromDBTest.php b/tests/Libraries/BBCodeFromDBTest.php index f7e91809879..f93373b8be7 100644 --- a/tests/Libraries/BBCodeFromDBTest.php +++ b/tests/Libraries/BBCodeFromDBTest.php @@ -54,6 +54,6 @@ protected function setUp(): void { parent::setUp(); - config()->set('osu.bbcode.uid', '1'); + config_set('osu.bbcode.uid', '1'); } } diff --git a/tests/Libraries/BeatmapsetDiscussion/DiscussionTest.php b/tests/Libraries/BeatmapsetDiscussion/DiscussionTest.php index c1b8105ae87..ff9f89b0ce4 100644 --- a/tests/Libraries/BeatmapsetDiscussion/DiscussionTest.php +++ b/tests/Libraries/BeatmapsetDiscussion/DiscussionTest.php @@ -37,7 +37,7 @@ class DiscussionTest extends TestCase */ public function testMinPlaysVerification(\Closure $minPlays, bool $verified, bool $success) { - config()->set('osu.user.post_action_verification', false); + config_set('osu.user.post_action_verification', false); $user = User::factory()->withPlays($minPlays())->create(); $beatmapset = $this->beatmapsetFactory()->create(); @@ -287,8 +287,8 @@ public function testProblemOnQualifiedBeatmapsetModesNotification(string $mode, public static function minPlaysVerificationDataProvider() { return [ - [fn () => config('osu.user.min_plays_for_posting') - 1, false, false], - [fn () => config('osu.user.min_plays_for_posting') - 1, true, true], + [fn () => $GLOBALS['cfg']['osu']['user']['min_plays_for_posting'] - 1, false, false], + [fn () => $GLOBALS['cfg']['osu']['user']['min_plays_for_posting'] - 1, true, true], [fn () => null, false, true], [fn () => null, true, true], ]; @@ -401,7 +401,7 @@ protected function setUp(): void Event::fake(); - config()->set('osu.beatmapset.required_nominations', 1); + config_set('osu.beatmapset.required_nominations', 1); $this->mapper = User::factory()->create()->markSessionVerified(); } diff --git a/tests/Libraries/BeatmapsetDiscussion/ReplyTest.php b/tests/Libraries/BeatmapsetDiscussion/ReplyTest.php index be8bfa66f42..f3f5be6b895 100644 --- a/tests/Libraries/BeatmapsetDiscussion/ReplyTest.php +++ b/tests/Libraries/BeatmapsetDiscussion/ReplyTest.php @@ -409,7 +409,7 @@ protected function setUp(): void Queue::fake(); Event::fake(); - config()->set('osu.beatmapset.required_nominations', 1); + config_set('osu.beatmapset.required_nominations', 1); $this->mapper = User::factory()->create()->markSessionVerified(); } diff --git a/tests/Libraries/BeatmapsetDiscussion/ReviewTest.php b/tests/Libraries/BeatmapsetDiscussion/ReviewTest.php index 611383ba6b1..68d7cd8ee31 100644 --- a/tests/Libraries/BeatmapsetDiscussion/ReviewTest.php +++ b/tests/Libraries/BeatmapsetDiscussion/ReviewTest.php @@ -732,7 +732,7 @@ protected function setUp(): void Queue::fake(); Event::fake(); - config()->set('osu.beatmapset.discussion_review_max_blocks', 4); + config_set('osu.beatmapset.discussion_review_max_blocks', 4); $this->user = User::factory()->create(); $this->beatmapset = Beatmapset::factory()->create([ diff --git a/tests/Libraries/ChatTest.php b/tests/Libraries/ChatTest.php index 3446e73d0fe..d333d4a9b14 100644 --- a/tests/Libraries/ChatTest.php +++ b/tests/Libraries/ChatTest.php @@ -85,8 +85,8 @@ public function testCreateAnnouncementSendsNotification() */ public function testMinPlaysSendMessage(?string $groupIdentifier, bool $hasMinPlays, bool $successful) { - config()->set('osu.user.min_plays_allow_verified_bypass', false); - config()->set('osu.user.min_plays_for_posting', 2); + config_set('osu.user.min_plays_allow_verified_bypass', false); + config_set('osu.user.min_plays_for_posting', 2); $playCount = $hasMinPlays ? null : 1; @@ -110,8 +110,8 @@ public function testMinPlaysSendMessage(?string $groupIdentifier, bool $hasMinPl */ public function testMinPlaysSendPM(?string $groupIdentifier, bool $hasMinPlays, bool $successful) { - config()->set('osu.user.min_plays_allow_verified_bypass', false); - config()->set('osu.user.min_plays_for_posting', 2); + config_set('osu.user.min_plays_allow_verified_bypass', false); + config_set('osu.user.min_plays_for_posting', 2); $playCount = $hasMinPlays ? null : 1; @@ -236,7 +236,7 @@ public function testSendPMTooLongNotCreatingNewChannel() $this->expectCountChange(fn () => Channel::count(), 0); $this->expectCountChange(fn () => Message::count(), 0); - $longMessage = str_repeat('a', config('osu.chat.message_length_limit') + 1); + $longMessage = str_repeat('a', $GLOBALS['cfg']['osu']['chat']['message_length_limit'] + 1); try { Chat::sendPrivateMessage($sender, $target, $longMessage, false); diff --git a/tests/Libraries/ClientCheckTest.php b/tests/Libraries/ClientCheckTest.php index c9ec1d41f34..3ffede7b3b1 100644 --- a/tests/Libraries/ClientCheckTest.php +++ b/tests/Libraries/ClientCheckTest.php @@ -68,7 +68,7 @@ public function testFindBuildNonexistentAsAdmin() public function testFindBuildNonexistentWithDisabledAssertion() { - config()->set('osu.client.check_version', false); + config_set('osu.client.check_version', false); $user = User::factory()->withGroup('default')->create(); diff --git a/tests/Libraries/Payments/CentiliPaymentProcessorTest.php b/tests/Libraries/Payments/CentiliPaymentProcessorTest.php index e26411badf7..578c2d40003 100644 --- a/tests/Libraries/Payments/CentiliPaymentProcessorTest.php +++ b/tests/Libraries/Payments/CentiliPaymentProcessorTest.php @@ -12,7 +12,6 @@ use App\Libraries\Payments\UnsupportedNotificationTypeException; use App\Models\Store\Order; use App\Models\Store\OrderItem; -use Config; use Illuminate\Support\Facades\Event; use Tests\TestCase; @@ -140,8 +139,8 @@ public function testWhenSignatureInvalid() protected function setUp(): void { parent::setUp(); - Config::set('payments.centili.api_key', 'api_key'); - Config::set('payments.centili.conversion_rate', 120.00); + config_set('payments.centili.api_key', 'api_key'); + config_set('payments.centili.conversion_rate', 120.00); $this->order = Order::factory()->checkout()->create(); } @@ -150,13 +149,13 @@ private function getTestParams(array $overrides = []) $base = [ 'reference' => $this->order->getOrderNumber(), 'country' => 'jp', - 'enduserprice' => $this->order->getTotal() * config('payments.centili.conversion_rate'), + 'enduserprice' => $this->order->getTotal() * $GLOBALS['cfg']['payments']['centili']['conversion_rate'], 'event_type' => 'one_off', 'mnocode' => 'BADDOG', 'phone' => 'test@example.org', 'revenue' => '4.34', 'revenuecurrency' => 'MONOPOLY', - 'service' => config('payments.centili.api_key'), + 'service' => $GLOBALS['cfg']['payments']['centili']['api_key'], 'status' => 'success', 'transactionid' => '111222333', ]; diff --git a/tests/Libraries/Payments/CentiliSignatureTest.php b/tests/Libraries/Payments/CentiliSignatureTest.php index ce698ceb52f..5af8966426c 100644 --- a/tests/Libraries/Payments/CentiliSignatureTest.php +++ b/tests/Libraries/Payments/CentiliSignatureTest.php @@ -6,7 +6,6 @@ namespace Tests\Libraries\Payments; use App\Libraries\Payments\CentiliSignature; -use Config; use Tests\TestCase; class CentiliSignatureTest extends TestCase @@ -52,6 +51,6 @@ public function testCalculateSignature() protected function setUp(): void { parent::setUp(); - Config::set('payments.centili.secret_key', 'magic'); + config_set('payments.centili.secret_key', 'magic'); } } diff --git a/tests/Libraries/Payments/PaymentProcessorTest.php b/tests/Libraries/Payments/PaymentProcessorTest.php index dc399a081b6..868d8f64661 100644 --- a/tests/Libraries/Payments/PaymentProcessorTest.php +++ b/tests/Libraries/Payments/PaymentProcessorTest.php @@ -83,7 +83,7 @@ protected function setUp(): void { parent::setUp(); - config()->set('store.order.prefix', 'test'); + config_set('store.order.prefix', 'test'); $this->order = Order::factory()->checkout()->create([ 'transaction_id' => 'test-123', diff --git a/tests/Libraries/Payments/ShopifySignatureTest.php b/tests/Libraries/Payments/ShopifySignatureTest.php index 633d37364a2..7a3ada1f7d5 100644 --- a/tests/Libraries/Payments/ShopifySignatureTest.php +++ b/tests/Libraries/Payments/ShopifySignatureTest.php @@ -6,7 +6,6 @@ namespace Tests\Libraries\Payments; use App\Libraries\Payments\ShopifySignature; -use Config; use Tests\TestCase; class ShopifySignatureTest extends TestCase @@ -22,6 +21,6 @@ public function testCalculateSignature() protected function setUp(): void { parent::setUp(); - Config::set('payments.shopify.webhook_key', 'magic'); + config_set('payments.shopify.webhook_key', 'magic'); } } diff --git a/tests/Libraries/Payments/XsollaPaymentProcessorTest.php b/tests/Libraries/Payments/XsollaPaymentProcessorTest.php index 8fbaee9eafa..a77fa3becb8 100644 --- a/tests/Libraries/Payments/XsollaPaymentProcessorTest.php +++ b/tests/Libraries/Payments/XsollaPaymentProcessorTest.php @@ -11,7 +11,6 @@ use App\Libraries\Payments\XsollaPaymentProcessor; use App\Models\Store\Order; use App\Models\Store\OrderItem; -use Config; use Tests\TestCase; class XsollaPaymentProcessorTest extends TestCase @@ -123,7 +122,7 @@ public function testWhenOrderHasPhysicalItems() protected function setUp(): void { parent::setUp(); - Config::set('payments.xsolla.api_key', 'api_key'); + config_set('payments.xsolla.api_key', 'api_key'); $this->order = Order::factory()->checkout()->create(); } diff --git a/tests/Libraries/Payments/XsollaSignatureTest.php b/tests/Libraries/Payments/XsollaSignatureTest.php index 07b5007c248..4b30447d841 100644 --- a/tests/Libraries/Payments/XsollaSignatureTest.php +++ b/tests/Libraries/Payments/XsollaSignatureTest.php @@ -6,7 +6,6 @@ namespace Tests\Libraries\Payments; use App\Libraries\Payments\XsollaSignature; -use Config; use Tests\TestCase; class XsollaSignatureTest extends TestCase @@ -22,6 +21,6 @@ public function testCalculateSignature() protected function setUp(): void { parent::setUp(); - Config::set('payments.xsolla.secret_key', 'magic'); + config_set('payments.xsolla.secret_key', 'magic'); } } diff --git a/tests/Middleware/ThrottleRequestsTest.php b/tests/Middleware/ThrottleRequestsTest.php index f289072cc18..4d671d6aafd 100644 --- a/tests/Middleware/ThrottleRequestsTest.php +++ b/tests/Middleware/ThrottleRequestsTest.php @@ -67,8 +67,8 @@ protected function setUp(): void protected function tearDown(): void { - if (config('cache.default') === 'redis') { - $key = config('cache.prefix').':'.sha1($this->token->getKey()); + if ($GLOBALS['cfg']['cache']['default'] === 'redis') { + $key = $GLOBALS['cfg']['cache']['prefix'].':'.sha1($this->token->getKey()); LaravelRedis::del($key); LaravelRedis::del("{$key}:timer"); } diff --git a/tests/Models/Forum/TopicTest.php b/tests/Models/Forum/TopicTest.php index 02c88327cd4..200c144ffa5 100644 --- a/tests/Models/Forum/TopicTest.php +++ b/tests/Models/Forum/TopicTest.php @@ -29,7 +29,7 @@ public function testTitleTrimOnAssignment() public function testIssueTags() { $topic = new Topic(); - $topic->forum_id = config('osu.forum.issue_forum_ids')[0]; + $topic->forum_id = $GLOBALS['cfg']['osu']['forum']['issue_forum_ids'][0]; $topic->topic_title = '[invalid] herp a derp'; $this->assertSame(['invalid'], $topic->issueTags()); @@ -38,7 +38,7 @@ public function testIssueTags() public function testIssueTagsWithKeywordAsTitle() { $topic = new Topic(); - $topic->forum_id = config('osu.forum.issue_forum_ids')[0]; + $topic->forum_id = $GLOBALS['cfg']['osu']['forum']['issue_forum_ids'][0]; $topic->topic_title = 'invalid herp a derp'; $this->assertSame([], $topic->issueTags()); diff --git a/tests/Models/Multiplayer/RoomTest.php b/tests/Models/Multiplayer/RoomTest.php index 1a0bd1077ac..f96954767aa 100644 --- a/tests/Models/Multiplayer/RoomTest.php +++ b/tests/Models/Multiplayer/RoomTest.php @@ -191,8 +191,8 @@ public static function startGameDurationDataProvider() static $dayMinutes = 1440; static::createApp(); - $maxDuration = config('osu.user.max_multiplayer_duration'); - $maxDurationSupporter = config('osu.user.max_multiplayer_duration_supporter'); + $maxDuration = $GLOBALS['cfg']['osu']['user']['max_multiplayer_duration']; + $maxDurationSupporter = $GLOBALS['cfg']['osu']['user']['max_multiplayer_duration_supporter']; return [ '2 weeks' => [$dayMinutes * $maxDuration, false, false], diff --git a/tests/Models/OAuth/ClientTest.php b/tests/Models/OAuth/ClientTest.php index 3bc743bfa2d..a8dbb2857a8 100644 --- a/tests/Models/OAuth/ClientTest.php +++ b/tests/Models/OAuth/ClientTest.php @@ -166,7 +166,7 @@ public function testDoesNotRevokeOtherUserTokens() public function testNumberOfClientsIsLimited() { - config()->set('osu.oauth.max_user_clients', 1); + config_set('osu.oauth.max_user_clients', 1); $client = Client::factory() ->allowUnsaved() @@ -177,7 +177,7 @@ public function testNumberOfClientsIsLimited() public function testNumberOfClientsLimitDoesNotIncludeRevokedClients() { - config()->set('osu.oauth.max_user_clients', 1); + config_set('osu.oauth.max_user_clients', 1); $this->client->update(['revoked' => true]); $client = Client::factory()->create(['user_id' => $this->owner]); diff --git a/tests/Models/UserTest.php b/tests/Models/UserTest.php index 457b193e05c..0367dd3a709 100644 --- a/tests/Models/UserTest.php +++ b/tests/Models/UserTest.php @@ -27,7 +27,7 @@ public function testAttributeTwitter($setValue, $getValue) public function testEmailLoginDisabled() { - config()->set('osu.user.allow_email_login', false); + config_set('osu.user.allow_email_login', false); User::factory()->create([ 'username' => 'test', 'user_email' => 'test@example.org', @@ -38,7 +38,7 @@ public function testEmailLoginDisabled() public function testEmailLoginEnabled() { - config()->set('osu.user.allow_email_login', true); + config_set('osu.user.allow_email_login', true); $user = User::factory()->create([ 'username' => 'test', 'user_email' => 'test@example.org', @@ -49,7 +49,7 @@ public function testEmailLoginEnabled() public function testUsernameAvailableAtForDefaultGroup() { - config()->set('osu.user.allowed_rename_groups', ['default']); + config_set('osu.user.allowed_rename_groups', ['default']); $allowedAtUpTo = now()->addYears(5); $user = User::factory()->withGroup('default')->create(); @@ -58,7 +58,7 @@ public function testUsernameAvailableAtForDefaultGroup() public function testUsernameAvailableAtForNonDefaultGroup() { - config()->set('osu.user.allowed_rename_groups', ['default']); + config_set('osu.user.allowed_rename_groups', ['default']); $allowedAt = now()->addYears(10); $user = User::factory()->withGroup('gmt')->create(['group_id' => app('groups')->byIdentifier('default')]); diff --git a/tests/OAuthAuthCodeRequestTest.php b/tests/OAuthAuthCodeRequestTest.php index d6b3940f7dc..29cde7e519a 100644 --- a/tests/OAuthAuthCodeRequestTest.php +++ b/tests/OAuthAuthCodeRequestTest.php @@ -62,7 +62,7 @@ protected function setUp(): void parent::setUp(); // otherwise exceptions won't render the actual view. - config()->set('app.debug', false); + config_set('app.debug', false); $this->client = Client::factory()->create([ 'user_id' => User::factory()->withGroup('bot'), diff --git a/tests/OAuthClientCredentialsRequestTest.php b/tests/OAuthClientCredentialsRequestTest.php index f5830976a87..c46e89d4723 100644 --- a/tests/OAuthClientCredentialsRequestTest.php +++ b/tests/OAuthClientCredentialsRequestTest.php @@ -75,6 +75,6 @@ protected function setUp(): void parent::setUp(); // otherwise exceptions won't render the actual view. - config()->set('app.debug', false); + config_set('app.debug', false); } } diff --git a/tests/TestCase.php b/tests/TestCase.php index b888c28428b..7fe0f8462e2 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -62,7 +62,7 @@ protected static function reindexScores() protected static function resetAppDb(DatabaseManager $database): void { - foreach (array_keys(config('database.connections')) as $name) { + foreach (array_keys($GLOBALS['cfg']['database']['connections']) as $name) { $connection = $database->connection($name); $connection->rollBack(); @@ -103,7 +103,7 @@ protected function setUp(): void parent::setUp(); // change config setting because we need more than 1 for the tests. - config()->set('osu.oauth.max_user_clients', 100); + config_set('osu.oauth.max_user_clients', 100); // Force connections to reset even if transactional tests were not used. // Should fix tests going wonky when different queue drivers are used, or anything that @@ -183,7 +183,7 @@ protected function actingWithToken($token) static $privateKey; if ($privateKey === null) { - $privateKey = config('passport.private_key') ?? file_get_contents(Passport::keyPath('oauth-private.key')); + $privateKey = $GLOBALS['cfg']['passport']['private_key'] ?? file_get_contents(Passport::keyPath('oauth-private.key')); } $encryptedToken = JWT::encode([ @@ -328,7 +328,7 @@ protected function runFakeQueue() protected function withInterOpHeader($url) { return $this->withHeaders([ - 'X-LIO-Signature' => hash_hmac('sha1', $url, config('osu.legacy.shared_interop_secret')), + 'X-LIO-Signature' => hash_hmac('sha1', $url, $GLOBALS['cfg']['osu']['legacy']['shared_interop_secret']), ]); } From 6fe40d4f65d7f79ec3b31e439a3d88ff167b0990 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 14 Dec 2023 21:44:05 +0900 Subject: [PATCH 065/102] Using something that's actually from carbon --- app/Libraries/SessionVerification/State.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Libraries/SessionVerification/State.php b/app/Libraries/SessionVerification/State.php index 1f8d814dce1..06a3db7ddc9 100644 --- a/app/Libraries/SessionVerification/State.php +++ b/app/Libraries/SessionVerification/State.php @@ -16,7 +16,7 @@ class State { private const KEY_VALID_DURATION = 5 * 3600; - public readonly \DateTimeInterface $expiresAt; + public readonly CarbonImmutable $expiresAt; public readonly string $key; public readonly string $linkKey; public int $tries = 0; From cc604e77c2050dc7182fc5464c170e86239cefe6 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 14 Dec 2023 21:47:58 +0900 Subject: [PATCH 066/102] Fix wrong variable and missing state delete on verified --- app/Libraries/SessionVerification/Controller.php | 4 ++-- app/Libraries/SessionVerification/Helper.php | 3 ++- app/Libraries/SessionVerification/State.php | 2 +- tests/Libraries/SessionVerification/ControllerTest.php | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/Libraries/SessionVerification/Controller.php b/app/Libraries/SessionVerification/Controller.php index ac17d75db18..1eafb8a03f8 100644 --- a/app/Libraries/SessionVerification/Controller.php +++ b/app/Libraries/SessionVerification/Controller.php @@ -80,7 +80,7 @@ public static function verify() } Helper::logAttempt('input', 'success'); - Helper::markVerified($session); + Helper::markVerified($session, $state); return response(null, 204); } @@ -99,7 +99,7 @@ public static function verifyLink() // Otherwise pretend everything is okay if session is missing if ($session !== null) { Helper::logAttempt('link', 'success'); - Helper::markVerified($session); + Helper::markVerified($session, $state); } return ext_view('accounts.verification_completed'); diff --git a/app/Libraries/SessionVerification/Helper.php b/app/Libraries/SessionVerification/Helper.php index 037c49f5b82..66d28e8bd7b 100644 --- a/app/Libraries/SessionVerification/Helper.php +++ b/app/Libraries/SessionVerification/Helper.php @@ -47,9 +47,10 @@ public static function logAttempt(string $source, string $type, string $reason = ); } - public static function markVerified(SessionVerificationInterface $session) + public static function markVerified(SessionVerificationInterface $session, State $state) { $session->markVerified(); + $state->delete(); UserSessionEvent::newVerified($session->userId(), $session->getKeyForEvent())->broadcast(); } } diff --git a/app/Libraries/SessionVerification/State.php b/app/Libraries/SessionVerification/State.php index 06a3db7ddc9..bf8b37ef9c9 100644 --- a/app/Libraries/SessionVerification/State.php +++ b/app/Libraries/SessionVerification/State.php @@ -68,7 +68,7 @@ private static function cacheLinkKey(string $linkKey): string public function delete(): void { \Cache::delete(static::cacheKey($this->sessionClass, $this->sessionId)); - \Cache::delete(static::cacheLinkKey($state->linkKey)); + \Cache::delete(static::cacheLinkKey($this->linkKey)); } public function findSession(): ?SessionVerificationInterface diff --git a/tests/Libraries/SessionVerification/ControllerTest.php b/tests/Libraries/SessionVerification/ControllerTest.php index cf8455084bf..58f3ecc3da9 100644 --- a/tests/Libraries/SessionVerification/ControllerTest.php +++ b/tests/Libraries/SessionVerification/ControllerTest.php @@ -79,6 +79,7 @@ public function testVerify(): void $this->assertFalse($record->containsUser($user, 'verify-mismatch:')); $this->assertTrue($session->isVerified()); + $this->assertNull(SessionVerification\State::fromSession($session)); } public function testVerifyLink(): void From 49e3d674f8cf97afba00d69a1cb315c356fe7cc5 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 14 Dec 2023 21:59:18 +0900 Subject: [PATCH 067/102] Assert current user --- app/Libraries/SessionVerification/Controller.php | 6 +++--- app/Libraries/SessionVerification/Helper.php | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/Libraries/SessionVerification/Controller.php b/app/Libraries/SessionVerification/Controller.php index 1eafb8a03f8..19b7c577622 100644 --- a/app/Libraries/SessionVerification/Controller.php +++ b/app/Libraries/SessionVerification/Controller.php @@ -18,7 +18,7 @@ public static function initiate() app('route-section')->setError("{$statusCode}-verification"); - $user = \Auth::user(); + $user = Helper::currentUser(); $email = $user->user_email; $session = \Session::instance(); @@ -48,7 +48,7 @@ public static function reissue() return response(null, 204); } - Helper::issue($session, \Auth::user()); + Helper::issue($session, Helper::currentUser()); return response(['message' => osu_trans('user_verification.errors.reissued')], 200); } @@ -56,7 +56,7 @@ public static function reissue() public static function verify() { $key = strtr(get_string(\Request::input('verification_key')) ?? '', [' ' => '']); - $user = \Auth::user(); + $user = Helper::currentUser(); $session = \Session::instance(); $state = State::fromSession($session); diff --git a/app/Libraries/SessionVerification/Helper.php b/app/Libraries/SessionVerification/Helper.php index 66d28e8bd7b..0763bc1d4fa 100644 --- a/app/Libraries/SessionVerification/Helper.php +++ b/app/Libraries/SessionVerification/Helper.php @@ -15,6 +15,14 @@ class Helper { + public static function currentUser(): User + { + $user = \Auth::user(); + app('OsuAuthorize')->ensureLoggedIn($user); + + return $user; + } + public static function issue(SessionVerificationInterface $session, User $user): void { if (!is_valid_email_format($user->user_email)) { From bf1c039ec5bf583cd6952b2748a3f498e8cf3dec Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 14 Dec 2023 22:19:25 +0900 Subject: [PATCH 068/102] Better function name --- app/Libraries/SessionVerification/Controller.php | 6 +++--- app/Libraries/SessionVerification/Helper.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Libraries/SessionVerification/Controller.php b/app/Libraries/SessionVerification/Controller.php index 19b7c577622..0333f65b192 100644 --- a/app/Libraries/SessionVerification/Controller.php +++ b/app/Libraries/SessionVerification/Controller.php @@ -18,7 +18,7 @@ public static function initiate() app('route-section')->setError("{$statusCode}-verification"); - $user = Helper::currentUser(); + $user = Helper::currentUserOrFail(); $email = $user->user_email; $session = \Session::instance(); @@ -48,7 +48,7 @@ public static function reissue() return response(null, 204); } - Helper::issue($session, Helper::currentUser()); + Helper::issue($session, Helper::currentUserOrFail()); return response(['message' => osu_trans('user_verification.errors.reissued')], 200); } @@ -56,7 +56,7 @@ public static function reissue() public static function verify() { $key = strtr(get_string(\Request::input('verification_key')) ?? '', [' ' => '']); - $user = Helper::currentUser(); + $user = Helper::currentUserOrFail(); $session = \Session::instance(); $state = State::fromSession($session); diff --git a/app/Libraries/SessionVerification/Helper.php b/app/Libraries/SessionVerification/Helper.php index 0763bc1d4fa..6e628f02a60 100644 --- a/app/Libraries/SessionVerification/Helper.php +++ b/app/Libraries/SessionVerification/Helper.php @@ -15,7 +15,7 @@ class Helper { - public static function currentUser(): User + public static function currentUserOrFail(): User { $user = \Auth::user(); app('OsuAuthorize')->ensureLoggedIn($user); From 9c1f6f41ebd5dba66591cdd3888f17dbe94245e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Dec 2023 16:41:37 +0900 Subject: [PATCH 069/102] Update translations from crowdin --- resources/lang/ar/accounts.php | 30 +++---- resources/lang/ar/api.php | 4 +- resources/lang/ar/authorization.php | 4 +- resources/lang/ar/bbcode.php | 2 +- resources/lang/ar/beatmap_discussions.php | 2 +- resources/lang/ar/beatmappacks.php | 2 +- resources/lang/ar/legacy_api_key.php | 8 +- resources/lang/ar/matches.php | 2 +- resources/lang/ar/model_validation.php | 8 +- resources/lang/bg/accounts.php | 16 ++-- resources/lang/bg/beatmap_discussions.php | 2 +- resources/lang/bg/comments.php | 2 +- resources/lang/bg/notifications.php | 6 +- resources/lang/bg/store.php | 72 +++++++-------- resources/lang/bg/users.php | 4 +- resources/lang/ca/comments.php | 2 +- resources/lang/ca/notifications.php | 6 +- resources/lang/ca/store.php | 88 +++++++++--------- resources/lang/ca/users.php | 4 +- resources/lang/cs/notifications.php | 8 +- resources/lang/cs/store.php | 48 +++++----- resources/lang/cs/users.php | 6 +- resources/lang/de/comments.php | 2 +- resources/lang/de/notifications.php | 10 +-- resources/lang/de/store.php | 74 +++++++-------- resources/lang/de/users.php | 4 +- resources/lang/es/beatmaps.php | 4 +- resources/lang/es/beatmapsets.php | 4 +- resources/lang/es/comments.php | 2 +- resources/lang/es/notifications.php | 6 +- resources/lang/es/store.php | 78 ++++++++-------- resources/lang/es/users.php | 4 +- resources/lang/fi/artist.php | 2 +- resources/lang/fi/beatmap_discussions.php | 4 +- resources/lang/fi/beatmappacks.php | 4 +- resources/lang/fi/beatmaps.php | 18 ++-- resources/lang/fi/beatmapset_watches.php | 2 +- resources/lang/fi/beatmapsets.php | 8 +- resources/lang/fi/comments.php | 2 +- resources/lang/fi/common.php | 6 +- resources/lang/fi/community.php | 2 +- resources/lang/fi/events.php | 2 +- resources/lang/fi/follows.php | 2 +- resources/lang/fi/home.php | 4 +- resources/lang/fi/layout.php | 2 +- resources/lang/fi/legacy_api_key.php | 6 +- resources/lang/fi/legacy_irc_key.php | 2 +- resources/lang/fi/livestreams.php | 2 +- resources/lang/fi/matches.php | 4 +- resources/lang/fi/model_validation.php | 10 +-- resources/lang/fi/multiplayer.php | 10 +-- resources/lang/fi/notifications.php | 10 +-- resources/lang/fi/page_title.php | 14 +-- resources/lang/fi/rankings.php | 2 +- resources/lang/fi/store.php | 90 +++++++++---------- resources/lang/fi/users.php | 16 ++-- resources/lang/fr/comments.php | 2 +- resources/lang/fr/notifications.php | 6 +- resources/lang/fr/store.php | 72 +++++++-------- resources/lang/fr/users.php | 4 +- resources/lang/hu/comments.php | 2 +- resources/lang/hu/notifications.php | 6 +- resources/lang/hu/store.php | 72 +++++++-------- resources/lang/hu/users.php | 4 +- resources/lang/id/comments.php | 2 +- resources/lang/id/notifications.php | 6 +- resources/lang/id/store.php | 76 ++++++++-------- resources/lang/id/users.php | 4 +- resources/lang/it/accounts.php | 2 +- resources/lang/it/beatmapsets.php | 2 +- resources/lang/it/comments.php | 2 +- resources/lang/it/notifications.php | 6 +- resources/lang/it/store.php | 58 ++++++------ resources/lang/it/users.php | 4 +- resources/lang/ko/comments.php | 2 +- resources/lang/ko/model_validation.php | 34 +++---- resources/lang/ko/notifications.php | 6 +- resources/lang/ko/password_reset.php | 2 +- resources/lang/ko/store.php | 74 +++++++-------- resources/lang/ko/users.php | 12 +-- resources/lang/lv-LV/api.php | 2 +- resources/lang/lv-LV/beatmap_discussions.php | 2 +- resources/lang/lv-LV/beatmaps.php | 14 +-- resources/lang/lv-LV/chat.php | 4 +- resources/lang/lv-LV/comments.php | 2 +- resources/lang/lv-LV/forum.php | 18 ++-- resources/lang/lv-LV/home.php | 38 ++++---- resources/lang/lv-LV/layout.php | 78 ++++++++-------- resources/lang/lv-LV/mail.php | 6 +- resources/lang/lv-LV/matches.php | 20 ++--- resources/lang/lv-LV/model_validation.php | 30 +++---- resources/lang/lv-LV/news.php | 4 +- resources/lang/lv-LV/password_reset.php | 4 +- resources/lang/lv-LV/quick_search.php | 6 +- resources/lang/lv-LV/rankings.php | 12 +-- resources/lang/lv-LV/store.php | 2 +- resources/lang/nl/password_reset.php | 6 +- resources/lang/nl/store.php | 50 +++++------ resources/lang/pl/store.php | 4 +- resources/lang/pt-br/comments.php | 2 +- resources/lang/pt-br/notifications.php | 6 +- resources/lang/pt-br/store.php | 72 +++++++-------- resources/lang/pt-br/users.php | 4 +- resources/lang/pt/comments.php | 2 +- resources/lang/pt/notifications.php | 6 +- resources/lang/pt/store.php | 72 +++++++-------- resources/lang/pt/users.php | 4 +- resources/lang/ro/comments.php | 2 +- resources/lang/ro/notifications.php | 6 +- resources/lang/ro/store.php | 72 +++++++-------- resources/lang/ro/users.php | 4 +- resources/lang/ru/authorization.php | 2 +- resources/lang/ru/beatmap_discussions.php | 10 +-- resources/lang/ru/beatmaps.php | 4 +- resources/lang/ru/beatmapset_events.php | 26 +++--- resources/lang/ru/comments.php | 2 +- resources/lang/ru/community.php | 10 +-- resources/lang/ru/forum.php | 6 +- resources/lang/ru/layout.php | 2 +- resources/lang/ru/mail.php | 4 +- resources/lang/ru/model_validation.php | 18 ++-- resources/lang/ru/notifications.php | 10 +-- resources/lang/ru/store.php | 76 ++++++++-------- resources/lang/ru/user_verification.php | 10 +-- resources/lang/ru/users.php | 16 ++-- resources/lang/th/accounts.php | 14 +-- resources/lang/th/beatmap_discussions.php | 2 +- resources/lang/th/comments.php | 2 +- resources/lang/th/notifications.php | 6 +- resources/lang/th/store.php | 72 +++++++-------- resources/lang/th/users.php | 4 +- resources/lang/tr/accounts.php | 4 +- resources/lang/tr/store.php | 40 ++++----- resources/lang/uk/comments.php | 2 +- resources/lang/uk/community.php | 4 +- resources/lang/uk/errors.php | 2 +- .../lang/uk/model_validation/fulfillments.php | 2 +- resources/lang/uk/notifications.php | 6 +- resources/lang/uk/store.php | 74 +++++++-------- resources/lang/uk/users.php | 4 +- resources/lang/vi/comments.php | 2 +- resources/lang/vi/notifications.php | 6 +- resources/lang/vi/store.php | 72 +++++++-------- resources/lang/vi/users.php | 4 +- resources/lang/zh-tw/store.php | 28 +++--- resources/lang/zh/comments.php | 2 +- resources/lang/zh/notifications.php | 6 +- resources/lang/zh/store.php | 72 +++++++-------- resources/lang/zh/users.php | 4 +- 149 files changed, 1191 insertions(+), 1191 deletions(-) diff --git a/resources/lang/ar/accounts.php b/resources/lang/ar/accounts.php index d868318f5b7..db165214c4e 100644 --- a/resources/lang/ar/accounts.php +++ b/resources/lang/ar/accounts.php @@ -19,15 +19,15 @@ 'new_confirmation' => 'تأكيد البريد الإلكتروني', 'title' => 'البريد الإلكتروني', 'locked' => [ - '_' => '', - 'accounts' => '', + '_' => 'الرجاء التواصل مع :accounts إذا احتجت إلى تحديث بريدك الإلكتروني.', + 'accounts' => 'فريق دعم الحسابات', ], ], 'legacy_api' => [ - 'api' => '', - 'irc' => '', - 'title' => '', + 'api' => 'واجهة برمجة التطبيقات', + 'irc' => 'بروتوكول الدردشة', + 'title' => 'واجهة برمجة التطبيقات القديمة', ], 'password' => [ @@ -38,12 +38,12 @@ ], 'profile' => [ - 'country' => '', + 'country' => 'الدولة', 'title' => 'الملف الشخصي', 'country_change' => [ - '_' => "", - 'update_link' => '', + '_' => "يبدو أن دولة حسابك لا تتطابق مع دولة الإقامة. :update_link.", + 'update_link' => 'التحديث إلى :country', ], 'user' => [ @@ -63,15 +63,15 @@ ], 'github_user' => [ - 'info' => "", - 'link' => '', - 'title' => '', - 'unlink' => '', + 'info' => "إذا كنت من مساهمي مستودعات osu! مفتوحة المصدر، فإن ربط حساب GitHub الخاص بك هنا سيربط إدخالات سجل التغييرات مع ملفك الشخصي على osu! لا يمكن ربط حسابات GitHub التي لم تساهم قبلًا في osu!.", + 'link' => 'ربط حساب GitHub', + 'title' => 'GitHub', + 'unlink' => 'إلغاء ربط حساب GitHub', 'error' => [ - 'already_linked' => '', - 'no_contribution' => '', - 'unverified_email' => '', + 'already_linked' => 'حساب GitHub هذا مرتبط بالفعل بمستخدم مختلف.', + 'no_contribution' => 'لا يمكن ربط حساب GitHub بلا أي مساهمات مسبقة في مستودعات osu!.', + 'unverified_email' => 'الرجاء تأكيد بريدك الإلكتروني الأساسي على GitHub، ثم محاولة ربط حسابك مرة أخرى.', ], ], diff --git a/resources/lang/ar/api.php b/resources/lang/ar/api.php index 417e90420d8..8c791deec5d 100644 --- a/resources/lang/ar/api.php +++ b/resources/lang/ar/api.php @@ -17,9 +17,9 @@ 'identify' => 'يتعرف عليك ويقرأ ملفك الشخصي العام.', 'chat' => [ - 'read' => '', + 'read' => 'قراءة الرسائل نيابةً عنك.', 'write' => 'إرسال رسائل نيابة عنك.', - 'write_manage' => '', + 'write_manage' => 'الانضمام إلى القنوات ومغادرتها نيابةً عنك.', ], 'forum' => [ diff --git a/resources/lang/ar/authorization.php b/resources/lang/ar/authorization.php index 39a116cb274..3f7d43689a3 100644 --- a/resources/lang/ar/authorization.php +++ b/resources/lang/ar/authorization.php @@ -171,7 +171,7 @@ 'score' => [ 'pin' => [ - 'disabled_type' => "", + 'disabled_type' => "لا يمكن تثبيت هذا النوع من النقاط", 'not_owner' => 'يمكن لمالك النتيجة فقط تثبيتها.', 'too_many' => 'قمت بتثبيت نتائج كثيرة.', ], @@ -186,7 +186,7 @@ ], ], 'update_email' => [ - 'locked' => '', + 'locked' => 'عنوان البريد الإلكتروني مقفل', ], ], ]; diff --git a/resources/lang/ar/bbcode.php b/resources/lang/ar/bbcode.php index 9c8727f80bb..2a5d3dc1a41 100644 --- a/resources/lang/ar/bbcode.php +++ b/resources/lang/ar/bbcode.php @@ -6,7 +6,7 @@ return [ 'bold' => 'عريض', 'heading' => 'عنوان', - 'help' => '', + 'help' => 'مساعدة', 'image' => 'صورة', 'imagemap' => '', 'italic' => 'مائل', diff --git a/resources/lang/ar/beatmap_discussions.php b/resources/lang/ar/beatmap_discussions.php index 775100cdf1a..f20562d8c23 100644 --- a/resources/lang/ar/beatmap_discussions.php +++ b/resources/lang/ar/beatmap_discussions.php @@ -26,7 +26,7 @@ 'deleted' => 'شمل المناقشات المحذوفة', 'mode' => 'نمط الخريطة', 'only_unresolved' => 'اظهار المناقشات التي لم تحل فقط', - 'show_review_embeds' => '', + 'show_review_embeds' => 'إظهار منشورات المراجعات', 'types' => 'أنواع الرسائل', 'username' => 'اسم المستخدم', diff --git a/resources/lang/ar/beatmappacks.php b/resources/lang/ar/beatmappacks.php index a3ecc824a72..0f99ce29dd0 100644 --- a/resources/lang/ar/beatmappacks.php +++ b/resources/lang/ar/beatmappacks.php @@ -39,7 +39,7 @@ 'loved' => '', 'standard' => 'أساسي', 'theme' => 'مظهر', - 'tournament' => '', + 'tournament' => 'البطولة', ], 'require_login' => [ diff --git a/resources/lang/ar/legacy_api_key.php b/resources/lang/ar/legacy_api_key.php index 562fed20b55..93492d7e0c7 100644 --- a/resources/lang/ar/legacy_api_key.php +++ b/resources/lang/ar/legacy_api_key.php @@ -19,12 +19,12 @@ 'view' => [ 'hide' => '', 'show' => '', - 'delete' => '', + 'delete' => 'حذف', ], 'warning' => [ - 'line1' => '', - 'line2' => "", - 'line3' => '', + 'line1' => 'لا تشاركه مع الآخرين.', + 'line2' => "إنه أشبه بكلمة مرورك.", + 'line3' => 'قد يتعرض حسابك للخطر.', ], ]; diff --git a/resources/lang/ar/matches.php b/resources/lang/ar/matches.php index 05f0b5489c8..bc7da124540 100644 --- a/resources/lang/ar/matches.php +++ b/resources/lang/ar/matches.php @@ -12,7 +12,7 @@ 'in_progress_spinner_label' => 'مباراة في التقدم', 'loading-events' => 'جارِ تحميل الأحداث...', 'winner' => ':team فاز', - 'winner_by' => '', + 'winner_by' => ':winner فاز بفارق :difference', 'events' => [ 'player-left' => ':user غادر الغرفة', diff --git a/resources/lang/ar/model_validation.php b/resources/lang/ar/model_validation.php index 5d1a75fcda7..5d39c105ad8 100644 --- a/resources/lang/ar/model_validation.php +++ b/resources/lang/ar/model_validation.php @@ -113,9 +113,9 @@ 'exists' => '', 'attributes' => [ - 'api_key' => '', - 'app_name' => '', - 'app_url' => '', + 'api_key' => 'مفتاح واجهة برمجة التطبيقات', + 'app_name' => 'اسم التطبيق', + 'app_url' => 'رابط التطبيق', ], ], @@ -175,7 +175,7 @@ 'user_report' => [ 'no_ranked_beatmapset' => 'الخرائط الـ Ranked لا يمكن الإبلاغ عنها', - 'not_in_channel' => '', + 'not_in_channel' => 'أنت لست في هذه القناة.', 'reason_not_valid' => ':reason ليس مقبولا لنوع الأبلاغ هذا.', 'self' => "لا يمكنك الإبلاغ عن نفسك!", ], diff --git a/resources/lang/bg/accounts.php b/resources/lang/bg/accounts.php index 431741bd750..672a00f627d 100644 --- a/resources/lang/bg/accounts.php +++ b/resources/lang/bg/accounts.php @@ -10,7 +10,7 @@ 'avatar' => [ 'title' => 'Аватар', - 'rules' => 'Моля уверете се, че вашият аватар се придържда към :link.
Това означава, че задължително трябва да бъде подходящ за всички възрасти. т.е. няма голота, ругатни или внушаващо съдържание.', + 'rules' => 'Моля, уверете се че вашият аватар се придържа към :link.
Това означава, че задължително трябва да бъде подходящ за всички възрасти. т.е. няма голота, ругатни или внушаващо съдържание.', 'rules_link' => 'обществените правила', ], @@ -63,15 +63,15 @@ ], 'github_user' => [ - 'info' => "", - 'link' => '', - 'title' => '', - 'unlink' => '', + 'info' => "Ако сте сътрудник в хранилищата с отворен код на osu!, свързването на вашия GitHub профил ще асоцира приносите ви от списъка с промени към вашия osu! профил. GitHub профилите без история за допринасяне към osu! не могат да бъдат свързани.", + 'link' => 'Свържете GitHub профил', + 'title' => 'GitHub', + 'unlink' => 'Премахнете GitHub профил', 'error' => [ - 'already_linked' => '', - 'no_contribution' => '', - 'unverified_email' => '', + 'already_linked' => 'Този GitHub профил е свързан към друг потребител.', + 'no_contribution' => 'Не може да добавите GitHub профил без никакъв принос в osu! хранилищата.', + 'unverified_email' => 'Потвърдете основния ви имейл в GitHub, след това опитайте да свържете профила отново.', ], ], diff --git a/resources/lang/bg/beatmap_discussions.php b/resources/lang/bg/beatmap_discussions.php index f98c716b6a4..e64ceedd7b5 100644 --- a/resources/lang/bg/beatmap_discussions.php +++ b/resources/lang/bg/beatmap_discussions.php @@ -26,7 +26,7 @@ 'deleted' => 'Включи изтрити дискусии', 'mode' => ' Вид на бийтмап', 'only_unresolved' => 'Покажи само нерешени дискусии', - 'show_review_embeds' => '', + 'show_review_embeds' => 'Покажи ревюта', 'types' => 'Тип съобщения', 'username' => 'Потребителско име', diff --git a/resources/lang/bg/comments.php b/resources/lang/bg/comments.php index 12136e3e631..2fefbe6bc4d 100644 --- a/resources/lang/bg/comments.php +++ b/resources/lang/bg/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'коментар от :user', ], 'placeholder' => [ diff --git a/resources/lang/bg/notifications.php b/resources/lang/bg/notifications.php index 56fe435df69..8f2b8616a0b 100644 --- a/resources/lang/bg/notifications.php +++ b/resources/lang/bg/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'Дискусията е отключена', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited похвала|:count_delimited похвали', + 'problems' => ':count_delimited проблем|:count_delimited проблема', + 'suggestions' => ':count_delimited предложение|:count_delimited предложения', ], ], diff --git a/resources/lang/bg/store.php b/resources/lang/bg/store.php index 2ccf04dc311..dd321600663 100644 --- a/resources/lang/bg/store.php +++ b/resources/lang/bg/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Разплащане', - 'empty_cart' => '', + 'empty_cart' => 'Премахване на всичко от количката', 'info' => ':count_delimited артикул в количката ($:subtotal)|:count_delimited артикула в количката ($:subtotal)', 'more_goodies' => 'Ще проверя още артикули, преди да приключа поръчката си', 'shipping_fees' => 'транспортни такси', @@ -49,37 +49,37 @@ ], 'discount' => 'спести :percent%', - 'free' => '', + 'free' => 'безплатно!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Контакт:', + 'date' => 'Дата:', 'echeck_delay' => 'Вие заплатихте чрез eCheck, което може да отнеме до 10 дена от страна на PayPal за потвърждение на плащането!', 'hide_from_activity' => 'osu!supporter етикетите от тази поръчка не са показани в активността ви.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Изпращане чрез:', + 'shipping_to' => 'Изпращане към:', + 'title' => 'Фактура', 'title_compact' => 'фактура', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Поръчката беше отменена', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Ако не сте заявили отмяна, молим да се свържете с :link като съобщите вашия номер на поръчка (#:order_number).", + 'link_text' => 'поддръжката на osu!магазин', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Поръчката ви беше доставена! Надяваме се че и се радвате!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'При затруднения с вашите поръчки, моля свържете се с :link.', + 'link_text' => 'поддръжката на osu!магазин', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Поръчката ви се подготвя!', + 'line_1' => 'Моля изчакайте малко повече за изпращането. Информацията за проследяване ще бъде достъпна веднага щом поръчката бъде обработена и изпратена. Това може да отнеме до 5 дни (но обичайно по-малко) в зависимост от натовареността.', + 'line_2' => 'Изпращаме всички продукти от Япония с различни доставчи в зависимост от стойността и размера. Тази зона ще бъде обновена с детайли веднага след изпращане на поръчката.', ], 'processing' => [ 'title' => 'Вашето плащане все още не е потвърдено!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Поръчката ви е изпратена!', + 'tracking_details' => 'Детайли за проследяване:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Нямаме данни за проследяване заради използвания доставчик Air Mail, но може да очаквате пристигане на поръчката ви след около 1-3 седмици. Понякога митниците в Европа може да забавят доставката, което е извън наш контрол. Ако имате притеснения, моля отговорете обратно в получения имейл за потвърждение на поръчката ви :link.", + 'link_text' => 'като ни изпратите имейл', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Нямате поръчки за преглед.', 'paid_on' => 'Поръчан на :date', 'resume' => 'Продължи разплащането', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Транспорт и обработка', 'shopify_expired' => 'Връзката за тази поръчката изтече.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Междинна сума', + 'total' => 'Общо', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Поръчка #', + 'payment_terms' => 'Условия за плащане', + 'salesperson' => 'Търговец', + 'shipping_method' => 'Начини за доставка', + 'shipping_terms' => 'Условия за доставка', + 'title' => 'Детайли на поръчка', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Платено', 'processing' => 'Изчаква одобрение', 'shipped' => 'Пътува', - 'title' => '', + 'title' => 'Статус на поръчка', ], 'thanks' => [ - 'title' => '', + 'title' => 'Благодарим ви за поръчката!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Скоро ще получите потвърдителен имейл. Ако имате въпроси, моля :link!', + 'link_text' => 'свържете се с нас', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Въведи потребителско име, за да проверите наличността му!', 'checking' => 'Проверка за наличност на :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Заявено име', + 'label' => 'Ново потребителско име', + 'current' => 'Текущото ви потребителско име е ":username".', 'require_login' => [ '_' => 'Трябва да сте :link , за да промените името си!', diff --git a/resources/lang/bg/users.php b/resources/lang/bg/users.php index c2766c43964..59601d8b0c6 100644 --- a/resources/lang/bg/users.php +++ b/resources/lang/bg/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Бийтмапове: :counts', + 'modding_description_empty' => 'Потребителят няма бийтмапове...', 'description' => [ '_' => 'Ранг (:ruleset): :global | :country', diff --git a/resources/lang/ca/comments.php b/resources/lang/ca/comments.php index bbad7a2c616..ddef31cf57d 100644 --- a/resources/lang/ca/comments.php +++ b/resources/lang/ca/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'comentari per :user', ], 'placeholder' => [ diff --git a/resources/lang/ca/notifications.php b/resources/lang/ca/notifications.php index 0689247e7ce..212dc82aa85 100644 --- a/resources/lang/ca/notifications.php +++ b/resources/lang/ca/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'La discussió s\'ha obert', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited elogi|:count_delimited elogis', + 'problems' => ':count_delimited problema|:count_delimited problemes', + 'suggestions' => ':count_delimited suggeriment|:count_delimited suggeriments', ], ], diff --git a/resources/lang/ca/store.php b/resources/lang/ca/store.php index 700e454fc7b..24d53341a09 100644 --- a/resources/lang/ca/store.php +++ b/resources/lang/ca/store.php @@ -5,9 +5,9 @@ return [ 'cart' => [ - 'checkout' => 'Realitza la compra', - 'empty_cart' => '', - 'info' => ':count_delimited producte al cistell ($:subtotal)|:count_delimited productes al cistell ($:subtotal)', + 'checkout' => 'Pagament', + 'empty_cart' => 'Eliminar tots els elements del cistell', + 'info' => ':count_delimited elements al cistell ($:subtotal)|:count_delimited elements al cistell ($:subtotal)', 'more_goodies' => 'Vull veure més productes abans de completar la compra', 'shipping_fees' => 'despeses d\'enviament', 'title' => 'Cistella de compra', @@ -15,14 +15,14 @@ 'errors_no_checkout' => [ 'line_1' => 'Oh, hi ha problemes a la teva cistella que no permeten el pagament!', - 'line_2' => 'Elimina o canvia els productes de sobre per a continuar. ', + 'line_2' => 'Elimina o actualitza els elements de dalt per continuar.', ], 'empty' => [ 'text' => 'La teva cistella està buida.', 'return_link' => [ - '_' => 'Torna a :link per a trobar bons productes!', - 'link_text' => 'articles', + '_' => 'Torna al :link per a trobar bons productes!', + 'link_text' => 'llistat d\'articles', ], ], ], @@ -33,7 +33,7 @@ 'declined' => 'El pagament s\'ha cancel·lat.', 'delayed_shipping' => 'Ara mateix no podem atendre totes les comandes! La teva compra és benvinguda, però considera un **retard addicional de 1-2 setmanes** mentre ens posem al dia amb les comandes actuals.', 'hide_from_activity' => 'Amaga totes les etiquetes osu!supporter en aquesta ordre de la meva activitat', - 'old_cart' => 'La vostra cistella sembla desactualitzada i s\'ha reiniciat, torna-ho a intentar.', + 'old_cart' => 'La teva cistella sembla desactualitzada i s\'ha reiniciat, torna-ho a intentar.', 'pay' => 'Pagament amb Paypal', 'title_compact' => 'pagament', @@ -49,37 +49,37 @@ ], 'discount' => 'estalvia :percent%', - 'free' => '', + 'free' => 'de franc!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Contacte:', + 'date' => 'Data:', 'echeck_delay' => 'Com que el seu pagament va ser un eCheck, si us plau permeti fins a 10 dies addicionals perquè el pagament es faci a través de PayPal!', 'hide_from_activity' => 'Les etiquetes d\'osu!supporter en aquesta ordre no es mostren a les teves activitats recents.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Enviat via:', + 'shipping_to' => 'Enviament a:', + 'title' => 'Factura', 'title_compact' => 'factura', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'La teva comanda s\'ha cancel·lat', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Si no has sol·licitat una cancel·lació, posa't en contacte amb el :link indicant el teu número de comanda (núm. :order_number).", + 'link_text' => 'suport de la osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'La teva comanda ha estat lliurada! Esperem que l\'estiguis gaudint!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Si tens algun problema amb la teva compra, posa\'t en contacte amb el :link.', + 'link_text' => 'suport de la osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Estem processant la teva comanda!', + 'line_1' => 'Si us plau, espera una mica més perquè s\'enviï. La informació de seguiment apareixerà aquí una vegada que la comanda hagi estat processada i enviada. Això pot trigar fins a 5 dies (però normalment menys!) depenent de tan ocupats estiguem.', + 'line_2' => 'Enviem totes les comandes des del Japó usant una varietat de serveis d\'enviament depenent del pes i el valor. Aquesta àrea s\'actualitzarà amb detalls una vegada hàgim enviat la comanda.', ], 'processing' => [ 'title' => 'El teu pagament encara no s\'ha confirmat!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'La vostra comanda ha estat enviada!', + 'tracking_details' => 'Detalls de seguiment:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "No tenim detalls de seguiment, ja que enviem el teu paquet a través d'Air Mail, però pots esperar rebre'l en un termini d'1-3 setmanes. Per a Europa, de vegades les duanes poden endarrerir la comanda fora del nostre control. Si tens algun dubte, si us plau respon al correu electrònic de confirmació de la comanda que vas rebre :link.", + 'link_text' => 'envia\'ns un correu electrònic', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'No hi ha comandes per veure.', 'paid_on' => 'Comanda realitzada :date', 'resume' => 'Continuar pagament', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Enviament i manipulació', 'shopify_expired' => 'L\'enllaç de pagament per aquesta comanda ha expirat.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Subtotal', + 'total' => 'Total', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Comanda núm. 4', + 'payment_terms' => 'Condicions de pagament', + 'salesperson' => 'Venedor', + 'shipping_method' => 'Mètode d\'enviament', + 'shipping_terms' => 'Terminis d\'enviament', + 'title' => 'Detalls de la comanda', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Pagada', 'processing' => 'Pendent de confirmació', 'shipped' => 'Enviada', - 'title' => '', + 'title' => 'Estat de la comanda', ], 'thanks' => [ - 'title' => '', + 'title' => 'Moltes gràcies per la teva comanda!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Rebràs un correu electrònic de confirmació aviat. Si tens alguna pregunta, si us plau :link!', + 'link_text' => 'contacta amb nosaltres', ], ], ], @@ -167,8 +167,8 @@ 'name' => 'Nom', 'stock' => [ - 'out' => 'Aquest producte està esgotat. Torna més endavant!', - 'out_with_alternative' => 'Aquest producte està esgotat. Utilitza el desplegable per a seleccionar un altre tipus o torna més endavant!', + 'out' => 'Aquest element està esgotat. Torna més endavant!', + 'out_with_alternative' => 'Aquest element està esgotat. Utilitza el desplegable per a seleccionar un altre tipus o torna més endavant!', ], 'add_to_cart' => 'Afegeix a la cistella', @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Escriu un nom d\'usuari per comprovar la disponibilitat!', 'checking' => 'Comprovant la disponibilitat de :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Nom d\'usuari sol·licitat', + 'label' => 'Nou nom d\'usuari', + 'current' => 'El teu nom d\'usuari actual és «:username».', 'require_login' => [ '_' => 'Has de ser :link per a canviar el teu nom!', diff --git a/resources/lang/ca/users.php b/resources/lang/ca/users.php index 35878e817a9..999ced7fbb9 100644 --- a/resources/lang/ca/users.php +++ b/resources/lang/ca/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmaps: :counts', + 'modding_description_empty' => 'L\'usuari no té cap beatmap...', 'description' => [ '_' => 'Clasificació (:ruleset): :global | :country', diff --git a/resources/lang/cs/notifications.php b/resources/lang/cs/notifications.php index dcef370d690..ce7d4be2c68 100644 --- a/resources/lang/cs/notifications.php +++ b/resources/lang/cs/notifications.php @@ -52,14 +52,14 @@ 'beatmapset_discussion_post_new_compact' => 'Nový příspěvek od :username ":content"', 'beatmapset_discussion_post_new_compact_empty' => 'Nový příspěvek od :username', 'beatmapset_discussion_review_new' => 'Nová recenze na ":title" od :username obsahující problémy: :problems, návrhy: :suggestions, ocenění: :praises', - 'beatmapset_discussion_review_new_compact' => 'Nová recenze od :username obsahující problémy: :problems, návrhy: :suggestions, ocenění: :praises', + 'beatmapset_discussion_review_new_compact' => 'Nová recenze od :username obsahující :review_counts', 'beatmapset_discussion_unlock' => 'Diskuze ":title" byla odemčena', 'beatmapset_discussion_unlock_compact' => 'Diskuze byla odemčena', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited ocenění|:count_delimited ocenění', + 'problems' => ':count_delimited problém|:count_delimited problémy|:count_delimited problémů', + 'suggestions' => ':count_delimited návrh|:count_delimited návrhy|:count_delimited návrhů', ], ], diff --git a/resources/lang/cs/store.php b/resources/lang/cs/store.php index 372e4f00ea5..7e073c3aeec 100644 --- a/resources/lang/cs/store.php +++ b/resources/lang/cs/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Zaplatit', - 'empty_cart' => '', + 'empty_cart' => 'Odebrat všechny položky z košíku', 'info' => ':count_delimited položka v košíku ($:subtotal)|:count_delimited položky v košíku ($:subtotal)|:count_delimited položek v košíku ($:subtotal)', 'more_goodies' => 'Chci se ještě podívat na nějaké dobroty než dokončím objednávku', 'shipping_fees' => 'poplatky za dopravu', @@ -49,35 +49,35 @@ ], 'discount' => 'ušetři :percent%', - 'free' => '', + 'free' => 'zdarma!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Kontakt:', + 'date' => 'Datum:', 'echeck_delay' => 'Jelikož vaše platba byla prováděna službou eCheck, prosím, dejte nám až 10 dní na to, aby platba úspěšně prošla přes PayPal!', 'hide_from_activity' => 'osu!supporter tagy v této objednávce se nebudou zobrazovat v nedávných aktivitách.', 'sent_via' => '', 'shipping_to' => '', - 'title' => '', + 'title' => 'Faktura', 'title_compact' => 'faktura', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Vaše objednávka byla zrušena', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Pokud jste nepožádali o zrušení, kontaktujte prosím :link se svým číslem objednávky (#:order_number).", + 'link_text' => 'podporu osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Vaše objednávka byla doručena! Doufáme, že si ji užíváte!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Pokud máte nějaké problémy s vaším nákupem, kontaktujte prosím :link.', + 'link_text' => 'podporu osu!store', ], ], 'prepared' => [ - 'title' => '', + 'title' => 'Vaše objednávka se připravuje!', 'line_1' => '', 'line_2' => '', ], @@ -90,7 +90,7 @@ ], ], 'shipped' => [ - 'title' => '', + 'title' => 'Vaše objednávka byla odeslána!', 'tracking_details' => '', 'no_tracking_details' => [ '_' => "", @@ -110,16 +110,16 @@ 'resume' => 'Obnovit objednávku', 'shipping_and_handling' => '', 'shopify_expired' => 'Odkaz na objednávku pro tuto objednávku vypršel.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Mezisoučet', + 'total' => 'Celkem', 'details' => [ - 'order_number' => '', + 'order_number' => 'Objednávka č.', 'payment_terms' => '', 'salesperson' => '', 'shipping_method' => '', 'shipping_terms' => '', - 'title' => '', + 'title' => 'Detail objednávky', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Zaplaceno', 'processing' => 'Očekávající potvrzení', 'shipped' => 'Na cestě', - 'title' => '', + 'title' => 'Stav objednávky', ], 'thanks' => [ - 'title' => '', + 'title' => 'Děkujeme za Vaši objednávku!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Brzy obdržíte potvrzovací email. Pokud máte nějaké dotazy, :link prosím!', + 'link_text' => 'kontaktujte nás', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Zadej uživatelské jméno pro kontrolu dostupnosti!', 'checking' => 'Probíhá kontrola dostupnosti uživatelského jména :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Kýžené uživatelské jméno', + 'label' => 'Nové uživatelské jméno', + 'current' => 'Tvoje aktuální uživatelské jméno je ":username".', 'require_login' => [ '_' => 'Pro změnu uživatelského jména se musíš :link!', diff --git a/resources/lang/cs/users.php b/resources/lang/cs/users.php index 157690ac1c9..36042000f20 100644 --- a/resources/lang/cs/users.php +++ b/resources/lang/cs/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmap: :counts', + 'modding_description_empty' => 'Uživatel nemá žádné beatmapy...', 'description' => [ '_' => 'Umístění (:ruleset): :global | :country', @@ -422,7 +422,7 @@ 'not_found' => [ 'reason_1' => 'Možná si změnil uživatelské jméno.', 'reason_2' => 'Účet může být dočasně nedostupný z důvodu problémů s bezpečností, nebo zneužitím.', - 'reason_3' => 'Možná jste se přepsal!', + 'reason_3' => 'Možná jsi se přepsal!', 'reason_header' => 'Existuje několik možných důvodů:', 'title' => 'Uživatel nebyl nalezen! ;_;', ], diff --git a/resources/lang/de/comments.php b/resources/lang/de/comments.php index 8125fe8bd13..3af5570d74d 100644 --- a/resources/lang/de/comments.php +++ b/resources/lang/de/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'Kommentar von :user', ], 'placeholder' => [ diff --git a/resources/lang/de/notifications.php b/resources/lang/de/notifications.php index 6c9e16212ac..f6be39ea699 100644 --- a/resources/lang/de/notifications.php +++ b/resources/lang/de/notifications.php @@ -51,15 +51,15 @@ 'beatmapset_discussion_post_new_empty' => 'Neuer Beitrag auf ":title" von :username', 'beatmapset_discussion_post_new_compact' => 'Neuer Beitrag von :username: ":content"', 'beatmapset_discussion_post_new_compact_empty' => 'Neuer Beitrag von :username', - 'beatmapset_discussion_review_new' => 'Neue Rezension zu ":title" von :username mit Problemen: :problems, Vorschlägen: :suggestions, Lob: :praises', - 'beatmapset_discussion_review_new_compact' => 'Neue Rezension von :username mit Problemen: :problems, Vorschlägen: :suggestions, Lob: :praises', + 'beatmapset_discussion_review_new' => 'Neue Rezension zu ":title" von :username mit :review_counts', + 'beatmapset_discussion_review_new_compact' => 'Neue Rezension von :username mit :review_counts', 'beatmapset_discussion_unlock' => 'Diskussion auf ":title" wurde freigegeben', 'beatmapset_discussion_unlock_compact' => 'Die Diskussion ist freigegeben', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited Zuspruch|:count_delimited Zusprüchen', + 'problems' => ':count_delimited Problem|:count_delimited Problemen', + 'suggestions' => ':count_delimited Vorschlag|:count_delimited Vorschlägen', ], ], diff --git a/resources/lang/de/store.php b/resources/lang/de/store.php index 052f758980b..4147ab54e28 100644 --- a/resources/lang/de/store.php +++ b/resources/lang/de/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Zur Kasse', - 'empty_cart' => '', + 'empty_cart' => 'Alle Artikel aus dem Warenkorb entfernen', 'info' => ':count_delimited Artikel im Warenkorb ($:subtotal)|:count_delimited Artikel im Warenkorb ($:subtotal)', 'more_goodies' => 'Ich möchte mich vor meiner Bestellung noch etwas umschauen', 'shipping_fees' => 'Versandkosten', @@ -49,37 +49,37 @@ ], 'discount' => 'Spare :percent%', - 'free' => '', + 'free' => 'kostenlos!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Kontakt:', + 'date' => 'Datum:', 'echeck_delay' => 'Da es sich bei deiner Zahlung um einen eCheck handelt, kannst du bis zu 10 zusätzliche Tage einplanen, um die Zahlung über PayPal abzuwickeln!', 'hide_from_activity' => 'osu!supporter-Tags in dieser Bestellung werden nicht in deinen letzten Aktivitäten angezeigt.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', - 'title_compact' => 'rechnung', + 'sent_via' => 'Versand durch:', + 'shipping_to' => 'Lieferung an:', + 'title' => 'Rechnung', + 'title_compact' => 'Rechnung', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Deine Bestellung wurde storniert', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Wenn du keine Stornierung angefordert hast, kontaktiere bitte den :link und nenne deine Bestellnummer (#:order_number).", + 'link_text' => 'osu!store-Support', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Deine Bestellung wurde zugestellt! Wir hoffen, dass du damit Spaß hast!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Wenn du irgendwelche Probleme mit deinem Kauf hast, kontaktiere bitte den :link.', + 'link_text' => 'osu!store-Support', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Deine Bestellung wird derzeit bearbeitet!', + 'line_1' => 'Bitte warte noch etwas, bis das Paket ausgeliefert wird. Informationen zur Verfolgung erscheinen hier, sobald die Bestellung bearbeitet und versandt wurde. Dies kann bis zu 5 Tage dauern (in der Regel aber weniger!), je nachdem, wie viel wir zu tun haben.', + 'line_2' => 'Wir versenden alle Bestellungen aus Japan je nach Gewicht und Wert mit verschiedenen Versanddiensten. Dieser Bereich wird aktualisiert, sobald wir die Bestellung ausgeliefert haben.', ], 'processing' => [ 'title' => 'Deine Zahlung wurde noch nicht bestätigt!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Deine Bestellung wurde versandt!', + 'tracking_details' => 'Hier sind Informationen zur Bestellung:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Uns stehen keine Tracking-Daten zur Verfügung, da wir das Paket per Air Mail versandt haben. Das Paket sollte jedoch innerhalb von 1 bis 3 Wochen ankommen. In Europa kann der Zoll manchmal die Bestellung außerhalb unserer Kontrolle verzögern. Wenn du irgendwelche Bedenken hast, antworte bitte auf die Bestätingsmail, die du erhalten hast (oder :link).", + 'link_text' => 'sende uns eine E-Mail', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Keine Bestellungen zum Anzeigen.', 'paid_on' => 'Bestellung :date aufgegeben', 'resume' => 'Bezahlung fortsetzen', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Lieferung und Verarbeitung', 'shopify_expired' => 'Der Zahlungslink für diese Bestellung ist abgelaufen.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Zwischensumme', + 'total' => 'Summe', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Bestellung #', + 'payment_terms' => 'Zahlungsbedingungen', + 'salesperson' => 'Verkäufer', + 'shipping_method' => 'Versandmethode', + 'shipping_terms' => 'Versandbedingungen', + 'title' => 'Bestelldetails', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Bezahlt', 'processing' => 'Bestätigung ausstehend', 'shipped' => 'In Bearbeitung', - 'title' => '', + 'title' => 'Bestellungsstatus', ], 'thanks' => [ - 'title' => '', + 'title' => 'Vielen Dank für deine Bestellung!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Du erhältst bald eine Bestätigungsmail. Wenn du Fragen hast, dann :link bitte!', + 'link_text' => 'kontaktiere uns', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Gib einen Nutzernamen ein, um die Verfügbarkeit zu prüfen!', 'checking' => 'Prüfe Verfügbarkeit von :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Gewünschter Benutzername', + 'label' => 'Neuer Benutzername', + 'current' => 'Dein aktueller Benutzername ist ":username".', 'require_login' => [ '_' => 'Um deinen Namen zu ändern, musst du :link sein!', diff --git a/resources/lang/de/users.php b/resources/lang/de/users.php index 3cab2a482e2..4b4da619d8d 100644 --- a/resources/lang/de/users.php +++ b/resources/lang/de/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmaps: :counts', + 'modding_description_empty' => 'Der Nutzer hat keine Beatmaps.', 'description' => [ '_' => 'Rang (:ruleset): :global | :country', diff --git a/resources/lang/es/beatmaps.php b/resources/lang/es/beatmaps.php index ffc1896fe29..2921a6824ad 100644 --- a/resources/lang/es/beatmaps.php +++ b/resources/lang/es/beatmaps.php @@ -143,7 +143,7 @@ 'deleted' => 'Eliminado', 'mapper_notes' => 'Notas', 'mine' => 'Mío', - 'pending' => 'Pendientes', + 'pending' => 'Pendiente', 'praises' => 'Elogios', 'resolved' => 'Resuelto', 'total' => 'Todo', @@ -290,7 +290,7 @@ 'leaderboard' => 'Tiene tabla de clasificación', 'loved' => 'Amados', 'mine' => 'Mis mapas', - 'pending' => 'Pendiente', + 'pending' => 'Pendientes', 'wip' => 'WIP', 'qualified' => 'Calificados', 'ranked' => 'Clasificados', diff --git a/resources/lang/es/beatmapsets.php b/resources/lang/es/beatmapsets.php index 9c805ec3613..9e6d2d4eb86 100644 --- a/resources/lang/es/beatmapsets.php +++ b/resources/lang/es/beatmapsets.php @@ -112,7 +112,7 @@ '_' => 'Este mapa está actualmente :status.', 'status' => [ - 'pending' => 'pendientes', + 'pending' => 'pendiente', 'qualified' => 'calificado', 'wip' => 'en progreso', ], @@ -221,7 +221,7 @@ 'loved' => 'Amado', 'qualified' => 'Calificado', 'wip' => 'WIP', - 'pending' => 'Pendientes', + 'pending' => 'Pendiente', 'graveyard' => 'Abandonado', ], ], diff --git a/resources/lang/es/comments.php b/resources/lang/es/comments.php index a20aa66aea7..2bd722428b8 100644 --- a/resources/lang/es/comments.php +++ b/resources/lang/es/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'comentario por :user', ], 'placeholder' => [ diff --git a/resources/lang/es/notifications.php b/resources/lang/es/notifications.php index 22f2dece4be..b04bb1a1730 100644 --- a/resources/lang/es/notifications.php +++ b/resources/lang/es/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'La discusión se ha desbloqueado', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited elogio|:count_delimited elogios', + 'problems' => ':count_delimited problema|:count_delimited problemas', + 'suggestions' => ':count_delimited sugerencia|:count_delimited sugerencias', ], ], diff --git a/resources/lang/es/store.php b/resources/lang/es/store.php index 435a294ebf0..468e914e745 100644 --- a/resources/lang/es/store.php +++ b/resources/lang/es/store.php @@ -6,8 +6,8 @@ return [ 'cart' => [ 'checkout' => 'Pagar', - 'empty_cart' => '', - 'info' => ':count_delimited producto en el carrito ($:subtotal)|:count_delimited productos en el carrito ($:subtotal)', + 'empty_cart' => 'Eliminar todos los elementos del carrito', + 'info' => ':count_delimited elemento en el carrito ($:subtotal)|:count_delimited elementos en el carrito ($:subtotal)', 'more_goodies' => 'Deseo revisar más productos antes de completar la orden', 'shipping_fees' => 'gastos de envío', 'title' => 'Carrito de compras', @@ -49,37 +49,37 @@ ], 'discount' => 'ahorra un :percent%', - 'free' => '', + 'free' => '¡gratis!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Contacto:', + 'date' => 'Fecha:', 'echeck_delay' => 'Como su pago fue un eCheck, ¡por favor permita hasta 10 días adicionales para que el pago se realice a través de PayPal!', 'hide_from_activity' => 'las etiquetas osu!supporter en esta orden no se muestran en tus actividades recientes.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Enviado vía:', + 'shipping_to' => 'Envío a:', + 'title' => 'Factura', 'title_compact' => 'factura', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Tu pedido ha sido cancelado', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Si no has solicitado una cancelación, ponte en contacto con el :link indicando tu número de pedido (n.º :order_number).", + 'link_text' => 'soporte de la osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => '¡Tu pedido ha sido entregado! ¡Esperamos que lo estés disfrutando!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Si tienes algún problema con tu compra, ponte en contacto con el :link.', + 'link_text' => 'soporte de la osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => '¡Tu pedido está siendo preparado!', + 'line_1' => 'Por favor, espera un poco más para que se envíe. La información de seguimiento aparecerá aquí una vez que el pedido haya sido procesado y enviado. Esto puede tardar hasta 5 días (¡pero normalmente menos!) dependiendo de lo ocupados que estemos.', + 'line_2' => 'Enviamos todos los pedidos desde Japón usando una variedad de servicios de envío dependiendo del peso y el valor. Esta área se actualizará con detalles una vez que hayamos enviado el pedido.', ], 'processing' => [ 'title' => '¡Aún no se ha confirmado tu pago!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => '¡Tu pedido ha sido enviado!', + 'tracking_details' => 'Detalles de seguimiento:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "No tenemos detalles de seguimiento, ya que enviamos tu paquete a través de Air Mail, pero puedes esperar recibirlo en un plazo de 1-3 semanas. Para Europa, a veces las aduanas pueden retrasar el pedido fuera de nuestro control. Si tienes alguna duda, por favor responde al correo electrónico de confirmación del pedido que recibiste :link.", + 'link_text' => 'envíanos un correo electrónico', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'No hay órdenes para ver.', 'paid_on' => 'Orden realizada :date', 'resume' => 'Reanudar pago', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Envío y manipulación', 'shopify_expired' => 'El enlace de pago de esta orden ha expirado.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Subtotal', + 'total' => 'Total', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Pedido n.º', + 'payment_terms' => 'Términos de pago', + 'salesperson' => 'Vendedor', + 'shipping_method' => 'Método de envío', + 'shipping_terms' => 'Términos de envío', + 'title' => 'Detalles del pedido', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Pagada', 'processing' => 'Confirmación pendiente', 'shipped' => 'En tránsito', - 'title' => '', + 'title' => 'Estado del pedido', ], 'thanks' => [ - 'title' => '', + 'title' => '¡Muchas gracias por tu pedido!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Recibirás un correo electrónico de confirmación pronto. ¡Si tienes alguna pregunta, por favor :link!', + 'link_text' => 'contáctanos', ], ], ], @@ -167,8 +167,8 @@ 'name' => 'Nombre', 'stock' => [ - 'out' => 'Este producto está actualmente agotado. ¡Vuelva más tarde!', - 'out_with_alternative' => 'Lamentablemente, este artículo esta agotado. ¡Usa el menú desplegable para elegir un tipo diferente o vuelve más tarde!', + 'out' => 'Este elemento está actualmente agotado. ¡Vuelve más tarde!', + 'out_with_alternative' => 'Desafortunadamente, este elemento está agotado. ¡Usa el menú desplegable para elegir un tipo diferente o vuelve más tarde!', ], 'add_to_cart' => 'Agregar al carrito', @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => '¡Escribe un nombre de usuario para revisar su disponibilidad!', 'checking' => 'Revisando la disponibilidad de :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Nombre de usuario solicitado', + 'label' => 'Nuevo nombre de usuario', + 'current' => 'Tu nombre de usuario actual es «:username».', 'require_login' => [ '_' => '¡Tienes que tener una :link para cambiar tu nombre de usuario!', diff --git a/resources/lang/es/users.php b/resources/lang/es/users.php index e31f5686dbd..68019f12eed 100644 --- a/resources/lang/es/users.php +++ b/resources/lang/es/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Mapas: :counts', + 'modding_description_empty' => 'El usuario no tiene ningún beatmap...', 'description' => [ '_' => 'Clasificación (:ruleset): :global | :country', diff --git a/resources/lang/fi/artist.php b/resources/lang/fi/artist.php index 64588b67247..8d3627eb064 100644 --- a/resources/lang/fi/artist.php +++ b/resources/lang/fi/artist.php @@ -13,7 +13,7 @@ 'beatmaps' => [ '_' => 'Beatmapit', - 'download' => 'Lataa Beatmap-Pohja', + 'download' => 'Lataa rytmikarttapohja', 'download-na' => 'rytmikarttapohja ei vielä saatavilla', ], diff --git a/resources/lang/fi/beatmap_discussions.php b/resources/lang/fi/beatmap_discussions.php index cf4e9930c50..9982870b548 100644 --- a/resources/lang/fi/beatmap_discussions.php +++ b/resources/lang/fi/beatmap_discussions.php @@ -31,12 +31,12 @@ 'username' => 'Käyttäjänimi', 'beatmapset_status' => [ - '_' => 'Beatmapin tila', + '_' => 'Rytmikartan tila', 'all' => 'Kaikki', 'disqualified' => 'Epäkelpuutettu', 'never_qualified' => 'Ei koskaan kelpuutettu', 'qualified' => 'Kelpuutettu', - 'ranked' => 'Hyväksytty', + 'ranked' => 'Pisteytetty', ], 'user' => [ diff --git a/resources/lang/fi/beatmappacks.php b/resources/lang/fi/beatmappacks.php index 189d0b5690e..809649ed5f7 100644 --- a/resources/lang/fi/beatmappacks.php +++ b/resources/lang/fi/beatmappacks.php @@ -28,7 +28,7 @@ ], 'no_diff_reduction' => [ '_' => ':link ei voi käyttää tämän paketin suorittamiseen.', - 'link' => 'Vaikeusastetta vähentäviä modeja', + 'link' => 'Vaikeusastetta vähentäviä muunnelmia', ], ], @@ -36,7 +36,7 @@ 'artist' => 'Esittäjä/Albumi', 'chart' => 'Kohdevaloissa', 'featured' => 'Esitelty artisti', - 'loved' => 'Project Loved', + 'loved' => 'Project Rakastettu', 'standard' => 'Tavallinen', 'theme' => 'Teema', 'tournament' => 'Turnaus', diff --git a/resources/lang/fi/beatmaps.php b/resources/lang/fi/beatmaps.php index 6f79eeb0bcf..b7ed4bf2930 100644 --- a/resources/lang/fi/beatmaps.php +++ b/resources/lang/fi/beatmaps.php @@ -153,7 +153,7 @@ 'approved' => 'Tämä rytmikartta hyväksyttiiin :date!', 'graveyard' => "Tätä beatmappia ei ole päivitetty sitten :date ja sen tekijä on todennäköisesti hylännyt sen...", 'loved' => 'Tämä rytmikartta lisättiin rakastettuihin :date!', - 'ranked' => 'Tämä beatmap hyväksyttiin :date!', + 'ranked' => 'Tämä rytmikartta rankattiin :date!', 'wip' => 'Huomaa: Tämän rytmikartan tekijä on merkannut sen keskeneräiseksi.', ], @@ -212,7 +212,7 @@ 'unresolved_issues' => 'Vanhat ongelmat on ratkaistava ensin.', 'rank_estimate' => [ - '_' => 'Tämä kartta tulee arvion perusteella rankatuksi:date, jos ongelmia ei löydy. Se on :position. :queue.', + '_' => 'Tämä kartta tulee arvion perusteella rankatuksi :date, jos ongelmia ei löydy. Se on :position. :queue.', 'on' => ':date', 'queue' => 'hyväksytysjonossa', 'soon' => 'pian', @@ -224,9 +224,9 @@ ], 'reset_confirm' => [ - 'disqualify' => 'Oletko varma? Tämä poistaa beatmapin esihyväksytyistä ja kumoaa suositusprosessin.', + 'disqualify' => 'Oletko varma? Tämä poistaa rytmikartan kelpuutetuista ja kumoaa ehdollepanoprosessin.', 'nomination_reset' => 'Oletko varma? Uuden ongelman lähettäminen kumoaa suositusprosessin.', - 'problem_warning' => 'Oletko varma rapoitoidaksesi ongelman tässä beatmapissa? Tämä hälyttää Beatmap nimittäjät.', + 'problem_warning' => 'Oletko varma, että haluat ilmoittaa ongelmasta tässä rytmikartassa? Tämä aiheuttaa hälytyksen rytmikarttojen ehdollepanijoille.', ], ], @@ -234,7 +234,7 @@ 'search' => [ 'prompt' => 'kirjoita hakusanoja...', 'login_required' => 'Kirjaudu sisään hakeaksesi.', - 'options' => 'Enemmän Hakuasetuksia', + 'options' => 'Lisää hakuvaihtoehtoja', 'supporter_filter' => 'Tunnisteella :filters rajaaminen vaatii aktiivisen osu!supporter-tagin', 'not-found' => 'ei tuloksia', 'not-found-quote' => '... mitään ei löytynyt.', @@ -255,7 +255,7 @@ 'difficulty' => 'Vaikeustaso', 'favourites' => 'Suosikit', 'updated' => 'Päivitetty', - 'ranked' => 'Hyväksytty', + 'ranked' => 'Pisteytetty', 'rating' => 'Luokitus', 'plays' => 'Pelikerrat', 'relevance' => 'Osuvuus', @@ -289,11 +289,11 @@ 'graveyard' => 'Hautausmaa', 'leaderboard' => 'Tulostaulukollinen', 'loved' => 'Rakastettu', - 'mine' => 'Mappini', + 'mine' => 'Omat kartat', 'pending' => 'Vireillä', 'wip' => 'Työn alla', - 'qualified' => 'Esihyväksytty', - 'ranked' => 'Hyväksytty', + 'qualified' => 'Kelpuutettu', + 'ranked' => 'Pisteytetty', ], 'genre' => [ 'any' => 'Kaikki', diff --git a/resources/lang/fi/beatmapset_watches.php b/resources/lang/fi/beatmapset_watches.php index 43e394753d3..f8f825e4c27 100644 --- a/resources/lang/fi/beatmapset_watches.php +++ b/resources/lang/fi/beatmapset_watches.php @@ -6,7 +6,7 @@ return [ 'index' => [ 'description' => 'Seuraat näiden beatmappien keskusteluja. Sinulle huomautetaan uusista viesteistä ja päivityksistä.', - 'title_compact' => 'rytmikarttakeskustelujen seurantalista', + 'title_compact' => 'rytmikarttojen keskustelujen seurantalista', 'counts' => [ 'total' => 'Rytmikarttoja seurattu', diff --git a/resources/lang/fi/beatmapsets.php b/resources/lang/fi/beatmapsets.php index 8a5be92e1e0..4a1d8c6631b 100644 --- a/resources/lang/fi/beatmapsets.php +++ b/resources/lang/fi/beatmapsets.php @@ -151,7 +151,7 @@ 'buttons' => [ 'disable' => 'Poista varoitus käytöstä', - 'listing' => 'Takaisin rytmikarttalistaukseen', + 'listing' => 'Rytmikarttojen listaukseen', 'show' => 'Näytä', ], ], @@ -168,7 +168,7 @@ 'headers' => [ 'accuracy' => 'Tarkkuus', - 'combo' => 'Maksimikombo', + 'combo' => 'Suurin iskuputki', 'miss' => 'Ohi', 'mods' => 'Muunnelmat', 'pin' => 'Kiinnitä', @@ -185,7 +185,7 @@ 'friend' => 'Kukaan kavereistasi ei vielä ole saanut tulosta tässä mapissa!', 'global' => 'Tuloksia ei ole. Voisit hankkia niitä.', 'loading' => 'Ladataan tuloksia...', - 'unranked' => 'Rankkaamaton rytmikartta.', + 'unranked' => 'Pisteyttämätön rytmikartta.', ], 'score' => [ 'first' => 'Johdossa', @@ -203,7 +203,7 @@ 'drain' => 'Terveyden valutus', 'accuracy' => 'Tarkkuus', 'ar' => 'Lähestymisnopeus', - 'stars' => 'Vaikeustaso', + 'stars' => 'Tähtiluokitus', 'total_length' => 'Pituus', 'bpm' => 'BPM', 'count_circles' => 'Ympyröiden määrä', diff --git a/resources/lang/fi/comments.php b/resources/lang/fi/comments.php index 74e434b831a..63287b7b248 100644 --- a/resources/lang/fi/comments.php +++ b/resources/lang/fi/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'käyttäjän :user kommentti', ], 'placeholder' => [ diff --git a/resources/lang/fi/common.php b/resources/lang/fi/common.php index a21e3eabeb5..34c5808f05f 100644 --- a/resources/lang/fi/common.php +++ b/resources/lang/fi/common.php @@ -40,7 +40,7 @@ 'post' => 'Lähetä', 'read_more' => 'lue lisää', 'reply' => 'Vastaa', - 'reply_reopen' => 'Vastaa ja uudelleenavaa', + 'reply_reopen' => 'Vastaa ja avaa uudelleen', 'reply_resolve' => 'Vastaa ja merkitse ratkaistuksi', 'reset' => 'Nollaa', 'restore' => 'Palauta', @@ -66,12 +66,12 @@ ], 'count' => [ - 'badges' => ':count kunniamerkki|:count kunniamerkkiä', + 'badges' => ':count_delimited kunniamerkki|:count_delimited kunniamerkkiä', 'days' => ':count päivä|:count päivää', 'hour_short_unit' => 't|t', 'hours' => ':count tunti|:count tuntia', 'item' => ':count kappale|:count kappaletta', - 'minute_short_unit' => 'm | m', + 'minute_short_unit' => 'min|min', 'minutes' => ':count_delimited minuutti|:count_delimited minuuttia', 'months' => ':count kuukausi|:count kuukautta', 'notifications' => ':count_delimited ilmoitus|:count_delimited ilmoitusta', diff --git a/resources/lang/fi/community.php b/resources/lang/fi/community.php index 9c283de4a28..da4fda72562 100644 --- a/resources/lang/fi/community.php +++ b/resources/lang/fi/community.php @@ -7,7 +7,7 @@ 'support' => [ 'convinced' => [ 'title' => 'Vakuutuin! :D', - 'support' => 'tue osua!', + 'support' => 'tue osu!a', 'gift' => 'tai lahjoita Tukija toiselle pelaajalle', 'instructions' => 'klikkaa sydäntä jatkaaksesi osu!kauppaan', ], diff --git a/resources/lang/fi/events.php b/resources/lang/fi/events.php index 487a0b1d8fb..caad9085257 100644 --- a/resources/lang/fi/events.php +++ b/resources/lang/fi/events.php @@ -23,7 +23,7 @@ 'approved' => 'vahvistettu', 'loved' => 'rakastettu', 'qualified' => 'kelpuutettu', - 'ranked' => 'hyväksytty', + 'ranked' => 'pisteytetty', ], 'value' => [ diff --git a/resources/lang/fi/follows.php b/resources/lang/fi/follows.php index 9e4b305c205..8352184478a 100644 --- a/resources/lang/fi/follows.php +++ b/resources/lang/fi/follows.php @@ -33,6 +33,6 @@ ], 'modding' => [ - 'title' => 'rytmikarttakeskustelu', + 'title' => 'rytmikartan keskustelu', ], ]; diff --git a/resources/lang/fi/home.php b/resources/lang/fi/home.php index a28c8f39479..ecdf855fad3 100644 --- a/resources/lang/fi/home.php +++ b/resources/lang/fi/home.php @@ -113,7 +113,7 @@ 'beatmaps' => [ 'title' => 'hanki beatmappeja', 'description' => [ - '_' => ':browse käyttäjien luomaa laajaa beatmapkokoelmaa ja ryhdy pelaamaan!', + '_' => ':browse käyttäjien luomaa laajaa rytmikarttakokoelmaa ja ryhdy pelaamaan!', 'browse' => 'selaa', ], ], @@ -134,7 +134,7 @@ ], ], 'beatmaps' => [ - 'new' => 'Uudet Hyväksytyt Beatmapit', + 'new' => 'Uudet rankatut rytmikartat', 'popular' => 'Suositut rytmikartat', 'by_user' => 'tehnyt :user', ], diff --git a/resources/lang/fi/layout.php b/resources/lang/fi/layout.php index d4b1d3b10f2..6455c45463e 100644 --- a/resources/lang/fi/layout.php +++ b/resources/lang/fi/layout.php @@ -67,7 +67,7 @@ 'menu' => [ 'beatmaps' => [ - '_' => 'beatmapit', + '_' => 'rytmikartat', ], 'community' => [ '_' => 'yhteisö', diff --git a/resources/lang/fi/legacy_api_key.php b/resources/lang/fi/legacy_api_key.php index 91a831cab03..305ad0170bc 100644 --- a/resources/lang/fi/legacy_api_key.php +++ b/resources/lang/fi/legacy_api_key.php @@ -4,12 +4,12 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'new' => 'Uusi legacy-rajapinnan avain', + 'new' => 'Uusi perinnerajapinnan avain', 'none' => 'Ei avainta.', 'docs' => [ - '_' => 'Dokumentaatio on saatavilla osoitteessa :github.', - 'github' => 'GitHub', + '_' => 'Dokumentaatio on saatavilla :github.', + 'github' => 'GitHubissa', ], 'form' => [ diff --git a/resources/lang/fi/legacy_irc_key.php b/resources/lang/fi/legacy_irc_key.php index a5c8df7c7a8..2ce3cf1e9c7 100644 --- a/resources/lang/fi/legacy_irc_key.php +++ b/resources/lang/fi/legacy_irc_key.php @@ -5,7 +5,7 @@ return [ 'confirm_new' => 'Luo uusi IRC-salasana?', - 'new' => 'Uusi IRC-salasana', + 'new' => 'Uusi IRC\'n perinnesalasana', 'none' => 'IRC-salasanaa ei asetettu.', 'form' => [ diff --git a/resources/lang/fi/livestreams.php b/resources/lang/fi/livestreams.php index 7498dbcd410..9c39c046f59 100644 --- a/resources/lang/fi/livestreams.php +++ b/resources/lang/fi/livestreams.php @@ -11,7 +11,7 @@ 'top-headers' => [ 'headline' => 'Suorat lähetykset', - 'description' => 'Tiedot noudetaan twitch.tv\'n listauksesta viiden minuutin välein. Voit vapaasti aloittaa suoran lähetyksen ja saada itsesi listalle! Lisää tietoja aloittelemisesta löydät :link.', + 'description' => 'Tiedot noudetaan twitch.tv\'n listauksesta viiden minuutin välein. Voit vapaasti aloittaa suoran lähetyksen ja päästä listalle! Lisää tietoja aloittelemisesta löydät :link.', 'link' => 'suoraa lähetystä käsittelevästä wikiartikkelista', ], diff --git a/resources/lang/fi/matches.php b/resources/lang/fi/matches.php index 85c82984d11..a8587886cca 100644 --- a/resources/lang/fi/matches.php +++ b/resources/lang/fi/matches.php @@ -33,7 +33,7 @@ 'score' => [ 'stats' => [ 'accuracy' => 'Tarkkuus', - 'combo' => 'Kombo', + 'combo' => 'Iskuputki', 'score' => 'Pisteet', ], ], @@ -54,7 +54,7 @@ 'scoring-type' => [ 'score' => 'Korkeimmat Pisteet', 'accuracy' => 'Korkein tarkkuus', - 'combo' => 'Korkein combo', + 'combo' => 'Korkein iskuputki', 'scorev2' => 'Pisteytys V2', ], ], diff --git a/resources/lang/fi/model_validation.php b/resources/lang/fi/model_validation.php index 9100cf9216e..7e5ac877d81 100644 --- a/resources/lang/fi/model_validation.php +++ b/resources/lang/fi/model_validation.php @@ -12,8 +12,8 @@ 'wrong_confirmation' => 'Tarkistus ei täsmää.', 'beatmapset_discussion' => [ - 'beatmap_missing' => 'Aikaleima on määritelty, mutta beatmap puuttuu.', - 'beatmapset_no_hype' => "Beatmappia ei voi hurrata.", + 'beatmap_missing' => 'Aikaleima on määritelty, mutta rytmikartta puuttuu.', + 'beatmapset_no_hype' => "Rytmikarttaa ei voida hurrata.", 'hype_requires_null_beatmap' => 'Hurraus täytyy tehdä Yleiset (kaikki vaikeustasot) -osiossa.', 'invalid_beatmap_id' => 'Määritelly vaikeustaso on virheellinen.', 'invalid_beatmapset_id' => 'Epäkelpo rytmikartta määritelty.', @@ -25,7 +25,7 @@ ], 'hype' => [ - 'discussion_locked' => "Tämän beatmapin keskustelu on lukittu eikä sitä voi hurrata", + 'discussion_locked' => "Tämän rytmikartan keskustelu on lukittu eikä sitä voi hurrata", 'guest' => 'Sinun on kirjauduttava sisään hurrataksesi.', 'hyped' => 'Hurrasit jo tätä rytmikarttaa.', 'limit_exceeded' => 'Olet käyttänyt kaikki hurrauksesi.', @@ -110,10 +110,10 @@ ], 'legacy_api_key' => [ - 'exists' => 'Käyttäjää kohti annetaan tällä hetkellä vain yksi API-avain.', + 'exists' => 'Käyttäjää kohti annetaan tällä hetkellä vain yksi rajapinnan avain.', 'attributes' => [ - 'api_key' => 'rajapinta-avain', + 'api_key' => 'rajapinnan avain', 'app_name' => 'sovelluksen nimi', 'app_url' => 'sovelluksen url', ], diff --git a/resources/lang/fi/multiplayer.php b/resources/lang/fi/multiplayer.php index 7790e713a6c..bf4ec4cca1d 100644 --- a/resources/lang/fi/multiplayer.php +++ b/resources/lang/fi/multiplayer.php @@ -5,15 +5,15 @@ return [ 'empty' => [ - '_' => 'Ei vielä yhtään osu!(lazer) :type_group pelattu!', - 'playlists' => 'soittolista', - 'realtime' => 'moninpeli', + '_' => 'Ei vielä osu!(lazer) -:type_group pelattu!', + 'playlists' => 'soittolistoja', + 'realtime' => 'moninpelejä', ], 'room' => [ 'hosted_by' => 'isännöi :user', 'invalid_password' => 'Virheellinen huoneen salasana', - 'map_count' => ':count_delimited mappi|:count_delimited mappia', + 'map_count' => ':count_delimited kartta|:count_delimited karttaa', 'player_count' => ':count_delimited pelaaja|:count_delimited pelaajaa', 'time_left' => ':time jäljellä', @@ -22,7 +22,7 @@ ], 'status' => [ - 'active' => 'aktiivinen', + 'active' => 'avoinna', 'ended' => 'päättynyt', 'soon' => 'päättyy kohta', ], diff --git a/resources/lang/fi/notifications.php b/resources/lang/fi/notifications.php index 001fa1e7856..37c04b5ced2 100644 --- a/resources/lang/fi/notifications.php +++ b/resources/lang/fi/notifications.php @@ -44,7 +44,7 @@ ], 'beatmapset_discussion' => [ - '_' => 'Rytmikarttakeskustelu', + '_' => 'Rytmikartan keskustelu', 'beatmapset_discussion_lock' => 'Keskustelu kohteessa ":title" on lukittu', 'beatmapset_discussion_lock_compact' => 'Keskustelu on lukittu', 'beatmapset_discussion_post_new' => 'Uusi viesti kohteessa ":title" käyttäjältä :username: ":content"', @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'Keskustelu on avattu', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited kehu|:count_delimited kehua', + 'problems' => ':count_delimited ongelma|:count_delimited ongelmaa', + 'suggestions' => ':count_delimited ehdotus|:count_delimited ehdotusta', ], ], @@ -72,7 +72,7 @@ ], 'beatmapset_state' => [ - '_' => 'Beatmapin tila muutettu', + '_' => 'Rytmikartan tilanne muuttui', 'beatmapset_disqualify' => '":title" on hylätty', 'beatmapset_disqualify_compact' => 'Rytmikartta epäkelpuutettiin', 'beatmapset_love' => '":title" ylennettiin rakastetuksi', diff --git a/resources/lang/fi/page_title.php b/resources/lang/fi/page_title.php index 328764cd918..8125eb9b979 100644 --- a/resources/lang/fi/page_title.php +++ b/resources/lang/fi/page_title.php @@ -35,23 +35,23 @@ '_' => 'esitellyt artistit', ], 'beatmap_discussion_posts_controller' => [ - '_' => 'viestit rytmikarttakeskustelussa', + '_' => 'viestit rytmikarttojen keskusteluissa', ], 'beatmap_discussions_controller' => [ - '_' => 'rytmikarttakeskustelut', + '_' => 'rytmikarttojen keskustelut', ], 'beatmap_packs_controller' => [ '_' => 'rytmikarttapaketit', ], 'beatmapset_discussion_votes_controller' => [ - '_' => 'äänet rytmikarttakeskusteluissa', + '_' => 'äänet rytmikarttojen keskusteluissa', ], 'beatmapset_events_controller' => [ '_' => 'rytmikarttahistoria', ], 'beatmapsets_controller' => [ - 'discussion' => 'rytmikarttakeskustelu', - 'index' => 'rytmikarttalistaus', + 'discussion' => 'rytmikartan keskustelu', + 'index' => 'rytmikarttojen listaus', 'show' => 'rytmikartan tiedot', ], 'changelog_controller' => [ @@ -107,7 +107,7 @@ '_' => 'turnaukset', ], 'users_controller' => [ - '_' => 'pelaajatiedot', + '_' => 'pelaajan tiedot', 'create' => 'luo tili', 'disabled' => 'huomautus', ], @@ -125,7 +125,7 @@ ], 'users' => [ 'modding_history_controller' => [ - '_' => 'modaajatiedot', + '_' => 'modaajan tiedot', ], 'multiplayer_controller' => [ '_' => 'moninpelihistoria', diff --git a/resources/lang/fi/rankings.php b/resources/lang/fi/rankings.php index 525e0538a8e..3d290e356ca 100644 --- a/resources/lang/fi/rankings.php +++ b/resources/lang/fi/rankings.php @@ -54,7 +54,7 @@ 'play_count' => 'Pelikerrat', 'performance' => 'Suorituskyky', 'total_score' => 'Kokonaispisteet', - 'ranked_score' => 'Tilastoidut pisteet', + 'ranked_score' => 'Rankatut pisteet', 'average_score' => 'Keskim. pisteet', 'average_performance' => 'Keskim. suorituskyky', 'ss' => '', diff --git a/resources/lang/fi/store.php b/resources/lang/fi/store.php index 7153b9214dd..9c238edf633 100644 --- a/resources/lang/fi/store.php +++ b/resources/lang/fi/store.php @@ -6,20 +6,20 @@ return [ 'cart' => [ 'checkout' => 'Kassa', - 'empty_cart' => '', - 'info' => ':count_delimited tuote ostoskorissa ($:subtotal)|:count_delimited tuotteet ostoskorissa ($:subtotal)', + 'empty_cart' => 'Poista kaikki tuotteet ostoskärrystä', + 'info' => ':count_delimited tuote ostoskärryssä ($:subtotal)|:count_delimited tuotetta ostoskärryssä ($:subtotal)', 'more_goodies' => 'Tarkastelisin vielä muita tuotteita ennen tilauksen tekemistä', 'shipping_fees' => 'toimituskulut', - 'title' => 'Ostoskori', + 'title' => 'Ostoskärry', 'total' => 'yhteensä', 'errors_no_checkout' => [ - 'line_1' => 'Jassoo... kassalle ei pääse, sillä ostoskorissasi on ongelmia!', + 'line_1' => 'Jassoo... kassalle ei pääse, sillä ostoskärryssäsi on ongelmia!', 'line_2' => 'Poista tai päivitä ylläolevat tavarat jatkaaksesi.', ], 'empty' => [ - 'text' => 'Ostoskorisi on tyhjä.', + 'text' => 'Ostoskärrysi on tyhjä.', 'return_link' => [ '_' => 'Palaa takaisin :link tehdäksesi löytöjä!', 'link_text' => 'kauppasivulle', @@ -28,7 +28,7 @@ ], 'checkout' => [ - 'cart_problems' => 'Oijoi, korisi kanssa on ongelmia!', + 'cart_problems' => 'Oijoi, ostoskärryssäsi on ongelmia!', 'cart_problems_edit' => 'Napsauta tästä muokataksesi sitä.', 'declined' => 'Maksu peruutettiin.', 'delayed_shipping' => 'Olemme tällä hetkellä hukkumassa tilauksiin! Olet vapaa tilaamaan, mutta ole valmis odottamaan **1-2 viikkoa lisää** kunnes olemme saaneet nykyiset tilaukset lähetettyä.', @@ -49,37 +49,37 @@ ], 'discount' => 'säästä :percent%', - 'free' => '', + 'free' => 'ilmainen!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Ota yhteyttä:', + 'date' => 'Päivämäärä:', 'echeck_delay' => 'Koska maksusi oli eCheck, anna maksimissaan 10 päivää että maksu pääsee PayPalin läpi!', - 'hide_from_activity' => 'Tämän tilauksen osu!supporter-tägejä ei näytetä profiilisi viimeaikainen toiminta kohdassa.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'hide_from_activity' => 'Tämän tilauksen osu!-tukijamerkkejä ei näytetä viimeaikaisessa toiminnassasi.', + 'sent_via' => 'Lähetetty kautta:', + 'shipping_to' => 'Toimitetaan kohteeseen:', + 'title' => 'Lasku', 'title_compact' => 'lasku', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Tilauksesi on peruutettu', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Jos et pyytänyt peruutusta, ota yhteyttä :link ja mainitse tilauksesi numero (#:order_number).", + 'link_text' => 'osu!-kaupan tukeen', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Tilauksesi on toimitettu! Toivottavasti pidät siitä!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Jos sinulla on ongelmia ostoksesi kanssa, ota yhteyttä :link.', + 'link_text' => 'osu!-kaupan tukeen', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Tilaustasi valmistellaan!', + 'line_1' => 'Odota sen lähettämistä vähän pidempään. Seurantatiedot tulevat näkyviin tässä, kun tilaus on käsitelty ja lähetetty. Tämä voi kestää jopa viisi päivää (mutta yleensä vähemmän!) riippuen siitä, kuinka kiireisiä olemme.', + 'line_2' => 'Lähetämme kaikki tilaukset Japanista käyttämällä erilaisia kuljetuspalveluja riippuen tilauksen painosta ja arvosta. Tämä alue päivittyy yksityiskohdilla, kun olemme lähettäneet tilauksen.', ], 'processing' => [ 'title' => 'Maksuasi ei ole vielä vahvistettu!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Tilauksesi on lähetetty!', + 'tracking_details' => 'Seurantatiedot ovat seuraavat:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Meillä ei ole seurantatietoja, koska lähetimme pakettisi lentopostin kautta, mutta voit odottaa saavasi sen 1-3 viikon päästä. Euroopan kohdalla tullit voivat joskus viivyttää tilausta, mille emme voi mitään. Jos sinulla herää huolia, ole hyvä ja vastaa sähköpostiin tilausvahvistuksesta, jonka sait :link.", + 'link_text' => 'lähetä meille sähköpostia', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Ei tilauksia katsottavissa.', 'paid_on' => 'Tilaus laitettu :date', 'resume' => 'Jatka kassalle', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Toimitus & käsittely', 'shopify_expired' => 'Tämän tilauksen kassalinkki on vanhentunut.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Välisumma', + 'total' => 'Yhteensä', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Tilaus #', + 'payment_terms' => 'Maksuehdot', + 'salesperson' => 'Myyjä', + 'shipping_method' => 'Toimitustapa', + 'shipping_terms' => 'Toimitusehdot', + 'title' => 'Tilauksen tiedot', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Maksettu', 'processing' => 'Odotetaan varmistusta', 'shipped' => 'Kuljetuksessa', - 'title' => '', + 'title' => 'Tilauksen tilanne', ], 'thanks' => [ - 'title' => '', + 'title' => 'Kiitos tilauksestasi!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Saat pian vahvistusviestin sähköpostilla. Jos sinulla on kysyttävää, ole hyvä ja :link!', + 'link_text' => 'ota yhteyttä meihin', ], ], ], @@ -182,20 +182,20 @@ 'supporter_tag' => [ 'gift' => 'lahjoita pelaajalle', - 'gift_message' => 'lisää omavalintainen viesti lahjaasi! (max. :length merkkiä)', + 'gift_message' => 'lisää omavalintainen viesti lahjaasi! (enintään :length merkkiä)', 'require_login' => [ - '_' => 'Sinun pitää olla :link saadaksesi osu!tukijan!', - 'link_text' => 'kirjautunut sisään', + '_' => 'Sinun pitää olla :link, jotta voit hankkia osu!-tukijamerkin!', + 'link_text' => 'kirjautuneena sisään', ], ], 'username_change' => [ 'check' => 'Kirjoita käyttäjänimi saatavuuden tarkistamiseksi!', 'checking' => 'Tarkistetaan saatavuutta nimelle :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Pyydetty käyttäjänimi', + 'label' => 'Uusi käyttäjänimi', + 'current' => 'Nykyinen käyttäjänimesi on ":username".', 'require_login' => [ '_' => 'Sinun on oltava :link vaihtaaksesi nimesi!', diff --git a/resources/lang/fi/users.php b/resources/lang/fi/users.php index 074bba59bad..64213d6e3bb 100644 --- a/resources/lang/fi/users.php +++ b/resources/lang/fi/users.php @@ -119,13 +119,13 @@ 'beta' => [ 'main' => 'Beta on tällä hetkellä käytössä vain siihen oikeutetuilla käyttäjillä.', - 'small' => '(osu!-tukijat tulevat kohta)', + 'small' => '(osu!n tukijat tulevat kohta)', ], ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Rytmikarttoja: :counts', + 'modding_description_empty' => 'Käyttäjällä ei ole rytmikarttoja...', 'description' => [ '_' => 'Sijoitus (:ruleset): :global | :country', @@ -178,7 +178,7 @@ 'change_avatar' => 'vaihda profiilikuvasi!', 'first_members' => 'Täällä alusta alkaen', 'is_developer' => 'osu!n kehittäjä', - 'is_supporter' => 'osu!-tukija', + 'is_supporter' => 'osu!n tukija', 'joined_at' => 'Liittyi :date', 'lastvisit' => 'Nähty viimeksi :date', 'lastvisit_online' => 'Tällä hetkellä paikalla', @@ -258,7 +258,7 @@ ], 'discussions' => [ 'title' => 'Keskustelut', - 'title_longer' => 'Viimeaikaiset Keskustelut', + 'title_longer' => 'Viimeaikaiset keskustelut', 'show_more' => 'nää lisää keskusteluja', ], 'events' => [ @@ -344,7 +344,7 @@ 'title' => 'Mitalit', ], 'playlists' => [ - 'title' => 'Soittolista Pelit', + 'title' => 'Soittolistapelit', ], 'posts' => [ 'title' => 'Julkaisut', @@ -449,10 +449,10 @@ 'highest' => 'Korkein sija :rank oli :date', ], 'stats' => [ - 'hit_accuracy' => 'Osumatarkkuus', + 'hit_accuracy' => 'Iskutarkkuus', 'level' => 'Taso :level', 'level_progress' => 'edistyminen seuraavalle tasolle', - 'maximum_combo' => 'Suurin combo', + 'maximum_combo' => 'Suurin iskuputki', 'medals' => 'Mitalit', 'play_count' => 'Pelikertoja', 'play_time' => 'Peliaikaa yhteensä', diff --git a/resources/lang/fr/comments.php b/resources/lang/fr/comments.php index 2a885bb3aac..b0575d11c61 100644 --- a/resources/lang/fr/comments.php +++ b/resources/lang/fr/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'commentaire de :user', ], 'placeholder' => [ diff --git a/resources/lang/fr/notifications.php b/resources/lang/fr/notifications.php index 2805b4dc311..06ec3f8711f 100644 --- a/resources/lang/fr/notifications.php +++ b/resources/lang/fr/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'La discussion n\'est plus verrouillée', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited compliment|:count_delimited compliments', + 'problems' => ':count_delimited problème|:count_delimited problèmes', + 'suggestions' => ':count_delimited suggestion|:count_delimited suggestions', ], ], diff --git a/resources/lang/fr/store.php b/resources/lang/fr/store.php index 10dec73371f..7418910b589 100644 --- a/resources/lang/fr/store.php +++ b/resources/lang/fr/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Acheter', - 'empty_cart' => '', + 'empty_cart' => 'Supprimer tous les articles du panier', 'info' => ':count_delimited article dans le panier ($:subtotal)|:count_delimited articles dans le panier ($:subtotal)', 'more_goodies' => 'Je souhaite chercher d\'autres goodies avant de passer commande', 'shipping_fees' => 'frais de livraison', @@ -49,37 +49,37 @@ ], 'discount' => 'économisez :percent%', - 'free' => '', + 'free' => 'gratuit !', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Contact :', + 'date' => 'Date :', 'echeck_delay' => 'Si votre paiement est en eCheck, comptez jusqu\'à 10 jours supplémentaires pour le paiement via PayPal !', 'hide_from_activity' => 'Les tags osu!supporter dans cette commande ne sont pas affichés dans vos activités récentes.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Envoyé via :', + 'shipping_to' => 'Expédition à :', + 'title' => 'Facture', 'title_compact' => 'facture', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Votre commande a été annulée', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Si vous n'avez pas demandé d'annulation, veuillez contacter le :link en citant votre numéro de commande (#:order_number).", + 'link_text' => 'support de l\'osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Votre commande a été livrée ! Nous espérons que vous l\'appréciez !', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Si vous avez un problème avec votre achat, veuillez contacter le :link.', + 'link_text' => 'support de l\'osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Votre commande est en cours de préparation !', + 'line_1' => 'Veuillez patienter un peu plus longtemps avant que la commande ne soit expédiée. Les informations de suivi apparaîtront ici une fois que la commande aura été traitée et envoyée. Cela peut prendre jusqu\'à 5 jours (mais généralement moins !) en fonction de notre activité.', + 'line_2' => 'Nous envoyons toutes les commandes depuis le Japon en utilisant divers services d\'expédition en fonction du poids et de la valeur. Cette section sera mise à jour une fois que nous aurons expédié la commande.', ], 'processing' => [ 'title' => 'Votre paiement n\'a pas encore été confirmé !', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Votre commande a été expédiée !', + 'tracking_details' => 'Détails de suivi :', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Nous n'avons pas d'informations de suivi puisque nous avons envoyé votre colis par Air Mail, mais vous pouvez vous attendre à le recevoir dans un délai de 1 à 3 semaines. Pour l'Europe, les douanes peuvent parfois retarder la commande hors de notre contrôle. Si vous avez des inquiétudes, veuillez répondre à l'e-mail de confirmation de commande que vous avez reçu :link.", + 'link_text' => 'envoyez-nous un email', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Aucune commande à voir.', 'paid_on' => 'Commande passée :date', 'resume' => 'Reprendre la commande', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Expédition et traitement', 'shopify_expired' => 'Le lien de commande pour cette commande a expiré.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Sous-total', + 'total' => 'Total', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Commande #', + 'payment_terms' => 'Conditions de paiement', + 'salesperson' => 'Vendeur', + 'shipping_method' => 'Mode de livraison', + 'shipping_terms' => 'Conditions d\'expédition', + 'title' => 'Détails de la commande', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Payée', 'processing' => 'En attente de confirmation', 'shipped' => 'Expédié', - 'title' => '', + 'title' => 'Statut de la commande', ], 'thanks' => [ - 'title' => '', + 'title' => 'Merci pour votre commande !', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Vous recevrez bientôt un email de confirmation. Si vous avez des questions, veuillez :link !', + 'link_text' => 'contactez-nous', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Entrez un nom d\'utilisateur pour vérifier sa disponibilité !', 'checking' => 'Vérification de la disponibilité de :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Nom d\'utilisateur demandé', + 'label' => 'Nouveau nom d\'utilisateur', + 'current' => 'Votre nom d\'utilisateur actuel est «:username».', 'require_login' => [ '_' => 'Vous devez être :link pour changer de nom !', diff --git a/resources/lang/fr/users.php b/resources/lang/fr/users.php index 8acaca8ebe7..ee1c36b5703 100644 --- a/resources/lang/fr/users.php +++ b/resources/lang/fr/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmaps : :counts', + 'modding_description_empty' => 'L\'utilisateur n\'a pas de beatmaps...', 'description' => [ '_' => 'Rang (:ruleset): :global | :country', diff --git a/resources/lang/hu/comments.php b/resources/lang/hu/comments.php index f35f11d27b4..a057077e14e 100644 --- a/resources/lang/hu/comments.php +++ b/resources/lang/hu/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => ':user hozzászólása', ], 'placeholder' => [ diff --git a/resources/lang/hu/notifications.php b/resources/lang/hu/notifications.php index 800ecc6f720..b2635a6fcb9 100644 --- a/resources/lang/hu/notifications.php +++ b/resources/lang/hu/notifications.php @@ -58,9 +58,9 @@ 'beatmapset_discussion_unlock_compact' => 'A beszélgetést feloldották', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited dicséret|:count_delimited dicséretek', + 'problems' => ':count_delimited probléma|:count_delimited problémák', + 'suggestions' => ':count_delimited javaslat|:count_delimited javaslatok', ], ], diff --git a/resources/lang/hu/store.php b/resources/lang/hu/store.php index 1fad4115777..3bc6ae985ee 100644 --- a/resources/lang/hu/store.php +++ b/resources/lang/hu/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Fizetés', - 'empty_cart' => '', + 'empty_cart' => 'Összes elem törlése a kosárból', 'info' => ':count_delimited elem a kosárban ($:subtotal)|:count_delimited elem a kosárban ($:subtotal)', 'more_goodies' => 'Még több cuccot szeretnék megnézni mielőtt befejezném a rendelésem', 'shipping_fees' => 'szállítási költség', @@ -49,37 +49,37 @@ ], 'discount' => ':percent% megtakaritása', - 'free' => '', + 'free' => 'ingyenes!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Kapcsolat:', + 'date' => 'Dátum:', 'echeck_delay' => 'Mivel a fizetésed egy eCheck volt, engedj meg neki legalább 10 napot a PayPal-es feldolgozásra!', 'hide_from_activity' => 'ebben a vásárlásban szereplő osu!supporter címkék nem jelennek meg a legutóbbi aktivitásaid között.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Általa küldve:', + 'shipping_to' => 'Szállítás ide:', + 'title' => 'Számla', 'title_compact' => 'számla', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'A rendelés törölve lett', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Ha nem kérted a lemondást, kérjük, vedd fel a kapcsolatot itt: :link, majd add meg a rendelésed számát (#:order_number).", + 'link_text' => 'osu!bolt támogatás', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'A rendelésed megérkezett! Reméljük, hogy tetszik neked!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Ha bármilyen problémád akad a vásárlással, kérlek lépj kapcsolatba :link helyen.', + 'link_text' => 'osu!bolt támogatás', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'A rendelés feldolgozás alatt!', + 'line_1' => 'Kérjük, várj még egy kicsit a szállításra. A csomagkövetési információk itt fognak majd megjelenni, amikor a rendelés feldolgozása és elküldése megtörtént. Ez akár 5 napot is igénybe vehet (de általában kevesebbet!) attól függően, hogy mennyire vagyunk elfoglaltak.', + 'line_2' => 'Minden megrendelést Japánból küldünk, a súlytól és értéktől függően különböző szállítási szolgáltatásokat használva. Ez a szakasz frissülni fog a részletekkel, amikor a megrendelést elküldtük.', ], 'processing' => [ 'title' => 'A fizetésed még nem lett megerősítve!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'A rendelés kiszállításra került!', + 'tracking_details' => 'Csomagkövetés részletei:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Nem rendelkezünk csomagkövetési adatokkal, mivel azt az Air Mailen keresztül küldtük el, de 1-3 héten belül várhatóan megkapod a csomagot. Európa esetében a vám néha késleltetheti a rendelést, amit mi nem tudunk befolyásolni. Ha bármilyen aggodalmad van, kérlek válaszolj a megrendelést visszaigazoló emailre, amit kaptál :link.", + 'link_text' => 'küldj nekünk egy emailt', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Nincs megtekinthető megrendelés.', 'paid_on' => 'Megrendelés feladva :date', 'resume' => 'Fizetés Folytatása', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Szállítás és kezelés', 'shopify_expired' => 'A rendelés fizetési linkje lejárt.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Részösszeg', + 'total' => 'Összesen', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Rendelési szám', + 'payment_terms' => 'Fizetési feltételek', + 'salesperson' => 'Értékesítő', + 'shipping_method' => 'Szállítási mód', + 'shipping_terms' => 'Szállítási feltételek', + 'title' => 'Rendelés részletei', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Fizetett', 'processing' => 'Megerősítés függőben', 'shipped' => 'Szállítás alatt', - 'title' => '', + 'title' => 'Rendelés állapota', ], 'thanks' => [ - 'title' => '', + 'title' => 'Köszönjük a megrendelést!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Hamarosan kapni fogsz egy megerősítő emailt. Ha bármilyen kérdésed van, kérlek :link!', + 'link_text' => 'lépj kapcsolatba velünk', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Adj meg egy felhasználónevet az elérhetőség ellenőrzéséhez!', 'checking' => ':username elérhetőségének ellenőrzése...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Kért Felhasználónév', + 'label' => 'Új Felhasználónév', + 'current' => 'A jelenlegi felhasználóneved ":username".', 'require_login' => [ '_' => ':link kell lenned a neved megváltoztatásához!', diff --git a/resources/lang/hu/users.php b/resources/lang/hu/users.php index d86c0185696..e2aa9be0c63 100644 --- a/resources/lang/hu/users.php +++ b/resources/lang/hu/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmapek: :counts', + 'modding_description_empty' => 'A felhasználónak nincsenek beatmapjai...', 'description' => [ '_' => 'Helyezés (:ruleset): :global | :country', diff --git a/resources/lang/id/comments.php b/resources/lang/id/comments.php index 3b5ffec95f6..00686eab548 100644 --- a/resources/lang/id/comments.php +++ b/resources/lang/id/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'komentar oleh :user', ], 'placeholder' => [ diff --git a/resources/lang/id/notifications.php b/resources/lang/id/notifications.php index ca2bcf6b91e..c882bfa332a 100644 --- a/resources/lang/id/notifications.php +++ b/resources/lang/id/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'Diskusi beatmap telah dibuka', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited pujian|:count_delimited pujian', + 'problems' => ':count_delimited masalah|:count_delimited masalah', + 'suggestions' => ':count_delimited saran|:count_delimited saran', ], ], diff --git a/resources/lang/id/store.php b/resources/lang/id/store.php index 926f5c10129..6cef00f2de2 100644 --- a/resources/lang/id/store.php +++ b/resources/lang/id/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Checkout', - 'empty_cart' => '', + 'empty_cart' => 'Hapus semua barang dari keranjang', 'info' => ':count_delimited barang dalam keranjang ($:subtotal)|:count_delimited barang dalam keranjang ($:subtotal)', 'more_goodies' => 'Saya ingin melihat produk lainnya sebelum merampungkan pesanan', 'shipping_fees' => 'biaya pengiriman', @@ -49,52 +49,52 @@ ], 'discount' => 'hemat :percent%', - 'free' => '', + 'free' => 'gratis!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Kontak:', + 'date' => 'Tanggal:', 'echeck_delay' => 'Berhubung pembayaranmu berupa eCheck, mohon tunggu hingga setidaknya 10 hari agar pembayaranmu dapat diproses oleh PayPal!', 'hide_from_activity' => 'Tag osu!supporter yang dipesan melalui pesanan ini tidak akan ditampilkan pada riwayat aktivitas terkini milikmu.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Dikirim Melalui:', + 'shipping_to' => 'Dikirim Ke:', + 'title' => 'Tagihan', 'title_compact' => 'faktur', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Pesananmu telah dibatalkan', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Apabila kamu tidak meminta pembatalan ini, silakan hubungi :link dengan menyertakan nomor pesananmu (#:order_number).", + 'link_text' => 'layanan dukungan osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Pesananmu sudah dikirim! Kami harap kamu menikmatinya!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Apabila kamu menemui masalah dengan pembelianmu, silakan hubungi :link.', + 'link_text' => 'layanan dukungan osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Pesananmu sedang disiapkan!', + 'line_1' => 'Harap tunggu sedikit lebih lama untuk pengiriman. Informasi pelacakan akan muncul di sini setelah pesanan telah diolah dan dikirim. Ini bisa perlu sampai 5 hari (tetapi biasanya lebih cepat!) tergantung kesibukan kami.', + 'line_2' => 'Kami mengirim seluruh pesanan dari Jepang dengan berbagai macam layanan pengiriman tergantung berat dan nilai. Bagian ini akan diperbarui dengan perincian setelah kami mengirimkan pesanan.', ], 'processing' => [ 'title' => 'Pembayaranmu belum terkonfirmasi!', 'line_1' => 'Apabila kamu telah membayar sebelumnya, ada kemungkinan sistem kami masih menunggu konfirmasi atas pembayaranmu. Silakan muat ulang halaman ini dalam beberapa menit!', 'line_2' => [ - '_' => 'Apabila kamu mengalami masalah dalam proses checkout, :link', + '_' => 'Apabila kamu menemui masalah dalam proses checkout, :link', 'link_text' => 'klik di sini untuk melanjutkan proses checkout', ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Pesananmu sudah dikirim!', + 'tracking_details' => 'Berikut rincian pelacakan yang terkait:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Kami tidak memiliki perincian pelacakan karena kami mengirim paketmu via Air Mail, tetapi kamu bisa mendapatkannya dalam 1-3 pekan. Untuk Eropa, terkadang bea cukai dapat menunda pesanan di luar kendali kami. Jika kamu punya kekhawatiran, silakan balas email konfirmasi pesanan yang kamu terima :link.", + 'link_text' => 'kirimi kami email', ], ], ], @@ -102,24 +102,24 @@ 'order' => [ 'cancel' => 'Batalkan Pesanan', - 'cancel_confirm' => 'Pesanan ini akan dibatalkan dan segala biaya yang telah kamu keluarkan tidak akan kami terima. Apakah kamu yakin?', + 'cancel_confirm' => 'Pesanan ini akan dibatalkan dan pembayaran yang masuk tidak akan diterima. Layanan pembayaran mungkin tidak akan mencairkan dana yang tersimpan dengan segera. Apakah kamu yakin?', 'cancel_not_allowed' => 'Pesanan ini tidak dapat dibatalkan pada saat ini.', 'invoice' => 'Lihat Faktur', 'no_orders' => 'Tidak ada pesanan yang tercatat.', 'paid_on' => 'Pemesanan dilangsungkan pada :date', 'resume' => 'Lanjutkan Proses Checkout', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Pengiriman & Penanganan', 'shopify_expired' => 'Tautan checkout untuk pesanan ini telah kedaluwarsa.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Subtotal', + 'total' => 'Total', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Pesanan #', + 'payment_terms' => 'Ketentuan Pembayaran', + 'salesperson' => 'Pramuniaga', + 'shipping_method' => 'Metode Pengiriman', + 'shipping_terms' => 'Ketentuan Pengiriman', + 'title' => 'Detail Pesanan', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Lunas', 'processing' => 'Menunggu konfirmasi', 'shipped' => 'Terkirim', - 'title' => '', + 'title' => 'Status Pesanan', ], 'thanks' => [ - 'title' => '', + 'title' => 'Terima kasih atas pesananmu!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Kamu akan menerima email konfirmasi dengan segera. Apabila kamu memiliki pertanyaan lebih lanjut, silakan :link!', + 'link_text' => 'hubungi kami', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Masukkan nama pengguna untuk memeriksa ketersediaannya!', 'checking' => 'Memeriksa ketersediaan :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Nama Pengguna yang Diminta', + 'label' => 'Nama Pengguna Baru', + 'current' => 'Nama penggunamu saat ini adalah ":username".', 'require_login' => [ '_' => 'Anda harus :link untuk mengubah nama Anda!', diff --git a/resources/lang/id/users.php b/resources/lang/id/users.php index 503ae972cbb..d7370612e5b 100644 --- a/resources/lang/id/users.php +++ b/resources/lang/id/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmap: :counts', + 'modding_description_empty' => 'Pengguna ini tidak memiliki beatmap apa pun...', 'description' => [ '_' => 'Peringkat (:ruleset): :global | :country', diff --git a/resources/lang/it/accounts.php b/resources/lang/it/accounts.php index 809790f738e..a106206a893 100644 --- a/resources/lang/it/accounts.php +++ b/resources/lang/it/accounts.php @@ -10,7 +10,7 @@ 'avatar' => [ 'title' => 'Avatar', - 'rules' => 'Assicurati che la tua immagine di profilo aderisca alle :link.
Questo significa che deve essere adatta a tutte le età (ad esempio: niente nudità, profanità o contenuti provocanti).', + 'rules' => 'Assicurati che la tua immagine di profilo aderisca alle :link.
Questo significa che dev\'essere adatta a tutte le età (quindi niente nudità, profanità o contenuti provocanti).', 'rules_link' => 'regole della comunità', ], diff --git a/resources/lang/it/beatmapsets.php b/resources/lang/it/beatmapsets.php index 9af13240df7..3ad4858f6a6 100644 --- a/resources/lang/it/beatmapsets.php +++ b/resources/lang/it/beatmapsets.php @@ -73,7 +73,7 @@ 'by_artist' => 'di :artist', 'favourite' => 'Mi piace questa beatmap', 'favourite_login' => 'Accedi per aggiungere questa beatmap ai preferiti', - 'logged-out' => 'Devi avere effettuato il login prima di scaricare qualsiasi beatmap!', + 'logged-out' => 'hai bisogno di accedere per scaricare le beatmap!', 'mapped_by' => 'mappata da :mapper', 'mapped_by_guest' => 'difficoltà guest di :mapper', 'unfavourite' => 'Non mi piace questa beatmap', diff --git a/resources/lang/it/comments.php b/resources/lang/it/comments.php index f668be0db28..29c8736bbe3 100644 --- a/resources/lang/it/comments.php +++ b/resources/lang/it/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'commento di :user', ], 'placeholder' => [ diff --git a/resources/lang/it/notifications.php b/resources/lang/it/notifications.php index 51a5d4c81c8..ad6bec68532 100644 --- a/resources/lang/it/notifications.php +++ b/resources/lang/it/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'La discussione è stata sbloccata', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited elogio|:count_delimited elogi', + 'problems' => ':count_delimited problema|:count_delimited problemi', + 'suggestions' => ':count_delimited suggerimento|:count_delimited suggerimenti', ], ], diff --git a/resources/lang/it/store.php b/resources/lang/it/store.php index 1962848461c..cebbc10abab 100644 --- a/resources/lang/it/store.php +++ b/resources/lang/it/store.php @@ -6,9 +6,9 @@ return [ 'cart' => [ 'checkout' => 'Paga', - 'empty_cart' => '', + 'empty_cart' => 'Rimuovi tutti gli articoli dal carrello', 'info' => ':count_delimited articolo nel carrello ($:subtotal)|:count_delimited articoli nel carrello ($:subtotal)', - 'more_goodies' => 'Voglio dare un\'occhiata ad altri elementi prima di completare l\'ordine', + 'more_goodies' => 'Voglio controllare altri articoli prima di completare l\'ordine', 'shipping_fees' => 'costi di spedizione', 'title' => 'Carrello', 'total' => 'totale', @@ -49,35 +49,35 @@ ], 'discount' => 'risparmi :percent%', - 'free' => '', + 'free' => 'gratis!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Referente:', + 'date' => 'Data:', 'echeck_delay' => 'Visto che il tuo pagamento era un eCheck, dovrai attendere altri 10 giorni per far passare il pagamento attraverso PayPal!', 'hide_from_activity' => 'I tag osu!supporter in questo ordine non verranno mostrati nella tua attività recente.', 'sent_via' => '', 'shipping_to' => '', - 'title' => '', + 'title' => 'Ricevuta', 'title_compact' => 'ricevuta', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Il tuo ordine è stato annullato', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Se non hai richiesto la cancellazione contatta il :link menzionando il tuo numero d'ordine (#:order_number).", + 'link_text' => 'supporto di osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Il tuo ordine è stato consegnato! Speriamo ti piaccia!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Se hai problemi con il tuo acquisto, contatta il :link.', + 'link_text' => 'supporto di osu!store', ], ], 'prepared' => [ - 'title' => '', + 'title' => 'Il tuo ordine è in preparazione!', 'line_1' => '', 'line_2' => '', ], @@ -90,7 +90,7 @@ ], ], 'shipped' => [ - 'title' => '', + 'title' => 'Il tuo ordine è stato spedito!', 'tracking_details' => '', 'no_tracking_details' => [ '_' => "", @@ -111,22 +111,22 @@ 'shipping_and_handling' => '', 'shopify_expired' => 'Il link del pagamento per quest\'ordine è scaduto.', 'subtotal' => '', - 'total' => '', + 'total' => 'Totale', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', + 'order_number' => 'Ordine #', + 'payment_terms' => 'Termini di Pagamento', 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'shipping_method' => 'Metodo di Spedizione', + 'shipping_terms' => 'Termini di Spedizione', + 'title' => 'Dettagli Ordine', ], 'item' => [ 'quantity' => 'Quantità', 'display_name' => [ - 'supporter_tag' => ':name per :username(:duration)', + 'supporter_tag' => ':name per :username (:duration)', ], 'subtext' => [ @@ -151,14 +151,14 @@ 'paid' => 'Pagato', 'processing' => 'In attesa di conferma', 'shipped' => 'In Transito', - 'title' => '', + 'title' => 'Stato Ordine', ], 'thanks' => [ - 'title' => '', + 'title' => 'Grazie per il tuo ordine!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Riceverai presto un\'email di conferma. Per qualsiasi richiesta, :link!', + 'link_text' => 'contattaci', ], ], ], @@ -181,7 +181,7 @@ ], 'supporter_tag' => [ - 'gift' => 'regalo ad un giocatore', + 'gift' => 'regala ad un giocatore', 'gift_message' => 'aggiungi un messaggio opzionale al tuo regalo (fino a :length caratteri)', 'require_login' => [ @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Inserisci un nome utente per controllare la disponibilità!', 'checking' => 'Controllando la disponibilità di :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Nome Utente Richiesto', + 'label' => 'Nuovo Nome Utente', + 'current' => 'Il tuo nome utente attuale è ":username".', 'require_login' => [ '_' => 'Devi :link per poter cambiare il tuo nome!', diff --git a/resources/lang/it/users.php b/resources/lang/it/users.php index 79506c3362f..6f08e9fe813 100644 --- a/resources/lang/it/users.php +++ b/resources/lang/it/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmap: :counts', + 'modding_description_empty' => 'L\'utente non ha beatmap...', 'description' => [ '_' => 'Posizione (:ruleset): :global | :country', diff --git a/resources/lang/ko/comments.php b/resources/lang/ko/comments.php index e1756a24905..4c17f145d0b 100644 --- a/resources/lang/ko/comments.php +++ b/resources/lang/ko/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => ':user님의 댓글', ], 'placeholder' => [ diff --git a/resources/lang/ko/model_validation.php b/resources/lang/ko/model_validation.php index 6a6129f5a0e..a361e972a8f 100644 --- a/resources/lang/ko/model_validation.php +++ b/resources/lang/ko/model_validation.php @@ -132,25 +132,25 @@ ], 'user' => [ - 'contains_username' => '비밀번호는 유저 이름을 포함할 수 없습니다.', + 'contains_username' => '비밀번호에 아이디를 포함할 수 없습니다.', 'email_already_used' => '이미 사용중인 이메일 주소입니다.', 'email_not_allowed' => '허용되지 않은 이메일 주소입니다.', 'invalid_country' => '해당하는 국가가 데이터베이스에 존재하지 않습니다.', - 'invalid_discord' => 'Discord 유저 이름이 올바르지 않습니다.', + 'invalid_discord' => 'Discord 사용자명이 올바르지 않습니다.', 'invalid_email' => "이메일 주소가 잘못되었습니다.", - 'invalid_twitter' => 'Twitter 유저 이름이 올바르지 않습니다.', + 'invalid_twitter' => 'Twitter 아이디가 올바르지 않습니다.', 'too_short' => '새 비밀번호가 너무 짧습니다.', - 'unknown_duplicate' => '유저 이름 또는 이메일 주소가 이미 사용중입니다.', - 'username_available_in' => '이 유저 이름은 :duration 안에 사용 가능합니다.', - 'username_available_soon' => '이 유저 이름은 곧 사용 가능 합니다!', - 'username_invalid_characters' => '요청한 유저 이름에 유효하지 않은 문자가 있습니다.', - 'username_in_use' => '이미 사용중인 유저 이름 입니다!', - 'username_locked' => '이미 사용 중인 사용자 이름입니다!', // TODO: language for this should be slightly different. + 'unknown_duplicate' => '아이디 또는 이메일 주소가 이미 사용중입니다.', + 'username_available_in' => '이 아이디는 :duration 안에 사용 가능합니다.', + 'username_available_soon' => '이 아이디는 곧 사용 가능 합니다!', + 'username_invalid_characters' => '요청한 아이디에 유효하지 않은 문자가 있습니다.', + 'username_in_use' => '이미 사용중인 아이디 입니다!', + 'username_locked' => '이미 사용 중인 아이디입니다!', // TODO: language for this should be slightly different. 'username_no_space_userscore_mix' => '언더바나 공백을 사용해주세요, 둘 중 하나요!', - 'username_no_spaces' => "유저 이름은 공백으로 시작하거나 끝날 수 없습니다!", - 'username_not_allowed' => '이 사용자 이름 선택은 허용되지 않습니다.', - 'username_too_short' => '요청하신 유저 이름이 너무 짧습니다.', - 'username_too_long' => '요청한 유저 이름이 너무 깁니다.', + 'username_no_spaces' => "아이디는 공백으로 시작하거나 끝날 수 없습니다!", + 'username_not_allowed' => '이 아이디 선택은 허용되지 않습니다.', + 'username_too_short' => '요청하신 아이디가 너무 짧습니다.', + 'username_too_long' => '요청한 아이디가 너무 깁니다.', 'weak' => '비밀번호에 사용할 수 없는 문자나 패턴이 포함되어 있습니다.', 'wrong_current_password' => '현재 비밀번호가 일치하지 않습니다.', 'wrong_email_confirmation' => '이메일과 이메일 확인란이 일치하지 않습니다.', @@ -158,18 +158,18 @@ 'too_long' => '최대 길이를 초과하셨습니다 - :limit자리 까지만 가능합니다.', 'attributes' => [ - 'username' => '유저 이름', + 'username' => '아이디', 'user_email' => '이메일 주소', 'password' => '비밀번호', ], 'change_username' => [ - 'restricted' => '제한된 상태의 계정은 유저 이름을 변경할 수 없습니다.', + 'restricted' => '제한된 상태의 계정은 아이디를 변경할 수 없습니다.', 'supporter_required' => [ - '_' => '무조건 :link해야만 이름을 변경할 수 있습니다!', + '_' => '무조건 :link해야만 아이디를 변경할 수 있습니다!', 'link_text' => 'osu!를 후원', ], - 'username_is_same' => '이미 당신이 사용 중인 이름입니다, 혹시.. 건망증?', + 'username_is_same' => '이미 당신이 사용 중인 아이디입니다, 혹시.. 건망증?', ], ], diff --git a/resources/lang/ko/notifications.php b/resources/lang/ko/notifications.php index 76bc0861cdd..177e5643cf2 100644 --- a/resources/lang/ko/notifications.php +++ b/resources/lang/ko/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => '토론이 잠금 해제되었습니다.', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited개의 칭찬', + 'problems' => ':count_delimited개의 문제 제기', + 'suggestions' => ':count_delimited개의 제안', ], ], diff --git a/resources/lang/ko/password_reset.php b/resources/lang/ko/password_reset.php index e0503ffe4d9..29678acfbff 100644 --- a/resources/lang/ko/password_reset.php +++ b/resources/lang/ko/password_reset.php @@ -34,7 +34,7 @@ ], 'starting' => [ - 'username' => '유저 이름이나 이메일 주소를 입력하세요.', + 'username' => '아이디나 이메일 주소를 입력하세요.', 'support' => [ '_' => '도움이 필요하신가요? :button을 통해 문의해보세요.', diff --git a/resources/lang/ko/store.php b/resources/lang/ko/store.php index 45377c9a558..af0fe33a307 100644 --- a/resources/lang/ko/store.php +++ b/resources/lang/ko/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => '결제', - 'empty_cart' => '', + 'empty_cart' => '장바구니의 모든 항목 삭제', 'info' => '장바구니에 담긴 :count_delimited개의 항목 ($:subtotal)', 'more_goodies' => '주문을 끝내기 전에 더 둘러볼게요.', 'shipping_fees' => '배송료', @@ -49,37 +49,37 @@ ], 'discount' => ':percent% 절약 가능', - 'free' => '', + 'free' => '무료!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => '연락처:', + 'date' => '날짜:', 'echeck_delay' => 'eCheck로 결제하셨다면 10일까지 PayPal을 통해 결제할 수 있도록 허용해주세요.', 'hide_from_activity' => '이 주문에 포함된 osu! 서포터 내역은 나의 최근 활동에 표시되지 않습니다.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => '배송 수단:', + 'shipping_to' => '배송지:', + 'title' => '청구서', 'title_compact' => '청구서', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => '주문이 취소되었습니다', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "취소를 요청하지 않으셨다면 주문 번호와 함께 :link에 문의해 주세요 (#:order_number).", + 'link_text' => 'osu!store 지원', ], ], 'delivered' => [ - 'title' => '', + 'title' => '주문하신 상품이 배송되었습니다! 마음에 드셨길 바랍니다!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => '구매에 문제가 있으시다면 :link에 문의해 주세요.', + 'link_text' => 'osu!store 지원', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => '주문하신 상품을 준비 중입니다!', + 'line_1' => '배송이 완료될 때까지 조금만 더 기다려 주세요. 주문이 처리되어 발송되면 배송 추적 정보가 여기에 표시됩니다. 저희 업무량에 따라 최대 5일까지 (보통은 더 짧아요!) 걸릴 수 있습니다.', + 'line_2' => '모든 주문은 무게와 금액에 따라 다양한 배송 서비스를 사용하여 일본에서 발송됩니다. 주문하신 상품이 발송되면 구체적인 정보가 이 영역에 업데이트됩니다.', ], 'processing' => [ 'title' => '당신의 결제가 아직 확인되지 않았습니다!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => '주문하신 상품이 발송되었습니다!', + 'tracking_details' => '추적 상세 정보는 다음과 같습니다:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "항공 우편으로 소포를 발송했기 때문에 추적 세부 정보는 없지만 1~3주 이내에 받으실 수 있습니다. 유럽의 경우, 가끔 세관 업무량 폭주로 인해 통관이 지연될 수 있습니다. 궁금하신 사항이 있으시다면 받으신 주문 확인 :link 해주시기 바랍니다.", + 'link_text' => '이메일로 답장', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => '주문 내역이 없습니다.', 'paid_on' => ':date에 주문함', 'resume' => '결제 계속하기', - 'shipping_and_handling' => '', + 'shipping_and_handling' => '배송료 & 포장료', 'shopify_expired' => '이 주문의 결제 링크가 만료되었습니다.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => '소계', + 'total' => '합계', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => '주문 #', + 'payment_terms' => '결제 조건', + 'salesperson' => '판매자', + 'shipping_method' => '배송 방법', + 'shipping_terms' => '배송 조건', + 'title' => '주문 상세내역', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => '결제 완료', 'processing' => '확인 대기 중', 'shipped' => '운송 중', - 'title' => '', + 'title' => '주문 상태', ], 'thanks' => [ - 'title' => '', + 'title' => '주문해 주셔서 감사합니다!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => '곧 확인 메일을 받으실 수 있습니다. 문의 사항이 있으시다면 :link해 주세요!', + 'link_text' => '저희에게 문의', ], ], ], @@ -193,12 +193,12 @@ 'username_change' => [ 'check' => '사용 가능한 이름인지 확인하려면 입력하세요!', 'checking' => ':username 사용 가능 여부 확인중..', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => '변경할 아이디', + 'label' => '새 아이디', + 'current' => '현재 사용하고 있는 아이디는 ":username" 입니다.', 'require_login' => [ - '_' => '유저이름을 바꾸려면 :link하셔야 합니다!', + '_' => '아이디를 바꾸려면 :link하셔야 합니다!', 'link_text' => '로그인', ], ], diff --git a/resources/lang/ko/users.php b/resources/lang/ko/users.php index 15f474f2192..a523728968b 100644 --- a/resources/lang/ko/users.php +++ b/resources/lang/ko/users.php @@ -115,7 +115,7 @@ 'register' => "osu!계정이 없으신가요? 새로 하나 만들어보세요", 'remember' => '이 컴퓨터에서 계정 정보 기억하기', 'title' => '계속하려면 로그인해 주세요', - 'username' => 'Username', + 'username' => '아이디', 'beta' => [ 'main' => '베타 엑세스는 현재 권한이 있는 사용자로 제한되어 있습니다.', @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => '비트맵: :counts', + 'modding_description_empty' => '이 유저는 아무런 비트맵이 없어요...', 'description' => [ '_' => '순위 (:ruleset:): :global | :country', @@ -151,7 +151,7 @@ 'placeholder' => '아시는 정보를 입력해 주세요. 유용하게 쓰일 수 있습니다.', 'reason' => '이유', 'thanks' => '신고해 주셔서 감사합니다!', - 'title' => ':username 님을 신고할까요?', + 'title' => ':username님을 신고할까요?', 'actions' => [ 'send' => '신고 보내기', @@ -389,8 +389,8 @@ ], 'account_standing' => [ 'title' => '계정 상태', - 'bad_standing' => ":username 님이 규칙을 위반하셨습니다. :(", - 'remaining_silence' => ':username 님은 :duration 후에 말할 수 있습니다.', + 'bad_standing' => ":username님이 규칙을 위반하셨습니다. :(", + 'remaining_silence' => ':username님은 :duration 후에 말할 수 있습니다.', 'recent_infringements' => [ 'title' => '최근 사건', diff --git a/resources/lang/lv-LV/api.php b/resources/lang/lv-LV/api.php index 6f304d05269..a48cd29e0b3 100644 --- a/resources/lang/lv-LV/api.php +++ b/resources/lang/lv-LV/api.php @@ -19,7 +19,7 @@ 'chat' => [ 'read' => 'Lasīt ziņas jūsu vārdā.', 'write' => 'Sūtīt ziņas jūsu vārdā.', - 'write_manage' => '', + 'write_manage' => 'Pievienoties un pamest kanālus jūsu vietā.', ], 'forum' => [ diff --git a/resources/lang/lv-LV/beatmap_discussions.php b/resources/lang/lv-LV/beatmap_discussions.php index 85134b38396..7d29f647a47 100644 --- a/resources/lang/lv-LV/beatmap_discussions.php +++ b/resources/lang/lv-LV/beatmap_discussions.php @@ -26,7 +26,7 @@ 'deleted' => 'Iekļaut dzēstās diskusijas', 'mode' => 'Bītmapes mods', 'only_unresolved' => 'Rādīt tikai neatrisinātās diskusijas', - 'show_review_embeds' => '', + 'show_review_embeds' => 'Rādīt apskata rakstus', 'types' => 'Ziņu tipi', 'username' => 'Lietotājvārds', diff --git a/resources/lang/lv-LV/beatmaps.php b/resources/lang/lv-LV/beatmaps.php index 50c8f1df875..23f97be37b1 100644 --- a/resources/lang/lv-LV/beatmaps.php +++ b/resources/lang/lv-LV/beatmaps.php @@ -79,15 +79,15 @@ ], 'message_type_title' => [ - 'disqualify' => '', + 'disqualify' => 'Publicēt diskvalifikāciju', 'hype' => '', - 'mapper_note' => '', + 'mapper_note' => 'Publicēt piezīmi', 'nomination_reset' => '', - 'praise' => '', - 'problem' => '', - 'problem_warning' => '', - 'review' => '', - 'suggestion' => '', + 'praise' => 'Publicēt slavējumu', + 'problem' => 'Publicēt problēmu', + 'problem_warning' => 'Publicēt problēmu', + 'review' => 'Publicēt atsauksmi', + 'suggestion' => 'Publicēt ieteikumu', ], 'mode' => [ diff --git a/resources/lang/lv-LV/chat.php b/resources/lang/lv-LV/chat.php index 4d2bc32fdad..acf4ccf70cc 100644 --- a/resources/lang/lv-LV/chat.php +++ b/resources/lang/lv-LV/chat.php @@ -8,7 +8,7 @@ 'talking_in' => 'runā :channel', 'talking_with' => 'runā ar :name', 'title_compact' => 'čats', - 'unread_messages' => '', + 'unread_messages' => 'nelasīti ziņojumi', 'cannot_send' => [ 'channel' => 'Šobrīd šajā kanālā nav iespējams nosūtīt ziņojumus.', @@ -36,7 +36,7 @@ 'labels' => [ 'description' => 'apraksts', - 'message' => '', + 'message' => 'ziņojumi', 'name' => 'istabas nosaukums', 'users' => 'pievienojamie spēlētāji', ], diff --git a/resources/lang/lv-LV/comments.php b/resources/lang/lv-LV/comments.php index 33034ab1f7d..f3b2e832625 100644 --- a/resources/lang/lv-LV/comments.php +++ b/resources/lang/lv-LV/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'komentējis :user', ], 'placeholder' => [ diff --git a/resources/lang/lv-LV/forum.php b/resources/lang/lv-LV/forum.php index 799421747ab..5cad4c926ce 100644 --- a/resources/lang/lv-LV/forum.php +++ b/resources/lang/lv-LV/forum.php @@ -178,8 +178,8 @@ ], 'post_edit' => [ - 'cancel' => '', - 'post' => '', + 'cancel' => 'Atcelt', + 'post' => 'Saglabāt', ], ], @@ -297,10 +297,10 @@ 'lock' => [ 'is_locked' => 'Šī tēma ir slēgta un nav iespējams caur to atbildēt', 'to_0' => 'Atvērt tēmu', - 'to_0_confirm' => '', + 'to_0_confirm' => 'Atslēgt tematu?', 'to_0_done' => 'Tēma tika atvērta', 'to_1' => 'Slēgt tēmu', - 'to_1_confirm' => '', + 'to_1_confirm' => 'Slēgt tematu?', 'to_1_done' => 'Tēma tika slēgta', ], @@ -310,13 +310,13 @@ 'moderate_pin' => [ 'to_0' => 'Atspraust tēmu', - 'to_0_confirm' => '', + 'to_0_confirm' => 'Atspraust tematu?', 'to_0_done' => 'Tēma tika atsprausta', 'to_1' => 'Piespraust tēmu', - 'to_1_confirm' => '', + 'to_1_confirm' => 'Piespraust tematu?', 'to_1_done' => 'Tēma tika piesprausta', 'to_2' => 'Piespraust tēmu un atzīmēt kā paziņojumu', - 'to_2_confirm' => '', + 'to_2_confirm' => 'Piespraust tematu un atzīmēt kā paziņojumu?', 'to_2_done' => 'Tēma tika piesprausta un atzīmēta kā paziņojums', ], @@ -341,7 +341,7 @@ 'user' => [ 'count' => '{0} nav balsu|{1} :count_delimited balss|[2,*] :count_delimited balsis', - 'current' => '', + 'current' => 'Jums palikušas :votes balsis.', 'not_enough' => "", ], ], @@ -349,7 +349,7 @@ 'poll' => [ 'edit' => 'Balsošanas Rediģēšana', 'edit_warning' => 'Rediģējot balsošanas metodi tiks noņemti visi esošie rezultāti!', - 'vote' => '', + 'vote' => 'Balsot', 'button' => [ 'change_vote' => 'Mainīt balsi', diff --git a/resources/lang/lv-LV/home.php b/resources/lang/lv-LV/home.php index 9ec66cb1c28..cc77d01adb5 100644 --- a/resources/lang/lv-LV/home.php +++ b/resources/lang/lv-LV/home.php @@ -14,45 +14,45 @@ 'slogan' => [ 'main' => '', - 'sub' => '', + 'sub' => 'ritms ir tikai klikšķa attālumā', ], ], 'search' => [ - 'advanced_link' => '', - 'button' => '', - 'empty_result' => '', + 'advanced_link' => 'Izvērstā meklēšana', + 'button' => 'Meklēt', + 'empty_result' => 'Nekas nav atrasts!', 'keyword_required' => '', - 'placeholder' => '', + 'placeholder' => 'rakstiet, lai meklētu', 'title' => 'meklēt', 'beatmapset' => [ - 'login_required' => '', + 'login_required' => 'Ielogojieties, lai meklētu bītmapes', 'more' => '', 'more_simple' => '', - 'title' => '', + 'title' => 'Bītmapes', ], 'forum_post' => [ - 'all' => '', - 'link' => '', - 'login_required' => '', + 'all' => 'Visi forumi', + 'link' => 'Meklēt forumā', + 'login_required' => 'Ieiet, lai meklētu forumā', 'more_simple' => '', - 'title' => '', + 'title' => 'Forums', 'label' => [ - 'forum' => '', - 'forum_children' => '', - 'include_deleted' => '', + 'forum' => 'meklēšana Forumos', + 'forum_children' => 'iekļaut apakšforumus', + 'include_deleted' => 'iekļaut dzēstos rakstus', 'topic_id' => '', - 'username' => '', + 'username' => 'autors', ], ], 'mode' => [ - 'all' => '', - 'beatmapset' => '', - 'forum_post' => '', + 'all' => 'visi', + 'beatmapset' => 'bītmape', + 'forum_post' => 'forums', 'user' => 'spēlētājs', 'wiki_page' => 'wiki', ], @@ -60,7 +60,7 @@ 'user' => [ 'login_required' => 'Ieiet, lai meklētu', 'more' => ':count vairāki spēlētāji meklēšanas rezultātā', - 'more_simple' => '', + 'more_simple' => 'Rādīt vairāk spēlētāju meklēšanas rezultātus', 'more_hidden' => '', 'title' => 'Spēlētāji', ], diff --git a/resources/lang/lv-LV/layout.php b/resources/lang/lv-LV/layout.php index 04e50217982..62b4df4d1ae 100644 --- a/resources/lang/lv-LV/layout.php +++ b/resources/lang/lv-LV/layout.php @@ -40,8 +40,8 @@ ], 'store' => [ - 'cart' => '', - 'orders' => '', + 'cart' => 'grozs', + 'orders' => 'pasūtījumu vēsture', 'products' => 'produkti', ], @@ -50,10 +50,10 @@ ], 'users' => [ - 'modding' => '', - 'playlists' => '', - 'realtime' => '', - 'show' => '', + 'modding' => 'modēšana', + 'playlists' => 'pleiliste', + 'realtime' => 'daudzspēlētāju režīms', + 'show' => 'info', ], ], @@ -67,55 +67,55 @@ 'menu' => [ 'beatmaps' => [ - '_' => '', + '_' => 'bītmapes', ], 'community' => [ - '_' => '', - 'dev' => '', + '_' => 'kopiena', + 'dev' => 'izstrāde', ], 'help' => [ - '_' => '', - 'getAbuse' => '', - 'getFaq' => '', - 'getRules' => '', - 'getSupport' => '', + '_' => 'palīdzība', + 'getAbuse' => 'ziņot par pārkāpumu', + 'getFaq' => 'bieži uzdoti jautājumi', + 'getRules' => 'noteikumi', + 'getSupport' => 'nē, patiešām, man vajag palīdzību!', ], 'home' => [ '_' => 'sākums', - 'team' => '', + 'team' => 'komanda', ], 'rankings' => [ - '_' => '', - 'kudosu' => '', + '_' => 'rangi', + 'kudosu' => 'kudosu', ], 'store' => [ - '_' => '', + '_' => 'veikals', ], ], 'footer' => [ 'general' => [ - '_' => '', - 'home' => '', - 'changelog-index' => '', + '_' => 'Vispārīgi', + 'home' => 'Sākums', + 'changelog-index' => 'Izmaiņu saraksts', 'beatmaps' => '', - 'download' => '', + 'download' => 'Lejupielādēt osu!', ], 'help' => [ - '_' => '', + '_' => 'Palīdzība & Kopiena', 'faq' => 'Biežāk Uzdotie Jautājumi', - 'forum' => '', - 'livestreams' => '', - 'report' => '', - 'wiki' => '', + 'forum' => 'Kopienas forumi', + 'livestreams' => 'Tiešraides', + 'report' => 'Ziņot par problēmu', + 'wiki' => 'Wiki', ], 'legal' => [ '_' => '', - 'copyright' => '', - 'privacy' => '', - 'server_status' => '', - 'source_code' => '', - 'terms' => '', + 'copyright' => 'Autortiesības (DMCA)', + 'privacy' => 'Konfidencialitāte', + 'server_status' => 'Servera stāvoklis', + 'source_code' => 'Pirmkods', + 'terms' => 'Nosacījumi', ], ], @@ -129,15 +129,15 @@ 'description' => "", ], '403' => [ - 'error' => "", - 'description' => '', + 'error' => "Tev šeit nevajedzētu būt.", + 'description' => 'Vari mēģināt iet atpakaļ, tomēr.', ], '401' => [ - 'error' => "", + 'error' => "Tev šeit nevajedzētu būt.", 'description' => '', ], '405' => [ - 'error' => '', + 'error' => 'Lapas Trūkst', 'description' => "", ], '422' => [ @@ -145,15 +145,15 @@ 'description' => '', ], '429' => [ - 'error' => '', + 'error' => 'Reitinga limits pārsniegts', 'description' => '', ], '500' => [ - 'error' => '', + 'error' => 'Ak nē! Kaut kas salūza! ;_;', 'description' => "", ], 'fatal' => [ - 'error' => '', + 'error' => 'Ak nē! Kaut kas salūza (ļoti)! ;_;', 'description' => "", ], '503' => [ diff --git a/resources/lang/lv-LV/mail.php b/resources/lang/lv-LV/mail.php index 4f9a21d26c4..4bbc650c8ce 100644 --- a/resources/lang/lv-LV/mail.php +++ b/resources/lang/lv-LV/mail.php @@ -58,7 +58,7 @@ 'shipping' => '', 'subject' => '', 'thank_you' => '', - 'total' => '', + 'total' => 'Kopā', ], 'supporter_gift' => [ @@ -81,7 +81,7 @@ 'user_force_reactivation' => [ 'main' => '', 'perform_reset' => '', - 'reason' => '', + 'reason' => 'Iemesls:', 'subject' => '', ], @@ -101,7 +101,7 @@ 'code_hint' => '', 'link' => '', 'report' => '', - 'subject' => '', + 'subject' => 'osu! konta apstiprināšana', 'action_from' => [ '_' => '', diff --git a/resources/lang/lv-LV/matches.php b/resources/lang/lv-LV/matches.php index 86316e2f844..0ccb74c823d 100644 --- a/resources/lang/lv-LV/matches.php +++ b/resources/lang/lv-LV/matches.php @@ -5,20 +5,20 @@ return [ 'match' => [ - 'beatmap-deleted' => '', + 'beatmap-deleted' => 'izdzēsta bītmape', 'failed' => '', 'header' => '', - 'in-progress' => '', - 'in_progress_spinner_label' => '', - 'loading-events' => '', - 'winner' => '', - 'winner_by' => '', + 'in-progress' => '(notiek mačs)', + 'in_progress_spinner_label' => 'notiek mačs', + 'loading-events' => 'Ielādē notikumus...', + 'winner' => ':team uzvar', + 'winner_by' => ':winner ar starpību :difference', 'events' => [ - 'player-left' => '', - 'player-joined' => '', - 'player-kicked' => '', - 'match-created' => '', + 'player-left' => ':user pameta maču', + 'player-joined' => ':user pievienojās mačam', + 'player-kicked' => ':user tika izraidīts no mača', + 'match-created' => ':user izveidoja maču', 'match-disbanded' => '', 'host-changed' => '', diff --git a/resources/lang/lv-LV/model_validation.php b/resources/lang/lv-LV/model_validation.php index 33c35d38e17..1352fe682bd 100644 --- a/resources/lang/lv-LV/model_validation.php +++ b/resources/lang/lv-LV/model_validation.php @@ -133,41 +133,41 @@ 'user' => [ 'contains_username' => '', - 'email_already_used' => '', + 'email_already_used' => 'E-pasta adrese jau tiek lietota.', 'email_not_allowed' => '', - 'invalid_country' => '', + 'invalid_country' => 'Valsts nav datubāzē.', 'invalid_discord' => '', 'invalid_email' => "", 'invalid_twitter' => '', - 'too_short' => '', + 'too_short' => 'Jaunā parole ir pārāk īsa.', 'unknown_duplicate' => '', 'username_available_in' => '', 'username_available_soon' => '', 'username_invalid_characters' => '', - 'username_in_use' => '', - 'username_locked' => '', // TODO: language for this should be slightly different. + 'username_in_use' => 'Lietotājvārds jau tiek lietots!', + 'username_locked' => 'Lietotājvārds jau tiek lietots!', // TODO: language for this should be slightly different. 'username_no_space_userscore_mix' => '', 'username_no_spaces' => "", 'username_not_allowed' => '', 'username_too_short' => '', 'username_too_long' => '', 'weak' => '', - 'wrong_current_password' => '', - 'wrong_email_confirmation' => '', - 'wrong_password_confirmation' => '', - 'too_long' => '', + 'wrong_current_password' => 'Pašreizējā parole ir nepareiza.', + 'wrong_email_confirmation' => 'E-pasta apstiprinājums nesakrīt.', + 'wrong_password_confirmation' => 'Paroles apstiprinājums neatbilst.', + 'too_long' => 'Pārsniedza maksimālo garumu - drīkst būt tikai līdz :limit zīmēm.', 'attributes' => [ - 'username' => '', - 'user_email' => '', - 'password' => '', + 'username' => 'Lietotājvārds', + 'user_email' => 'E-pasta adrese', + 'password' => 'Parole', ], 'change_username' => [ 'restricted' => '', 'supporter_required' => [ '_' => '', - 'link_text' => '', + 'link_text' => 'atbalstīja osu!', ], 'username_is_same' => '', ], @@ -183,8 +183,8 @@ 'store' => [ 'order_item' => [ 'attributes' => [ - 'quantity' => '', - 'cost' => '', + 'quantity' => 'Daudzums', + 'cost' => 'Izmaksas', ], ], ], diff --git a/resources/lang/lv-LV/news.php b/resources/lang/lv-LV/news.php index 3b8a8136c73..daac46c44ef 100644 --- a/resources/lang/lv-LV/news.php +++ b/resources/lang/lv-LV/news.php @@ -42,7 +42,7 @@ ], 'update' => [ - 'button' => '', - 'ok' => '', + 'button' => 'Atjaunināt', + 'ok' => 'Raksts atjaunināts.', ], ]; diff --git a/resources/lang/lv-LV/password_reset.php b/resources/lang/lv-LV/password_reset.php index 0dce7499d26..96ae7eb4319 100644 --- a/resources/lang/lv-LV/password_reset.php +++ b/resources/lang/lv-LV/password_reset.php @@ -12,8 +12,8 @@ 'error' => [ 'contact_support' => 'Sazinieties ar atbalsta centru, lai atgūtu kontu.', - 'expired' => '', - 'invalid' => '', + 'expired' => 'Apstiprinājuma koda termiņš ir beidzies.', + 'invalid' => 'Negaidīta kļūme apstiprināšanas kodā.', 'is_privileged' => 'Sazinieties ar peppy lulz.', 'missing_key' => 'Nepieciešams.', 'too_many_tries' => 'Pārāk daudz neizdevušos mēģinājumu.', diff --git a/resources/lang/lv-LV/quick_search.php b/resources/lang/lv-LV/quick_search.php index 9600f365454..bf03d341a7e 100644 --- a/resources/lang/lv-LV/quick_search.php +++ b/resources/lang/lv-LV/quick_search.php @@ -14,8 +14,8 @@ 'result' => [ 'empty' => 'Nav rezultātu', - 'empty_for' => '', - 'more' => '', - 'title' => '', + 'empty_for' => 'Nav rezultātu priekš :modes', + 'more' => 'Vairāk :mode meklēšanas rezultātu', + 'title' => ':mode meklēšanas rezultāti', ], ]; diff --git a/resources/lang/lv-LV/rankings.php b/resources/lang/lv-LV/rankings.php index 2b4999d2310..54a8cd84bec 100644 --- a/resources/lang/lv-LV/rankings.php +++ b/resources/lang/lv-LV/rankings.php @@ -18,15 +18,15 @@ ], 'kudosu' => [ - 'total' => '', - 'available' => '', - 'used' => '', + 'total' => 'Nopelnīts', + 'available' => 'Pieejams', + 'used' => 'Iztērēts', ], 'type' => [ 'charts' => 'Uzmanības centrā', 'country' => 'Valsts', - 'kudosu' => '', + 'kudosu' => 'kudosu', 'multiplayer' => 'Daudzspēlētāju režīms', 'performance' => 'Veiktspēja', 'score' => 'Punktu skaits', @@ -42,7 +42,7 @@ 'spotlight' => [ 'end_date' => 'Beigu datums', - 'map_count' => '', + 'map_count' => 'Mapu skaits', 'participants' => 'Dalībnieki', 'start_date' => 'Sākuma datums', ], @@ -51,7 +51,7 @@ 'accuracy' => 'Precizināte', 'active_users' => 'Aktīvie lietotāji', 'country' => 'Valsts', - 'play_count' => '', + 'play_count' => 'Spēļu skaits', 'performance' => 'Veiktspēja', 'total_score' => 'Kopējais punktu skaits', 'ranked_score' => '', diff --git a/resources/lang/lv-LV/store.php b/resources/lang/lv-LV/store.php index eefe7b28b0b..38685c3ac56 100644 --- a/resources/lang/lv-LV/store.php +++ b/resources/lang/lv-LV/store.php @@ -5,7 +5,7 @@ return [ 'cart' => [ - 'checkout' => '', + 'checkout' => 'Pirkuma noformēšana', 'empty_cart' => '', 'info' => '', 'more_goodies' => '', diff --git a/resources/lang/nl/password_reset.php b/resources/lang/nl/password_reset.php index c033e2fd657..f93d6eeb7a9 100644 --- a/resources/lang/nl/password_reset.php +++ b/resources/lang/nl/password_reset.php @@ -5,16 +5,16 @@ return [ 'button' => [ - 'resend' => 'Verificatie e-mail opnieuw versturen', + 'resend' => 'Verstuur verificatie e-mail opnieuw', 'set' => 'Wachtwoord instellen', 'start' => 'Start', ], 'error' => [ - 'contact_support' => 'Contakteer support om je account te herstellen.', + 'contact_support' => 'Contacteer support om je account te herstellen.', 'expired' => 'Verificatiecode is verlopen.', 'invalid' => 'Onverwachte fout in verificatiecode.', - 'is_privileged' => 'Contacteer peppy lol.', + 'is_privileged' => 'Neem contact op met een beheerder van een hoog niveau om je account te herstellen.', 'missing_key' => 'Vereist.', 'too_many_tries' => 'Te veel mislukte pogingen.', 'user_not_found' => 'Deze gebruiker bestaat niet.', diff --git a/resources/lang/nl/store.php b/resources/lang/nl/store.php index 528411ec0b4..0a522f7ede7 100644 --- a/resources/lang/nl/store.php +++ b/resources/lang/nl/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Afrekenen', - 'empty_cart' => '', + 'empty_cart' => 'Verwijder alle items uit de winkelwagen', 'info' => ':count_delimited artikel in winkelwagen ($:subtotal)|:count_delimited artikels in winkelwagen ($:subtotal)', 'more_goodies' => 'Ik wil meer goodies bekijken voordat ik de bestelling voltooi', 'shipping_fees' => 'verzendkosten', @@ -49,35 +49,35 @@ ], 'discount' => 'bespaar :percent%', - 'free' => '', + 'free' => 'gratis!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Contact:', + 'date' => 'Datum:', 'echeck_delay' => 'Aangezien uw betaling een eCheck was, Wacht maximaal 10 dagen extra om de betaling veilig via PayPal te laten gaan!', 'hide_from_activity' => 'osu!supporter tags in deze bestelling worden niet weergegeven in je recente activiteiten.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Gestuurd Via:', + 'shipping_to' => 'Verzenden Naar:', + 'title' => 'Factuur', 'title_compact' => 'factuur', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Je bestelling is geannuleerd', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Als je geen annulering hebt aangevraagd, neem dan contact op met :link en vermeld je bestelnummer (#:order_number).", + 'link_text' => 'osu!store support', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Je bestelling is geleverd! We hopen dat je ervan geniet!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Als je problemen hebt met je aankoop, neem dan contact op met de :link.', + 'link_text' => 'osu!store support', ], ], 'prepared' => [ - 'title' => '', + 'title' => 'Je bestelling wordt voorbereid!', 'line_1' => '', 'line_2' => '', ], @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', + 'title' => 'Je bestelling is verzonden!', 'tracking_details' => '', 'no_tracking_details' => [ '_' => "", - 'link_text' => '', + 'link_text' => 'stuur ons een email', ], ], ], @@ -108,13 +108,13 @@ 'no_orders' => 'Geen bestellingen om te bekijken.', 'paid_on' => 'Bestelling geplaatst :date', 'resume' => 'Hervat afrekenen', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Verzending & Verwerking', 'shopify_expired' => 'De checkout link voor deze bestelling is verlopen.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Subtotaal', + 'total' => 'Totaal', 'details' => [ - 'order_number' => '', + 'order_number' => 'Bestelling #', 'payment_terms' => '', 'salesperson' => '', 'shipping_method' => '', @@ -155,10 +155,10 @@ ], 'thanks' => [ - 'title' => '', + 'title' => 'Bedankt voor je bestelling!', 'line_1' => [ '_' => '', - 'link_text' => '', + 'link_text' => 'contacteer ons', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Voer een gebruikersnaam in om de beschikbaarheid te controleren!', 'checking' => 'Bezig met beschikbaarheid te controleren van :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Aangevraagde Gebruikersnaam', + 'label' => 'Nieuwe Gebruikersnaam', + 'current' => 'Je huidige gebruikersnaam is ":username".', 'require_login' => [ '_' => 'Je moet :link zijn om je naam te veranderen!', diff --git a/resources/lang/pl/store.php b/resources/lang/pl/store.php index f5c595b2193..20fcb2eb7dc 100644 --- a/resources/lang/pl/store.php +++ b/resources/lang/pl/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Zapłać', - 'empty_cart' => '', + 'empty_cart' => 'Usuń wszystkie produkty z koszyka', 'info' => ':count_delimited produkt w koszyku (:subtotal$)|:count_delimited produkty w koszyku (:subtotal$)|:count_delimited produktów w koszyku (:subtotal$)', 'more_goodies' => 'Chcę przejrzeć inne produkty przed zakończeniem zamówienia', 'shipping_fees' => 'koszt wysyłki', @@ -63,7 +63,7 @@ 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Twoje zamówienie zostało anulowane', 'line_1' => [ '_' => "", 'link_text' => '', diff --git a/resources/lang/pt-br/comments.php b/resources/lang/pt-br/comments.php index e878d65eb1e..5309f4018f9 100644 --- a/resources/lang/pt-br/comments.php +++ b/resources/lang/pt-br/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'comentário de :user', ], 'placeholder' => [ diff --git a/resources/lang/pt-br/notifications.php b/resources/lang/pt-br/notifications.php index 99e9a319f59..2f4280a2ad7 100644 --- a/resources/lang/pt-br/notifications.php +++ b/resources/lang/pt-br/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'A discussão foi destrancada', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited elogio|:count_delimited elogios', + 'problems' => ':count_delimited problema|:count_delimited problemas', + 'suggestions' => ':count_delimited sugestão|:count_delimited sugestões', ], ], diff --git a/resources/lang/pt-br/store.php b/resources/lang/pt-br/store.php index ad2018c31f2..cb9f7f4bd8b 100644 --- a/resources/lang/pt-br/store.php +++ b/resources/lang/pt-br/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Pagar', - 'empty_cart' => '', + 'empty_cart' => 'Remover todos os itens do carrinho', 'info' => ':count_delimited item no carrinho ($:subtotal)|:count_delimited itens no carrinho ($:subtotal)', 'more_goodies' => 'Gostaria de conferir mais coisas antes de finalizar meu pedido', 'shipping_fees' => 'taxas de envio', @@ -49,37 +49,37 @@ ], 'discount' => 'economize :percent%', - 'free' => '', + 'free' => 'gratuito! ', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Contato:', + 'date' => 'Data:', 'echeck_delay' => 'Como seu pagamento foi um eCheck, por favor aguarde por até 10 dias para se concluir o pagamento via PayPal!', 'hide_from_activity' => 'As tags de osu!supporter nesta ordem não são exibidas nas suas atividades recentes.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Enviado via:', + 'shipping_to' => 'Envio para:', + 'title' => 'Fatura', 'title_compact' => 'fatura', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'O seu pedido foi cancelado', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Se você não solicitou um cancelamento, entre em contato com :link com o número do seu pedido (#:order_number).", + 'link_text' => 'suporte da osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Seu pedido foi entregue! Esperamos que esteja gostando!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Se você tiver algum problema com a sua compra, por favor, entre em contato com :link.', + 'link_text' => 'suporte da osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Seu pedido está sendo preparado!', + 'line_1' => 'Por favor, aguarde um pouco mais para que seu produto seja enviado. As informações de rastreamento aparecerão aqui assim que o pedido for processado e enviado. Isso pode levar até 5 dias (mas geralmente menos!) dependendo da demanda.', + 'line_2' => 'Enviamos todas as encomendas do Japão usando uma variedade de serviços de transporte, dependendo do peso e do valor. Esta área será atualizada com mais detalhes após enviarmos a encomenda.', ], 'processing' => [ 'title' => 'Seu pagamento ainda não foi confirmado!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Seu pedido foi enviado!', + 'tracking_details' => 'Detalhes do rastreamento:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Não temos detalhes de rastreio já que enviamos o seu pacote via Air Mail, mas você pode esperar recebê-lo dentro de 1-3 semanas. Para a Europa, as alfândegas podem atrasar a ordem e isso está fora do nosso controle. Se você tiver algum problema, por favor, responda o e-mail de confirmação de pedido que você recebeu :link.", + 'link_text' => 'envie-nos um e-mail', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Sem pedidos para ver.', 'paid_on' => 'Ordem colocara :date', 'resume' => 'Continuar Compra', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Envio e Manuseio', 'shopify_expired' => 'O link de verificação deste pedido expirou.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Subtotal', + 'total' => 'Total', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Pedido #', + 'payment_terms' => 'Condições de pagamento', + 'salesperson' => 'Vendedor(a)', + 'shipping_method' => 'Método de Envio', + 'shipping_terms' => 'Termos de envio', + 'title' => 'Detalhes do pedido', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Pago', 'processing' => 'Aguardando confirmação', 'shipped' => 'Em Trânsito', - 'title' => '', + 'title' => 'Status do pedido', ], 'thanks' => [ - 'title' => '', + 'title' => 'Obrigado pela sua compra!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Você receberá um e-mail de confirmação em breve. Se você tiver alguma dúvida, por favor, :link!', + 'link_text' => 'fale conosco', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Insira um nome de usuário para verificar a disponibilidade!', 'checking' => 'Checando disponibilidade de :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Nome de usuário solicitado', + 'label' => 'Novo nome de usuário', + 'current' => 'Seu nome de usuário atual é ":username".', 'require_login' => [ '_' => 'Você precisa estar :link para mudar o seu nome!', diff --git a/resources/lang/pt-br/users.php b/resources/lang/pt-br/users.php index 5894ef623fc..032ef45f44d 100644 --- a/resources/lang/pt-br/users.php +++ b/resources/lang/pt-br/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmaps: :counts', + 'modding_description_empty' => 'O usuário não possui nenhum beatmap...', 'description' => [ '_' => 'Rank (:ruleset): :global | :country', diff --git a/resources/lang/pt/comments.php b/resources/lang/pt/comments.php index 672ab12dab9..67d12a9bce2 100644 --- a/resources/lang/pt/comments.php +++ b/resources/lang/pt/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'comentário de :user', ], 'placeholder' => [ diff --git a/resources/lang/pt/notifications.php b/resources/lang/pt/notifications.php index acb1c1feedc..1a6e3435f27 100644 --- a/resources/lang/pt/notifications.php +++ b/resources/lang/pt/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'A discussão foi aberta', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited elogio|:count_delimited elogios', + 'problems' => ':count_delimited problema|:count_delimited problemas', + 'suggestions' => ':count_delimited sugestão|:count_delimited sugestões', ], ], diff --git a/resources/lang/pt/store.php b/resources/lang/pt/store.php index c9d0efaf690..f048eee36c6 100644 --- a/resources/lang/pt/store.php +++ b/resources/lang/pt/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Pagamento', - 'empty_cart' => '', + 'empty_cart' => 'Remover todos os artigos do carrinho', 'info' => ':count_delimited artigo no carrinho ($:subtotal)|:count_delimited artigos no carrinho ($:subtotal)', 'more_goodies' => 'Quero adicionar mais brindes antes de completar o pedido', 'shipping_fees' => 'custos de envio', @@ -49,37 +49,37 @@ ], 'discount' => 'poupa :percent%', - 'free' => '', + 'free' => 'grátis!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Contacto:', + 'date' => 'Data:', 'echeck_delay' => 'Como o teu pagamento era um eCheck, por favor permite até 10 dias extras para o pagamento ser autorizado através do PayPal!', 'hide_from_activity' => 'As etiquetas osu!supporter nesta ordem não estão visíveis nas tuas atividades recentes.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Enviado através de:', + 'shipping_to' => 'Enviar para:', + 'title' => 'Fatura', 'title_compact' => 'fatura', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'A tua encomenda foi cancelada', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Se não pediste o cancelamento, contacta :link indicando o teu número da encomenda (#:order_number).", + 'link_text' => 'Apoio da osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'A tua encomenda foi entregue. Esperemos que gostes!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Se tiveres algum problema com a tua compra, contacta :link.', + 'link_text' => 'Apoio da osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'O teu pedido está a ser preparado!', + 'line_1' => 'Aguarda um pouco mais para que a encomenda seja enviada. A informação de seguimento aparecerá aqui assim que ela for processada e enviada. Isto pode demorar até 5 dias (normalmente menos), dependendo do nosso nível de atividade.', + 'line_2' => 'Enviamos todas as encomendas do Japão utilizando uma variedade de serviços de envio, consoante o peso e o valor. Esta área será atualizada com os detalhes específicos assim que a encomenda for enviada.', ], 'processing' => [ 'title' => 'O teu pagamento ainda não foi confirmado!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'O teu pedido foi enviado!', + 'tracking_details' => 'Detalhes do seguimento:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Não temos detalhes de seguimento, pois enviamos a tua embalagem por correio aéreo, mas podes esperar recebê-lo dentro de 1 a 3 semanas. Para a Europa, por vezes a alfândega poderá atrasar a encomenda. Este processo está fora do nosso controlo. Se tiveres alguma dúvida, responde ao email de confirmação da encomenda que recebeste :link.", + 'link_text' => 'envia-nos um email', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Sem pedidos para ver.', 'paid_on' => 'Pedido colocado em :date', 'resume' => 'Retomar pagamento', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Expedição e manuseamento', 'shopify_expired' => 'O link de pagamento para este pedido expirou.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Subtotal', + 'total' => 'Total', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Pedido n.º ', + 'payment_terms' => 'Condições de pagamento', + 'salesperson' => 'Vendedor', + 'shipping_method' => 'Método de envío', + 'shipping_terms' => 'Condições de envio', + 'title' => 'Detalhes do pedido', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Pagos', 'processing' => 'Confirmação pendente', 'shipped' => 'Em curso', - 'title' => '', + 'title' => 'Estado do pedido', ], 'thanks' => [ - 'title' => '', + 'title' => 'Obrigado pelo teu pedido!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Receberás um email de confirmação em breve. Se tiveres alguma dúvida, por favor :link!', + 'link_text' => 'contacta-nos', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Introduz um nome de utilizador para confirmar disponibilidade!', 'checking' => 'A confirmar disponibilidade de :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Nome de utilizador solicitado', + 'label' => 'Novo nome de utilizador', + 'current' => 'O teu nome de utilizador atual: :username.', 'require_login' => [ '_' => 'Precisas de ter :link para mudares o teu nome!', diff --git a/resources/lang/pt/users.php b/resources/lang/pt/users.php index dbbf16f6016..9f26b157897 100644 --- a/resources/lang/pt/users.php +++ b/resources/lang/pt/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmaps: :counts', + 'modding_description_empty' => 'O utilizador não possui nenhum beatmap...', 'description' => [ '_' => 'Classificação (:ruleset): :global | :country', diff --git a/resources/lang/ro/comments.php b/resources/lang/ro/comments.php index dedb1bdaca6..812ee7c002d 100644 --- a/resources/lang/ro/comments.php +++ b/resources/lang/ro/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'comentariu de :user', ], 'placeholder' => [ diff --git a/resources/lang/ro/notifications.php b/resources/lang/ro/notifications.php index 58d15ef0665..9aca353948c 100644 --- a/resources/lang/ro/notifications.php +++ b/resources/lang/ro/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'Discuția a fost redeschisă', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => 'o laudă|:count_delimited laude|:count_delimited de laude', + 'problems' => 'o problemă|:count_delimited probleme|:count_delimited de probleme', + 'suggestions' => 'o sugestie|:count_delimited sugestii|:count_delimited de sugestii', ], ], diff --git a/resources/lang/ro/store.php b/resources/lang/ro/store.php index 8f4a3f4371f..ca9bc08e8d2 100644 --- a/resources/lang/ro/store.php +++ b/resources/lang/ro/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Plată', - 'empty_cart' => '', + 'empty_cart' => 'Elimină toate articolele din coș', 'info' => 'un obiect în coș ($:subtotal)|:count_delimited obiecte în coș ($:subtotal)|:count_delimited de obiecte în coș ($:subtotal)', 'more_goodies' => 'Vreau să-mi verific bunătățile înainte de a completa comanda', 'shipping_fees' => 'taxe de livrare', @@ -49,37 +49,37 @@ ], 'discount' => 'economisește :percent%', - 'free' => '', + 'free' => 'gratuit!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Contact:', + 'date' => 'Dată:', 'echeck_delay' => 'Pentru că plata ta a fost făcută electronic, te rugăm să aștepți încă 10 zile pentru ca plata să se afișeze prin PayPal!', 'hide_from_activity' => 'Statusul de suporter osu! din această comandă nu sunt afișate în activitățile tale recente.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Trimis Prin:', + 'shipping_to' => 'Livrare Către:', + 'title' => 'Factură', 'title_compact' => 'factură fiscală', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Comanda ta a fost anulată', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Dacă nu ai solicitat o anulare, te rugăm să contactezi :link precizând numărul comenzii tale (#:order_number).", + 'link_text' => 'echipa de suport pentru magazinul osu!', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Comanda ta a fost livrată! Sperăm că vă bucurați de ea!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Dacă întâmpini probleme cu achiziția ta, te rugăm să contactați :link.', + 'link_text' => 'echipa de suport pentru magazinul osu!', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Comanda ta este în curs de pregătire!', + 'line_1' => 'Te rugăm să mai aștepți pentru expediere. Informațiile de urmărire vor apărea aici odată ce comanda a fost procesată și trimisă. Acest lucru poate dura până la 5 zile (dar de obicei mai puțin!) în funcție de cât de ocupați suntem.', + 'line_2' => 'Toate comenzile sunt expediate din Japonia folosind o varietate de servicii de transport în funcție de greutate și valoare. Această zonă se va actualiza cu mai multe informații odată ce comanda este expediată.', ], 'processing' => [ 'title' => 'Plata nu a fost încă confirmată!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Comanda ta a fost expediată!', + 'tracking_details' => 'Detalii de urmărire:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Nu avem detalii de urmărire fiindca am trimis coletul tău prin Air Mail, dar te poți aștepta să îl primești in 1-3 săptămâni. Pentru Europa, uneori vămile pot întârzia comenzile fapt care nu este sub controlul nostru. Dacă aveți solicitări adiționale, vă rugăm să răspundeți la e-mailul de confirmare al comenzii pe care l-ați primit :link.", + 'link_text' => 'trimiteți-ne un e-mail', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Nu sunt comenzi pentru vizualizare.', 'paid_on' => 'Comandă plasată pe :date', 'resume' => 'Reia finalizarea comenzii', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Livrare și Procesare', 'shopify_expired' => 'Link-ul de finalizare a comenzii a expirat.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Subtotal', + 'total' => 'Total', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Comanda #', + 'payment_terms' => 'Termeni de plată', + 'salesperson' => 'Agent de vânzare', + 'shipping_method' => 'Metoda Livrare', + 'shipping_terms' => 'Termeni de livrare', + 'title' => 'Detaliile Comenzii', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Plătit', 'processing' => 'Confirmarea plății', 'shipped' => 'Expediat', - 'title' => '', + 'title' => 'Starea Comenzii', ], 'thanks' => [ - 'title' => '', + 'title' => 'Mulțumim pentru comandă!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Veți primi în curând un e-mail de confirmare. Dacă aveți solicitări, vă rugăm să :link!', + 'link_text' => 'ne contactați', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Întrodu un nume de utilizator pentru a verifica disponibilitatea!', 'checking' => 'Se verifică disponibilitatea lui :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Nume Utilizator Solicitat', + 'label' => 'Nume Utilizator Nou', + 'current' => 'Numele tău de utilizator actual este ":username".', 'require_login' => [ '_' => 'Trebuie să fii :link pentru a îți schimba numele!', diff --git a/resources/lang/ro/users.php b/resources/lang/ro/users.php index bc519c67a1e..101e33afae7 100644 --- a/resources/lang/ro/users.php +++ b/resources/lang/ro/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmap-uri: :counts', + 'modding_description_empty' => 'Utilizatorul nu are nici un beatmap...', 'description' => [ '_' => 'Rang (:ruleset): :global | :country', diff --git a/resources/lang/ru/authorization.php b/resources/lang/ru/authorization.php index 5f57dde44e6..fc99a78f93d 100644 --- a/resources/lang/ru/authorization.php +++ b/resources/lang/ru/authorization.php @@ -53,7 +53,7 @@ ], 'beatmapset' => [ - 'discussion_locked' => 'Обсуждение этой карты закрыто.', + 'discussion_locked' => 'Возможность обсуждения этой карты закрыта.', 'metadata' => [ 'nominated' => 'Вы не можете изменить метаданные номинируемой карты. В случае ошибок свяжитесь с номнатором или членом NAT.', diff --git a/resources/lang/ru/beatmap_discussions.php b/resources/lang/ru/beatmap_discussions.php index 1235899a919..9be37b582f7 100644 --- a/resources/lang/ru/beatmap_discussions.php +++ b/resources/lang/ru/beatmap_discussions.php @@ -27,15 +27,15 @@ 'mode' => 'Режим игры', 'only_unresolved' => 'Показать только нерешённые обсуждения', 'show_review_embeds' => 'Показать посты рецензии', - 'types' => 'Типы сообщений', + 'types' => 'Виды сообщений', 'username' => 'Никнейм', 'beatmapset_status' => [ '_' => 'Статус карты', 'all' => 'Все', - 'disqualified' => 'Дисквалифицирована', + 'disqualified' => 'Была дисквалифицирована', 'never_qualified' => 'Никогда не квалифицировалась', - 'qualified' => 'Квалифицирована', + 'qualified' => 'Квалифицированная', 'ranked' => 'Рейтинговая', ], @@ -75,8 +75,8 @@ 'review' => [ 'block_count' => ':used / :max блоков использовано', - 'go_to_parent' => 'Посмотреть рецензию', - 'go_to_child' => 'Посмотреть обсуждение', + 'go_to_parent' => 'Перейти к рецензии', + 'go_to_child' => 'Перейти к обсуждению', 'validation' => [ 'block_too_large' => 'каждый блок может содержать до :limit символов', 'external_references' => 'отзыв содержит ссылки на проблемы, не отноcящиеся к этому отзыву', diff --git a/resources/lang/ru/beatmaps.php b/resources/lang/ru/beatmaps.php index 95a39311e00..beca52dec72 100644 --- a/resources/lang/ru/beatmaps.php +++ b/resources/lang/ru/beatmaps.php @@ -21,7 +21,7 @@ 'guest' => 'Гостевая сложность от :user', 'kudosu_denied' => 'Отказано в получении кудосу.', 'message_placeholder_deleted_beatmap' => 'Эта сложность была удалена, и поэтому обсуждать её больше нельзя.', - 'message_placeholder_locked' => 'Обсуждение этой карты было отключено.', + 'message_placeholder_locked' => 'Возможность обсуждения этой карты закрыта.', 'message_placeholder_silenced' => "Запрещено писать посты в обсуждении, пока вы заглушены.", 'message_type_select' => 'Выбрать тип комментария', 'reply_notice' => 'Нажмите Enter, чтобы ответить.', @@ -62,7 +62,7 @@ 'message_placeholder' => [ 'general' => 'Оставьте отзыв в Общее (:version)', 'generalAll' => 'Оставьте отзыв в Общее (все сложности)', - 'review' => 'Напишите рецензию', + 'review' => 'Начните печатать', 'timeline' => 'Сообщите о тайм-коде в сложности :version', ], diff --git a/resources/lang/ru/beatmapset_events.php b/resources/lang/ru/beatmapset_events.php index be1b22bcf8e..b4ffc3d83a1 100644 --- a/resources/lang/ru/beatmapset_events.php +++ b/resources/lang/ru/beatmapset_events.php @@ -6,32 +6,32 @@ return [ 'event' => [ 'approve' => 'Карта получила категорию Одобрена.', - 'beatmap_owner_change' => 'Владелец сложности :beatmap изменен на :new_user.', + 'beatmap_owner_change' => 'Владелец сложности :beatmap изменён на :new_user.', 'discussion_delete' => 'Модератор удалил отзыв :discussion.', - 'discussion_lock' => 'Обсуждение для этой карты было отключено. (:text)', + 'discussion_lock' => 'Возможность обсуждения этой карты закрыта. (:text)', 'discussion_post_delete' => 'Модератор удалил пост к отзыву :discussion.', - 'discussion_post_restore' => 'Модератор восстановил пост в обсуждении :discussion.', + 'discussion_post_restore' => 'Модератор восстановил пост к отзыву :discussion.', 'discussion_restore' => 'Модератор восстановил отзыв :discussion.', - 'discussion_unlock' => 'Обсуждение для этой карты было включено.', + 'discussion_unlock' => 'Возможность обсуждения этой карты снова открыта.', 'disqualify' => 'Дисквалифицирована :user. Причина: :discussion (:text).', - 'disqualify_legacy' => 'Дисквалифицирована :user. Причина: :text.', + 'disqualify_legacy' => 'Получена дисквалификация от :user. Причина: :text.', 'genre_edit' => 'Жанр изменен с :old на :new.', 'issue_reopen' => 'Проблема :discussion, которая была решена пользователем :discussion_user, вновь открыта :user.', 'issue_resolve' => 'Проблема :discussion, открытая :discussion_user, решена :user.', - 'kudosu_allow' => 'Отказ в кудосу :discussion был удален.', - 'kudosu_deny' => 'Отзыву :discussion отказано в кудосу.', - 'kudosu_gain' => 'Отзыв :discussion от :user получил достаточно голосов для получения кудосу.', - 'kudosu_lost' => 'Отзыв :discussion от :user потерял голоса и присуждённые кудосу были удалены.', + 'kudosu_allow' => 'Вето на начисление кудосу за отзыв :discussion было снято.', + 'kudosu_deny' => 'На начисление кудосу за отзыв :discussion наложено вето.', + 'kudosu_gain' => 'Отзыв :discussion от :user получил достаточно голосов для начисления кудосу.', + 'kudosu_lost' => 'Отзыв :discussion от :user потерял голоса и начисленные кудосу были отозваны.', 'kudosu_recalculate' => 'Кудосу за отзыв :discussion были пересчитаны.', 'language_edit' => 'Язык изменен с :old на :new.', 'love' => 'Карта получила категорию Любимая. (:user)', - 'nominate' => 'Номинирована :user.', + 'nominate' => 'Карта получила номинацию от :user.', 'nominate_modes' => 'Карта получила номинацию от :user (:modes).', 'nomination_reset' => 'Из-за новой проблемы в :discussion (:text) статус номинации был сброшен.', 'nomination_reset_received' => 'Номинация пользователя :user была сброшена :source_user (:text)', 'nomination_reset_received_profile' => 'Номинация была сброшена :user (:text)', 'offset_edit' => 'Значение оффсета изменено с :old на :new.', - 'qualify' => 'Эта карта была номинирована достаточное количество раз для квалификации.', + 'qualify' => 'Карта получила достаточное количество номинаций и стала квалифицированной.', 'rank' => 'Карта получила категорию Рейтинговая.', 'remove_from_loved' => ':user удалил карту из категории Любимая. (:text)', 'tags_edit' => 'Теги изменены с ":old" на ":new".', @@ -47,7 +47,7 @@ 'form' => [ 'period' => 'Период', - 'types' => 'Типы событий', + 'types' => 'Виды событий', ], ], @@ -66,7 +66,7 @@ 'discussion_restore' => 'Восстановление обсуждения', 'disqualify' => 'Дисквалификация', 'genre_edit' => 'Изменение жанра', - 'issue_reopen' => 'Возобновление обсуждения', + 'issue_reopen' => 'Возобновление обсуждения проблемы', 'issue_resolve' => 'Решение проблем', 'kudosu_allow' => 'Квота кудосу', 'kudosu_deny' => 'Отказ в кудосу', diff --git a/resources/lang/ru/comments.php b/resources/lang/ru/comments.php index 5d7358ae401..65f9ffaf358 100644 --- a/resources/lang/ru/comments.php +++ b/resources/lang/ru/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'комментарий от :user', ], 'placeholder' => [ diff --git a/resources/lang/ru/community.php b/resources/lang/ru/community.php index 2a800aa371a..4db102923ba 100644 --- a/resources/lang/ru/community.php +++ b/resources/lang/ru/community.php @@ -100,7 +100,7 @@ ], 'change_username' => [ - 'title' => 'Смена никнейма', + 'title' => 'Смена ника', 'description' => 'Одно бесплатное изменение ника с первым приобретением osu!supporter.', ], @@ -138,10 +138,10 @@ ], 'supporter_status' => [ - 'contribution' => 'Большое спасибо за Вашу поддержку! Всего Вы пожертвовали :dollars за :tags покупок!', - 'gifted' => "Из них Вы подарили :giftedTags тегов (на сумму :giftedDollars) – как щедро!", - 'not_yet' => "У вас нет и ещё не было osu!supporter :(", - 'valid_until' => 'Ваш osu!supporter активен до :date!', + 'contribution' => 'Большое спасибо за вашу поддержку! Всего вы пожертвовали :dollars за :tags покупок тега!', + 'gifted' => "Из них вы подарили :giftedTags тегов на сумму в :giftedDollars – как щедро с вашей стороны!", + 'not_yet' => "У вас нет и ещё не было тега osu!supporter :(", + 'valid_until' => 'Ваш тег osu!supporter активен до :date!', 'was_valid_until' => 'Ваш тег osu!supporter истёк :date.', ], ], diff --git a/resources/lang/ru/forum.php b/resources/lang/ru/forum.php index 6aaf097f097..c920b694b9e 100644 --- a/resources/lang/ru/forum.php +++ b/resources/lang/ru/forum.php @@ -15,7 +15,7 @@ 'create' => [ '_' => 'Установить обложку', 'button' => 'Загрузить изображение', - 'info' => 'Разрешение изображения должно быть :dimensions. Для загрузки изображения, вы можете просто бросить его сюда.', + 'info' => 'Необходимый размер обложки: :dimensions. Вы также можете перетащить изображение сюда для загрузки.', ], 'destroy' => [ @@ -334,8 +334,8 @@ 'do' => 'Продвинуть эту идею', 'info' => [ - '_' => 'Это :feature_request. За идею можно проголосовать только с :supporters.', - 'feature_request' => 'предложенная идея', + '_' => 'Это :feature_request. За неё можно проголосовать только с тегом :supporters.', + 'feature_request' => 'запрос на разработку новой функции', 'supporters' => 'osu!supporter', ], diff --git a/resources/lang/ru/layout.php b/resources/lang/ru/layout.php index b42047c1e39..cf0a0458ae9 100644 --- a/resources/lang/ru/layout.php +++ b/resources/lang/ru/layout.php @@ -178,7 +178,7 @@ 'username' => 'никнейм', 'error' => [ - 'email' => "Никнейм или электронная почта не существуют", + 'email' => "Ник или электронная почта не существуют", 'password' => 'Неверный пароль', ], ], diff --git a/resources/lang/ru/mail.php b/resources/lang/ru/mail.php index 69dad5c7b18..c682e46f5a6 100644 --- a/resources/lang/ru/mail.php +++ b/resources/lang/ru/mail.php @@ -99,8 +99,8 @@ 'user_verification' => [ 'code' => 'Ваш код подтверждения:', 'code_hint' => 'Вы можете ввести код с пробелами или без них.', - 'link' => 'В качестве альтернативы, Вы также можете перейти по ссылке ниже для завершения верификации:', - 'report' => 'Если Вы его не запрашивали, пожалуйста, НЕМЕДЛЕННО ОТВЕТЬТЕ на это письмо, так как Ваш аккаунт может быть под угрозой.', + 'link' => 'В качестве альтернативы вы также можете перейти по ссылке ниже для завершения верификации:', + 'report' => 'Если вы его не запрашивали, пожалуйста, НЕМЕДЛЕННО ОТВЕТЬТЕ на это письмо, так как ваш аккаунт может быть под угрозой.', 'subject' => 'Подтверждение доступа к аккаунту osu!', 'action_from' => [ diff --git a/resources/lang/ru/model_validation.php b/resources/lang/ru/model_validation.php index 48224810a3b..0237bf02c97 100644 --- a/resources/lang/ru/model_validation.php +++ b/resources/lang/ru/model_validation.php @@ -132,7 +132,7 @@ ], 'user' => [ - 'contains_username' => 'Пароль не должен содержать никнейм.', + 'contains_username' => 'Пароль не должен содержать ник.', 'email_already_used' => 'Эта почта занята.', 'email_not_allowed' => 'Недопустимый адрес электронной почты.', 'invalid_country' => 'Вашей страны нет в базе данных.', @@ -140,15 +140,15 @@ 'invalid_email' => "Кажется, эта почта недействительна.", 'invalid_twitter' => 'Неверное имя пользователя Twitter.', 'too_short' => 'Новый пароль слишком короткий.', - 'unknown_duplicate' => 'Никнейм или почта уже занята.', + 'unknown_duplicate' => 'Ник или почта уже занята.', 'username_available_in' => 'Этот никнейм будет доступен через :duration.', 'username_available_soon' => 'Этот никнейм будет доступен в любой момент!', - 'username_invalid_characters' => 'Введённый никнейм содержит недопустимые символы.', - 'username_in_use' => 'Этот никнейм занят!', - 'username_locked' => 'Этот никнейм занят!', // TODO: language for this should be slightly different. + 'username_invalid_characters' => 'Введённый ник содержит недопустимые символы.', + 'username_in_use' => 'Этот ник уже занят!', + 'username_locked' => 'Этот ник уже занят!', // TODO: language for this should be slightly different. 'username_no_space_userscore_mix' => 'Пожалуйста не используйте пробелы и подчёркивания одновременно!', 'username_no_spaces' => "Никнейм не может начинаться или заканчиваться пробелами!", - 'username_not_allowed' => 'Этот никнейм запрещён.', + 'username_not_allowed' => 'Этот ник запрещён к регистрации.', 'username_too_short' => 'Введённый никнейм слишком короткий.', 'username_too_long' => 'Введённый никнейм слишком длинный.', 'weak' => 'Введённый пароль находится в чёрном списке.', @@ -158,15 +158,15 @@ 'too_long' => 'Превышено максимальное количество символов - можно использовать только до :limit characters символов.', 'attributes' => [ - 'username' => 'Никнейм', + 'username' => 'Ник', 'user_email' => 'E-mail адрес', 'password' => 'Пароль', ], 'change_username' => [ - 'restricted' => 'Вы не можете сменить свой никнейм, пока ваш аккаунт ограничен.', + 'restricted' => 'Вы не можете сменить свой ник, пока ваш аккаунт ограничен.', 'supporter_required' => [ - '_' => 'Вы должны :link , чтобы изменить свой никнейм!', + '_' => 'Вы должны :link , чтобы изменить свой ник!', 'link_text' => 'поддержать osu!', ], 'username_is_same' => 'Это уже и есть Ваш никнейм!', diff --git a/resources/lang/ru/notifications.php b/resources/lang/ru/notifications.php index 2823f0cb996..e0bc5fd33db 100644 --- a/resources/lang/ru/notifications.php +++ b/resources/lang/ru/notifications.php @@ -51,15 +51,15 @@ 'beatmapset_discussion_post_new_empty' => 'Новый пост в ":title" от :username', 'beatmapset_discussion_post_new_compact' => 'Новый пост от :username: ":content"', 'beatmapset_discussion_post_new_compact_empty' => 'Новый пост от :username', - 'beatmapset_discussion_review_new' => 'Новый отзыв на ":title" от :username, содержащий проблемы: :problems, предложения: :suggestions, похвалы: :praises', - 'beatmapset_discussion_review_new_compact' => 'Новый отзыв от :username, содержащий проблемы: :problems, предложения: :suggestions, похвалы: :praises', + 'beatmapset_discussion_review_new' => 'Новый отзыв на ":title" от :username, содержащий :review_counts', + 'beatmapset_discussion_review_new_compact' => 'Новый отзыв от :username, содержащий :review_counts', 'beatmapset_discussion_unlock' => 'Карта ":title" разблокирована для обсуждений', 'beatmapset_discussion_unlock_compact' => 'Обсуждение было разблокировано', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited похвалу|:count_delimited похвалы|:count_delimited похвал', + 'problems' => ':count_delimited проблему|:count_delimited проблемы|:count_delimited проблем', + 'suggestions' => ':count_delimited предложение|:count_delimited предложения|:count_delimited предложений', ], ], diff --git a/resources/lang/ru/store.php b/resources/lang/ru/store.php index 9e2aa7dde47..fec6def83f6 100644 --- a/resources/lang/ru/store.php +++ b/resources/lang/ru/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Оплатить', - 'empty_cart' => '', + 'empty_cart' => 'Удалить все товары из корзины', 'info' => ':count_delimited товар в корзине ($:subtotal)|:count_delimited товара в корзине ($:subtotal)|:count_delimited товаров в корзине ($:subtotal)', 'more_goodies' => 'Я хочу посмотреть другие товары перед завершением заказа', 'shipping_fees' => 'стоимость доставки', @@ -15,7 +15,7 @@ 'errors_no_checkout' => [ 'line_1' => 'Ой-ой, обнаружены проблемы, мешающие завершить заказ!', - 'line_2' => 'Удалите товары выше или обновите их статус для продолжения.', + 'line_2' => 'Удалите товары выше или обновите их статус, чтобы продолжить.', ], 'empty' => [ @@ -49,37 +49,37 @@ ], 'discount' => 'вы сэкономите :percent%', - 'free' => '', + 'free' => 'бесплатно!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Контакты:', + 'date' => 'Дата:', 'echeck_delay' => 'Поскольку оплата была через eCheck, ожидание подтверждения оплаты через Paypal может занят до 10 дней!', 'hide_from_activity' => 'сообщения о тегах osu!supporter после покупки не будут отображены в вашем профиле.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Отправлено через:', + 'shipping_to' => 'Доставка в:', + 'title' => 'Чек', 'title_compact' => 'чек', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Ваш заказ был отменён', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Если вы не отменяли заказ самостоятельно, пожалуйста, свяжитесь с :link, указав номер вашего заказа (#:order_number).", + 'link_text' => 'поддержкой osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Ваш заказ доставлен! Мы надеемся, что он вам понравился!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Если у вас возникли проблемы с покупкой, пожалуйста, свяжитесь с :link.', + 'link_text' => 'поддержкой osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Ваш заказ готовится к отправке!', + 'line_1' => 'Пожалуйста, дождитесь отправки заказа. Информация об отслеживании появится здесь после того, как заказ будет обработан и отправлен. Этот процесс может занять до 5 дней (но обычно меньше!) в зависимости от нашей загруженности.', + 'line_2' => 'Мы отправляем все заказы из Японии различными службами доставки в зависимости от веса и стоимости. Подробности доставки появятся тут, как только мы отправим ваш заказ.', ], 'processing' => [ 'title' => 'Ваш платеж ещё не подтверждён!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Ваш заказ отправлен!', + 'tracking_details' => 'Подробности отслеживания:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "У нас нет данных отслеживания, поскольку мы отправили ваш заказ авиапочтой, однако вы можете рассчитывать на их получение в течение 1-3 недель. Иногда таможня в Европе может задержать заказ вне нашего контроля. Если у вас остались вопросы, ответьте на полученное вами письмо с подтверждением заказа :link.", + 'link_text' => 'отправьте нам письмо', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Вы ничего не заказывали.', 'paid_on' => 'Заказ размещён :date', 'resume' => 'Продолжить оплату', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Доставка и обработка', 'shopify_expired' => 'Срок действия ссылки на чек вашего заказа кончился.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Итого', + 'total' => 'Итого', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Заказ #', + 'payment_terms' => 'Условия оплаты', + 'salesperson' => 'Продавец', + 'shipping_method' => 'Способ доставки', + 'shipping_terms' => 'Условия доставки', + 'title' => 'Состав заказа', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Оплачено', 'processing' => 'Ожидает подтверждения', 'shipped' => 'В пути', - 'title' => '', + 'title' => 'Статус заказа', ], 'thanks' => [ - 'title' => '', + 'title' => 'Спасибо за ваш заказ!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'В ближайшее время вы получите письмо с подтверждением заказа. Если у вас остались вопросы, пожалуйста, :link!', + 'link_text' => 'свяжитесь с нами', ], ], ], @@ -192,10 +192,10 @@ 'username_change' => [ 'check' => 'Введите ник, чтобы проверить его доступность!', - 'checking' => 'Проверяем доступность никнейма :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'checking' => 'Проверяем доступность ника :username...', + 'placeholder' => 'Введите ник', + 'label' => 'Новый ник', + 'current' => 'Ваш текущий ник: ":username".', 'require_login' => [ '_' => 'Вы должны :link для смены никнейма!', diff --git a/resources/lang/ru/user_verification.php b/resources/lang/ru/user_verification.php index a5f1bdf5d9c..adf65656c9d 100644 --- a/resources/lang/ru/user_verification.php +++ b/resources/lang/ru/user_verification.php @@ -5,16 +5,16 @@ return [ 'box' => [ - 'sent' => 'В целях безопасности мы отправили на вашу почту :mail письмо с кодом подтверждения. Введите полученный код.', + 'sent' => 'В целях безопасности мы отправили на вашу почту :mail письмо с кодом подтверждения. Введите его ниже.', 'title' => 'Подтверждение аккаунта', 'verifying' => 'Проверка кода...', 'issuing' => 'Отправка нового кода...', 'info' => [ - 'check_spam' => "Проверьте папку «Спам», если Вы не можете найти письмо.", - 'recover' => "Если Вы потеряли доступ к вашей почте или забыли, какую почту Вы использовали, пройдите :link.", + 'check_spam' => "Проверьте папку «Спам», если вы не можете найти письмо.", + 'recover' => "Если вы потеряли доступ к своей почте или забыли, какую почту вы использовали, пройдите :link.", 'recover_link' => 'процедуру восстановления', - 'reissue' => 'Также, Вы можете :reissue_link или :logout_link.', + 'reissue' => 'Также, вы можете :reissue_link или :logout_link.', 'reissue_link' => 'запросить другой код', 'logout_link' => 'выйти', ], @@ -23,7 +23,7 @@ 'errors' => [ 'expired' => 'Код подтверждения устарел, отправлено новое письмо.', 'incorrect_key' => 'Неверный код.', - 'retries_exceeded' => 'Неверный код. Вы привысили лимит попыток, поэтому Вам отправлено новое письмо.', + 'retries_exceeded' => 'Неверный код. Вы привысили лимит попыток, поэтому вам отправлено новое письмо.', 'reissued' => 'Код подтверждения устарел, отправлено новое письмо.', 'unknown' => 'Произошла неизвестная ошибка, отправлено новое письмо.', ], diff --git a/resources/lang/ru/users.php b/resources/lang/ru/users.php index d09992f261e..e7a07ef2703 100644 --- a/resources/lang/ru/users.php +++ b/resources/lang/ru/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Карты пользователя: :counts', + 'modding_description_empty' => 'У пользователя нет своих карт...', 'description' => [ '_' => 'Рейтинг (:ruleset): :global | :country', @@ -271,7 +271,7 @@ 'monthly_playcounts' => [ 'title' => 'График игр по месяцам', - 'count_label' => 'Игр', + 'count_label' => 'Игры:', ], 'most_played' => [ 'count' => 'количество раз сыграно', @@ -297,7 +297,7 @@ 'beatmap_discussion' => [ 'allow_kudosu' => [ - 'give' => 'Получено :amount за ответ в :post', + 'give' => 'Начислено :amount за снятие вето на получение кудосу за отзыв :post', ], 'deny_kudosu' => [ @@ -309,22 +309,22 @@ ], 'restore' => [ - 'give' => 'Получено :amount за восстановление ответа в посте :post', + 'give' => 'Начислено :amount за восстановление ответа :post', ], 'vote' => [ - 'give' => 'Получено :amount за получение голосов в посте :post', + 'give' => 'Начислено :amount за получение голосов за отзыв :post', 'reset' => 'Потеряно :amount за потерю голосов в посте :post', ], 'recalculate' => [ - 'give' => 'Получено :amount за перерасчёт голосов в посте :post', + 'give' => 'Начислено :amount за перерасчёт голосов у отзыва :post', 'reset' => 'Потеряно :amount за перерасчёт голосов в посте :post', ], ], 'forum_post' => [ - 'give' => 'Получено :amount от :giver за сообщение в посте :post', + 'give' => 'Начислено :amount от :giver за пост в отзыве :post', 'reset' => ':giver сбросил кудосу за ответ в посте :post', 'revoke' => ':giver отнял кудосу за ответ в посте :post', ], diff --git a/resources/lang/th/accounts.php b/resources/lang/th/accounts.php index 0ce5e043ab0..fff8d8336b4 100644 --- a/resources/lang/th/accounts.php +++ b/resources/lang/th/accounts.php @@ -63,15 +63,15 @@ ], 'github_user' => [ - 'info' => "", - 'link' => '', - 'title' => '', - 'unlink' => '', + 'info' => "หากคุณเป็นผู้มีส่วนร่วมในพื้นที่เก็บข้อมูลโอเพ่นซอร์สของ osu! การเชื่อมโยงบัญชี GitHub ของคุณที่นี่จะเชื่อมโยงรายการบันทึกการเปลี่ยนแปลงของคุณกับ osu! ประวัติโดยย่อ. บัญชี GitHub ที่ไม่มีประวัติการมีส่วนร่วมกับ osu! ไม่สามารถเชื่อมโยงได้", + 'link' => 'เชื่อมโยงบัญชี GitHub', + 'title' => 'GitHub', + 'unlink' => 'ยกเลิกการเชื่อมโยงบัญชี GitHub', 'error' => [ - 'already_linked' => '', - 'no_contribution' => '', - 'unverified_email' => '', + 'already_linked' => 'บัญชี GitHub นี้เชื่อมโยงกับผู้ใช้รายอื่นแล้ว', + 'no_contribution' => 'ไม่สามารถเชื่อมโยงบัญชี GitHub โดยไม่มีประวัติการมีส่วนร่วมใน osu! ที่เก็บ', + 'unverified_email' => 'โปรดยืนยันอีเมลหลักของคุณบน GitHub จากนั้นลองเชื่อมโยงบัญชีของคุณอีกครั้ง', ], ], diff --git a/resources/lang/th/beatmap_discussions.php b/resources/lang/th/beatmap_discussions.php index f6f1d7696b8..ff900fbbfa9 100644 --- a/resources/lang/th/beatmap_discussions.php +++ b/resources/lang/th/beatmap_discussions.php @@ -26,7 +26,7 @@ 'deleted' => 'รวมการสนทนาที่ถูกลบ', 'mode' => 'โหมดของบีทแมพ', 'only_unresolved' => 'มองเห็นเฉพาะการสนทนา/ปัญหาที่ยังไม่ได้แก้', - 'show_review_embeds' => '', + 'show_review_embeds' => 'แสดงกระทู้รีวิว', 'types' => 'ชนิดของข้อความ', 'username' => 'ชื่อผู้ใช้', diff --git a/resources/lang/th/comments.php b/resources/lang/th/comments.php index 57cda687d3e..e78b055cce1 100644 --- a/resources/lang/th/comments.php +++ b/resources/lang/th/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'แสดงความคิดเห็นโดย :user', ], 'placeholder' => [ diff --git a/resources/lang/th/notifications.php b/resources/lang/th/notifications.php index 532baf60f28..557f834b651 100644 --- a/resources/lang/th/notifications.php +++ b/resources/lang/th/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'การสนทนาได้ถูกปลดล๊อค', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited คำชม|:count_delimited คำชม', + 'problems' => ':count_delimited ปัญหา|:count_delimited ปัญหา', + 'suggestions' => ':count_delimited คำแนะนำ|:count_delimited คำแนะนำ', ], ], diff --git a/resources/lang/th/store.php b/resources/lang/th/store.php index 29c88617788..32182b8cfc5 100644 --- a/resources/lang/th/store.php +++ b/resources/lang/th/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'ชำระเงิน', - 'empty_cart' => '', + 'empty_cart' => 'ลบรายการทั้งหมดออกจากรถเข็น', 'info' => ':count_delimited รายการในตะกร้า ($:subtotal)|:count_delimited รายการในตะกร้า ($:subtotal)', 'more_goodies' => 'ฉันอยากจะดูของอย่างอื่นก่อนที่จะดําเนินการสั่งซื้อ', 'shipping_fees' => 'ค่าส่ง', @@ -49,37 +49,37 @@ ], 'discount' => 'ถูกลง :percent%', - 'free' => '', + 'free' => 'ฟรี!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'ติดต่อ:', + 'date' => 'วันที่:', 'echeck_delay' => 'เนื่องจากการชำระเงินของคุณเป็น eCheck โปรดรอเพิ่มอีก 10 วันเพื่อให้การชำระเงินผ่าน PayPal!', 'hide_from_activity' => 'แท็กผู้สนับสนุน osu! ในคำสั่งซื้อนี้จะไม่แสดงในกิจกรรมล่าสุดของคุณ', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'ส่งทาง:', + 'shipping_to' => 'การจัดส่งสินค้า:', + 'title' => 'ใบแจ้งหนี้', 'title_compact' => 'ใบกำกับสินค้า', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'คำสั่งซื้อของคุณถูกยกเลิกแล้ว', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "หากคุณไม่ได้ขอยกเลิก โปรดติดต่อ :link โดยแจ้งหมายเลขคำสั่งซื้อของคุณ (#:order_number)", + 'link_text' => 'osu!store สนับสนุน', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'คำสั่งซื้อของคุณถูกส่งแล้ว! เราหวังว่าคุณจะสนุกกับมัน!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'หากคุณมีปัญหาใดๆ เกี่ยวกับการซื้อของคุณ โปรดติดต่อ :link', + 'link_text' => 'osu!store สนับสนุน', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'คำสั่งซื้อของคุณอยู่ระหว่างเตรียมการ!', + 'line_1' => 'โปรดอดใจรออีกหน่อยเดี่ยวทางเราจะรีบจัดส่งให้ ข้อมูลการติดตามจะปรากฏที่นี่เมื่อคำสั่งซื้อได้รับการประมวลผลและส่งแล้ว การดำเนินการนี้อาจใช้เวลาสูงสุด 5 วัน (แต่โดยปกติจะใช้เวลาน้อยกว่านั้น!) ขึ้นอยู่กับว่าเรายุ่งแค่ไหน', + 'line_2' => 'เราส่งคำสั่งซื้อทั้งหมดจากประเทศญี่ปุ่นโดยใช้บริการจัดส่งที่หลากหลายขึ้นอยู่กับน้ำหนักและมูลค่า พื้นที่นี้จะอัปเดตข้อมูลเฉพาะเมื่อเราจัดส่งคำสั่งซื้อแล้ว', ], 'processing' => [ 'title' => 'การชำระเงินของคุณยังไม่ได้รับการยืนยัน!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'คำสั่งซื้อของคุณได้รับการจัดส่งแล้ว!', + 'tracking_details' => 'รายละเอียดการติดตามมีดังนี้:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "เราไม่มีรายละเอียดการติดตามเนื่องจากเราส่งพัสดุของคุณทางไปรษณีย์ทางอากาศ แต่คุณสามารถคาดว่าจะได้รับภายใน 1-3 สัปดาห์ สำหรับยุโรป บางครั้งศุลกากรอาจทำให้คำสั่งซื้ออยู่นอกเหนือการควบคุมของเรา หากคุณมีข้อกังวลใดๆ โปรดตอบกลับอีเมลยืนยันคำสั่งซื้อที่คุณได้รับ :link", + 'link_text' => 'ส่งอีเมลหาเรา', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'ไม่มีรายการให้ดู', 'paid_on' => 'สั่งซื้อเมื่อ :date', 'resume' => 'ดำเนินการชำระเงินต่อ', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'การจัดส่งสินค้า & การจัดการ', 'shopify_expired' => 'ลิงค์ชำระเงินสำหรับคำสั่งซื้อนี้หมดอายุแล้ว', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'ยอดรวม', + 'total' => 'ทั้งหมด', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'คำสั่ง #', + 'payment_terms' => 'เงื่อนไขการชำระเงิน', + 'salesperson' => 'พนักงานขาย', + 'shipping_method' => 'วิธีการจัดส่ง', + 'shipping_terms' => 'เงื่อนไขการจัดส่ง', + 'title' => 'รายละเอียดการสั่งซื้อ', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'ชำระเงินแล้ว', 'processing' => 'กำลังรอการยืนยัน', 'shipped' => 'จัดส่งแล้ว', - 'title' => '', + 'title' => 'สถานะการสั่งซื้อ', ], 'thanks' => [ - 'title' => '', + 'title' => 'ขอบคุณสำหรับการสั่งซื้อ!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'คุณจะได้รับอีเมลยืนยันเร็วๆ นี้ หากคุณมีคำถามใด ๆ กรุณา:link!', + 'link_text' => 'ติดต่อเรา', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'ใส่ชื่อผู้ใช้เพื่อตรวจสอบสถานะ!', 'checking' => 'กำลังตรวจสถานะของ :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'ชื่อผู้ใช้ที่ร้องขอ', + 'label' => 'ชื่อผู้ใช้ใหม่', + 'current' => 'ชื่อผู้ใช้ปัจจุบันของคุณคือ ":username"', 'require_login' => [ '_' => 'คุณจะต้อง:linkจึงจะเปลี่ยนชื่อได้!', diff --git a/resources/lang/th/users.php b/resources/lang/th/users.php index 17547effa3f..122696317c4 100644 --- a/resources/lang/th/users.php +++ b/resources/lang/th/users.php @@ -125,8 +125,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'บีทแมป: :counts', + 'modding_description_empty' => 'ผู้ใช้ยังไม่มีบีทแมปใดๆ...', 'description' => [ '_' => 'อันดับ (:ruleset): :global | :country', diff --git a/resources/lang/tr/accounts.php b/resources/lang/tr/accounts.php index 6f73107c0ad..4050ba16f8f 100644 --- a/resources/lang/tr/accounts.php +++ b/resources/lang/tr/accounts.php @@ -64,9 +64,9 @@ 'github_user' => [ 'info' => "", - 'link' => '', + 'link' => 'GitHub Hesabını Bağla', 'title' => 'GitHub', - 'unlink' => '', + 'unlink' => 'GitHub Hesabının bağlantısını Kaldır', 'error' => [ 'already_linked' => '', diff --git a/resources/lang/tr/store.php b/resources/lang/tr/store.php index f0629a32032..d0142b9740a 100644 --- a/resources/lang/tr/store.php +++ b/resources/lang/tr/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Ödeme', - 'empty_cart' => '', + 'empty_cart' => 'Sepetteki tüm ürünleri kaldır', 'info' => ':count_delimited ürün sepette ($:subtotal)|:count_delimited ürün sepette ($:subtotal)', 'more_goodies' => 'Ödememi yapmadan önce başka eşyalara göz atmak istiyorum', 'shipping_fees' => 'kargo ücretleri', @@ -52,32 +52,32 @@ 'free' => '', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'İletişim:', + 'date' => 'Tarih:', 'echeck_delay' => 'Ödemenizin bir eCheck olması nedeniyle, ödemenizin PayPal\'dan temizlenmesi için 10 ekstra günü göz önüne alın!', 'hide_from_activity' => 'Bu siparişteki osu!supporter etiketleri yakın zamandaki etkinliklerinizde gösterilmez.', 'sent_via' => '', 'shipping_to' => '', - 'title' => '', + 'title' => 'Fatura', 'title_compact' => 'fatura', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Siparişiniz iptal edildi', 'line_1' => [ '_' => "", 'link_text' => '', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Siparişiniz teslim edildi! İyi günlerde kullanmanız dileğiyle!', 'line_1' => [ - '_' => '', + '_' => 'Satın alımınızla ilgili bir problem yaşıyorsanız,lütfen :link ile görüşün.', 'link_text' => '', ], ], 'prepared' => [ - 'title' => '', + 'title' => 'Siparişiniz hazılrlanıyor!', 'line_1' => '', 'line_2' => '', ], @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', + 'title' => 'Siparişiniz kargoya verildi!', 'tracking_details' => '', 'no_tracking_details' => [ '_' => "", - 'link_text' => '', + 'link_text' => 'bize bir e-mail yollayın', ], ], ], @@ -110,16 +110,16 @@ 'resume' => 'Sepete Dön', 'shipping_and_handling' => '', 'shopify_expired' => 'Bu sipariş için ödeme bağlantısının süresi doldu.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Ara toplam', + 'total' => 'Toplam', 'details' => [ 'order_number' => '', 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', + 'salesperson' => 'Satış Temsilcisi', + 'shipping_method' => 'Gönderim Yolu', 'shipping_terms' => '', - 'title' => '', + 'title' => 'Sipariş Detayları', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Ödendi', 'processing' => 'Onay bekleniyor', 'shipped' => 'Ulaştırılıyor', - 'title' => '', + 'title' => 'Sipariş Durumu', ], 'thanks' => [ - 'title' => '', + 'title' => 'Siparişiniz için teşekkür ederiz!', 'line_1' => [ '_' => '', - 'link_text' => '', + 'link_text' => 'bizimle iletişime geçin', ], ], ], @@ -194,8 +194,8 @@ 'check' => 'Geçerliliğini kontrol etmek için bir kullanıcı adı girin!', 'checking' => ':username geçerliliği kontrol ediliyor...', 'placeholder' => '', - 'label' => '', - 'current' => '', + 'label' => 'Yeni kullanıcı adı', + 'current' => 'Şu anki kullanıcı adınız ":username".', 'require_login' => [ '_' => 'İsmini değiştirmek için :link olman gerekiyor!', diff --git a/resources/lang/uk/comments.php b/resources/lang/uk/comments.php index e5fc3c39b8e..046d0461244 100644 --- a/resources/lang/uk/comments.php +++ b/resources/lang/uk/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'комментар від :user', ], 'placeholder' => [ diff --git a/resources/lang/uk/community.php b/resources/lang/uk/community.php index 1bdfd567c7d..cc577d93685 100644 --- a/resources/lang/uk/community.php +++ b/resources/lang/uk/community.php @@ -8,7 +8,7 @@ 'convinced' => [ 'title' => 'Переконав! :D', 'support' => 'підтримай osu!', - 'gift' => 'або подаруйте osu!supporter іншим гравцям', + 'gift' => 'або подаруй osu!прихильник іншому гравцеві', 'instructions' => 'натисніть на кнопку з сердечком для переходу в крамницю', ], 'why-support' => [ @@ -129,7 +129,7 @@ ], 'more_beatmaps' => [ 'title' => 'Завантажуйте більше мап', - 'description' => 'Кількість мап "На розгляді", які ви можете мати, вираховується з базового значення плюс додатковий бонус за кожну рейтингову мапу, яку ви зараз маєте (до певного ліміту).

Зазвичай це :base плюс :bonus за кожну рейтингову мапу (до :bonus_max). З тегом osu!supporter це значення збільшується до :supporter_base плюс :supporter_bonus за кожну рейтингову мапу (до :supporter_bonus_max).', + 'description' => 'Скільки нерейтингових мап ви можете мати одночасно, залежить від базового значення, плюс бонус за кожну рейтингову мапу яку ви маєте (до певного ліміту).

Зазвичай це :base плюс :bonus за кожну рейтингову мапу (до :bonus_max). З osu!прихильником це значення збільшується до :supporter_base плюс :supporter_bonus за кожну рейтингову мапу (до :supporter_bonus_max).', ], 'friend_filtering' => [ 'title' => 'Рейтинг друзів', diff --git a/resources/lang/uk/errors.php b/resources/lang/uk/errors.php index f9e1ad56b29..cfbbd8f8aea 100644 --- a/resources/lang/uk/errors.php +++ b/resources/lang/uk/errors.php @@ -7,7 +7,7 @@ 'load_failed' => 'Не вдалось завантажити дані.', 'missing_route' => 'Некоректна адреса або некоректний метод запиту.', 'no_restricted_access' => 'Ви не можете виконати цю дію, поки ваш обліковий запис знаходиться в обмеженому режимі.', - 'supporter_only' => 'Ви повинні мати osu!прихильника для використання цієї можливості.', + 'supporter_only' => 'Ви повинні мати osu!прихильник для використання цієї можливості.', 'unknown' => 'Сталась невідома помилка.', 'codes' => [ diff --git a/resources/lang/uk/model_validation/fulfillments.php b/resources/lang/uk/model_validation/fulfillments.php index 2098dad7719..f358b80920e 100644 --- a/resources/lang/uk/model_validation/fulfillments.php +++ b/resources/lang/uk/model_validation/fulfillments.php @@ -10,6 +10,6 @@ 'reverting_username_mismatch' => '', ], 'supporter_tag' => [ - 'insufficient_paid' => 'Сума платежу менша необхідної, щоб отримати тег osu!прихильник (:actual > :expected)', + 'insufficient_paid' => 'Сума платежу менша необхідної, щоб отримати тег osu!прихильника (:actual > :expected)', ], ]; diff --git a/resources/lang/uk/notifications.php b/resources/lang/uk/notifications.php index 0f4eb3e3161..2133f6a013f 100644 --- a/resources/lang/uk/notifications.php +++ b/resources/lang/uk/notifications.php @@ -57,9 +57,9 @@ 'beatmapset_discussion_unlock_compact' => 'Обговорення відкрито', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited похвал|:count_delimited похвали', + 'problems' => ':count_delimited проблем|:count_delimited проблеми', + 'suggestions' => ':count_delimited пропозиція|:count_delimited пропозицій', ], ], diff --git a/resources/lang/uk/store.php b/resources/lang/uk/store.php index 1652265b91d..7188872c76f 100644 --- a/resources/lang/uk/store.php +++ b/resources/lang/uk/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Перевірка', - 'empty_cart' => '', + 'empty_cart' => 'Видалити всі товари з кошику', 'info' => ':count_delimited товар в кошику ($:subtotal)|:count_delimited товару в кошику ($:subtotal)|:count_delimited товарів в кошику ($:subtotal)', 'more_goodies' => 'Я хочу подивитися на інші товари перед завершенням замовлення', 'shipping_fees' => 'вартість доставки', @@ -49,37 +49,37 @@ ], 'discount' => 'ви заощадите :percent%', - 'free' => '', + 'free' => 'безкоштовно!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Контактна особа:', + 'date' => 'Дата:', 'echeck_delay' => 'Оскільки оплата була через eCheck, очікування підтвердження оплати через Paypal може зайнятий до 10 днів!', - 'hide_from_activity' => 'тег osu!прихильника в цьому замовленні не буде показуватись в останніх активностях.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'hide_from_activity' => 'тег osu!прихильника в цьому замовленні не буде показуватися в останніх активностях.', + 'sent_via' => 'Надіслати через:', + 'shipping_to' => 'Доставити за адресою:', + 'title' => 'До сплати', 'title_compact' => 'рахунок', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Ваше замовлення було скасовано', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Якщо ви не робили запит на скасовування замовлення, будь ласка, зв'яжіться з :link вказуючи номер замовлення (#:order_number).", + 'link_text' => 'службою підтримки osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Ваше замовлення було доставлено! Сподіваємось, що вам сподобається!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Якщо у вас виникли проблеми при покупці, зв\'яжіться з :link.', + 'link_text' => 'службою підтримки osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Ваше замовлення готується!', + 'line_1' => 'Зачекайте трохи більше часу на доставлення. Інформація про відслідковування замовлення з\'явиться тут, як тільки воно буде оброблено й надіслано. Цей процес може зайняти до 5 днів (але зазвичай менше!) в залежності від того, наскільки ми зайняті.', + 'line_2' => 'Ми надсилаємо всі замовлення з Японії, використовуючи різні транспортні служби доставлення в залежності від ваги та вартості. Ця область оновиться зі специфікацією як тільки ми відправили замовлення.', ], 'processing' => [ 'title' => 'Ваш платіж ще не підтверджений!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Ваше замовлення вже доставлено!', + 'tracking_details' => 'Деталі відстежування:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "У нас немає деталей про трек, коли ми відправляли ваш пакет через Air Mail, але ви можете очікувати на отримання його протягом 1-3 тижнів. Для Європи іноді митниці можуть затримувати замовлення без нашого відома. Якщо ви маєте будь-які занепокоєння, надішліть відповіть на електронний лист з підтвердженням замовлення, який ви отримали :link.", + 'link_text' => 'надішліть нам email', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Ви нічого не замовляли.', 'paid_on' => 'Замовлення розміщено :date', 'resume' => 'Продовжити покупку', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Доставка та оброблення', 'shopify_expired' => 'Термін дії посилання для оформлення замовлення закінчився.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Проміжна сума', + 'total' => 'Всього', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Замовлення #', + 'payment_terms' => 'Умови оплати', + 'salesperson' => 'Продавець', + 'shipping_method' => 'Спосіб доставки', + 'shipping_terms' => 'Умови доставки', + 'title' => 'Деталі замовлення', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Оплачено', 'processing' => 'Очікування підтвердження', 'shipped' => 'В дорозі', - 'title' => '', + 'title' => 'Статус замовлення', ], 'thanks' => [ - 'title' => '', + 'title' => 'Дякуємо за замовлення!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Ви отримаєте підтвердження електронною поштою вже найближчим часом. Якщо у вас є будь-які запитання, будь ласка, :link!', + 'link_text' => 'зв\'яжіться з нами', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Введіть ім\'я, щоб перевірити його доступність!', 'checking' => 'Перевіряємо доступність імені :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Запитане ім\'я користувача', + 'label' => 'Нове ім\'я користувача', + 'current' => 'Ваше поточне ім\'я користувача - ":username".', 'require_login' => [ '_' => 'Ви повинні :link для зміни ніку!', diff --git a/resources/lang/uk/users.php b/resources/lang/uk/users.php index 7f844df7405..cbb00fe34e6 100644 --- a/resources/lang/uk/users.php +++ b/resources/lang/uk/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Мап: :counts', + 'modding_description_empty' => 'Користувач не має жодної мапи...', 'description' => [ '_' => 'Ранг (:ruleset): :global | :country', diff --git a/resources/lang/vi/comments.php b/resources/lang/vi/comments.php index ea30e105990..89d67c369f0 100644 --- a/resources/lang/vi/comments.php +++ b/resources/lang/vi/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'bình luận bởi :user', ], 'placeholder' => [ diff --git a/resources/lang/vi/notifications.php b/resources/lang/vi/notifications.php index 3f3c1b05446..ea0e03d5fb6 100644 --- a/resources/lang/vi/notifications.php +++ b/resources/lang/vi/notifications.php @@ -58,9 +58,9 @@ 'beatmapset_discussion_unlock_compact' => 'Cuộc thảo luận đã được mở khóa', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited lời khen|:count_delimited lời khen', + 'problems' => ':count_delimited vấn đề|:count_delimited vấn đề', + 'suggestions' => ':count_delimited gợi ý|:count_delimited gợi ý', ], ], diff --git a/resources/lang/vi/store.php b/resources/lang/vi/store.php index 1164ff0868c..559efb623c0 100644 --- a/resources/lang/vi/store.php +++ b/resources/lang/vi/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => 'Thanh Toán', - 'empty_cart' => '', + 'empty_cart' => 'Xoá tất cả mặt hàng khỏi giỏ hàng', 'info' => ':count_delimited sản phẩm trong giỏ ($:subtotal)|:count_delimited sản phẩm trong giỏ ($:subtotal)', 'more_goodies' => 'Tôi muốn xem thêm nhiều mặt hàng nữa trước khi hoàn thành đơn hàng', 'shipping_fees' => 'phí vận chuyển', @@ -49,37 +49,37 @@ ], 'discount' => 'tiết kiệm :percent%', - 'free' => '', + 'free' => 'miễn phí!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Liên hệ:', + 'date' => 'Ngày:', 'echeck_delay' => 'Vì bạn thanh toán bằng eCheck, hãy chờ thêm tối đa 10 ngày để thanh toán qua khỏi PayPal!', 'hide_from_activity' => 'thẻ osu!supporter ở trong đơn hàng này sẽ không được hiện lên ở trong hoạt động gần đây của bạn.', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => 'Đã gửi qua:', + 'shipping_to' => 'Vận chuyển đến:', + 'title' => 'Hoá đơn', 'title_compact' => 'hóa đơn', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => 'Đơn hàng đã bị huỷ', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "Nếu bạn không yêu cầu hủy, vui lòng liên hệ :link trích dẫn số đơn hàng của bạn (#:order_number).", + 'link_text' => 'hỗ trợ osu!store', ], ], 'delivered' => [ - 'title' => '', + 'title' => 'Đơn hàng của bạn đã được giao! Chúng tôi hy vọng bạn thích nó!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Nếu bạn có bất kỳ vấn đề gì khi mua hàng, vui lòng liên hệ :link.', + 'link_text' => 'hỗ trợ osu!store', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => 'Đơn hàng của bạn đang được chuẩn bị!', + 'line_1' => 'Vui lòng chờ thêm một thời gian nữa để hàng được chuyển đi. Thông tin theo dõi sẽ xuất hiện ở đây sau khi đơn hàng được xử lý và gửi. Việc này có thể mất tới 5 ngày (nhưng thường ít hơn!) tùy thuộc vào độ bận rộn của chúng tôi.', + 'line_2' => 'Chúng tôi gửi tất cả các đơn hàng từ Nhật Bản bằng nhiều dịch vụ vận chuyển tùy theo trọng lượng và giá trị. Khu vực này sẽ cập nhật thông tin cụ thể sau khi chúng tôi gửi đơn đặt hàng.', ], 'processing' => [ 'title' => 'Thanh toán của bạn chưa được xác nhận!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => 'Đơn hàng đã được giao!', + 'tracking_details' => 'Chi tiết theo dõi như sau:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "Chúng tôi không có chi tiết theo dõi vì chúng tôi đã gửi gói hàng của bạn qua Air Mail, nhưng bạn có thể nhận được gói hàng trong vòng 1-3 tuần. Đối với Châu Âu, đôi khi hải quan có thể trì hoãn đơn hàng ngoài tầm kiểm soát của chúng tôi. Nếu bạn có bất kỳ thắc mắc nào, vui lòng trả lời email xác nhận đơn hàng bạn nhận được :link.", + 'link_text' => 'gửi email cho chúng tôi', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => 'Không có đơn đặt hàng.', 'paid_on' => 'Đã đặt hàng :date', 'resume' => 'Tiếp Tục Thanh Toán', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Vận chuyển & Xử lí', 'shopify_expired' => 'Link thanh toán cho đơn hàng này đã hết hạn.', - 'subtotal' => '', - 'total' => '', + 'subtotal' => 'Tổng phụ', + 'total' => 'Tổng cộng', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => 'Đơn hàng #', + 'payment_terms' => 'Điều khoản thanh toán', + 'salesperson' => 'Người bán hàng', + 'shipping_method' => 'Phương thức vận chuyển', + 'shipping_terms' => 'Điều khoản vận chuyển', + 'title' => 'Chi tiết đơn hàng', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => 'Đã Thanh Toán', 'processing' => 'Đang chờ xác nhận', 'shipped' => 'Đã giao hàng', - 'title' => '', + 'title' => 'Trạng thái đơn hàng', ], 'thanks' => [ - 'title' => '', + 'title' => 'Cảm ơn đơn hàng của bạn!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => 'Bạn sẽ nhận được một email xác nhận. Nếu bạn có bất kỳ thắc mắc nào, vui lòng :link!', + 'link_text' => 'liên hệ chúng tôi', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => 'Nhập tên người dùng để kiểm tra tính khả dụng!', 'checking' => 'Đang kiểm tra tính khả dụng của :username...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => 'Tên người dùng được yêu cầu', + 'label' => 'Tên người dùng mới', + 'current' => 'Tên người dùng hiện tại của bạn là ":username".', 'require_login' => [ '_' => 'Bạn cần phải :link để đổi tên!', diff --git a/resources/lang/vi/users.php b/resources/lang/vi/users.php index 91d68e0bbbf..00bd1e94d32 100644 --- a/resources/lang/vi/users.php +++ b/resources/lang/vi/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmap: :counts', + 'modding_description_empty' => 'Người dùng không có bất kỳ beatmap nào...', 'description' => [ '_' => 'Hạng (:ruleset): :global | :country', diff --git a/resources/lang/zh-tw/store.php b/resources/lang/zh-tw/store.php index 21a7480bf2c..0298c6cef8d 100644 --- a/resources/lang/zh-tw/store.php +++ b/resources/lang/zh-tw/store.php @@ -49,15 +49,15 @@ ], 'discount' => '折扣 :percent%', - 'free' => '', + 'free' => '免費!', 'invoice' => [ 'contact' => '', - 'date' => '', + 'date' => '日期:', 'echeck_delay' => '由於您是用 eCheck 付款,請等待至多 10 天以使該支付通過 PayPal 完成!', 'hide_from_activity' => '這項 osu! 贊助者訂單未在您的最近活動中顯示。', 'sent_via' => '', - 'shipping_to' => '', + 'shipping_to' => '運送至:', 'title' => '', 'title_compact' => '帳單', @@ -66,18 +66,18 @@ 'title' => '', 'line_1' => [ '_' => "", - 'link_text' => '', + 'link_text' => 'osu!store 支援', ], ], 'delivered' => [ 'title' => '', 'line_1' => [ '_' => '', - 'link_text' => '', + 'link_text' => 'osu!store 支援', ], ], 'prepared' => [ - 'title' => '', + 'title' => '正在準備您的訂單!', 'line_1' => '', 'line_2' => '', ], @@ -94,7 +94,7 @@ 'tracking_details' => '', 'no_tracking_details' => [ '_' => "", - 'link_text' => '', + 'link_text' => '向我們發送電子郵件', ], ], ], @@ -110,14 +110,14 @@ 'resume' => '繼續結賬', 'shipping_and_handling' => '', 'shopify_expired' => '此訂單的結帳網址已經過期。', - 'subtotal' => '', - 'total' => '', + 'subtotal' => '小計', + 'total' => '總計', 'details' => [ 'order_number' => '', 'payment_terms' => '', 'salesperson' => '', - 'shipping_method' => '', + 'shipping_method' => '運送方式', 'shipping_terms' => '', 'title' => '', ], @@ -151,14 +151,14 @@ 'paid' => '已付款', 'processing' => '待確認', 'shipped' => '已出貨', - 'title' => '', + 'title' => '訂單狀態', ], 'thanks' => [ 'title' => '', 'line_1' => [ '_' => '', - 'link_text' => '', + 'link_text' => '聯絡我們', ], ], ], @@ -194,8 +194,8 @@ 'check' => '输入使用者名稱並檢查是否可用', 'checking' => '正在檢查 :username 是否可用。。。', 'placeholder' => '', - 'label' => '', - 'current' => '', + 'label' => '新的使用者名稱', + 'current' => '您目前的使用者名稱是 ":username"。', 'require_login' => [ '_' => '需要 :link 才能變更使用者名稱!', diff --git a/resources/lang/zh/comments.php b/resources/lang/zh/comments.php index 3ab1c1c8341..6ccf4998cdc 100644 --- a/resources/lang/zh/comments.php +++ b/resources/lang/zh/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => ':user 的评论', ], 'placeholder' => [ diff --git a/resources/lang/zh/notifications.php b/resources/lang/zh/notifications.php index 14fd8e2a3ba..56a337bc2d9 100644 --- a/resources/lang/zh/notifications.php +++ b/resources/lang/zh/notifications.php @@ -59,9 +59,9 @@ 'beatmapset_discussion_unlock_compact' => '讨论已解锁', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited 个赞', + 'problems' => ':count_delimited 个问题', + 'suggestions' => ':count_delimited 个建议', ], ], diff --git a/resources/lang/zh/store.php b/resources/lang/zh/store.php index 98e6a86f4b6..a4414e38730 100644 --- a/resources/lang/zh/store.php +++ b/resources/lang/zh/store.php @@ -6,7 +6,7 @@ return [ 'cart' => [ 'checkout' => '结账', - 'empty_cart' => '', + 'empty_cart' => '清空购物车', 'info' => '购物车里有 :count_delimited 件商品($:subtotal)', 'more_goodies' => '在完成订单之前,我想看看其他商品', 'shipping_fees' => '运费', @@ -49,37 +49,37 @@ ], 'discount' => '节省 :percent%', - 'free' => '', + 'free' => '免费!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => '联系:', + 'date' => '日期:', 'echeck_delay' => '由于您的支付是通过 eCheck 进行的,请再等待至多 10 天来让 PayPal 完成支付。', 'hide_from_activity' => '此订单的支持者标签购买未显示在你的个人活动中。', - 'sent_via' => '', - 'shipping_to' => '', - 'title' => '', + 'sent_via' => '通过:', + 'shipping_to' => '送货到:', + 'title' => '账单', 'title_compact' => '账单', 'status' => [ 'cancelled' => [ - 'title' => '', + 'title' => '已取消您的订单', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "如果并不是您本人取消,请联系 :link 并提供您的订单号 (#:order_number)。", + 'link_text' => 'osu!store 支持', ], ], 'delivered' => [ - 'title' => '', + 'title' => '您的订单已经送达!享受这一刻吧!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => '如果您对此次购买有任何疑问,请联系 :link。', + 'link_text' => 'osu!store 支持', ], ], 'prepared' => [ - 'title' => '', - 'line_1' => '', - 'line_2' => '', + 'title' => '正在准备您的订单!', + 'line_1' => '在订单发货前请耐心等待。一旦订单处理完毕并发货,此处将会显示最新的运输信息。取决于我们的繁忙程度,这段时间可能会长达五天(通常不会这么久!)。', + 'line_2' => '所有订单都将从日本发出,订单会根据商品的重量和价值使用对应的物流运输业务。一旦开始发货,这里将会显示物流的细节。', ], 'processing' => [ 'title' => '您的付款信息尚未确认!', @@ -90,11 +90,11 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => '您的订单已发货!', + 'tracking_details' => '物流信息如下:', 'no_tracking_details' => [ - '_' => "", - 'link_text' => '', + '_' => "由于我们使用 Air Mail 发货,所以无法记录物流信息。但您可以在 1-3 周内收到包裹。如果收货地位于欧洲,则海关可能会在这个基础上延长订单的运输时间。如果您有任何问题,请回复您收到的 :link 邮件。", + 'link_text' => '给我们发送邮件', ], ], ], @@ -108,18 +108,18 @@ 'no_orders' => '没有可显示的订单。', 'paid_on' => ':date 支付订单', 'resume' => '恢复结账', - 'shipping_and_handling' => '', + 'shipping_and_handling' => '运输和处理', 'shopify_expired' => '此订单的结账链接已过期。', - 'subtotal' => '', - 'total' => '', + 'subtotal' => '小计', + 'total' => '总计', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', - 'salesperson' => '', - 'shipping_method' => '', - 'shipping_terms' => '', - 'title' => '', + 'order_number' => '订单 #', + 'payment_terms' => '支付条款', + 'salesperson' => '销售员', + 'shipping_method' => '运输方式', + 'shipping_terms' => '运输条款', + 'title' => '订单详情', ], 'item' => [ @@ -151,14 +151,14 @@ 'paid' => '已付款', 'processing' => '待确认', 'shipped' => '运送中', - 'title' => '', + 'title' => '订单状态', ], 'thanks' => [ - 'title' => '', + 'title' => '感谢惠顾!', 'line_1' => [ - '_' => '', - 'link_text' => '', + '_' => '您将收到一封确认邮件。如果您有任何疑问,请 :link!', + 'link_text' => '联系我们', ], ], ], @@ -193,9 +193,9 @@ 'username_change' => [ 'check' => '输入用户名并检查是否可用', 'checking' => '正在检查 :username 是否可用...', - 'placeholder' => '', - 'label' => '', - 'current' => '', + 'placeholder' => '想要使用的玩家名', + 'label' => '新玩家名', + 'current' => '您现在的玩家名是 ":username"。', 'require_login' => [ '_' => '需要 :link 才能改变用户名!', diff --git a/resources/lang/zh/users.php b/resources/lang/zh/users.php index 9b07b0853d2..06909e3001b 100644 --- a/resources/lang/zh/users.php +++ b/resources/lang/zh/users.php @@ -124,8 +124,8 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => '谱面::counts', + 'modding_description_empty' => '玩家没有任何谱面...', 'description' => [ '_' => '排名 (:ruleset): :global | :country', From 04c73958879c2791c22ae9a55abd873e1dbb175d Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 15 Dec 2023 18:31:23 +0900 Subject: [PATCH 070/102] Remove incorrectly merged line --- app/Http/Controllers/Controller.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 2ffb9394c2c..56e01897774 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -44,7 +44,6 @@ protected function login($user, $remember = false) Auth::login($user, $remember); if ($GLOBALS['cfg']['osu']['user']['bypass_verification']) { $session->markVerified(); - UserVerificationState::fromCurrentRequest()->markVerified(); } $session->migrate(true); } From 65fc078d7798e92e6fc299e479b0ab56f0ad1c21 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 15 Dec 2023 22:51:58 +0900 Subject: [PATCH 071/102] Fix spinner not showing on avatar upload --- resources/views/accounts/edit.blade.php | 2 +- resources/views/objects/_spinner.blade.php | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 resources/views/objects/_spinner.blade.php diff --git a/resources/views/accounts/edit.blade.php b/resources/views/accounts/edit.blade.php index 2fbc77a0442..b48d51a10d5 100644 --- a/resources/views/accounts/edit.blade.php +++ b/resources/views/accounts/edit.blade.php @@ -87,7 +87,7 @@
diff --git a/resources/views/objects/_spinner.blade.php b/resources/views/objects/_spinner.blade.php deleted file mode 100644 index 2b6fbe24a08..00000000000 --- a/resources/views/objects/_spinner.blade.php +++ /dev/null @@ -1,8 +0,0 @@ -{{-- - Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. - See the LICENCE file in the repository root for full licence text. ---}} -
-
-
-
From 6a73eea26c7db5c238f40ca812aa603a5f48a6d5 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 18 Dec 2023 06:22:04 +0900 Subject: [PATCH 072/102] Don't render spoiler button in button --- app/Libraries/BBCodeFromDB.php | 11 ++++++++++- .../bbcode_examples/box_with_spoilerbox.base.txt | 1 + .../bbcode_examples/box_with_spoilerbox.db.txt | 1 + .../bbcode_examples/box_with_spoilerbox.html | 4 ++++ 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/Libraries/bbcode_examples/box_with_spoilerbox.base.txt create mode 100644 tests/Libraries/bbcode_examples/box_with_spoilerbox.db.txt create mode 100644 tests/Libraries/bbcode_examples/box_with_spoilerbox.html diff --git a/app/Libraries/BBCodeFromDB.php b/app/Libraries/BBCodeFromDB.php index 1abe791a85c..a12074f3142 100644 --- a/app/Libraries/BBCodeFromDB.php +++ b/app/Libraries/BBCodeFromDB.php @@ -62,7 +62,16 @@ public function parseBold($text) public function parseBox($text) { - $text = preg_replace("#\[box=((\\\[\[\]]|[^][]|\[(\\\[\[\]]|[^][]|(?R))*\])*?):{$this->uid}\]\n*#s", $this->parseBoxHelperPrefix('\\1'), $text); + $text = preg_replace_callback("#\[box=((\\\[\[\]]|[^][]|\[(\\\[\[\]]|[^][]|(?R))*\])*?):{$this->uid}\]\n*#s", function ($m) { + // don't render button in button. + $escapedMatch = strtr($m[1], [ + "[spoilerbox:{$this->uid}]" => '', + "[/spoilerbox:{$this->uid}]" => '', + ]); + + return $this->parseBoxHelperPrefix($escapedMatch); + }, $text); + $text = preg_replace("#\n*\[/box:{$this->uid}]\n?#s", $this->parseBoxHelperSuffix(), $text); $text = preg_replace("#\[spoilerbox:{$this->uid}\]\n*#s", $this->parseBoxHelperPrefix(), $text); diff --git a/tests/Libraries/bbcode_examples/box_with_spoilerbox.base.txt b/tests/Libraries/bbcode_examples/box_with_spoilerbox.base.txt new file mode 100644 index 00000000000..464bc966fe4 --- /dev/null +++ b/tests/Libraries/bbcode_examples/box_with_spoilerbox.base.txt @@ -0,0 +1 @@ +[box=button[spoilerbox]in button[/spoilerbox]]best regex[/box] diff --git a/tests/Libraries/bbcode_examples/box_with_spoilerbox.db.txt b/tests/Libraries/bbcode_examples/box_with_spoilerbox.db.txt new file mode 100644 index 00000000000..5211ad089d2 --- /dev/null +++ b/tests/Libraries/bbcode_examples/box_with_spoilerbox.db.txt @@ -0,0 +1 @@ +[box=button[spoilerbox:1]in button[/spoilerbox:1]:1]best regex[/box:1] diff --git a/tests/Libraries/bbcode_examples/box_with_spoilerbox.html b/tests/Libraries/bbcode_examples/box_with_spoilerbox.html new file mode 100644 index 00000000000..0871abba69d --- /dev/null +++ b/tests/Libraries/bbcode_examples/box_with_spoilerbox.html @@ -0,0 +1,4 @@ +
+ +
best regex
+
From d68dc2a79a42978c00e20e528fbe0f09e0d99748 Mon Sep 17 00:00:00 2001 From: peppy Date: Mon, 18 Dec 2023 04:13:35 +0000 Subject: [PATCH 073/102] Update mod definitions --- database/mods.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/database/mods.json b/database/mods.json index d40e14a5430..bf82cf1b2f5 100644 --- a/database/mods.json +++ b/database/mods.json @@ -475,6 +475,12 @@ "Type": "boolean", "Label": "Fade out hit circles earlier", "Description": "Make hit circles fade out into a miss, rather than after it." + }, + { + "Name": "classic_health", + "Type": "boolean", + "Label": "Classic health", + "Description": "More closely resembles the original HP drain mechanics." } ], "IncompatibleMods": [ From 0389c65f7fe727630bdf5a60cbe4b974ae7fb819 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 18 Dec 2023 15:29:31 +0900 Subject: [PATCH 074/102] use anchor and let htmlpurifier deal with it instead --- app/Libraries/BBCodeFromDB.php | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/app/Libraries/BBCodeFromDB.php b/app/Libraries/BBCodeFromDB.php index a12074f3142..b82abdbbb95 100644 --- a/app/Libraries/BBCodeFromDB.php +++ b/app/Libraries/BBCodeFromDB.php @@ -62,16 +62,7 @@ public function parseBold($text) public function parseBox($text) { - $text = preg_replace_callback("#\[box=((\\\[\[\]]|[^][]|\[(\\\[\[\]]|[^][]|(?R))*\])*?):{$this->uid}\]\n*#s", function ($m) { - // don't render button in button. - $escapedMatch = strtr($m[1], [ - "[spoilerbox:{$this->uid}]" => '', - "[/spoilerbox:{$this->uid}]" => '', - ]); - - return $this->parseBoxHelperPrefix($escapedMatch); - }, $text); - + $text = preg_replace("#\[box=((\\\[\[\]]|[^][]|\[(\\\[\[\]]|[^][]|(?R))*\])*?):{$this->uid}\]\n*#s", $this->parseBoxHelperPrefix('\\1'), $text); $text = preg_replace("#\n*\[/box:{$this->uid}]\n?#s", $this->parseBoxHelperSuffix(), $text); $text = preg_replace("#\[spoilerbox:{$this->uid}\]\n*#s", $this->parseBoxHelperPrefix(), $text); @@ -84,7 +75,7 @@ public function parseBoxHelperPrefix($linkText = null) { $linkText = presence($linkText) ?? 'SPOILER'; - return "
"; + return "
{$linkText}
"; } public function parseBoxHelperSuffix() From 790912bf89faf1de4f68673b1c065cc68ddde19c Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 18 Dec 2023 15:41:22 +0900 Subject: [PATCH 075/102] update tests --- tests/Libraries/bbcode_examples/box_nested.html | 8 ++++---- .../bbcode_examples/box_with_bbcode_title.html | 6 +++--- .../Libraries/bbcode_examples/box_with_spoilerbox.html | 10 +++++++++- .../bbcode_examples/box_with_surrounding_newlines.html | 6 +++--- .../spoilerbox_with_surrounding_newlines.html | 6 +++--- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/tests/Libraries/bbcode_examples/box_nested.html b/tests/Libraries/bbcode_examples/box_nested.html index 1a6195eb276..1ea642b4c46 100644 --- a/tests/Libraries/bbcode_examples/box_nested.html +++ b/tests/Libraries/bbcode_examples/box_nested.html @@ -1,12 +1,12 @@
- +
- +
Content
Another content diff --git a/tests/Libraries/bbcode_examples/box_with_bbcode_title.html b/tests/Libraries/bbcode_examples/box_with_bbcode_title.html index f827e8de58e..f4bc7509c75 100644 --- a/tests/Libraries/bbcode_examples/box_with_bbcode_title.html +++ b/tests/Libraries/bbcode_examples/box_with_bbcode_title.html @@ -1,13 +1,13 @@
other content

- + [\[] weird \[ title
box content

other content 2
diff --git a/tests/Libraries/bbcode_examples/box_with_spoilerbox.html b/tests/Libraries/bbcode_examples/box_with_spoilerbox.html index 0871abba69d..e2dcf799dc6 100644 --- a/tests/Libraries/bbcode_examples/box_with_spoilerbox.html +++ b/tests/Libraries/bbcode_examples/box_with_spoilerbox.html @@ -1,4 +1,12 @@
- + button +
+ +
+ in button +
+ +
+
best regex
diff --git a/tests/Libraries/bbcode_examples/box_with_surrounding_newlines.html b/tests/Libraries/bbcode_examples/box_with_surrounding_newlines.html index 028c3eec25a..e07a79111da 100644 --- a/tests/Libraries/bbcode_examples/box_with_surrounding_newlines.html +++ b/tests/Libraries/bbcode_examples/box_with_surrounding_newlines.html @@ -1,13 +1,13 @@ Upper line text.
-
Packed box.
+
First!
Packed box.
Bottom line text.

Prefix text. -
Inline box (except it's not).
+
Second box
Inline box (except it's not).
Suffix text.

Upper line text.

-
Box with blank lines.
+
Third box
Box with blank lines.

Bottom line text. diff --git a/tests/Libraries/bbcode_examples/spoilerbox_with_surrounding_newlines.html b/tests/Libraries/bbcode_examples/spoilerbox_with_surrounding_newlines.html index 966e9614b31..4159b1893da 100644 --- a/tests/Libraries/bbcode_examples/spoilerbox_with_surrounding_newlines.html +++ b/tests/Libraries/bbcode_examples/spoilerbox_with_surrounding_newlines.html @@ -1,13 +1,13 @@ Upper line text.
-
Packed spoilerbox.
+
SPOILER
Packed spoilerbox.
Bottom line text.

Prefix text. -
Inline spoilerbox (except it's not).
+
SPOILER
Inline spoilerbox (except it's not).
Suffix text.

Upper line text.

-
Spoilerbox with blank lines.
+
SPOILER
Spoilerbox with blank lines.

Bottom line text. From ac4a5a9d25c91c9c5da3e9d5cc14c9942f9edca4 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 18 Dec 2023 16:19:52 +0900 Subject: [PATCH 076/102] remove button definition --- app/Libraries/CleanHTML.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/Libraries/CleanHTML.php b/app/Libraries/CleanHTML.php index c7a5b2cd4e9..0a7ead84c8c 100644 --- a/app/Libraries/CleanHTML.php +++ b/app/Libraries/CleanHTML.php @@ -47,14 +47,6 @@ public function __construct() ] ); - $def->addElement( - 'button', - 'Formctrl', - 'Optional: #PCDATA | Heading | List | Block | Inline', - 'Common', - ['type' => 'Enum#button'], - ); - $def->addAttribute('audio', 'preload', 'Text'); $def->addAttribute('img', 'loading', 'Text'); From b8f55ad1db33abc6392a27ddc26497c0a33fc09b Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 18 Dec 2023 16:22:40 +0900 Subject: [PATCH 077/102] add href to anchor --- app/Libraries/BBCodeFromDB.php | 2 +- tests/Libraries/bbcode_examples/box_nested.html | 4 ++-- .../bbcode_examples/box_with_bbcode_title.html | 4 ++-- .../Libraries/bbcode_examples/box_with_spoilerbox.html | 10 +++++----- .../bbcode_examples/box_with_surrounding_newlines.html | 6 +++--- .../spoilerbox_with_surrounding_newlines.html | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/Libraries/BBCodeFromDB.php b/app/Libraries/BBCodeFromDB.php index b82abdbbb95..d043398c180 100644 --- a/app/Libraries/BBCodeFromDB.php +++ b/app/Libraries/BBCodeFromDB.php @@ -75,7 +75,7 @@ public function parseBoxHelperPrefix($linkText = null) { $linkText = presence($linkText) ?? 'SPOILER'; - return "
{$linkText}
"; + return "
{$linkText}
"; } public function parseBoxHelperSuffix() diff --git a/tests/Libraries/bbcode_examples/box_nested.html b/tests/Libraries/bbcode_examples/box_nested.html index 1ea642b4c46..875c09151d7 100644 --- a/tests/Libraries/bbcode_examples/box_nested.html +++ b/tests/Libraries/bbcode_examples/box_nested.html @@ -1,10 +1,10 @@
- + hello
- + another box
Content
diff --git a/tests/Libraries/bbcode_examples/box_with_bbcode_title.html b/tests/Libraries/bbcode_examples/box_with_bbcode_title.html index f4bc7509c75..7a2a63dc1db 100644 --- a/tests/Libraries/bbcode_examples/box_with_bbcode_title.html +++ b/tests/Libraries/bbcode_examples/box_with_bbcode_title.html @@ -1,5 +1,5 @@
- + colored box title
box content
@@ -7,7 +7,7 @@ other content


other content 2
diff --git a/tests/Libraries/bbcode_examples/box_with_spoilerbox.html b/tests/Libraries/bbcode_examples/box_with_spoilerbox.html index e2dcf799dc6..d69735163e2 100644 --- a/tests/Libraries/bbcode_examples/box_with_spoilerbox.html +++ b/tests/Libraries/bbcode_examples/box_with_spoilerbox.html @@ -1,12 +1,12 @@
- button + button
- + - +
- +
best regex
diff --git a/tests/Libraries/bbcode_examples/box_with_surrounding_newlines.html b/tests/Libraries/bbcode_examples/box_with_surrounding_newlines.html index e07a79111da..20d4e5b464b 100644 --- a/tests/Libraries/bbcode_examples/box_with_surrounding_newlines.html +++ b/tests/Libraries/bbcode_examples/box_with_surrounding_newlines.html @@ -1,13 +1,13 @@ Upper line text.
-
First!
Packed box.
+
First!
Packed box.
Bottom line text.

Prefix text. -
Second box
Inline box (except it's not).
+
Second box
Inline box (except it's not).
Suffix text.

Upper line text.

-
Third box
Box with blank lines.
+
Third box
Box with blank lines.

Bottom line text. diff --git a/tests/Libraries/bbcode_examples/spoilerbox_with_surrounding_newlines.html b/tests/Libraries/bbcode_examples/spoilerbox_with_surrounding_newlines.html index 4159b1893da..61a84425c37 100644 --- a/tests/Libraries/bbcode_examples/spoilerbox_with_surrounding_newlines.html +++ b/tests/Libraries/bbcode_examples/spoilerbox_with_surrounding_newlines.html @@ -1,13 +1,13 @@ Upper line text.
-
SPOILER
Packed spoilerbox.
+
SPOILER
Packed spoilerbox.
Bottom line text.

Prefix text. -
SPOILER
Inline spoilerbox (except it's not).
+
SPOILER
Inline spoilerbox (except it's not).
Suffix text.

Upper line text.

-
SPOILER
Spoilerbox with blank lines.
+
SPOILER
Spoilerbox with blank lines.

Bottom line text. From c77c892a24fd464f4d4956f55eef400b2df8d005 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 18 Dec 2023 18:30:59 +0900 Subject: [PATCH 078/102] Update scores table structure --- app/Models/Solo/Score.php | 20 +++--- .../2023_12_18_085034_update_scores_table.php | 69 +++++++++++++++++++ 2 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 database/migrations/2023_12_18_085034_update_scores_table.php diff --git a/app/Models/Solo/Score.php b/app/Models/Solo/Score.php index 544966b3bf3..64a85d27ca5 100644 --- a/app/Models/Solo/Score.php +++ b/app/Models/Solo/Score.php @@ -24,12 +24,14 @@ /** * @property int $beatmap_id * @property \Carbon\Carbon|null $created_at - * @property \stdClass $data - * @property \Carbon\Carbon|null $deleted_at + * @property string|null $created_at_json + * @property ScoreData $data + * @property bool $has_replay * @property int $id * @property bool $preserve + * @property bool $ranked * @property int $ruleset_id - * @property \Carbon\Carbon|null $updated_at + * @property int $unix_updated_at * @property User $user * @property int $user_id */ @@ -39,6 +41,8 @@ class Score extends Model implements Traits\ReportableInterface const PROCESSING_QUEUE = 'osu-queue:score-statistics'; + public $timestamps = false; + protected $casts = [ 'data' => ScoreData::class, 'has_replay' => 'boolean', @@ -151,13 +155,13 @@ public function getAttribute($key) 'data' => $this->getClassCastableAttributeValue($key, $this->getRawAttribute($key)), 'has_replay', - 'preserve' => (bool) $this->getRawAttribute($key), + 'preserve', + 'ranked' => (bool) $this->getRawAttribute($key), - 'created_at', - 'updated_at' => $this->getTimeFast($key), + 'unix_updated_at' => $this->getRawAttribute($key), - 'created_at_json', - 'updated_at_json' => $this->getJsonTimeFast($key), + 'created_at' => $this->getTimeFast($key), + 'created_at_json' => $this->getJsonTimeFast($key), 'pp' => $this->performance?->pp, diff --git a/database/migrations/2023_12_18_085034_update_scores_table.php b/database/migrations/2023_12_18_085034_update_scores_table.php new file mode 100644 index 00000000000..d67902fb822 --- /dev/null +++ b/database/migrations/2023_12_18_085034_update_scores_table.php @@ -0,0 +1,69 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class extends Migration +{ + private static function resetView(): void + { + DB::statement('DROP VIEW scores'); + DB::statement('CREATE VIEW scores AS SELECT * FROM solo_scores'); + } + + public function up(): void + { + Schema::table('solo_scores', function (Blueprint $table) { + $table->dropColumn('updated_at'); + + $table->dropIndex('solo_scores_beatmap_id_index'); + $table->dropIndex('solo_scores_preserve_index'); + $table->dropIndex('user_ruleset_id_index'); + + $table->boolean('ranked')->default(true)->after('preserve'); + $table->unsignedInteger('unix_updated_at')->default(DB::raw('(unix_timestamp())')); + $table->timestamp('created_at')->useCurrent()->change(); + + $table->index(['user_id', 'ruleset_id'], 'user_ruleset_index'); + $table->index(['beatmap_id', 'user_id'], 'beatmap_user_index'); + }); + + DB::statement('ALTER TABLE solo_scores MODIFY id bigint unsigned NOT NULL'); + DB::statement('ALTER TABLE solo_scores DROP PRIMARY KEY'); + DB::statement('ALTER TABLE solo_scores ADD PRIMARY KEY (id, preserve, unix_updated_at)'); + DB::statement('ALTER TABLE solo_scores MODIFY id bigint unsigned NOT NULL AUTO_INCREMENT'); + + static::resetView(); + } + + public function down(): void + { + Schema::table('solo_scores', function (Blueprint $table) { + $table->dropColumn('unix_updated_at'); + $table->dropColumn('ranked'); + + $table->dropIndex('user_ruleset_index'); + $table->dropIndex('beatmap_user_index'); + + $table->datetime('created_at')->change(); + $table->timestamp('updated_at')->nullable(true); + + $table->index('preserve', 'solo_scores_preserve_index'); + $table->index('beatmap_id', 'solo_scores_beatmap_id_index'); + $table->index(['user_id', 'ruleset_id', DB::raw('id DESC')], 'user_ruleset_id_index'); + }); + + DB::statement('ALTER TABLE solo_scores MODIFY id bigint unsigned NOT NULL'); + DB::statement('ALTER TABLE solo_scores DROP PRIMARY KEY'); + DB::statement('ALTER TABLE solo_scores ADD PRIMARY KEY (id)'); + DB::statement('ALTER TABLE solo_scores MODIFY id bigint unsigned NOT NULL AUTO_INCREMENT'); + + static::resetView(); + } +}; From 1fae706cabc88bd85339432d79e80eda86977e3a Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 9 Nov 2022 17:31:22 +0900 Subject: [PATCH 079/102] Reuse generated id array for queue --- app/Libraries/Search/ScoreSearch.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/Libraries/Search/ScoreSearch.php b/app/Libraries/Search/ScoreSearch.php index 7a4668a9a34..75f9ed3d4e6 100644 --- a/app/Libraries/Search/ScoreSearch.php +++ b/app/Libraries/Search/ScoreSearch.php @@ -116,11 +116,13 @@ public function queueForIndex(?array $schemas, array $ids): void $schemas ??= $this->getActiveSchemas(); + $values = array_map( + static fn (int $id): string => json_encode(['ScoreId' => $id]), + $ids, + ); + foreach ($schemas as $schema) { - LaravelRedis::lpush("osu-queue:score-index-{$schema}", ...array_map( - fn (int $id): string => json_encode(['ScoreId' => $id]), - $ids, - )); + LaravelRedis::lpush("osu-queue:score-index-{$schema}", ...$values); } } From ab2cf138bb1c1cd2fd2dc9a0412e660c43ec24a5 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 17 Oct 2023 20:32:36 +0900 Subject: [PATCH 080/102] Support multiple file upload in single model --- app/Casts/LegacyFilename.php | 41 ++++++ .../Commands/ForumTopicCoversCleanup.php | 2 +- app/Http/Controllers/AccountController.php | 6 +- .../Controllers/Admin/ContestsController.php | 6 +- .../Controllers/ContestEntriesController.php | 2 +- .../Forum/TopicCoversController.php | 2 +- app/Libraries/ForumDefaultTopicCover.php | 35 ----- .../Opengraph/Forum/ForumOpengraph.php | 2 +- .../Opengraph/Forum/TopicOpengraph.php | 2 +- app/Libraries/ProfileCover.php | 103 -------------- app/Libraries/Uploader.php | 108 +++++++++++++++ app/Libraries/User/Cover.php | 91 +++++++++++++ app/Models/Forum/ForumCover.php | 99 ++++++++------ app/Models/Forum/TopicCover.php | 42 +++--- app/Models/UserContestEntry.php | 37 +++-- app/Models/UserProfileCustomization.php | 50 ++++--- app/Traits/Imageable.php | 28 ---- app/Traits/Uploadable.php | 127 ------------------ .../Forum/ForumCoverTransformer.php | 12 +- .../Forum/TopicCoverTransformer.php | 8 +- .../SeasonalBackgroundTransformer.php | 8 +- app/Transformers/UserCompactTransformer.php | 8 +- .../UserContestEntryTransformer.php | 6 +- .../admin/forum/forum_covers/index.blade.php | 8 +- 24 files changed, 418 insertions(+), 415 deletions(-) create mode 100644 app/Casts/LegacyFilename.php delete mode 100644 app/Libraries/ForumDefaultTopicCover.php delete mode 100644 app/Libraries/ProfileCover.php create mode 100644 app/Libraries/Uploader.php create mode 100644 app/Libraries/User/Cover.php delete mode 100644 app/Traits/Imageable.php delete mode 100644 app/Traits/Uploadable.php diff --git a/app/Casts/LegacyFilename.php b/app/Casts/LegacyFilename.php new file mode 100644 index 00000000000..df5b623b480 --- /dev/null +++ b/app/Casts/LegacyFilename.php @@ -0,0 +1,41 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Casts; + +use Illuminate\Contracts\Database\Eloquent\CastsAttributes; +use Illuminate\Database\Eloquent\Model; + +class LegacyFilename implements CastsAttributes +{ + public static function makeFromAttributes(?array $attributes): ?string + { + if (!isset($attributes['hash'])) { + return null; + } + + $filename = $attributes['hash']; + if (isset($attributes['ext'])) { + $filename .= ".{$attributes['ext']}"; + } + + return $filename; + } + + public function get(Model $model, string $key, mixed $value, array $attributes) + { + return static::makeFromAttributes($attributes); + } + + public function set(Model $model, string $key, mixed $value, array $attributes) + { + return [ + 'ext' => null, + 'hash' => $value, + ]; + } +} diff --git a/app/Console/Commands/ForumTopicCoversCleanup.php b/app/Console/Commands/ForumTopicCoversCleanup.php index 2ed291a66b6..0d29fd80be7 100644 --- a/app/Console/Commands/ForumTopicCoversCleanup.php +++ b/app/Console/Commands/ForumTopicCoversCleanup.php @@ -51,7 +51,7 @@ public function handle() $deleted++; $progress->advance(); - $cover->deleteWithFile(); + $cover->delete(); } }); diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 9388137daa1..b8a7d06e91d 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -92,9 +92,9 @@ public function cover() } try { - $user - ->profileCustomization() - ->setCover(Request::input('cover_id'), Request::file('cover_file')); + $profile = $user->profileCustomization(); + $profile->cover()->set(Request::input('cover_id'), Request::file('cover_file')); + $profile->save(); } catch (ImageProcessorException $e) { return error_popup($e->getMessage()); } diff --git a/app/Http/Controllers/Admin/ContestsController.php b/app/Http/Controllers/Admin/ContestsController.php index a7029a214c4..bbcee86f5a8 100644 --- a/app/Http/Controllers/Admin/ContestsController.php +++ b/app/Http/Controllers/Admin/ContestsController.php @@ -8,7 +8,6 @@ use App\Models\Contest; use App\Models\DeletedUser; use App\Models\UserContestEntry; -use GuzzleHttp; use ZipStream\ZipStream; class ContestsController extends Controller @@ -47,14 +46,11 @@ public function gimmeZip($id) return response()->streamDownload(function () use ($entries) { $zip = new ZipStream(); - $client = new GuzzleHttp\Client(); - $deletedUser = new DeletedUser(); foreach ($entries as $entry) { $targetDir = ($entry->user ?? $deletedUser)->username." ({$entry->user_id})"; $filename = sanitize_filename($entry->original_filename); - $file = $client->get($entry->fileUrl())->getBody(); - $zip->addFileFromPsr7Stream("$targetDir/{$filename}", $file); + $zip->addFile("$targetDir/{$filename}", $entry->file()->get()); } $zip->finish(); diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index df6975ab4d9..018b6ff6297 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -97,7 +97,7 @@ public function destroy($id) priv_check('ContestEntryDestroy', $entry)->ensureCan(); - $entry->deleteWithFile(); + $entry->delete(); return $contest->userEntries($user); } diff --git a/app/Http/Controllers/Forum/TopicCoversController.php b/app/Http/Controllers/Forum/TopicCoversController.php index dab773dbc82..9d3129f1924 100644 --- a/app/Http/Controllers/Forum/TopicCoversController.php +++ b/app/Http/Controllers/Forum/TopicCoversController.php @@ -78,7 +78,7 @@ public function destroy($id) if ($cover !== null) { priv_check('ForumTopicCoverEdit', $cover)->ensureCan(); - $cover->deleteWithFile(); + $cover->delete(); } return json_item($cover, new TopicCoverTransformer()); diff --git a/app/Libraries/ForumDefaultTopicCover.php b/app/Libraries/ForumDefaultTopicCover.php deleted file mode 100644 index 7596903bbda..00000000000 --- a/app/Libraries/ForumDefaultTopicCover.php +++ /dev/null @@ -1,35 +0,0 @@ -. Licensed under the GNU Affero General Public License v3.0. -// See the LICENCE file in the repository root for full licence text. - -namespace App\Libraries; - -use App\Models\Forum\TopicCover; -use App\Traits\Imageable; - -class ForumDefaultTopicCover -{ - use Imageable; - - public $hash; - public $ext; - public $id; - - public function __construct($id, $data) - { - $this->id = $id; - $this->hash = $data['hash'] ?? null; - $this->ext = $data['ext'] ?? null; - } - - public function getMaxDimensions() - { - return TopicCover::MAX_DIMENSIONS; - } - - public function getFileRoot() - { - return 'forum-default-topic-covers'; - } -} diff --git a/app/Libraries/Opengraph/Forum/ForumOpengraph.php b/app/Libraries/Opengraph/Forum/ForumOpengraph.php index 6d730161cc4..1017ba7c852 100644 --- a/app/Libraries/Opengraph/Forum/ForumOpengraph.php +++ b/app/Libraries/Opengraph/Forum/ForumOpengraph.php @@ -35,7 +35,7 @@ public function get(): array return [ 'description' => $this->description(), 'title' => $this->forum->forum_name, - 'image' => $this->forum->cover?->fileUrl(), + 'image' => $this->forum->cover?->file()->Url(), ]; } } diff --git a/app/Libraries/Opengraph/Forum/TopicOpengraph.php b/app/Libraries/Opengraph/Forum/TopicOpengraph.php index 1db89abe3d3..cf33fd7b59b 100644 --- a/app/Libraries/Opengraph/Forum/TopicOpengraph.php +++ b/app/Libraries/Opengraph/Forum/TopicOpengraph.php @@ -22,7 +22,7 @@ public function get(): array return [ 'description' => "{$forumDescription} » {$this->topic->topic_title}", - 'image' => $this->topic->cover?->fileUrl() ?? $this->topic->forum->cover?->defaultTopicCover->fileUrl(), + 'image' => $this->topic->cover?->file()->url() ?? $this->topic->forum->cover?->defaultTopicCover->Url(), 'title' => $this->topic->topic_title, ]; } diff --git a/app/Libraries/ProfileCover.php b/app/Libraries/ProfileCover.php deleted file mode 100644 index 6fa89c18f6c..00000000000 --- a/app/Libraries/ProfileCover.php +++ /dev/null @@ -1,103 +0,0 @@ -. Licensed under the GNU Affero General Public License v3.0. -// See the LICENCE file in the repository root for full licence text. - -namespace App\Libraries; - -use App\Traits\Imageable; - -class ProfileCover -{ - use Imageable; - - public $data; - public $userId; - - private $availableIds = ['1', '2', '3', '4', '5', '6', '7', '8']; - - public function __construct($userId, $data) - { - $this->data = $data; - $this->userId = $userId; - } - - public function getMaxDimensions() - { - return [2400, 640]; - } - - public function getFileRoot() - { - return 'user-profile-covers'; - } - - public function getFileId() - { - return $this->userId; - } - - public function getFileProperties() - { - return array_get($this->data, 'file'); - } - - public function setFileProperties($props) - { - if ($this->data === null) { - $this->data = []; - } - - $this->data['file'] = $props; - } - - public function hasCustomCover() - { - return !isset($this->data['id']) && isset($this->data['file']); - } - - public function id() - { - if ($this->hasCustomCover()) { - return; - } - - if ($this->userId === null || $this->userId < 1) { - return; - } - - if (!in_array($this->data['id'] ?? null, $this->availableIds, true)) { - return $this->availableIds[$this->userId % count($this->availableIds)]; - } - - return $this->data['id']; - } - - public function set($id, $file) - { - if ($id !== null && in_array($id, $this->availableIds, true)) { - $this->data['id'] = $id; - } else { - $this->data['id'] = null; - } - - if ($file !== null) { - $this->storeFile($file->getRealPath()); - } - - return array_only($this->data, ['id', 'file']); - } - - public function url() - { - if ($this->hasCustomCover()) { - return $this->fileUrl(); - } - - $id = $this->id(); - - if ($id !== null) { - return $GLOBALS['cfg']['app']['url'].'/images/headers/profile-covers/c'.$id.'.jpg'; - } - } -} diff --git a/app/Libraries/Uploader.php b/app/Libraries/Uploader.php new file mode 100644 index 00000000000..365d6cccb7d --- /dev/null +++ b/app/Libraries/Uploader.php @@ -0,0 +1,108 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Libraries; + +use App\Exceptions\InvariantException; +use App\Models\Model; +use Illuminate\Http\File; +use League\Flysystem\Local\LocalFilesystemAdapter; + +class Uploader +{ + private ?string $filename; + + public function __construct( + private string $baseDir, + public Model $model, + private string $attr, + private array $processors = [], + ) { + $this->filename = $this->model->{$this->attr}; + } + + private static function process(string $name, ?array $options, string $srcPath): ?string + { + switch ($name) { + case 'image': + $processor = new ImageProcessor($srcPath, $options['maxDimensions'], $options['maxFileSize'] ?? 10_000_000); + $processor->process(); + + return $processor->ext(); + } + + throw new InvariantException('unknown process name'); + } + + public function delete(): void + { + $this->setFilename(null); + \Storage::deleteDirectory($this->dir()); + } + + public function get(): ?string + { + $path = $this->path(); + + return $path === null ? null : \Storage::get($path); + } + + public function store(string $srcPath, string $ext = ''): void + { + foreach ($this->processors as $processName => $processOptions) { + $newExt = static::process($processName, $processOptions, $srcPath); + if ($newExt !== null) { + $ext = $newExt; + } + } + + $this->delete(); + $filename = hash_file('sha256', $srcPath); + if (present($ext)) { + $filename .= ".{$ext}"; + } + $this->setFilename($filename); + $storage = \Storage::disk(); + + if ($storage->getAdapter() instanceof LocalFilesystemAdapter) { + $options = [ + 'visibility' => 'public', + 'directory_visibility' => 'public', + ]; + } + + $storage->putFileAs( + $this->dir(), + new File($srcPath), + $this->filename, + $options ?? [], + ); + } + + public function url(): ?string + { + $path = $this->path(); + + return $path === null ? null : StorageUrl::make(null, $path); + } + + private function dir(): string + { + return "{$this->baseDir}/{$this->model->getKey()}"; + } + + private function path(): ?string + { + return $this->filename === null ? null : "{$this->dir()}/{$this->filename}"; + } + + private function setFilename(?string $filename): void + { + $this->filename = $filename; + $this->model->{$this->attr} = $filename; + } +} diff --git a/app/Libraries/User/Cover.php b/app/Libraries/User/Cover.php new file mode 100644 index 00000000000..b6e89e698f5 --- /dev/null +++ b/app/Libraries/User/Cover.php @@ -0,0 +1,91 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Libraries\User; + +use App\Models\UserProfileCustomization; +use Illuminate\Http\UploadedFile; + +/** + * This class doesn't sync with underlying model to save attribute casting time + */ +class Cover +{ + private const AVAILABLE_PRESET_IDS = ['1', '2', '3', '4', '5', '6', '7', '8']; + + private ?array $json; + + public function __construct(private UserProfileCustomization $userProfileCustomization) + { + $this->json = $this->userProfileCustomization->cover_json; + } + + public static function isValidPresetId(?string $presetId): bool + { + return $presetId !== null + && in_array($presetId, static::AVAILABLE_PRESET_IDS, true); + } + + public function customUrl(): ?string + { + return $this->userProfileCustomization->customCover()->url(); + } + + public function presetId(): ?string + { + if ($this->hasCustomCover()) { + return null; + } + + $id = $this->userProfileCustomization->getKey(); + + if ($id === null || $id < 1) { + return null; + } + + $presetId = $this->json['id'] ?? null; + + return static::isValidPresetId($presetId) + ? $presetId + : static::AVAILABLE_PRESET_IDS[$id % count(static::AVAILABLE_PRESET_IDS)]; + } + + public function set(?string $presetId, ?UploadedFile $file) + { + $this->userProfileCustomization->cover_json = [ + ...($this->json ?? []), + 'id' => static::isValidPresetId($presetId) ? $presetId : null, + ]; + + if ($file !== null) { + $this->userProfileCustomization->customCover()->store($file->getRealPath()); + } + + $this->json = $this->userProfileCustomization->cover_json; + } + + public function url(): ?string + { + return $this->hasCustomCover() + ? $this->customUrl() + : $this->presetUrl(); + } + + private function hasCustomCover(): bool + { + return !isset($this->json['id']) && isset($this->json['file']); + } + + private function presetUrl(): ?string + { + $presetId = $this->presetId(); + + return $presetId === null + ? null + : "{$GLOBALS['cfg']['app']['url']}/images/headers/profile-covers/c{$presetId}.jpg"; + } +} diff --git a/app/Models/Forum/ForumCover.php b/app/Models/Forum/ForumCover.php index ebdf04bdc8c..5ae561f926f 100644 --- a/app/Models/Forum/ForumCover.php +++ b/app/Models/Forum/ForumCover.php @@ -5,9 +5,9 @@ namespace App\Models\Forum; -use App\Libraries\ForumDefaultTopicCover; +use App\Casts\LegacyFilename; +use App\Libraries\Uploader; use App\Models\User; -use App\Traits\Imageable; use DB; /** @@ -26,25 +26,16 @@ */ class ForumCover extends Model { - use Imageable; - - protected $table = 'forum_forum_covers'; + const MAX_DIMENSIONS = [2000, 400]; protected $casts = [ 'default_topic_cover_json' => 'array', + 'filename' => LegacyFilename::class, ]; + protected $table = 'forum_forum_covers'; - private $_defaultTopicCover; - - public function getMaxDimensions() - { - return [2000, 400]; - } - - public function getFileRoot() - { - return 'forum-covers'; - } + private Uploader $defaultTopicCoverUploader; + private Uploader $file; public static function upload($filePath, $user, $forum = null) { @@ -54,7 +45,7 @@ public static function upload($filePath, $user, $forum = null) $cover->save(); // get id $cover->user()->associate($user); $cover->forum()->associate($forum); - $cover->storeFile($filePath); + $cover->file()->store($filePath); $cover->save(); }); @@ -71,41 +62,71 @@ public function user() return $this->belongsTo(User::class, 'user_id'); } - public function updateFile($filePath, $user) + public function getDefaultTopicCoverAttribute(): Uploader { - $this->user()->associate($user); - $this->storeFile($filePath); - $this->save(); - - return $this->fresh(); + return $this->defaultTopicCoverUploader ??= new Uploader( + 'forum-default-topic-covers', + $this, + 'default_topic_cover_filename', + ['image' => ['maxDimensions' => TopicCover::MAX_DIMENSIONS]], + ); } - public function getDefaultTopicCoverAttribute() + public function setDefaultTopicCoverAttribute($value): void { - if ($this->_defaultTopicCover === null) { - $this->_defaultTopicCover = new ForumDefaultTopicCover($this->id, $this->default_topic_cover_json); + if (($value['_delete'] ?? false) === true) { + $this->defaultTopicCover->delete(); + } elseif (($value['cover_file'] ?? null) !== null) { + $this->defaultTopicCover->store($value['cover_file']); } + } - return $this->_defaultTopicCover; + public function getDefaultTopicCoverFilenameAttribute(): ?string + { + return LegacyFilename::makeFromAttributes($this->default_topic_cover_json); } - public function setMainCoverAttribute($value) + public function setDefaultTopicCoverFilenameAttribute(?string $value): void { - if (($value['_delete'] ?? false) === true) { - $this->deleteFile(); - } elseif (($value['cover_file'] ?? null) !== null) { - $this->storeFile($value['cover_file']); - } + $this->default_topic_cover_json = [ + 'ext' => null, + 'hash' => $value, + ]; } - public function setDefaultTopicCoverAttribute($value) + public function setMainCoverAttribute($value): void { - if (($value['_delete'] ?? false) === true) { - $this->defaultTopicCover->deleteFile(); - } elseif (($value['cover_file'] ?? null) !== null) { - $this->defaultTopicCover->storeFile($value['cover_file']); + if ($value['_delete'] ?? false) { + $this->file()->delete(); + } elseif (isset($value['cover_file'])) { + $this->file()->store($value['cover_file']); } + } + + public function delete() + { + $this->file()->delete(); + $this->defaultTopicCover->delete(); + + return parent::delete(); + } - $this->default_topic_cover_json = $this->defaultTopicCover->getFileProperties(); + public function file(): Uploader + { + return $this->file ??= new Uploader( + 'forum-covers', + $this, + 'filename', + ['image' => ['maxDimensions' => static::MAX_DIMENSIONS]], + ); + } + + public function updateFile($filePath, $user) + { + $this->user()->associate($user); + $this->file()->store($filePath); + $this->save(); + + return $this->fresh(); } } diff --git a/app/Models/Forum/TopicCover.php b/app/Models/Forum/TopicCover.php index 199a70ce311..462462ec866 100644 --- a/app/Models/Forum/TopicCover.php +++ b/app/Models/Forum/TopicCover.php @@ -5,8 +5,9 @@ namespace App\Models\Forum; +use App\Casts\LegacyFilename; +use App\Libraries\Uploader; use App\Models\User; -use App\Traits\Imageable; use DB; use Exception; @@ -23,27 +24,19 @@ */ class TopicCover extends Model { - use Imageable; - const MAX_DIMENSIONS = [2400, 580]; // To be passed to transformer for generating url for initial cover upload public ?int $newForumId = null; + protected $casts = [ + 'filename' => LegacyFilename::class, + ]; protected $table = 'forum_topic_covers'; + private Uploader $file; private $_owner = [false, null]; - public function getMaxDimensions() - { - return static::MAX_DIMENSIONS; - } - - public function getFileRoot() - { - return 'topic-covers'; - } - public static function findForUse($id, $user) { if ($user === null) { @@ -67,7 +60,7 @@ public static function upload($filePath, $user, $topic = null) $cover->save(); // get id $cover->user()->associate($user); $cover->topic()->associate($topic); - $cover->storeFile($filePath); + $cover->file()->store($filePath); $cover->save(); }); @@ -104,7 +97,7 @@ public function owner() public function updateFile($filePath, $user) { $this->user()->associate($user); - $this->storeFile($filePath); + $this->file()->store($filePath); $this->save(); return $this->fresh(); @@ -113,12 +106,29 @@ public function updateFile($filePath, $user) public function defaultFileUrl() { try { - return $this->topic->forum->cover->defaultTopicCover->fileUrl(); + return $this->topic->forum->cover->defaultTopicCover->url(); } catch (Exception $_e) { // do nothing } } + public function delete() + { + $this->file()->delete(); + + return parent::delete(); + } + + public function file(): Uploader + { + return $this->file ??= new Uploader( + 'topic-covers', + $this, + 'filename', + ['image' => ['maxDimensions' => static::MAX_DIMENSIONS]], + ); + } + public function getForumId(): ?int { return $this->topic?->forum_id ?? $this->newForumId; diff --git a/app/Models/UserContestEntry.php b/app/Models/UserContestEntry.php index 1a57a3e0a80..f2bcdaf3176 100644 --- a/app/Models/UserContestEntry.php +++ b/app/Models/UserContestEntry.php @@ -5,7 +5,8 @@ namespace App\Models; -use App\Traits\Uploadable; +use App\Casts\LegacyFilename; +use App\Libraries\Uploader; use DB; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Http\UploadedFile; @@ -27,14 +28,12 @@ class UserContestEntry extends Model { use SoftDeletes; - use Uploadable; - protected $casts = ['deleted_at' => 'datetime']; + protected $casts = [ + 'filename' => LegacyFilename::class, + ]; - public function getFileRoot() - { - return 'user-contest-entries'; - } + private Uploader $file; public static function upload(UploadedFile $file, $user, $contest = null) { @@ -47,7 +46,7 @@ public static function upload(UploadedFile $file, $user, $contest = null) $entry->original_filename = $file->getClientOriginalName(); $entry->user()->associate($user); $entry->contest()->associate($contest); - $entry->storeFile($file->getRealPath(), $file->getClientOriginalExtension()); + $entry->file()->store($file->getRealPath(), $file->getClientOriginalExtension()); $entry->save(); }); @@ -63,4 +62,26 @@ public function contest() { return $this->belongsTo(Contest::class); } + + public function delete() + { + $this->file()->delete(); + + return parent::delete(); + } + + public function file(): Uploader + { + return $this->file ??= new Uploader('user-contest-entries', $this, 'filename'); + } + + // file generated by process separate from osu-web + public function seasonalUrl(): ?string + { + $url = $this->file()->url(); + + return $url === null + ? null + : preg_replace('#(\.[^/.]+)$#', '', $url).'_opt.jpg'; + } } diff --git a/app/Models/UserProfileCustomization.php b/app/Models/UserProfileCustomization.php index cc4ab6305ca..357cb3d66a2 100644 --- a/app/Models/UserProfileCustomization.php +++ b/app/Models/UserProfileCustomization.php @@ -5,7 +5,9 @@ namespace App\Models; -use App\Libraries\ProfileCover; +use App\Casts\LegacyFilename; +use App\Libraries\Uploader; +use App\Libraries\User\Cover; use Illuminate\Database\Eloquent\Casts\AsArrayObject; /** @@ -49,7 +51,7 @@ class UserProfileCustomization extends Model ]; protected $primaryKey = 'user_id'; - private $cover; + private Uploader $customCover; public static function repairExtrasOrder($value) { @@ -67,22 +69,6 @@ public static function repairExtrasOrder($value) ); } - public function cover() - { - if ($this->cover === null) { - $this->cover = new ProfileCover($this->user_id, $this->cover_json); - } - - return $this->cover; - } - - public function setCover($id, $file) - { - $this->cover_json = $this->cover()->set($id, $file); - - $this->save(); - } - public function getAudioAutoplayAttribute() { return $this->options['audio_autoplay'] ?? false; @@ -185,6 +171,19 @@ public function setCommentsSortAttribute($value) $this->setOption('comments_sort', $value); } + public function getCustomCoverFilenameAttribute(): ?string + { + return LegacyFilename::makeFromAttributes($this->cover_json['file'] ?? null); + } + + public function setCustomCoverFilenameAttribute(?string $value): void + { + $this->cover_json = [ + ...($this->cover_json ?? []), + 'file' => ['hash' => $value], + ]; + } + public function getForumPostsShowDeletedAttribute() { return $this->options['forum_posts_show_deleted'] ?? true; @@ -268,6 +267,21 @@ public function setProfileCoverExpandedAttribute($value) $this->setOption('profile_cover_expanded', get_bool($value)); } + public function customCover() + { + return $this->customCover ??= new Uploader( + 'user-profile-covers', + $this, + 'custom_cover_filename', + ['image' => ['maxDimensions' => [2400, 640]]], + ); + } + + public function cover() + { + return new Cover($this); + } + private function setOption($key, $value) { $this->options ??= []; diff --git a/app/Traits/Imageable.php b/app/Traits/Imageable.php deleted file mode 100644 index abc55d64ab8..00000000000 --- a/app/Traits/Imageable.php +++ /dev/null @@ -1,28 +0,0 @@ -. Licensed under the GNU Affero General Public License v3.0. -// See the LICENCE file in the repository root for full licence text. - -namespace App\Traits; - -use App\Libraries\ImageProcessor; - -trait Imageable -{ - use Uploadable { - storeFile as _storeFile; // rename storeFile in the Uploadable trait so we can override it - } - - /** - * Returns maximum dimensions of the image as an array of [width, height]. - */ - abstract public function getMaxDimensions(); - - public function storeFile($filePath) - { - $image = new ImageProcessor($filePath, $this->getMaxDimensions(), $this->getMaxFileSize()); - $image->process(); - - $this->_storeFile($image->inputPath, $image->ext()); - } -} diff --git a/app/Traits/Uploadable.php b/app/Traits/Uploadable.php deleted file mode 100644 index d48346b8715..00000000000 --- a/app/Traits/Uploadable.php +++ /dev/null @@ -1,127 +0,0 @@ -. Licensed under the GNU Affero General Public License v3.0. -// See the LICENCE file in the repository root for full licence text. - -namespace App\Traits; - -use App\Libraries\StorageUrl; -use Illuminate\Http\File; -use League\Flysystem\Local\LocalFilesystemAdapter; - -trait Uploadable -{ - /** - * Returns maximum size of the file in bytes. Defaults to 1 MB. - */ - public function getMaxFileSize() - { - return 1000000; - } - - /** - * Returns root path of where the files are to be stored. - */ - abstract public function getFileRoot(); - - public function getFileId() - { - return $this->id; - } - - /** - * Returns a hash with contents of at least 'hash' and 'ext' if there's - * image or otherwise null. - * - * Assumes attributes 'hash' and 'ext' of the object by default. - */ - public function getFileProperties() - { - if (!present($this->hash) || !present($this->ext)) { - return; - } - - return [ - 'hash' => $this->hash, - 'ext' => $this->ext, - ]; - } - - /** - * Sets file properties. Either a hash of 'hash' and 'ext' or null. - * - * Assumes attributes 'hash' and 'ext' of the object by default. - */ - public function setFileProperties($props) - { - $this->hash = $props['hash'] ?? null; - $this->ext = $props['ext'] ?? null; - } - - public function fileDir() - { - return $this->getFileRoot().'/'.$this->getFileId(); - } - - public function fileName() - { - return $this->getFileProperties()['hash'].'.'.$this->getFileProperties()['ext']; - } - - public function filePath() - { - return $this->fileDir().'/'.$this->fileName(); - } - - public function fileUrl() - { - if ($this->getFileProperties() === null) { - return; - } - - return StorageUrl::make(null, $this->filePath()); - } - - public function deleteWithFile() - { - $this->deleteFile(); - - return $this->delete(); - } - - public function deleteFile() - { - if ($this->getFileProperties() === null) { - return; - } - - $this->setFileProperties(null); - - return \Storage::deleteDirectory($this->fileDir()); - } - - public function storeFile($filePath, $fileExtension = '') - { - $this->deleteFile(); - $this->setFileProperties([ - 'hash' => hash_file('sha256', $filePath), - 'ext' => $fileExtension, - ]); - - $storage = \Storage::disk(); - - if ($storage->getAdapter() instanceof LocalFilesystemAdapter) { - $options = [ - 'visibility' => 'public', - 'directory_visibility' => 'public', - ]; - } - - $storage->putFileAs( - $this->fileDir(), - new File($filePath), - $this->fileName(), - $options ?? [], - ); - } -} diff --git a/app/Transformers/Forum/ForumCoverTransformer.php b/app/Transformers/Forum/ForumCoverTransformer.php index 72c80e1b5c8..50b0b364621 100644 --- a/app/Transformers/Forum/ForumCoverTransformer.php +++ b/app/Transformers/Forum/ForumCoverTransformer.php @@ -10,13 +10,11 @@ class ForumCoverTransformer extends TransformerAbstract { - public function transform(ForumCover $cover = null) + public function transform(?ForumCover $cover = null) { - if ($cover === null) { - $cover = new ForumCover(); - } + $fileUrl = $cover === null ? null : $cover->file()->url(); - if ($cover->getFileProperties() === null) { + if ($fileUrl === null) { $data = [ 'method' => 'post', 'url' => route('forum.forum-covers.store', ['forum_id' => $cover->forum_id]), @@ -27,11 +25,11 @@ public function transform(ForumCover $cover = null) 'url' => route('forum.forum-covers.update', [$cover, 'forum_id' => $cover->forum_id]), 'id' => $cover->id, - 'fileUrl' => $cover->fileUrl(), + 'fileUrl' => $fileUrl, ]; } - $data['dimensions'] = $cover->getMaxDimensions(); + $data['dimensions'] = $cover::MAX_DIMENSIONS; return $data; } diff --git a/app/Transformers/Forum/TopicCoverTransformer.php b/app/Transformers/Forum/TopicCoverTransformer.php index 31caf758226..b15615267a6 100644 --- a/app/Transformers/Forum/TopicCoverTransformer.php +++ b/app/Transformers/Forum/TopicCoverTransformer.php @@ -12,7 +12,7 @@ class TopicCoverTransformer extends TransformerAbstract { public function transform(TopicCover $cover) { - if ($cover->getFileProperties() === null) { + if ($cover->file_json === null) { $data = [ 'method' => 'post', 'url' => route('forum.topic-covers.store', [ @@ -25,12 +25,12 @@ public function transform(TopicCover $cover) 'method' => 'put', 'url' => route('forum.topic-covers.update', [$cover, 'topic_id' => $cover->topic_id]), - 'id' => $cover->id, - 'fileUrl' => $cover->fileUrl(), + 'id' => $cover->getKey(), + 'fileUrl' => $cover->file()->url(), ]; } - $data['dimensions'] = $cover->getMaxDimensions(); + $data['dimensions'] = $cover::MAX_DIMENSIONS; $data['defaultFileUrl'] = $cover->defaultFileUrl(); return $data; diff --git a/app/Transformers/SeasonalBackgroundTransformer.php b/app/Transformers/SeasonalBackgroundTransformer.php index a35da6936e7..6a24ea718f5 100644 --- a/app/Transformers/SeasonalBackgroundTransformer.php +++ b/app/Transformers/SeasonalBackgroundTransformer.php @@ -5,7 +5,6 @@ namespace App\Transformers; -use App\Libraries\StorageUrl; use App\Models\UserContestEntry; class SeasonalBackgroundTransformer extends TransformerAbstract @@ -18,15 +17,10 @@ class SeasonalBackgroundTransformer extends TransformerAbstract 'user', ]; - /** - * At least the url generation "logic" probably should be part of a decorator. - * Please look into doing that before extending this further. - */ public function transform(UserContestEntry $entry) { return [ - // files generated by process separate from osu-web - 'url' => StorageUrl::make(null, "{$entry->fileDir()}/{$entry->hash}_opt.jpg"), + 'url' => $entry->seasonalUrl(), ]; } diff --git a/app/Transformers/UserCompactTransformer.php b/app/Transformers/UserCompactTransformer.php index 9532222aebe..4df771e6390 100644 --- a/app/Transformers/UserCompactTransformer.php +++ b/app/Transformers/UserCompactTransformer.php @@ -199,12 +199,12 @@ public function includeCountry(User $user) public function includeCover(User $user) { - $profileCustomization = $this->userProfileCustomization($user); + $cover = $this->userProfileCustomization($user)->cover(); return $this->primitive([ - 'custom_url' => $profileCustomization->cover()->fileUrl(), - 'url' => $profileCustomization->cover()->url(), - 'id' => $profileCustomization->cover()->id(), + 'custom_url' => $cover->customUrl(), + 'url' => $cover->url(), + 'id' => $cover->presetId(), ]); } diff --git a/app/Transformers/UserContestEntryTransformer.php b/app/Transformers/UserContestEntryTransformer.php index 309e002411e..b602b17b6b6 100644 --- a/app/Transformers/UserContestEntryTransformer.php +++ b/app/Transformers/UserContestEntryTransformer.php @@ -16,12 +16,14 @@ class UserContestEntryTransformer extends TransformerAbstract public function transform(UserContestEntry $entry) { + $url = $entry->file()->url(); + return [ 'id' => $entry->id, 'filename' => $entry->original_filename, 'filesize' => $entry->filesize, - 'url' => $entry->fileUrl(), - 'thumb' => mini_asset($entry->fileUrl()), + 'url' => $url, + 'thumb' => mini_asset($url), 'created_at' => json_time($entry->created_at), 'deleted' => $entry->deleted_at !== null, ]; diff --git a/resources/views/admin/forum/forum_covers/index.blade.php b/resources/views/admin/forum/forum_covers/index.blade.php index 160d5fa9eea..1a57ea18f69 100644 --- a/resources/views/admin/forum/forum_covers/index.blade.php +++ b/resources/views/admin/forum/forum_covers/index.blade.php @@ -18,19 +18,19 @@ @foreach ([ - 'main' => ['cover' => $forum->cover, 'key' => 'main_cover'], + 'main' => ['cover' => $forum->cover->file(), 'key' => 'main_cover'], 'default-topic' => ['cover' => $forum->cover->defaultTopicCover ?? null, 'key' => 'default_topic_cover'] ] as $type => $cover)

{{ osu_trans("admin.forum.forum-covers.index.type-title.{$type}") }}

- @if ($cover['cover'] !== null && $cover['cover']->fileUrl() !== null) + @if ($cover['cover'] !== null && $cover['cover']->url() !== null)
From 2b3377ea986dc2aa4089c2f6c75cb0f767e25999 Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 20 Dec 2023 17:19:25 +0900 Subject: [PATCH 081/102] Fix style --- resources/css/bem/profile-info.less | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/css/bem/profile-info.less b/resources/css/bem/profile-info.less index ce11d01d982..00fe84197d5 100644 --- a/resources/css/bem/profile-info.less +++ b/resources/css/bem/profile-info.less @@ -130,6 +130,8 @@ &--supporter { .center-content(); + .link-plain(); + .link-white(); border-radius: 10000px; background-color: @osu-colour-h1; padding: 0 10px; From 36fcfca80f54442aa67d077b59aa6a938663ce6f Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 20 Dec 2023 17:19:55 +0900 Subject: [PATCH 082/102] Fix indent --- resources/js/profile-page/cover.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/profile-page/cover.tsx b/resources/js/profile-page/cover.tsx index 2b697df647a..fce522ee12f 100644 --- a/resources/js/profile-page/cover.tsx +++ b/resources/js/profile-page/cover.tsx @@ -127,7 +127,7 @@ export default class Cover extends React.Component { <> {this.props.user.is_supporter && - {times(this.props.user.support_level ?? 0, (i) => )} + {times(this.props.user.support_level ?? 0, (i) => )} } From f1ae7c9afe67cb3b8068ddc119e80357a0636b76 Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 20 Dec 2023 17:23:37 +0900 Subject: [PATCH 083/102] Lint fix --- resources/js/profile-page/cover.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/profile-page/cover.tsx b/resources/js/profile-page/cover.tsx index fce522ee12f..b608920468b 100644 --- a/resources/js/profile-page/cover.tsx +++ b/resources/js/profile-page/cover.tsx @@ -126,7 +126,7 @@ export default class Cover extends React.Component { return ( <> {this.props.user.is_supporter && - + {times(this.props.user.support_level ?? 0, (i) => )} } From 7554eea41685e3c97f8266194341ca1b1754680b Mon Sep 17 00:00:00 2001 From: peppy Date: Wed, 20 Dec 2023 17:06:58 +0000 Subject: [PATCH 084/102] Update mod definitions --- database/mods.json | 40 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/database/mods.json b/database/mods.json index bf82cf1b2f5..0fb0df78b26 100644 --- a/database/mods.json +++ b/database/mods.json @@ -37,7 +37,6 @@ "SD", "PF", "AC", - "RX", "AP" ], "RequiresConfiguration": false, @@ -142,7 +141,6 @@ "NF", "PF", "TP", - "RX", "AP" ], "RequiresConfiguration": false, @@ -168,7 +166,6 @@ "NF", "SD", "AC", - "RX", "AP" ], "RequiresConfiguration": false, @@ -357,7 +354,6 @@ "EZ", "NF", "PF", - "RX", "AP" ], "RequiresConfiguration": false, @@ -634,10 +630,6 @@ "Type": "Automation", "Settings": [], "IncompatibleMods": [ - "NF", - "SD", - "PF", - "AC", "AL", "SG", "AT", @@ -1222,8 +1214,7 @@ "IncompatibleMods": [ "SD", "PF", - "AC", - "RX" + "AC" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -1324,8 +1315,7 @@ ], "IncompatibleMods": [ "NF", - "PF", - "RX" + "PF" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -1349,8 +1339,7 @@ "IncompatibleMods": [ "NF", "SD", - "AC", - "RX" + "AC" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -1486,8 +1475,7 @@ ], "IncompatibleMods": [ "NF", - "PF", - "RX" + "PF" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -1647,10 +1635,6 @@ "Type": "Automation", "Settings": [], "IncompatibleMods": [ - "NF", - "SD", - "PF", - "AC", "SG", "AT", "CN" @@ -1864,8 +1848,7 @@ "IncompatibleMods": [ "SD", "PF", - "AC", - "RX" + "AC" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -1964,8 +1947,7 @@ ], "IncompatibleMods": [ "NF", - "PF", - "RX" + "PF" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -1989,8 +1971,7 @@ "IncompatibleMods": [ "NF", "SD", - "AC", - "RX" + "AC" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -2125,8 +2106,7 @@ "IncompatibleMods": [ "EZ", "NF", - "PF", - "RX" + "PF" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -2253,10 +2233,6 @@ "Type": "Automation", "Settings": [], "IncompatibleMods": [ - "NF", - "SD", - "PF", - "AC", "AT", "CN" ], From 12a56b96ebca67838a85cd91110a4a96821bd549 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 21 Dec 2023 16:37:36 +0900 Subject: [PATCH 085/102] Combine same caster --- app/Models/Solo/Score.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/Models/Solo/Score.php b/app/Models/Solo/Score.php index 64a85d27ca5..6b4632a30a2 100644 --- a/app/Models/Solo/Score.php +++ b/app/Models/Solo/Score.php @@ -150,6 +150,7 @@ public function getAttribute($key) 'beatmap_id', 'id', 'ruleset_id', + 'unix_updated_at', 'user_id' => $this->getRawAttribute($key), 'data' => $this->getClassCastableAttributeValue($key, $this->getRawAttribute($key)), @@ -158,8 +159,6 @@ public function getAttribute($key) 'preserve', 'ranked' => (bool) $this->getRawAttribute($key), - 'unix_updated_at' => $this->getRawAttribute($key), - 'created_at' => $this->getTimeFast($key), 'created_at_json' => $this->getJsonTimeFast($key), From 693ab6cc603283ca6a1acb809734a3f3b5e2deac Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 21 Dec 2023 18:30:48 +0900 Subject: [PATCH 086/102] Update mods test RX and PF combination is now allowed. --- tests/Libraries/ModsTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Libraries/ModsTest.php b/tests/Libraries/ModsTest.php index 9e2fcb9e885..ddf54798ad5 100644 --- a/tests/Libraries/ModsTest.php +++ b/tests/Libraries/ModsTest.php @@ -152,12 +152,12 @@ public static function modComboExclusives() [Ruleset::mania, ['DT'], ['PF'], true], // conflicting exclusive required mods - [Ruleset::osu, ['RX', 'PF'], [], false], + [Ruleset::osu, ['HT', 'DT'], [], false], [Ruleset::mania, ['FI', 'HD'], [], false], // allowed mods conflicts with exclusive required mods - [Ruleset::osu, ['RX'], ['PF'], false], - [Ruleset::taiko, ['RX'], ['PF'], false], + [Ruleset::osu, ['HT'], ['DT'], false], + [Ruleset::taiko, ['HT'], ['DT'], false], ]; } } From dcc9d49fc99c82b734d0274889ba1c767864a401 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 21 Dec 2023 18:49:21 +0900 Subject: [PATCH 087/102] Fix case --- app/Libraries/Opengraph/Forum/ForumOpengraph.php | 2 +- app/Libraries/Opengraph/Forum/TopicOpengraph.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Libraries/Opengraph/Forum/ForumOpengraph.php b/app/Libraries/Opengraph/Forum/ForumOpengraph.php index 1017ba7c852..cfc6dabbb22 100644 --- a/app/Libraries/Opengraph/Forum/ForumOpengraph.php +++ b/app/Libraries/Opengraph/Forum/ForumOpengraph.php @@ -35,7 +35,7 @@ public function get(): array return [ 'description' => $this->description(), 'title' => $this->forum->forum_name, - 'image' => $this->forum->cover?->file()->Url(), + 'image' => $this->forum->cover?->file()->url(), ]; } } diff --git a/app/Libraries/Opengraph/Forum/TopicOpengraph.php b/app/Libraries/Opengraph/Forum/TopicOpengraph.php index cf33fd7b59b..16947822eac 100644 --- a/app/Libraries/Opengraph/Forum/TopicOpengraph.php +++ b/app/Libraries/Opengraph/Forum/TopicOpengraph.php @@ -22,7 +22,7 @@ public function get(): array return [ 'description' => "{$forumDescription} » {$this->topic->topic_title}", - 'image' => $this->topic->cover?->file()->url() ?? $this->topic->forum->cover?->defaultTopicCover->Url(), + 'image' => $this->topic->cover?->file()->url() ?? $this->topic->forum->cover?->defaultTopicCover->url(), 'title' => $this->topic->topic_title, ]; } From 0cb1a6470e5e7c7c0407538eaaf5073f068c2e5f Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 21 Dec 2023 18:58:19 +0900 Subject: [PATCH 088/102] Null check and move to variable --- .../admin/forum/forum_covers/index.blade.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/resources/views/admin/forum/forum_covers/index.blade.php b/resources/views/admin/forum/forum_covers/index.blade.php index 1a57ea18f69..4d0494c87d1 100644 --- a/resources/views/admin/forum/forum_covers/index.blade.php +++ b/resources/views/admin/forum/forum_covers/index.blade.php @@ -9,17 +9,21 @@
@foreach ($forums as $forum) -
+ @php + $forumId = $forum->getKey(); + $forumCover = $forum->cover; + @endphp +

{!! link_to( - route('forum.forums.show', $forum->forum_id), - osu_trans('admin.forum.forum-covers.index.forum-name', ['id' => $forum->forum_id, 'name' => $forum->forum_name]) + route('forum.forums.show', $forumId), + osu_trans('admin.forum.forum-covers.index.forum-name', ['id' => $forumId, 'name' => $forum->forum_name]) ) !!}

@foreach ([ - 'main' => ['cover' => $forum->cover->file(), 'key' => 'main_cover'], - 'default-topic' => ['cover' => $forum->cover->defaultTopicCover ?? null, 'key' => 'default_topic_cover'] + 'main' => ['cover' => $forumCover?->file(), 'key' => 'main_cover'], + 'default-topic' => ['cover' => $forumCover?->defaultTopicCover, 'key' => 'default_topic_cover'] ] as $type => $cover)

{{ osu_trans("admin.forum.forum-covers.index.type-title.{$type}") }}

@@ -54,7 +58,7 @@ > @csrf - + From 00c04f454b03e399e310a53d813212ffe9b14233 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 21 Dec 2023 18:59:53 +0900 Subject: [PATCH 089/102] Move to const and adjust case --- app/Libraries/Uploader.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/Libraries/Uploader.php b/app/Libraries/Uploader.php index 365d6cccb7d..34c8ce4a850 100644 --- a/app/Libraries/Uploader.php +++ b/app/Libraries/Uploader.php @@ -14,6 +14,8 @@ class Uploader { + private const DEFAULT_MAX_FILESIZE = 10_000_000; + private ?string $filename; public function __construct( @@ -29,7 +31,11 @@ private static function process(string $name, ?array $options, string $srcPath): { switch ($name) { case 'image': - $processor = new ImageProcessor($srcPath, $options['maxDimensions'], $options['maxFileSize'] ?? 10_000_000); + $processor = new ImageProcessor( + $srcPath, + $options['maxDimensions'], + $options['maxFilesize'] ?? static::DEFAULT_MAX_FILESIZE, + ); $processor->process(); return $processor->ext(); From 5a1b348d23eb8de6fbe1edabe03a1821da2efe0a Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 21 Dec 2023 19:02:21 +0900 Subject: [PATCH 090/102] More move to const --- app/Libraries/User/Cover.php | 2 ++ app/Models/UserProfileCustomization.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Libraries/User/Cover.php b/app/Libraries/User/Cover.php index b6e89e698f5..b008e8e1045 100644 --- a/app/Libraries/User/Cover.php +++ b/app/Libraries/User/Cover.php @@ -15,6 +15,8 @@ */ class Cover { + const CUSTOM_COVER_MAX_DIMENSIONS = [2400, 640]; + private const AVAILABLE_PRESET_IDS = ['1', '2', '3', '4', '5', '6', '7', '8']; private ?array $json; diff --git a/app/Models/UserProfileCustomization.php b/app/Models/UserProfileCustomization.php index 357cb3d66a2..cc567cced5d 100644 --- a/app/Models/UserProfileCustomization.php +++ b/app/Models/UserProfileCustomization.php @@ -273,7 +273,7 @@ public function customCover() 'user-profile-covers', $this, 'custom_cover_filename', - ['image' => ['maxDimensions' => [2400, 640]]], + ['image' => ['maxDimensions' => Cover::CUSTOM_COVER_MAX_DIMENSIONS]], ); } From 3c391bd3b8efa3823c05a172bef1460fe3f7fd9f Mon Sep 17 00:00:00 2001 From: bakaneko Date: Tue, 12 Dec 2023 21:55:24 +0900 Subject: [PATCH 091/102] updates for https://github.com/ppy/osu-elastic-indexer/pull/152 --- app/Libraries/Search/ScoreSearch.php | 4 ++-- tests/Commands/EsIndexScoresQueueTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Libraries/Search/ScoreSearch.php b/app/Libraries/Search/ScoreSearch.php index 75f9ed3d4e6..c7125d1ce28 100644 --- a/app/Libraries/Search/ScoreSearch.php +++ b/app/Libraries/Search/ScoreSearch.php @@ -21,7 +21,7 @@ class ScoreSearch extends RecordSearch public function __construct(?ScoreSearchParams $params = null) { parent::__construct( - $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'solo_scores', + $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'scores', $params ?? new ScoreSearchParams(), Score::class ); @@ -122,7 +122,7 @@ public function queueForIndex(?array $schemas, array $ids): void ); foreach ($schemas as $schema) { - LaravelRedis::lpush("osu-queue:score-index-{$schema}", ...$values); + LaravelRedis::lpush("osu-queue:{$schema}", ...$values); } } diff --git a/tests/Commands/EsIndexScoresQueueTest.php b/tests/Commands/EsIndexScoresQueueTest.php index e2b288f5c6c..50ed2a59628 100644 --- a/tests/Commands/EsIndexScoresQueueTest.php +++ b/tests/Commands/EsIndexScoresQueueTest.php @@ -22,7 +22,7 @@ private static function clearQueue(): void private static function queueKey(): string { - return 'osu-queue:score-index-'.static::SCHEMA; + return 'osu-queue:'.static::SCHEMA; } private static function queueSize(): int From 66d5fe4ddca2527660c7fd02147e993c9fe1d1e2 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 21 Dec 2023 22:11:22 +0900 Subject: [PATCH 092/102] Fix bbcode spoiler box link width --- resources/css/bem/bbcode-spoilerbox.less | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/css/bem/bbcode-spoilerbox.less b/resources/css/bem/bbcode-spoilerbox.less index 93d7073c521..80186f178fe 100644 --- a/resources/css/bem/bbcode-spoilerbox.less +++ b/resources/css/bem/bbcode-spoilerbox.less @@ -24,6 +24,8 @@ flex-wrap: wrap; overflow-wrap: anywhere; font-weight: bold; + width: max-content; + max-width: 100%; &:hover { text-decoration: underline; From a5ecf4014ceddf1e381dcd8ed8a18c8ec79e9b87 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 21 Dec 2023 23:07:54 +0900 Subject: [PATCH 093/102] Use cached countries data for session record --- app/Http/Middleware/UpdateUserLastvisit.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Http/Middleware/UpdateUserLastvisit.php b/app/Http/Middleware/UpdateUserLastvisit.php index a817773224a..2ba7144c29b 100644 --- a/app/Http/Middleware/UpdateUserLastvisit.php +++ b/app/Http/Middleware/UpdateUserLastvisit.php @@ -56,12 +56,13 @@ public function handle($request, Closure $next) private function recordSession($request) { // Add metadata to session to help user recognize this login location - $countryCode = presence(request_country($request)) ?? Country::UNKNOWN; + $countryCode = request_country($request); + $country = $countryCode === null ? null : app('countries')->byCode($countryCode); $request->session()->put('meta', [ 'agent' => $request->header('User-Agent'), 'country' => [ - 'code' => $countryCode, - 'name' => presence(Country::where('acronym', $countryCode)->pluck('name')->first()) ?? 'Unknown', + 'code' => $country?->acronym ?? Country::UNKNOWN, + 'name' => presence($country?->name) ?? 'Unknown', ], 'ip' => $request->ip(), 'last_visit' => Carbon::now(), From 9b598b0a98ce621b39c08cd4500fe73f57737180 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Dec 2023 00:13:48 +0000 Subject: [PATCH 094/102] Bump aws/aws-sdk-php from 3.274.0 to 3.294.5 Bumps [aws/aws-sdk-php](https://github.com/aws/aws-sdk-php) from 3.274.0 to 3.294.5. - [Release notes](https://github.com/aws/aws-sdk-php/releases) - [Commits](https://github.com/aws/aws-sdk-php/compare/3.274.0...3.294.5) --- updated-dependencies: - dependency-name: aws/aws-sdk-php dependency-type: indirect ... Signed-off-by: dependabot[bot] --- composer.lock | 207 ++++++++++++++++++++++++++------------------------ 1 file changed, 108 insertions(+), 99 deletions(-) diff --git a/composer.lock b/composer.lock index 45ae87b2800..1d433d09a0e 100644 --- a/composer.lock +++ b/composer.lock @@ -72,16 +72,16 @@ }, { "name": "aws/aws-crt-php", - "version": "v1.2.1", + "version": "v1.2.4", "source": { "type": "git", "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "1926277fc71d253dfa820271ac5987bdb193ccf5" + "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/1926277fc71d253dfa820271ac5987bdb193ccf5", - "reference": "1926277fc71d253dfa820271ac5987bdb193ccf5", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/eb0c6e4e142224a10b08f49ebf87f32611d162b2", + "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2", "shasum": "" }, "require": { @@ -120,35 +120,35 @@ ], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.1" + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.4" }, - "time": "2023-03-24T20:22:19+00:00" + "time": "2023-11-08T00:42:13+00:00" }, { "name": "aws/aws-sdk-php", - "version": "3.274.0", + "version": "3.294.5", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "b2f37a49ca40bce633323a6988477c22be562c37" + "reference": "2e34d45e970c77775e4c298e08732d64b647c41c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/b2f37a49ca40bce633323a6988477c22be562c37", - "reference": "b2f37a49ca40bce633323a6988477c22be562c37", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2e34d45e970c77775e4c298e08732d64b647c41c", + "reference": "2e34d45e970c77775e4c298e08732d64b647c41c", "shasum": "" }, "require": { - "aws/aws-crt-php": "^1.0.4", + "aws/aws-crt-php": "^1.2.3", "ext-json": "*", "ext-pcre": "*", "ext-simplexml": "*", "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", - "guzzlehttp/promises": "^1.4.0", + "guzzlehttp/promises": "^1.4.0 || ^2.0", "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", "mtdowling/jmespath.php": "^2.6", - "php": ">=5.5", - "psr/http-message": "^1.0" + "php": ">=7.2.5", + "psr/http-message": "^1.0 || ^2.0" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", @@ -163,7 +163,7 @@ "ext-sockets": "*", "nette/neon": "^2.3", "paragonie/random_compat": ">= 2", - "phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", "psr/cache": "^1.0", "psr/simple-cache": "^1.0", "sebastian/comparator": "^1.2.3 || ^4.0", @@ -215,9 +215,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.274.0" + "source": "https://github.com/aws/aws-sdk-php/tree/3.294.5" }, - "time": "2023-06-27T18:32:17+00:00" + "time": "2023-12-21T19:10:21+00:00" }, { "name": "brick/math", @@ -1756,22 +1756,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.7.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1780,11 +1780,11 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -1862,7 +1862,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.7.0" + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" }, "funding": [ { @@ -1878,33 +1878,37 @@ "type": "tidelift" } ], - "time": "2023-05-21T14:04:53+00:00" + "time": "2023-12-03T20:35:24+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.3", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", - "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" }, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -1941,7 +1945,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.3" + "source": "https://github.com/guzzle/promises/tree/2.0.2" }, "funding": [ { @@ -1957,20 +1961,20 @@ "type": "tidelift" } ], - "time": "2023-05-21T12:31:43+00:00" + "time": "2023-12-03T20:19:20+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.5.0", + "version": "2.6.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6" + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", "shasum": "" }, "require": { @@ -1984,9 +1988,9 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", + "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "phpunit/phpunit": "^8.5.36 || ^9.6.15" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -2057,7 +2061,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.5.0" + "source": "https://github.com/guzzle/psr7/tree/2.6.2" }, "funding": [ { @@ -2073,7 +2077,7 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:11:26+00:00" + "time": "2023-12-03T20:05:35+00:00" }, { "name": "guzzlehttp/uri-template", @@ -4913,25 +4917,25 @@ }, { "name": "mtdowling/jmespath.php", - "version": "2.6.1", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb" + "reference": "bbb69a935c2cbb0c03d7f481a238027430f6440b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/9b87907a81b87bc76d19a7fb2d61e61486ee9edb", - "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/bbb69a935c2cbb0c03d7f481a238027430f6440b", + "reference": "bbb69a935c2cbb0c03d7f481a238027430f6440b", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0 || ^8.0", + "php": "^7.2.5 || ^8.0", "symfony/polyfill-mbstring": "^1.17" }, "require-dev": { - "composer/xdebug-handler": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^7.5.15" + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" }, "bin": [ "bin/jp.php" @@ -4939,7 +4943,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { @@ -4955,6 +4959,11 @@ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", @@ -4968,9 +4977,9 @@ ], "support": { "issues": "https://github.com/jmespath/jmespath.php/issues", - "source": "https://github.com/jmespath/jmespath.php/tree/2.6.1" + "source": "https://github.com/jmespath/jmespath.php/tree/2.7.0" }, - "time": "2021-06-14T00:11:39+00:00" + "time": "2023-08-25T10:54:48+00:00" }, { "name": "myclabs/php-enum", @@ -6689,16 +6698,16 @@ }, { "name": "psr/http-client", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { @@ -6735,9 +6744,9 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" + "source": "https://github.com/php-fig/http-client" }, - "time": "2023-04-10T20:12:12+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", @@ -7251,23 +7260,23 @@ }, { "name": "react/promise", - "version": "v2.10.0", + "version": "v2.11.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "f913fb8cceba1e6644b7b90c4bfb678ed8a3ef38" + "reference": "1a8460931ea36dc5c76838fec5734d55c88c6831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/f913fb8cceba1e6644b7b90c4bfb678ed8a3ef38", - "reference": "f913fb8cceba1e6644b7b90c4bfb678ed8a3ef38", + "url": "https://api.github.com/repos/reactphp/promise/zipball/1a8460931ea36dc5c76838fec5734d55c88c6831", + "reference": "1a8460931ea36dc5c76838fec5734d55c88c6831", "shasum": "" }, "require": { "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" }, "type": "library", "autoload": { @@ -7311,7 +7320,7 @@ ], "support": { "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v2.10.0" + "source": "https://github.com/reactphp/promise/tree/v2.11.0" }, "funding": [ { @@ -7319,7 +7328,7 @@ "type": "open_collective" } ], - "time": "2023-05-02T15:15:43+00:00" + "time": "2023-11-16T16:16:50+00:00" }, { "name": "sentry/sdk", @@ -8071,7 +8080,7 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -8118,7 +8127,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" }, "funding": [ { @@ -9185,16 +9194,16 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da" + "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", + "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", "shasum": "" }, "require": { @@ -9208,7 +9217,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -9252,7 +9261,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" }, "funding": [ { @@ -9268,20 +9277,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:30:37+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { @@ -9293,7 +9302,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -9336,7 +9345,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" }, "funding": [ { @@ -9352,20 +9361,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { @@ -9380,7 +9389,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -9419,7 +9428,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -9435,20 +9444,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", "shasum": "" }, "require": { @@ -9457,7 +9466,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -9495,7 +9504,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" }, "funding": [ { @@ -9511,7 +9520,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php80", From 8282cad103252d3339344de0b6398c6386800d8f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Dec 2023 16:36:14 +0900 Subject: [PATCH 095/102] Update translations from crowdin --- resources/lang/de/home.php | 2 +- resources/lang/es/authorization.php | 16 +++--- resources/lang/fi/accounts.php | 2 +- resources/lang/fi/authorization.php | 2 +- resources/lang/fi/beatmap_discussions.php | 2 +- resources/lang/fi/beatmaps.php | 4 +- resources/lang/fi/beatmapset_events.php | 4 +- resources/lang/fi/beatmapsets.php | 6 +-- resources/lang/fi/common.php | 2 +- resources/lang/fi/errors.php | 2 +- resources/lang/fi/events.php | 2 +- resources/lang/fi/forum.php | 6 +-- resources/lang/fi/home.php | 10 ++-- resources/lang/fi/layout.php | 2 +- resources/lang/fi/news.php | 2 +- resources/lang/fi/notifications.php | 10 ++-- resources/lang/fi/password_reset.php | 4 +- resources/lang/fi/store.php | 4 +- resources/lang/fi/supporter_tag.php | 2 +- resources/lang/it/changelog.php | 2 +- resources/lang/ja/authorization.php | 2 +- resources/lang/lt/authorization.php | 2 +- resources/lang/lt/comments.php | 2 +- resources/lang/lt/events.php | 2 +- resources/lang/lt/notifications.php | 4 +- resources/lang/lt/store.php | 8 +-- resources/lang/lt/users.php | 10 ++-- resources/lang/pl/accounts.php | 6 +-- resources/lang/pl/store.php | 12 ++--- .../lang/ru/beatmap_discussion_posts.php | 2 +- resources/lang/ru/beatmap_discussions.php | 2 +- resources/lang/ru/beatmapset_events.php | 2 +- resources/lang/ru/notifications.php | 2 +- resources/lang/tr/accounts.php | 24 ++++----- resources/lang/tr/api.php | 8 +-- resources/lang/tr/artist.php | 2 +- resources/lang/tr/authorization.php | 4 +- resources/lang/tr/beatmap_discussions.php | 6 +-- resources/lang/tr/beatmaps.php | 30 +++++------ resources/lang/tr/beatmapset_events.php | 6 +-- resources/lang/tr/beatmapset_watches.php | 6 +-- resources/lang/tr/beatmapsets.php | 34 ++++++------- resources/lang/tr/comments.php | 4 +- resources/lang/tr/community.php | 26 +++++----- resources/lang/tr/contest.php | 4 +- resources/lang/tr/errors.php | 2 +- resources/lang/tr/events.php | 8 +-- resources/lang/tr/follows.php | 6 +-- resources/lang/tr/home.php | 18 +++---- resources/lang/tr/layout.php | 8 +-- resources/lang/tr/mail.php | 22 ++++---- resources/lang/tr/matches.php | 2 +- resources/lang/tr/model_validation.php | 22 ++++---- resources/lang/tr/notifications.php | 50 +++++++++---------- resources/lang/tr/page_title.php | 16 +++--- resources/lang/tr/quick_search.php | 2 +- resources/lang/tr/report.php | 2 +- resources/lang/tr/store.php | 32 ++++++------ resources/lang/tr/users.php | 40 +++++++-------- resources/lang/zh-tw/accounts.php | 2 +- resources/lang/zh-tw/store.php | 6 +-- resources/lang/zh-tw/users.php | 2 +- 62 files changed, 268 insertions(+), 268 deletions(-) diff --git a/resources/lang/de/home.php b/resources/lang/de/home.php index af9453d4234..430aeed0b53 100644 --- a/resources/lang/de/home.php +++ b/resources/lang/de/home.php @@ -113,7 +113,7 @@ 'beatmaps' => [ 'title' => 'Beatmaps runterladen', 'description' => [ - '_' => ':browse durch die riesige Bibliothek von an Nutzern erstellten Beatmaps und fang an zu spielen!', + '_' => ':browse durch die riesige Bibliothek an von Nutzern erstellten Beatmaps und fang an zu spielen!', 'browse' => 'Stöbere', ], ], diff --git a/resources/lang/es/authorization.php b/resources/lang/es/authorization.php index 85fd16376cb..8098424c35b 100644 --- a/resources/lang/es/authorization.php +++ b/resources/lang/es/authorization.php @@ -7,8 +7,8 @@ 'play_more' => '¿Qué tal si en vez de eso jugamos un poco de osu!?', 'require_login' => 'Por favor, inicia sesión para continuar.', 'require_verification' => 'Verifique para continuar.', - 'restricted' => "No puede hacer eso mientras esté restringido.", - 'silenced' => "No puede hacer eso mientras esté silenciado.", + 'restricted' => "No puedes hacer eso mientras estás restringido.", + 'silenced' => "No puedes hacer eso mientras estás silenciado.", 'unauthorized' => 'Acceso denegado.', 'beatmap_discussion' => [ @@ -20,7 +20,7 @@ 'exhausted' => 'Has alcanzado tu límite de nominaciones diarias, por favor inténtalo de nuevo mañana.', 'incorrect_state' => 'Error al realizar esa acción, intente actualizar la página.', 'owner' => "No puedes nominar tu propio mapa.", - 'set_metadata' => 'Debe establecer el género y el idioma antes de nominar.', + 'set_metadata' => 'Debes establecer el género y el idioma antes de nominar.', ], 'resolve' => [ 'not_owner' => 'Solo el creador del tema y el dueño del mapa pueden resolver una discusión.', @@ -31,7 +31,7 @@ ], 'vote' => [ - 'bot' => "No puede votar en una discusión hecha por un bot", + 'bot' => "No puedes votar en una discusión hecha por un bot", 'limit_exceeded' => 'Espera un poco antes de seguir votando', 'owner' => "No puedes votar tus propias discusiones.", 'wrong_beatmapset_state' => 'Solo puedes votar en discusiones de mapas pendientes.', @@ -64,11 +64,11 @@ 'annnonce_only' => 'Este canal es solo para anuncios.', 'blocked' => 'No puedes enviar mensajes a un usuario que bloqueaste o que te haya bloqueado.', 'friends_only' => 'Este usuario está bloqueando los mensajes de personas que no están en su lista de amigos.', - 'moderated' => 'Ese canal está actualmente siendo moderado.', + 'moderated' => 'Este canal está actualmente siendo moderado.', 'no_access' => 'No tienes acceso a ese canal.', 'receive_friends_only' => 'Es posible que el usuario no pueda responder porque solo acepta mensajes de personas de su lista de amigos.', - 'restricted' => 'No puede enviar mensajes mientras esté silenciado, restringido o baneado.', - 'silenced' => 'No puede enviar mensajes mientras esté silenciado, restringido o baneado.', + 'restricted' => 'No puedes enviar mensajes mientras estás silenciado, restringido o baneado.', + 'silenced' => 'No puedes enviar mensajes mientras estás silenciado, restringido o baneado.', ], 'comment' => [ @@ -118,7 +118,7 @@ 'topic' => [ 'reply' => [ - 'double_post' => 'Por favor, edite su última publicación en lugar de publicarla de nuevo.', + 'double_post' => 'Por favor, edita tu última publicación en lugar de publicarla de nuevo.', 'locked' => 'No puedes responder a un hilo cerrado.', 'no_forum_access' => 'Se requiere acceso al foro solicitado.', 'no_permission' => 'No tienes permisos para responder.', diff --git a/resources/lang/fi/accounts.php b/resources/lang/fi/accounts.php index a7e69c2e86d..b3d9c7dfddb 100644 --- a/resources/lang/fi/accounts.php +++ b/resources/lang/fi/accounts.php @@ -125,7 +125,7 @@ 'privacy' => [ 'friends_only' => 'estä yksityisviestit henkilöiltä jotka eivät ole kaverilistallasi', - 'hide_online' => 'piilota online-tilasi', + 'hide_online' => 'piilota paikallaolotilasi', 'title' => 'Yksityisyys', ], diff --git a/resources/lang/fi/authorization.php b/resources/lang/fi/authorization.php index 05fe30b0c6c..bfc3c68aa8c 100644 --- a/resources/lang/fi/authorization.php +++ b/resources/lang/fi/authorization.php @@ -61,7 +61,7 @@ ], 'chat' => [ - 'annnonce_only' => 'Tämä kanava on tarkoitettu vain tiedotuksiin.', + 'annnonce_only' => 'Tämä kanava on vain tiedotteita varten.', 'blocked' => 'Et voi lähettää viestejä käyttäjälle, joka on estänyt sinut tai jonka olet estänyt.', 'friends_only' => 'Käyttäjä on estänyt viestit henkilöiltä, jotka eivät ole hänen kaverilistassaan.', 'moderated' => 'Tätä kanavaa moderoidaan.', diff --git a/resources/lang/fi/beatmap_discussions.php b/resources/lang/fi/beatmap_discussions.php index 9982870b548..0ec2d80016e 100644 --- a/resources/lang/fi/beatmap_discussions.php +++ b/resources/lang/fi/beatmap_discussions.php @@ -36,7 +36,7 @@ 'disqualified' => 'Epäkelpuutettu', 'never_qualified' => 'Ei koskaan kelpuutettu', 'qualified' => 'Kelpuutettu', - 'ranked' => 'Pisteytetty', + 'ranked' => 'Rankattu', ], 'user' => [ diff --git a/resources/lang/fi/beatmaps.php b/resources/lang/fi/beatmaps.php index b7ed4bf2930..f216348433f 100644 --- a/resources/lang/fi/beatmaps.php +++ b/resources/lang/fi/beatmaps.php @@ -255,7 +255,7 @@ 'difficulty' => 'Vaikeustaso', 'favourites' => 'Suosikit', 'updated' => 'Päivitetty', - 'ranked' => 'Pisteytetty', + 'ranked' => 'Rankattu', 'rating' => 'Luokitus', 'plays' => 'Pelikerrat', 'relevance' => 'Osuvuus', @@ -263,7 +263,7 @@ ], 'supporter_filter_quote' => [ '_' => 'Rajataksesi tunnisteella :filters sinulla on oltava aktiivinen :link', - 'link_text' => 'osu!supporter-tagi', + 'link_text' => 'osu!n tukijan merkki', ], ], ], diff --git a/resources/lang/fi/beatmapset_events.php b/resources/lang/fi/beatmapset_events.php index ce51ee33dfb..462181b7428 100644 --- a/resources/lang/fi/beatmapset_events.php +++ b/resources/lang/fi/beatmapset_events.php @@ -68,8 +68,8 @@ 'genre_edit' => 'Genren muokkaus', 'issue_reopen' => 'Keskustelun uudelleenavaaminen', 'issue_resolve' => 'Keskustelun ratkaiseminen', - 'kudosu_allow' => 'Kusodun hyväksyntä', - 'kudosu_deny' => 'Kusodun kieltäminen', + 'kudosu_allow' => 'Kudosun hyväksyntä', + 'kudosu_deny' => 'Kudosun kieltäminen', 'kudosu_gain' => 'Kusodun ansaitseminen', 'kudosu_lost' => 'Kusodun menettäminen', 'kudosu_recalculate' => 'Kusodun uudelleenlaskenta', diff --git a/resources/lang/fi/beatmapsets.php b/resources/lang/fi/beatmapsets.php index 4a1d8c6631b..c3407d3133f 100644 --- a/resources/lang/fi/beatmapsets.php +++ b/resources/lang/fi/beatmapsets.php @@ -123,7 +123,7 @@ ], 'report' => [ - '_' => 'Jos löydät jonkun ongelman tämän beatmapin kanssa, olmoita siitä :link hälyttääksesi tiimiä.', + '_' => 'Jos löydät jonkun ongelman tässä rytmikartassa, ilmoita siitä :link hälyttääksesi tiimin paikalle.', 'button' => 'Ilmoita Ongelma', 'link' => 'täällä', ], @@ -136,7 +136,7 @@ 'no_scores' => 'Dataa lasketaan...', 'nominators' => 'Ehdollepanijat', 'nsfw' => 'Sopimaton sisältö', - 'offset' => 'Online tasoitus', + 'offset' => 'Vastapaino verkossa', 'points-of-failure' => 'Epäonnistumiskohdat', 'source' => 'Lähde', 'storyboard' => 'Tämä rytmikartta sisältää taustaesityksen', @@ -208,7 +208,7 @@ 'bpm' => 'BPM', 'count_circles' => 'Ympyröiden määrä', 'count_sliders' => 'Slidereiden määrä', - 'offset' => 'Online tasoitus :offset', + 'offset' => 'Vastapaino verkossa: :offset', 'user-rating' => 'Käyttäjien arvio', 'rating-spread' => 'Arvioiden jakauma', 'nominations' => 'Suositukset', diff --git a/resources/lang/fi/common.php b/resources/lang/fi/common.php index 34c5808f05f..bfed28e116c 100644 --- a/resources/lang/fi/common.php +++ b/resources/lang/fi/common.php @@ -113,7 +113,7 @@ ], 'input' => [ - 'search' => 'etsi...', + 'search' => 'hae...', ], 'pagination' => [ diff --git a/resources/lang/fi/errors.php b/resources/lang/fi/errors.php index 6da648c7b69..c3ea7f303bf 100644 --- a/resources/lang/fi/errors.php +++ b/resources/lang/fi/errors.php @@ -31,6 +31,6 @@ 'search' => [ 'default' => 'Tuloksia ei saatu, yritä myöhemmin uudelleen.', 'invalid_cursor_exception' => 'Virheellinen kohdistimen parametri määritetty.', - 'operation_timeout_exception' => 'Haku on tavallista aktiivisempi. Yritä uudelleen myöhemmin.', + 'operation_timeout_exception' => 'Haku on tavallista ruuhkaisempi, yritä myöhemmin uudelleen.', ], ]; diff --git a/resources/lang/fi/events.php b/resources/lang/fi/events.php index caad9085257..2462614ac32 100644 --- a/resources/lang/fi/events.php +++ b/resources/lang/fi/events.php @@ -23,7 +23,7 @@ 'approved' => 'vahvistettu', 'loved' => 'rakastettu', 'qualified' => 'kelpuutettu', - 'ranked' => 'pisteytetty', + 'ranked' => 'rankattu', ], 'value' => [ diff --git a/resources/lang/fi/forum.php b/resources/lang/fi/forum.php index 6809449d27f..1d76e9b3b18 100644 --- a/resources/lang/fi/forum.php +++ b/resources/lang/fi/forum.php @@ -315,9 +315,9 @@ 'to_1' => 'Kiinnitä aihe', 'to_1_confirm' => 'Kiinnitä aihe?', 'to_1_done' => 'Aihe kiinnitetty', - 'to_2' => 'Kiinnitä aihe ja merkkaa ilmoitukseksi', - 'to_2_confirm' => 'Kiinnitä aihe ja merkkaa ilmoitukseksi?', - 'to_2_done' => 'Aihe on kiinnitetty ja merkattu ilmoitukseksi', + 'to_2' => 'Kiinnitä aihe ja merkitse tiedotteeksi', + 'to_2_confirm' => 'Kiinnitetäänkö aihe ja merkitään tiedotteeksi?', + 'to_2_done' => 'Aihe on kiinnitetty ja merkitty tiedotteeksi', ], 'moderate_toggle_deleted' => [ diff --git a/resources/lang/fi/home.php b/resources/lang/fi/home.php index ecdf855fad3..09c92fa6f93 100644 --- a/resources/lang/fi/home.php +++ b/resources/lang/fi/home.php @@ -6,7 +6,7 @@ return [ 'landing' => [ 'download' => 'Lataa nyt', - 'online' => ':players online-tilassa :games pelaamassa', + 'online' => ':players tällä hetkellä paikalla :games pelissä', 'peak' => 'Huipussaan :count käyttäjää paikalla', 'players' => ':count rekisteröitynyttä pelaajaa', 'title' => 'tervetuloa', @@ -23,13 +23,13 @@ 'button' => 'Hae', 'empty_result' => 'Mitään ei löytynyt!', 'keyword_required' => 'Syötä hakusana', - 'placeholder' => 'kirjoita etsiäksesi', + 'placeholder' => 'kirjoita hakeaksesi', 'title' => 'Hae', 'beatmapset' => [ - 'login_required' => 'Kirjaudu sisään etsiäksesi rytmikarttoja', + 'login_required' => 'Kirjaudu sisään hakeaksesi rytmikarttoja', 'more' => ':count lisää hakutulosta', - 'more_simple' => 'Katso lisää hakutuloksia', + 'more_simple' => 'Katso lisää rytmikarttojen hakutuloksia', 'title' => 'Beatmapit', ], @@ -140,7 +140,7 @@ ], 'buttons' => [ 'download' => 'Lataa osu!', - 'support' => 'Tue osua!', + 'support' => 'Tue osu!a', 'store' => 'osu!kauppa', ], ], diff --git a/resources/lang/fi/layout.php b/resources/lang/fi/layout.php index 6455c45463e..57c6cee5b40 100644 --- a/resources/lang/fi/layout.php +++ b/resources/lang/fi/layout.php @@ -201,7 +201,7 @@ ], 'popup_search' => [ - 'initial' => 'Kirjoita etsiäksesi!', + 'initial' => 'Kirjoita hakeaksesi!', 'retry' => 'Haku epäonnistui. Yritä uudelleen napsauttamalla.', ], ]; diff --git a/resources/lang/fi/news.php b/resources/lang/fi/news.php index c8d437b3d63..c2069bd6e3e 100644 --- a/resources/lang/fi/news.php +++ b/resources/lang/fi/news.php @@ -19,7 +19,7 @@ ], 'show' => [ - 'by' => ':user\'lta', + 'by' => 'kirjoittanut :user', 'nav' => [ 'newer' => 'Uudempi viesti', diff --git a/resources/lang/fi/notifications.php b/resources/lang/fi/notifications.php index 37c04b5ced2..df74fc03043 100644 --- a/resources/lang/fi/notifications.php +++ b/resources/lang/fi/notifications.php @@ -108,7 +108,7 @@ 'announce' => [ 'channel_announcement' => ':username sanoo ":title"', 'channel_announcement_compact' => ':title', - 'channel_announcement_group' => 'Ilmoitus :username\'lta', + 'channel_announcement_group' => 'Tiedote käyttäjältä :username', ], ], @@ -118,7 +118,7 @@ 'pm' => [ 'channel_message' => ':username sanoo ":title"', 'channel_message_compact' => ':title', - 'channel_message_group' => ':username\'lta', + 'channel_message_group' => 'käyttäjältä :username', ], ], ], @@ -163,9 +163,9 @@ 'user_beatmapset_new' => [ '_' => 'Uusi rytmikartta', - 'user_beatmapset_new' => 'Uusi rytmikartta ":title" :username\'lta', + 'user_beatmapset_new' => 'Uusi rytmikartta ":title" kartoittajalta :username', 'user_beatmapset_new_compact' => 'Uusi rytmikartta ":title"', - 'user_beatmapset_new_group' => 'Uusia rytmikarttoja :username\'lta', + 'user_beatmapset_new_group' => 'Uusia rytmikarttoja kartoittajalta :username', 'user_beatmapset_revive' => ':username elvytti rytmikartan ":title"', 'user_beatmapset_revive_compact' => 'Rytmikartta ":title" elvytetty', @@ -217,7 +217,7 @@ 'channel' => [ 'announcement' => [ - 'announce' => '":name" on saanut uuden ilmoituksen', + 'announce' => '":name" on saanut uuden tiedotteen', ], 'channel' => [ diff --git a/resources/lang/fi/password_reset.php b/resources/lang/fi/password_reset.php index ce4cb220144..d6789d54c55 100644 --- a/resources/lang/fi/password_reset.php +++ b/resources/lang/fi/password_reset.php @@ -11,10 +11,10 @@ ], 'error' => [ - 'contact_support' => 'Ota yhteyttä tukeen palauttaakesi käyttäjä.', + 'contact_support' => 'Ota yhteyttä tukeen palauttaaksesi käyttäjäsi.', 'expired' => 'Vahvistuskoodi on vanhentunut.', 'invalid' => 'Odottamaton virhe vahvistuskoodissa.', - 'is_privileged' => 'Ota yhteyttä peppyyn ebin :-D', + 'is_privileged' => 'Ota yhteyttä ylemmän tason ylläpitäjään tilisi palauttamista varten.', 'missing_key' => 'Vaaditaan.', 'too_many_tries' => 'Liian monta epäonnistunutta yritystä.', 'user_not_found' => 'Käyttäjää ei ole olemassa.', diff --git a/resources/lang/fi/store.php b/resources/lang/fi/store.php index 9c238edf633..c0d35a450ab 100644 --- a/resources/lang/fi/store.php +++ b/resources/lang/fi/store.php @@ -66,14 +66,14 @@ 'title' => 'Tilauksesi on peruutettu', 'line_1' => [ '_' => "Jos et pyytänyt peruutusta, ota yhteyttä :link ja mainitse tilauksesi numero (#:order_number).", - 'link_text' => 'osu!-kaupan tukeen', + 'link_text' => 'osu!kaupan tukeen', ], ], 'delivered' => [ 'title' => 'Tilauksesi on toimitettu! Toivottavasti pidät siitä!', 'line_1' => [ '_' => 'Jos sinulla on ongelmia ostoksesi kanssa, ota yhteyttä :link.', - 'link_text' => 'osu!-kaupan tukeen', + 'link_text' => 'osu!kaupan tukeen', ], ], 'prepared' => [ diff --git a/resources/lang/fi/supporter_tag.php b/resources/lang/fi/supporter_tag.php index 3920734553a..a02f7097f43 100644 --- a/resources/lang/fi/supporter_tag.php +++ b/resources/lang/fi/supporter_tag.php @@ -7,7 +7,7 @@ 'months' => 'kuukautta', 'user_search' => [ - 'searching' => 'etsitään...', + 'searching' => 'hakee...', 'not_found' => "Tätä käyttäjää ei ole olemassa", ], ]; diff --git a/resources/lang/it/changelog.php b/resources/lang/it/changelog.php index e9bd16dec2a..89109c1dfef 100644 --- a/resources/lang/it/changelog.php +++ b/resources/lang/it/changelog.php @@ -33,7 +33,7 @@ 'support' => [ 'heading' => 'Ti piace questo aggiornamento?', - 'text_1' => 'Sostieni gli sviluppi futuri di osu! e :link oggi!', + 'text_1' => 'Sostieni gli sviluppi futuri di osu! e :link oggi stesso!', 'text_1_link' => 'diventa un osu!supporter', 'text_2' => 'Non solo aiuterai a velocizzare lo sviluppo, ma riceverai anche funzionalità e personalizzazioni extra!', ], diff --git a/resources/lang/ja/authorization.php b/resources/lang/ja/authorization.php index 5b34c35452f..8754e282f09 100644 --- a/resources/lang/ja/authorization.php +++ b/resources/lang/ja/authorization.php @@ -186,7 +186,7 @@ ], ], 'update_email' => [ - 'locked' => '', + 'locked' => 'メールアドレスがロックされています', ], ], ]; diff --git a/resources/lang/lt/authorization.php b/resources/lang/lt/authorization.php index d53ca91ca19..0b4add59399 100644 --- a/resources/lang/lt/authorization.php +++ b/resources/lang/lt/authorization.php @@ -186,7 +186,7 @@ ], ], 'update_email' => [ - 'locked' => '', + 'locked' => 'el. paštas užrakintas', ], ], ]; diff --git a/resources/lang/lt/comments.php b/resources/lang/lt/comments.php index 9e91aff1cee..17b2bfa88b2 100644 --- a/resources/lang/lt/comments.php +++ b/resources/lang/lt/comments.php @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'komentaras iš :user', ], 'placeholder' => [ diff --git a/resources/lang/lt/events.php b/resources/lang/lt/events.php index 29ad9116cc0..36b070b8199 100644 --- a/resources/lang/lt/events.php +++ b/resources/lang/lt/events.php @@ -27,6 +27,6 @@ ], 'value' => [ - 'rank' => '', + 'rank' => 'reitingas #:rank', ], ]; diff --git a/resources/lang/lt/notifications.php b/resources/lang/lt/notifications.php index 0c4f8a5d4f8..56adf0e4c6a 100644 --- a/resources/lang/lt/notifications.php +++ b/resources/lang/lt/notifications.php @@ -57,8 +57,8 @@ 'beatmapset_discussion_unlock_compact' => 'Diskusija buvo atrakinta', 'review_count' => [ - 'praises' => '', - 'problems' => '', + 'praises' => ':count_delimited pagyrimas|:count_delimited pagyrimai', + 'problems' => ':count_delimited problema|:count_delimited problemos', 'suggestions' => '', ], ], diff --git a/resources/lang/lt/store.php b/resources/lang/lt/store.php index c27ddb374c5..38e18152048 100644 --- a/resources/lang/lt/store.php +++ b/resources/lang/lt/store.php @@ -53,7 +53,7 @@ 'invoice' => [ 'contact' => '', - 'date' => '', + 'date' => 'Data:', 'echeck_delay' => 'Kadangi jūsų mokėjote el. čekiu, pervedimas gali užtrukti iki 10 dienų kol praeis per PayPal sistemą!', 'hide_from_activity' => 'osu!rėmėjo žymos šiame užsakyme nerodomos jūsų pastarojoje veikloje.', 'sent_via' => '', @@ -111,7 +111,7 @@ 'shipping_and_handling' => '', 'shopify_expired' => 'Ši apmokėjimo nuoroda nebegalioja.', 'subtotal' => '', - 'total' => '', + 'total' => 'Iš viso', 'details' => [ 'order_number' => '', @@ -119,7 +119,7 @@ 'salesperson' => '', 'shipping_method' => '', 'shipping_terms' => '', - 'title' => '', + 'title' => 'Užsakymo Informacija', ], 'item' => [ @@ -151,7 +151,7 @@ 'paid' => 'Apmokėta', 'processing' => 'Laukiantis patvirtinimo', 'shipped' => 'Išsiųsta', - 'title' => '', + 'title' => 'Užsakymo Būsena', ], 'thanks' => [ diff --git a/resources/lang/lt/users.php b/resources/lang/lt/users.php index 95736cf5a28..49a39e174ef 100644 --- a/resources/lang/lt/users.php +++ b/resources/lang/lt/users.php @@ -124,13 +124,13 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Beatmap\'ai: :counts', + 'modding_description_empty' => 'Vartotojas nėra sukūręs beatmap\'ų...', 'description' => [ - '_' => '', - 'country' => '', - 'global' => '', + '_' => 'Reitingas (:ruleset): :global | :country', + 'country' => 'Šalyje :rank', + 'global' => 'Pasaulyje :rank', ], ], diff --git a/resources/lang/pl/accounts.php b/resources/lang/pl/accounts.php index f227bb3e30c..bb66202ae83 100644 --- a/resources/lang/pl/accounts.php +++ b/resources/lang/pl/accounts.php @@ -66,11 +66,11 @@ 'info' => "", 'link' => 'Połącz konto GitHub', 'title' => 'GitHub', - 'unlink' => 'Odłącz konto GitHub', + 'unlink' => 'Rozłącz konto GitHub', 'error' => [ - 'already_linked' => 'To konto GitHub jest już połączane z innym użytkownikiem.', - 'no_contribution' => '', + 'already_linked' => 'To konto GitHub jest już połączone z innym użytkownikiem.', + 'no_contribution' => 'Nie można połączyć konta GitHub bez historii wkładu w repozytoriach osu!', 'unverified_email' => 'Zweryfikuj swój główny email na GitHub, a następnie spróbuj ponownie połączyć swoje konto.', ], ], diff --git a/resources/lang/pl/store.php b/resources/lang/pl/store.php index 20fcb2eb7dc..d1a9c486542 100644 --- a/resources/lang/pl/store.php +++ b/resources/lang/pl/store.php @@ -49,16 +49,16 @@ ], 'discount' => 'zaoszczędź :percent%', - 'free' => '', + 'free' => 'bezpłatne!', 'invoice' => [ - 'contact' => '', - 'date' => '', + 'contact' => 'Kontakt:', + 'date' => 'Data:', 'echeck_delay' => 'Jako że twoja płatność została przesłana czekiem elektronicznym, odczekaj do 10 dni na przetworzenie transakcji przez PayPal.', 'hide_from_activity' => 'Zakup statusów donatora osu! z tego zamówienia nie zostanie wyświetlony w twojej aktywności.', - 'sent_via' => '', + 'sent_via' => 'Wysłane poprzez:', 'shipping_to' => '', - 'title' => '', + 'title' => 'Faktura', 'title_compact' => 'faktura', 'status' => [ @@ -195,7 +195,7 @@ 'checking' => 'Sprawdzanie możliwości zmiany na :username...', 'placeholder' => '', 'label' => '', - 'current' => '', + 'current' => 'Twoja aktualna nazwa użytkownika to ":username".', 'require_login' => [ '_' => 'Aby zmienić swoją nazwę użytkownika, musisz się :link!', diff --git a/resources/lang/ru/beatmap_discussion_posts.php b/resources/lang/ru/beatmap_discussion_posts.php index a7c3d42a370..957aa678ea3 100644 --- a/resources/lang/ru/beatmap_discussion_posts.php +++ b/resources/lang/ru/beatmap_discussion_posts.php @@ -10,6 +10,6 @@ 'item' => [ 'content' => 'Содержимое', - 'modding_history_link' => 'Просмотреть историю моддинга', + 'modding_history_link' => 'Открыть историю моддинга', ], ]; diff --git a/resources/lang/ru/beatmap_discussions.php b/resources/lang/ru/beatmap_discussions.php index 9be37b582f7..c052086466d 100644 --- a/resources/lang/ru/beatmap_discussions.php +++ b/resources/lang/ru/beatmap_discussions.php @@ -27,7 +27,7 @@ 'mode' => 'Режим игры', 'only_unresolved' => 'Показать только нерешённые обсуждения', 'show_review_embeds' => 'Показать посты рецензии', - 'types' => 'Виды сообщений', + 'types' => 'Виды отзывов', 'username' => 'Никнейм', 'beatmapset_status' => [ diff --git a/resources/lang/ru/beatmapset_events.php b/resources/lang/ru/beatmapset_events.php index b4ffc3d83a1..a48ca28bd90 100644 --- a/resources/lang/ru/beatmapset_events.php +++ b/resources/lang/ru/beatmapset_events.php @@ -13,7 +13,7 @@ 'discussion_post_restore' => 'Модератор восстановил пост к отзыву :discussion.', 'discussion_restore' => 'Модератор восстановил отзыв :discussion.', 'discussion_unlock' => 'Возможность обсуждения этой карты снова открыта.', - 'disqualify' => 'Дисквалифицирована :user. Причина: :discussion (:text).', + 'disqualify' => 'Получена дисквалификация от :user. Причина: :discussion (:text).', 'disqualify_legacy' => 'Получена дисквалификация от :user. Причина: :text.', 'genre_edit' => 'Жанр изменен с :old на :new.', 'issue_reopen' => 'Проблема :discussion, которая была решена пользователем :discussion_user, вновь открыта :user.', diff --git a/resources/lang/ru/notifications.php b/resources/lang/ru/notifications.php index e0bc5fd33db..57beafebd6c 100644 --- a/resources/lang/ru/notifications.php +++ b/resources/lang/ru/notifications.php @@ -201,7 +201,7 @@ ], 'beatmapset_state' => [ - 'beatmapset_disqualify' => 'Карта ":title" дисквалифицирована', + 'beatmapset_disqualify' => 'Карта ":title" была дисквалифицирована', 'beatmapset_love' => '":title" был повышен до любимого', 'beatmapset_nominate' => 'Карта ":title" номинирована', 'beatmapset_qualify' => 'Карта ":title" получила достаточно номинаций и вошла в очередь ранкинга', diff --git a/resources/lang/tr/accounts.php b/resources/lang/tr/accounts.php index 4050ba16f8f..a7188444507 100644 --- a/resources/lang/tr/accounts.php +++ b/resources/lang/tr/accounts.php @@ -63,21 +63,21 @@ ], 'github_user' => [ - 'info' => "", + 'info' => "osu!'nun açık kaynak depolarına katkıda bulunuyorsan GitHub hesabını buraya bağlamak, değişiklik günlüğü girişlerini osu! profilinle ilişkilendirecektir. osu!'ya katkı geçmişi olmayan GitHub hesapları bağlanamaz.", 'link' => 'GitHub Hesabını Bağla', 'title' => 'GitHub', 'unlink' => 'GitHub Hesabının bağlantısını Kaldır', 'error' => [ - 'already_linked' => '', - 'no_contribution' => '', - 'unverified_email' => '', + 'already_linked' => 'Bu GitHub hesabı zaten farklı bir kullanıcıya bağlı.', + 'no_contribution' => 'osu! depolarında herhangi bir katkı geçmişi olmayan GitHub hesabı bağlanamıyor.', + 'unverified_email' => 'Lütfen GitHub\'da e-posta adresini doğrula ve ardından hesabını bağlamayı tekrar dene.', ], ], 'notifications' => [ - 'beatmapset_discussion_qualified_problem' => 'belirtilen modlardaki nitelikli maplerin yeni sorunlarında bildirim al ', - 'beatmapset_disqualify' => 'belirtilen modların beatmapleri diskalifiye edildiğinde bildirim al', + 'beatmapset_discussion_qualified_problem' => 'doğrulanmış ritimharitalarının belirtilen modlardaki yeni sorunlarının bildirimlerini al', + 'beatmapset_disqualify' => 'belirtilen modların ritimharitaları diskalifiye edildiğinde bildirim al', 'comment_reply' => 'yorumlarına yapılan yanıtlar için bildirim al', 'title' => 'Bildirimler', 'topic_auto_subscribe' => 'oluşturduğunuz yeni forum başlıklarında bildirimleri otomatik olarak etkinleştir', @@ -85,12 +85,12 @@ 'options' => [ '_' => 'bildirim seçenekleri', 'beatmap_owner_change' => 'konuk zorluk', - 'beatmapset:modding' => 'beatmap modlama', + 'beatmapset:modding' => 'ritimharitası modlama', 'channel_message' => 'özel sohbet mesajları', 'comment_new' => 'yeni yorumlar', 'forum_topic_reply' => 'konu yanıtı', 'mail' => 'posta', - 'mapping' => 'beatmap mapper', + 'mapping' => 'ritimharitası yaratıcısı', 'push' => 'anlık', 'user_achievement_unlock' => 'kullanıcı madalyası açıldı', ], @@ -98,17 +98,17 @@ 'oauth' => [ 'authorized_clients' => 'izin verilen istemciler', - 'own_clients' => 'size ait istemciler', + 'own_clients' => 'sana ait istemciler', 'title' => 'OAuth', ], 'options' => [ - 'beatmapset_show_nsfw' => 'beatmaplerdeki müstehcen içerikler için uyarıları gizle', - 'beatmapset_title_show_original' => 'beatmap metaverisini orijinal dilinde göster', + 'beatmapset_show_nsfw' => 'ritimharitalarındaki müstehcen içerikler için uyarıları gizle', + 'beatmapset_title_show_original' => 'ritimharitası metaverisini orijinal dilinde göster', 'title' => 'Seçenekler', 'beatmapset_download' => [ - '_' => 'varsayılan beatmap indirme tipi', + '_' => 'varsayılan ritimharitası indirme tipi', 'all' => 'eğer varsa video ile beraber', 'direct' => 'osu!direct\'de aç', 'no_video' => 'video olmadan', diff --git a/resources/lang/tr/api.php b/resources/lang/tr/api.php index 648cde803e9..041606e4e38 100644 --- a/resources/lang/tr/api.php +++ b/resources/lang/tr/api.php @@ -17,9 +17,9 @@ 'identify' => 'Kim olduğunuzu ve herkese açık profilinizi görüntüleyebilir.', 'chat' => [ - 'read' => 'Sizin adınıza mesajları okuyun.', - 'write' => 'Sizin adınıza mesaj gönderebilir.', - 'write_manage' => 'Kanallara sizin adınıza katılın ve ayrılın.', + 'read' => 'Senin adına mesajları oku.', + 'write' => 'Senin adına mesaj gönder.', + 'write_manage' => 'Kanallara senin adına katıl ve ayrıl.', ], 'forum' => [ @@ -30,6 +30,6 @@ 'read' => 'Kimi takip ettiğinizi görebilir.', ], - 'public' => 'Herkese açık verilerinizi sizin adınıza okuyabilir.', + 'public' => 'Herkese açık verileri senin adına oku.', ], ]; diff --git a/resources/lang/tr/artist.php b/resources/lang/tr/artist.php index 34fefe33738..7eb12a2e854 100644 --- a/resources/lang/tr/artist.php +++ b/resources/lang/tr/artist.php @@ -22,7 +22,7 @@ ], 'links' => [ - 'beatmaps' => 'osu! beatmapleri', + 'beatmaps' => 'osu! Ritimharitaları', 'osu' => 'osu! profili', 'site' => 'Resmi Website', ], diff --git a/resources/lang/tr/authorization.php b/resources/lang/tr/authorization.php index b2b968fa04a..27ac4ac9a34 100644 --- a/resources/lang/tr/authorization.php +++ b/resources/lang/tr/authorization.php @@ -27,7 +27,7 @@ ], 'store' => [ - 'mapper_note_wrong_user' => 'Yalnızca beatmap sahibi ya da aday gösterici/NAT grup üyesi mapper notu gönderebilir.', + 'mapper_note_wrong_user' => 'Yalnızca ritimharitası sahibi ya da aday gösterici/NAT grup üyesi ritimharitası yaratıcısı notu gönderebilir.', ], 'vote' => [ @@ -53,7 +53,7 @@ ], 'beatmapset' => [ - 'discussion_locked' => 'Bu harita tartışma için kilitlenmiştir.', + 'discussion_locked' => 'Bu ritimharitası, tartışma için kilitlenmiştir.', 'metadata' => [ 'nominated' => 'Aday gösterilen bir mapin metaverisini değiştiremezsiniz. Hatalı ayarlandığını düşünüyorsanız bir BN ya da NAT üyesiyle iletişime geçiniz.', diff --git a/resources/lang/tr/beatmap_discussions.php b/resources/lang/tr/beatmap_discussions.php index 34f52123997..55492d5f5b2 100644 --- a/resources/lang/tr/beatmap_discussions.php +++ b/resources/lang/tr/beatmap_discussions.php @@ -24,14 +24,14 @@ 'form' => [ '_' => 'Ara', 'deleted' => 'Silinmiş tartışmaları dahil et', - 'mode' => 'Beatmap modu', + 'mode' => 'Ritimharitası modu', 'only_unresolved' => 'Sadece çözülmemiş tartışmaları göster', - 'show_review_embeds' => '', + 'show_review_embeds' => 'İnceleme gönderilerini göster', 'types' => 'Mesaj türü', 'username' => 'Kullanıcı adı', 'beatmapset_status' => [ - '_' => 'Beatmap Durumu', + '_' => 'Ritimharitası Durumu', 'all' => 'Tümü', 'disqualified' => 'Diskalifiye edildi', 'never_qualified' => 'Niteliklendirilmedi', diff --git a/resources/lang/tr/beatmaps.php b/resources/lang/tr/beatmaps.php index 6072b3c932e..370e795b499 100644 --- a/resources/lang/tr/beatmaps.php +++ b/resources/lang/tr/beatmaps.php @@ -21,7 +21,7 @@ 'guest' => ':user kullanıcısının konuk zorluğu', 'kudosu_denied' => 'Kudosu almaktan mahrum bırakıldı.', 'message_placeholder_deleted_beatmap' => 'Bu zorluk seviyesi silindi o yüzden hakkında daha fazla tartışılamaz.', - 'message_placeholder_locked' => 'Bu beatmap için tartışma devre dışı bırakıldı.', + 'message_placeholder_locked' => 'Bu ritimharitası için tartışma devre dışı bırakıldı.', 'message_placeholder_silenced' => "Susturulduğunuzda tartışma gönderisi gönderemezsiniz.", 'message_type_select' => 'Yorum Türünü Seçin', 'reply_notice' => 'Cevaplamak için Enter tuşuna basın.', @@ -153,8 +153,8 @@ 'approved' => 'Bu beatmap :date tarihinde onaylandı!', 'graveyard' => "Bu beatmap :date tarihinden beri güncellenmedi ve büyük ihtimalle yaratıcısı tarafından terk edildi...", 'loved' => 'Bu beatmap :date tarihinde sevilenler kategorisine eklendi!', - 'ranked' => 'Bu beatmap :date tarihinde dereceli oldu!', - 'wip' => 'Dikkat: Bu beatmap yaratıcısı tarafından yapım aşamasında olarak işaretlendi.', + 'ranked' => 'Bu ritimharitası :date tarihinde dereceli oldu!', + 'wip' => 'Dikkat: Bu ritimharitası yaratıcısı tarafından yapım aşamasında olarak işaretlendi.', ], 'votes' => [ @@ -170,11 +170,11 @@ ], 'hype' => [ - 'button' => 'Beatmapi Gazla!', + 'button' => 'Ritimharitasını Gazla!', 'button_done' => 'Çoktan Gazlandı!', 'confirm' => "Emin misiniz? Bu işlem kalan :n adet gaz hakkından birini kullanacak ve geriye alınamayacak.", - 'explanation' => 'Bu beatmapi aday gösterilmesi ve dereceli olması için daha görünür yapmak için gazla!', - 'explanation_guest' => 'Giriş yap ve bu beatmapi gazlayarak, aday gösterilmesi ve dereceli olması için daha görünür yap!', + 'explanation' => 'Bu ritimharitasını, aday gösterilmesi ve dereceli olması için daha görünür yapmak için gazla!', + 'explanation_guest' => 'Bu ritimharitasının aday gösterilmesi ve dereceli olması için daha görünür yapmak için gazlamak için giriş yap!', 'new_time' => "Bir sonraki gaz :new_time tarihinde gelecek.", 'remaining' => ':remaining gazınız kaldı.', 'required_text' => 'Gaz: :current/:required', @@ -187,11 +187,11 @@ ], 'nominations' => [ - 'already_nominated' => 'Bu beatmapi zaten aday gösterdiniz.', - 'cannot_nominate' => 'Bu beatmap oyun modunu aday gösteremezsiniz.', + 'already_nominated' => 'Bu ritimharitasını zaten aday gösterdiniz.', + 'cannot_nominate' => 'Bu ritimharitası oyun modunu aday gösteremezsiniz.', 'delete' => 'Sil', - 'delete_own_confirm' => 'Emin misin? Beatmap silinecek ve profiline yönlendirileceksin.', - 'delete_other_confirm' => 'Emin misin? Beatmap silinecek ve kullanıcının profiline yönlendirileceksin.', + 'delete_own_confirm' => 'Emin misin? Ritimharitası silinecek ve profiline yönlendirileceksin.', + 'delete_other_confirm' => 'Emin misin? Ritimharitası silinecek ve kullanıcının profiline yönlendirileceksin.', 'disqualification_prompt' => 'Diskalifiye sebebi nedir?', 'disqualified_at' => ':time_ago: diskalifiye edildi (:reason).', 'disqualified_no_reason' => 'bir sebep belirtilmedi', @@ -199,7 +199,7 @@ 'incorrect_state' => 'Bu eylemi gerçekleştirirken bir hata oluştu, sayfayı yenilemeyi deneyin.', 'love' => 'Sevilenlere ekle', 'love_choose' => 'Sevilen\'lere eklenecek zorluğu seçin', - 'love_confirm' => 'Bu beatmapi seviyor musun?', + 'love_confirm' => 'Bu ritimharitasını seviyor musun?', 'nominate' => 'Aday Göster', 'nominate_confirm' => 'Beatmap aday gösterilsin mi?', 'nominated_by' => ':users tarafından aday gösterildi', @@ -224,9 +224,9 @@ ], 'reset_confirm' => [ - 'disqualify' => 'Emin misiniz? Bu, beatmapin nitelikli olmasını önleyecek ve aday gösterme sürecini sıfırlayacak.', + 'disqualify' => 'Emin misin? Bu, ritimharitasının nitelikli olmasını önleyecek ve aday gösterme sürecini sıfırlayacak.', 'nomination_reset' => 'Emin misin? Yeni bir sorun bildirmek aday gösterme sürecini sıfırlayacaktır.', - 'problem_warning' => 'Bu beatmap\'teki sorunu bildireceğinizden emin misiniz? Bu, Beatmap adaylarını uyaracaktır.', + 'problem_warning' => 'Bu ritimharitasındaki sorunu bildireceğinden emin misin? Bu, ritimharitası adaylarını uyaracaktır.', ], ], @@ -268,11 +268,11 @@ ], ], 'general' => [ - 'converts' => 'Dönüştürülmüş beatmapleri dahil et', + 'converts' => 'Dönüştürülmüş ritimharitalarını dahil et', 'featured_artists' => 'Featured artist\'ler', 'follows' => 'Abone olunan mapperlar', 'recommended' => 'Önerilen zorluk seviyesi', - 'spotlights' => 'Öne çıkan beatmapler', + 'spotlights' => 'Öne çıkan ritimharitaları', ], 'mode' => [ 'all' => 'Hepsi', diff --git a/resources/lang/tr/beatmapset_events.php b/resources/lang/tr/beatmapset_events.php index 7547ac13b85..84e96b9044d 100644 --- a/resources/lang/tr/beatmapset_events.php +++ b/resources/lang/tr/beatmapset_events.php @@ -8,11 +8,11 @@ 'approve' => 'Onaylı.', 'beatmap_owner_change' => ':beatmap zorluğunun sahibi :new_user kullanıcısı ile değiştirildi.', 'discussion_delete' => 'Moderatör :discussion tartışmasını sildi.', - 'discussion_lock' => 'Bu beatmap için tartışma sağlandı', + 'discussion_lock' => 'Bu ritimharitası için tartışma devre dışı bırakıldı. (:text)', 'discussion_post_delete' => ':discussion tartışmasındaki gönderi Moderatör tarafından silindi.', 'discussion_post_restore' => ':discussion tartışmasındaki gönderi Moderatör tarafından restore edildi.', 'discussion_restore' => ':discussion tartışması moderatör tarafından restore edildi.', - 'discussion_unlock' => 'Bu beatmap için tartışma sağlandı.', + 'discussion_unlock' => 'Bu ritimharitası için tartışma aktif edildi.', 'disqualify' => ':user tarafından diskalifiye edildi. Sebep: :discussion (:text).', 'disqualify_legacy' => ':user tarafından diskalifiye edildi. Sebep: :text.', 'genre_edit' => 'Tür :old dan :new ile değiştirildi.', @@ -31,7 +31,7 @@ 'nomination_reset_received' => ':user tarafından gerçekleştirilen aday gösterme :source_user tarafından sıfırlandı (:text)', 'nomination_reset_received_profile' => 'Adaylık :user tarafından sıfırlandı (:text)', 'offset_edit' => 'Çevrimiçi ofset :old dan :new e değiştirildi.', - 'qualify' => 'Bu beatmap gerekli aday gösterilme miktarına ulaştı ve nitelikli oldu.', + 'qualify' => 'Bu ritimharitası gerekli aday gösterilme miktarına ulaştı ve nitelikli oldu.', 'rank' => 'Dereceli.', 'remove_from_loved' => ':user tarafından Sevilenlerden çıkarıldı (:text)', 'tags_edit' => 'Etiketler ":old" dan ":new" ile değiştirildi.', diff --git a/resources/lang/tr/beatmapset_watches.php b/resources/lang/tr/beatmapset_watches.php index ae00fdfcafd..468ab6e8b95 100644 --- a/resources/lang/tr/beatmapset_watches.php +++ b/resources/lang/tr/beatmapset_watches.php @@ -6,11 +6,11 @@ return [ 'index' => [ 'description' => 'Bunlar sizin takip ettiğiniz beatmap tartışmaları. Yeni bir gönderi veya güncelleme olduğunda bildirileceksiniz.', - 'title_compact' => 'beatmap tartışma izleme listesi', + 'title_compact' => 'modlama izleme listesi', 'counts' => [ - 'total' => 'İzlenen beatmapler', - 'unread' => 'Yeni gelişmelere sahip beatmapler', + 'total' => 'İzlenen ritimharitaları', + 'unread' => 'Yeni gelişmelere sahip ritimharitaları', ], 'table' => [ diff --git a/resources/lang/tr/beatmapsets.php b/resources/lang/tr/beatmapsets.php index cf2c48ce791..f786200e105 100644 --- a/resources/lang/tr/beatmapsets.php +++ b/resources/lang/tr/beatmapsets.php @@ -12,7 +12,7 @@ ], 'cover' => [ - 'deleted' => 'Silinmiş beatmap', + 'deleted' => 'Silinmiş ritimharitası', ], 'download' => [ @@ -24,12 +24,12 @@ ], 'index' => [ - 'title' => 'Beatmap Kataloğu', + 'title' => 'Ritimharitası Kataloğu', 'guest_title' => 'Beatmapler', ], 'panel' => [ - 'empty' => 'beatmap yok', + 'empty' => 'ritimharitası yok', 'download' => [ 'all' => 'indir', @@ -40,14 +40,14 @@ ], 'nominate' => [ - 'hybrid_requires_modes' => 'Karma bir beatmap seti, adaylık için en az bir oyun modu seçmenizi gerektirir.', + 'hybrid_requires_modes' => 'Karma bir ritimharitası, adaylık için en az bir oyun modu seçmenizi gerektirir.', 'incorrect_mode' => ':mode modunu aday göstermek için izniniz yok.', 'full_bn_required' => 'Bu niteliklendirme aday gösterimini gerçekleştirebilmeniz için asil aday gösterici olmanız gerekmektedir.', 'too_many' => 'Adaylık şartı zaten yerine getirildi.', 'dialog' => [ - 'confirmation' => 'Bu beatmapi aday göstermek istediğinize emin misiniz?', - 'header' => 'Beatmap aday gösterin', + 'confirmation' => 'Bu ritimharitasını aday göstermek istediğinize emin misiniz?', + 'header' => 'Ritimharitasını aday gösterin', 'hybrid_warning' => 'not: sadece bir kez aday gösterebilirsiniz, bu yüzden lütfen istediğiniz tüm oyun modlarını aday gösterdiğinizden emin olun', 'which_modes' => 'Hangi modlar için aday gösterilsin?', ], @@ -65,18 +65,18 @@ ], 'deleted_banner' => [ - 'title' => 'Bu beatmap silindi.', + 'title' => 'Bu ritimharitası silindi.', 'message' => '(bunu sadece moderatörler görebilir)', ], 'details' => [ 'by_artist' => ':artist tarafından', - 'favourite' => 'Beatmap setini favorilere ekle', - 'favourite_login' => 'Beatmapi favorilere eklemek için giriş yap', + 'favourite' => 'ritimharitasını favorilere ekle', + 'favourite_login' => 'ritimharitasını favorilere eklemek için giriş yap', 'logged-out' => 'Herhangi bir beatmapi indirmeden önce giriş yapmalısınız!', 'mapped_by' => ':mapper tarafından yapıldı', 'mapped_by_guest' => ':mapper tarafından konuk zorluk', - 'unfavourite' => 'Beatmap setini favorilerden çıkar', + 'unfavourite' => 'ritimharitasını favorilerden çıkar', 'updated_timeago' => 'son güncelleme: :timeago', 'download' => [ @@ -102,7 +102,7 @@ ], 'favourites' => [ - 'limit_reached' => 'Favorilerinizde çok fazla beatmap\'iniz var! Lütfen devam etmeden önce birini çıkartın.', + 'limit_reached' => 'Favorilerinizde çok fazla ritimharitası var! Lütfen birkaç tanesini çıkarıp tekrar deneyin.', ], 'hype' => [ @@ -123,7 +123,7 @@ ], 'report' => [ - '_' => 'Eğer bu beatmapte bir sorun bulduysanız, takımı uyarmak için lütfen :link bildirin.', + '_' => 'Eğer bu ritimharitasında bir sorun bulduysanız, takımı uyarmak için lütfen :link bildirin.', 'button' => 'Sorun Bildir', 'link' => 'buradan', ], @@ -139,19 +139,19 @@ 'offset' => 'Çevrimiçi ofset', 'points-of-failure' => 'Başarısız Olunan Kısımlar', 'source' => 'Kaynak', - 'storyboard' => 'Bu beatmap storyboard içeriyor', + 'storyboard' => 'Bu ritimharitası arkaplan animasyonu içeriyor', 'success-rate' => 'Başarı Oranı', 'tags' => 'Etiketler', - 'video' => 'Bu beatmap video içeriyor', + 'video' => 'Bu ritimharitası video içeriyor', ], 'nsfw_warning' => [ - 'details' => 'Bu beatmap müstehcen, ofansif, veya rahatsız edici içerik içermektedir. Yine de görüntülemek istiyor musunuz?', + 'details' => 'Bu ritimharitası müstehcen, ofansif, veya rahatsız edici içerik içeriyor. Yine de görüntülemek istiyor musun?', 'title' => 'Müstehcen İçerik', 'buttons' => [ 'disable' => 'Uyarıyı devre dışı bırak', - 'listing' => 'Beatmap kataloğu', + 'listing' => 'Ritimharitası kataloğu', 'show' => 'Göster', ], ], @@ -185,7 +185,7 @@ 'friend' => 'Hiçbir arkadaşın henüz bu mapte bir skora sahip değil!', 'global' => 'Henüz skor yok. Biraz skor yapmaya ne dersin?', 'loading' => 'Skorlar yükleniyor...', - 'unranked' => 'Derecelendirilmemiş beatmap.', + 'unranked' => 'Derecesiz ritimharitası.', ], 'score' => [ 'first' => 'Lider', diff --git a/resources/lang/tr/comments.php b/resources/lang/tr/comments.php index e190a9cfd48..2be9ad83f41 100644 --- a/resources/lang/tr/comments.php +++ b/resources/lang/tr/comments.php @@ -17,7 +17,7 @@ 'title' => 'Yorumlar', 'commentable_name' => [ - 'beatmapset' => 'Beatmap', + 'beatmapset' => 'Ritimharitası', 'build' => 'Değişiklik kayıtları', 'news_post' => 'Haberler', '_deleted' => 'Silinmiş Öge', @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => '', + 'title' => 'yorumlayan :user', ], 'placeholder' => [ diff --git a/resources/lang/tr/community.php b/resources/lang/tr/community.php index d1ca886f62f..699f07270c9 100644 --- a/resources/lang/tr/community.php +++ b/resources/lang/tr/community.php @@ -24,12 +24,12 @@ ], 'featured-artists' => [ 'title' => 'Featured Artist\'ler', - 'description' => 'Sizin desteğinizle, daha çok müzisyen ile iletişim kurabilir ve onların güzel şarkılarını osu! için lisanslayabiliriz!', + 'description' => 'Senin desteğinle, daha çok müzisyen ile iletişim kurabilir ve onların güzel şarkılarını osu! için lisanslayabiliriz!', 'link_text' => 'Güncel listeyi görüntüleyin »', ], 'ads' => [ 'title' => 'osu!\'nun kendi kendine devam etmesini sağlayın', - 'description' => 'Sizin katkılarınız oyunun özgür, reklamlardan ve sponsorlardan tamamen bağımsız kalmasına yardımcı olur.', + 'description' => 'Senin katkıların oyunun özgür, reklamlardan ve sponsorlardan tamamen bağımsız kalmasına yardımcı olur.', ], 'tournaments' => [ 'title' => 'Resmi Turnuvalar', @@ -46,12 +46,12 @@ 'title' => 'Öyle mi? Neler alacağım?!', 'osu_direct' => [ 'title' => 'osu!direct', - 'description' => 'Oyundan çıkmaya gerek kalmadan hızlıca beatmapleri arayıp indirebilirsin.', + 'description' => 'Oyundan çıkmaya gerek kalmadan hızlıca ritimharitalarını arayıp indirebilirsin.', ], 'friend_ranking' => [ 'title' => 'Arkadaş Sıralaması', - 'description' => "Hem oyun içinde hem de websitede, bir beatmapin sıralamasında arkadaşlarınız ile karşılaştırıldığında nasıl olduğunuzu görün.", + 'description' => "Hem oyun içinde hem de websitede, bir ritimharitası sıralamasında arkadaşlarınız ile karşılaştırıldığında nasıl olduğunuzu görün.", ], 'country_ranking' => [ @@ -66,12 +66,12 @@ 'auto_downloads' => [ 'title' => 'Otomatik İndirme', - 'description' => 'Çok oyunculu oyunlardayken, başkalarını seyrederken, veya sohbetteki linklere tıkladığınızda beatmapler otomatik olarak indirilir!', + 'description' => 'Çok oyunculu oyunlardayken, başkalarını seyrederken, veya sohbetteki linklere tıkladığınızda ritimharitaları otomatik olarak indirilir!', ], 'upload_more' => [ 'title' => 'Daha Fazla Yükle', - 'description' => 'Maksimum 10 olmak üzere fazladan (dereceli beatmap başına) beklemede beatmap yuvası.', + 'description' => 'Maksimum 10 olmak üzere fazladan (dereceli ritimharitası başına) beklemede ritimharitası yuvası.', ], 'early_access' => [ @@ -85,8 +85,8 @@ ], 'beatmap_filters' => [ - 'title' => 'Beatmap Filtreleri', - 'description' => 'Beatmap aramalarınızı oynanmış, oynanmamış ya da (eğer varsa) elde edilmiş dereceye göre filtreleme.', + 'title' => 'Ritimharitası Filtreleri', + 'description' => 'Ritimharitası aramalarını oynanmış, oynanmamış ya da elde edilmiş dereceye göre filtreleyebilme.', ], 'yellow_fellow' => [ @@ -101,7 +101,7 @@ 'change_username' => [ 'title' => 'Kullanıcı Adı Değiştirme', - 'description' => 'Tek seferlik isim değiştirme hakkı ilk supporter satın alımınız ile birlikte ücretsiz verilir.', + 'description' => 'Tek seferlik isim değiştirme hakkı ilk supporter satın alımın ile birlikte ücretsiz verilir.', ], 'skinnables' => [ @@ -116,20 +116,20 @@ 'sort_options' => [ 'title' => 'Sıralama Seçenekleri', - 'description' => 'Oyun içinde beatmaplerin ülke/arkadaş/moda göre sıralamalarını görme yeteneği.', + 'description' => 'Oyun içinde ritimharitalarının ülke/arkadaş/moda göre sıralamalarını görme yeteneği.', ], 'more_favourites' => [ 'title' => 'Daha Fazla Favori', - 'description' => 'Favorine ekleyebileceğin maksimum beatmap sayısı :normally → :supporter olarak yükseltilir.', + 'description' => 'Favorine ekleyebileceğin maksimum ritimharitası sayısı :normally → :supporter olarak yükseltilir.', ], 'more_friends' => [ 'title' => 'Daha Fazla Arkadaş', 'description' => 'Ekleyebileceğin maksimum arkadaş sayısı :normally → :supporter olarak yükseltilir.', ], 'more_beatmaps' => [ - 'title' => 'Daha Fazla Beatmap Yükle', - 'description' => 'Ne kadar ranked olmayan beatmaplere sahip olabileceğin, temel bir değere ek olarak, ne kadar ranked beatmap sahip olmuşluğun varsa eklenerek belirlenir (bir sınıra kadar).
Normalde bu her bir ranked map için fazladan 4 tane daha fazla ranked olmayan beatmap hakkına erişirsin (2\'ye kadar). Destekçilik ile bu 1 ranked beatmap için 8 e çıkar (12\'ye kadar).
', + 'title' => 'Daha Fazla Ritimharitası Yükle', + 'description' => 'Aynı anda kaç tane bekleyen ritimharitasına sahip olabileceğiniz, temel değer artı halihazırda sahip olduğunuz her dereceli ritimharitası için ek bir bonusla hesaplanır (bir limite kadar).

Normalde bu, dereceli ritimharitası başına :base artı :bonus şeklindedir. (:bonus_max kadar). osu!supporter ile bu, dereceli ritimharitası başına :supporter_base artı :supporter_bonus olur. (:supporter_bonus_max kadar).', ], 'friend_filtering' => [ 'title' => 'Arkadaş Sıralamaları', diff --git a/resources/lang/tr/contest.php b/resources/lang/tr/contest.php index f26307a570d..3b74820c968 100644 --- a/resources/lang/tr/contest.php +++ b/resources/lang/tr/contest.php @@ -19,7 +19,7 @@ 'show_voted_only' => 'Oy verilenleri göster', 'best_of' => [ - 'none_played' => "Bu yarışma için geçerli olan hiçbir beatmapi oynamamışsınız!", + 'none_played' => "Bu yarışma için geçerli olan hiçbir ritimharitasını oynamamışsınız!", ], 'button' => [ @@ -34,7 +34,7 @@ 'requirement' => [ 'playlist_beatmapsets' => [ - 'incomplete_play' => 'Oylama yapabilmek için belirli playlistlerdeki bütün haritaları oynamanız gerekmektedir', + 'incomplete_play' => 'Oylama yapabilmen için belirli oynatma listelerindeki bütün ritimharitalarını oynaman gerekiyor', ], ], ], diff --git a/resources/lang/tr/errors.php b/resources/lang/tr/errors.php index 87ca4f94556..4fbd207772b 100644 --- a/resources/lang/tr/errors.php +++ b/resources/lang/tr/errors.php @@ -23,7 +23,7 @@ ], 'beatmaps' => [ 'invalid_mode' => 'Geçersiz mod seçildi.', - 'standard_converts_only' => 'Bu beatmap zorluğunda seçilen mod\'da şuanda skor mevcut değil.', + 'standard_converts_only' => 'Bu ritimharitası zorluğunda seçilen modda şuanda skor mevcut değil.', ], 'checkout' => [ 'generic' => 'Checkout\'unuzu hazırlarken bir hata oluştu.', diff --git a/resources/lang/tr/events.php b/resources/lang/tr/events.php index 91e6b30e042..4bf819f7713 100644 --- a/resources/lang/tr/events.php +++ b/resources/lang/tr/events.php @@ -9,11 +9,11 @@ 'beatmapset_approve' => ':user tarafından yapılan :beatmapset :approval!', 'beatmapset_delete' => ':beatmapset silindi.', 'beatmapset_revive' => ':beatmapset :user tarafından ebedi uykusundan uyandırıldı.', - 'beatmapset_update' => ':user ":beatmapset" beatmapini güncelledi', - 'beatmapset_upload' => ':user yeni bir beatmap oluşturdu ":beatmapset"', + 'beatmapset_update' => ':user ":beatmapset" ritimharitasını güncelledi', + 'beatmapset_upload' => ':user yeni bir ritimharitası oluşturdu ":beatmapset"', 'empty' => "Bu kullanıcı son zamanlarda kayda değer bir şey yapmamış!", - 'rank' => ':user :beatmap (:mode) beatmapinde #:rank sıralamaya ulaştı', - 'rank_lost' => ':user :beatmap (:mode) beatmapinde birinciliği kaybetti', + 'rank' => ':user, :beatmap (:mode) ritimharitasında #:rank sıralamaya ulaştı', + 'rank_lost' => ':user :beatmap (:mode) ritimharitasında birinciliği kaybetti', 'user_support_again' => ':user bir kez daha osu!\'yu desteklemeyi seçti - cömertliğinden dolayı teşekkürler!', 'user_support_first' => ':user osu! supporter satın aldı - cömertliğinden dolayı teşekkür ederiz!', 'user_support_gift' => ':user osu!supporter hediyesi aldı!', diff --git a/resources/lang/tr/follows.php b/resources/lang/tr/follows.php index 3bd83c88978..f6820ce8b1c 100644 --- a/resources/lang/tr/follows.php +++ b/resources/lang/tr/follows.php @@ -28,11 +28,11 @@ 'followers' => 'mapping aboneleri', 'page_title' => 'mapper izleme listesi', 'title' => 'mapper', - 'to_0' => 'bu kullanıcı yeni bir beatmap yüklediğinde bana bildirmeyi bırak', - 'to_1' => 'bu kullanıcı yeni bir beatmap yüklediğinde bana bildir', + 'to_0' => 'bu kullanıcı yeni bir ritimharitası yüklediğinde bana bildirmeyi bırak', + 'to_1' => 'bu kullanıcı yeni bir ritimharitası yüklediğinde bana bildir', ], 'modding' => [ - 'title' => 'beatmap tartışması', + 'title' => 'ritimharitası tartışması', ], ]; diff --git a/resources/lang/tr/home.php b/resources/lang/tr/home.php index 2d90d7ac66c..c713dd54b38 100644 --- a/resources/lang/tr/home.php +++ b/resources/lang/tr/home.php @@ -27,10 +27,10 @@ 'title' => 'Ara', 'beatmapset' => [ - 'login_required' => 'Beatmapleri aramak için giriş yapın', - 'more' => ':count tane daha beatmap arama sonucu', - 'more_simple' => 'Daha fazla beatmap arama sonucu gör', - 'title' => 'Beatmapler', + 'login_required' => 'Ritimharitalarını aramak için giriş yapın', + 'more' => ':count tane daha ritimharitası arama sonucu', + 'more_simple' => 'Daha fazla ritimharitası arama sonucu gör', + 'title' => 'Ritimharitaları', ], 'forum_post' => [ @@ -51,7 +51,7 @@ 'mode' => [ 'all' => 'hepsi', - 'beatmapset' => 'beatmap', + 'beatmapset' => 'ritimharitası', 'forum_post' => 'forum', 'user' => 'oyuncu', 'wiki_page' => 'wiki', @@ -111,9 +111,9 @@ 'description' => 'yükleyiciyi indirmek için yukarıdaki düğmeye tıklayın, sonra çalıştırın!', ], 'beatmaps' => [ - 'title' => 'beatmap edinin', + 'title' => 'ritimharitaları edinin', 'description' => [ - '_' => 'Kullanıcılar tarafından oluşturulmuş engin beatmap kütüphanesine :browse ve oynamaya başla!', + '_' => 'Kullanıcılar tarafından oluşturulmuş zengin ritimharitası kütüphanesine:browse göz at ve oynamaya başla!', 'browse' => 'göz at', ], ], @@ -134,8 +134,8 @@ ], ], 'beatmaps' => [ - 'new' => 'Yeni Dereceli Beatmapler', - 'popular' => 'Popüler Beatmapler', + 'new' => 'Yeni Dereceli Ritimharitaları', + 'popular' => 'Popüler Ritimharitaları', 'by_user' => ':user tarafından', ], 'buttons' => [ diff --git a/resources/lang/tr/layout.php b/resources/lang/tr/layout.php index ff3be9ac7d1..2b92d57e1df 100644 --- a/resources/lang/tr/layout.php +++ b/resources/lang/tr/layout.php @@ -14,8 +14,8 @@ 'header' => [ 'admin' => [ - 'beatmapset' => 'beatmap seti', - 'beatmapset_covers' => 'beatmap seti kapakları', + 'beatmapset' => 'ritimharitası seti', + 'beatmapset_covers' => 'ritimharitası seti kapakları', 'contest' => 'yarışma', 'contests' => 'yarışmalar', 'root' => 'konsol', @@ -67,7 +67,7 @@ 'menu' => [ 'beatmaps' => [ - '_' => 'beatmapler', + '_' => 'ritimharitaları', ], 'community' => [ '_' => 'topluluk', @@ -98,7 +98,7 @@ '_' => 'Genel', 'home' => 'Anasayfa', 'changelog-index' => 'Değişiklikler', - 'beatmaps' => 'Beatmap Kataloğu', + 'beatmaps' => 'Ritimharitası Kataloğu', 'download' => 'osu!\'yu indir!', ], 'help' => [ diff --git a/resources/lang/tr/mail.php b/resources/lang/tr/mail.php index cf0931b59ef..dc03bc7ce95 100644 --- a/resources/lang/tr/mail.php +++ b/resources/lang/tr/mail.php @@ -5,9 +5,9 @@ return [ 'beatmapset_update_notice' => [ - 'new' => 'Sadece sana son girdiğinden beri ":title" beatmap\'inde yeni bir güncelleme olduğunu bildiriyoruz.', - 'subject' => '":title" beatmapi için yeni bir güncelleme', - 'unwatch' => 'Artık bu beatmap\'i izlemek istemiyorsan, yukarıdaki sayfada veya modlama izleme listesi sayfasında bulunan "İzlemeyi Bırak" bağlantısına tıklayabilirsin:', + 'new' => 'Sadece sana son girdiğinden beri ":title" ritimharitarında yeni bir güncelleme olduğunu bildiriyoruz.', + 'subject' => '":title" ritimharitasında için yeni bir güncelleme', + 'unwatch' => 'Artık bu ritimharitasını izlemek istemiyorsan, yukarıdaki sayfada veya modlama izleme listesi sayfasında bulunan "İzlemeyi Bırak" bağlantısına tıklayabilirsin:', 'visit' => 'Tartışma sayfasını buradan ziyaret edin:', ], @@ -15,15 +15,15 @@ 'closing' => 'Saygılarımızla,', 'hello' => 'Selam :user,', 'report' => 'Eğer böyle bir değişiklik talep etmediyseniz lütfen DERHAL bu e-postayı yanıtlayın.', - 'ignore' => 'Eğer bunu isteyen siz değilseniz, bu mesajı görmezden gelebilirsiniz.', + 'ignore' => 'Eğer bunu isteyen sen değilsen, bu mesajı görmezden gelebilirsin.', ], 'donation_thanks' => [ 'benefit_more' => 'Zaman içinde daha fazla yeni supporter ayrıcalığı da eklenecek bu arada!', - 'feedback' => "Eğer herhangi bir sorunuz veya geribildiriminiz varsa, bu postaya cevap yazmaktan çekinmeyin; Size en kısa zamanda geri döneceğim!", - 'keep_free' => 'Sizin gibi insanlar sayesinde osu!, oyunu ve topluluğu akıcı bir şekilde hiçbir reklam veya zorla ödeme olmadan oyunu devam ettirebiliyor.', + 'feedback' => "Eğer herhangi bir sorun veya geribildirimin varsa, bu e-postaya cevap yazmaktan çekinmeyin; Sana en kısa zamanda geri döneceğim!", + 'keep_free' => 'Senin gibi insanlar sayesinde osu!, oyunu ve topluluğu akıcı bir şekilde hiçbir reklam veya zorla ödeme olmadan oyunu devam ettirebiliyor.', 'keep_running' => 'Senin katkın osu!\'yu :minutes kadardır ayakta tutuyor. Fazla görünmüyor olabilir ama damlaya damlaya göl olur :).', - 'subject' => 'Teşekkürler, osu! sizi seviyor <3', + 'subject' => 'Teşekkürler, osu! seni seviyor <3', 'translation' => 'Metnin topluluk tarafından sağlanan bilgi amaçlı çevirisi aşağıdaki gibidir:', 'benefit' => [ @@ -66,9 +66,9 @@ 'anonymous_gift_maybe_not' => 'Ama muhtemelen kim olduğunu biliyorsun ;).', 'duration' => 'Onun sayesinde, sonraki :duration boyunca osu!direct\'e ve diğer osu!supporter ayrıcalıklarına sahip olacaksın.', 'features' => 'Bu avantajlar hakkında daha fazla detaylı bilgiye buradan ulaşabilirsiniz:', - 'gifted' => 'Birisi size az önce bir osu!supporter etiketi hediye etti!', - 'gift_message' => 'Bu etiketi hediye eden kişi size bir mesaj bıraktı:', - 'subject' => 'Size bir osu! Destekçisi etiketi verildi!', + 'gifted' => 'Birisi sana az önce bir osu!supporter etiketi hediye etti!', + 'gift_message' => 'Bu etiketi hediye eden kişi sana bir mesaj bıraktı:', + 'subject' => 'Sana bir osu!supporter etiketi verildi!', ], 'user_email_updated' => [ @@ -100,7 +100,7 @@ 'code' => 'Doğrulama kodun:', 'code_hint' => 'Kodu boşluk bırakarak ya da bırakmadan girebilirsiniz.', 'link' => 'Alternatif olarak, doğrulamayı bitirmek için bu bağlantıya da gidebilirsin:', - 'report' => 'Eğer siz böyle bir istemde bulunmadıysanız, hesabınız tehlikede olabileceğinden lütfen HEMEN YANITLAYIN. ', + 'report' => 'Eğer böyle bir istemde bulunmadıysan, hesabın tehlikede olabilir, lütfen HEMEN YANITLA.', 'subject' => 'osu! hesap doğrulama', 'action_from' => [ diff --git a/resources/lang/tr/matches.php b/resources/lang/tr/matches.php index 5c0119c13f8..655695b5e08 100644 --- a/resources/lang/tr/matches.php +++ b/resources/lang/tr/matches.php @@ -5,7 +5,7 @@ return [ 'match' => [ - 'beatmap-deleted' => 'silinmiş beatmap', + 'beatmap-deleted' => 'silinmiş ritimharitası', 'failed' => 'BAŞARISIZ', 'header' => 'Çok Oyunculu Maçlar', 'in-progress' => '(devam eden maç)', diff --git a/resources/lang/tr/model_validation.php b/resources/lang/tr/model_validation.php index 4937eedeb75..d7b1909853f 100644 --- a/resources/lang/tr/model_validation.php +++ b/resources/lang/tr/model_validation.php @@ -12,11 +12,11 @@ 'wrong_confirmation' => 'Doğrulama eşleşmiyor.', 'beatmapset_discussion' => [ - 'beatmap_missing' => 'Zaman damgası belirtildi, ancak beatmap eksik.', - 'beatmapset_no_hype' => "Beatmap gazlanamaz.", + 'beatmap_missing' => 'Zaman damgası belirtildi, ancak ritimharitası eksik.', + 'beatmapset_no_hype' => "Ritimharitası gazlanamaz.", 'hype_requires_null_beatmap' => 'Gaz, Genel (tüm zorluklar) sekmesinde verilmelidir.', 'invalid_beatmap_id' => 'Yanlış zorluk belirtildi.', - 'invalid_beatmapset_id' => 'Yanlış beatmap belirtildi.', + 'invalid_beatmapset_id' => 'Yanlış ritimharitası belirtildi.', 'locked' => 'Tartışma kilitli.', 'attributes' => [ @@ -25,16 +25,16 @@ ], 'hype' => [ - 'discussion_locked' => "Bu beatmap şu anda tartışmaya kapalıdır ve gazlanamaz", + 'discussion_locked' => "Bu ritimharitası şu anda tartışmaya kapalıdır ve gazlanamaz", 'guest' => 'Gazlamak giriş yapmalısın.', - 'hyped' => 'Bu beatmapi çoktan gazladın.', + 'hyped' => 'Bu ritimharitasını çoktan gazladın.', 'limit_exceeded' => 'Bütün gazını kullandın.', - 'not_hypeable' => 'Bu beatmap gazlanamaz', - 'owner' => 'Kendi beatmapini gazlayamazsın.', + 'not_hypeable' => 'Bu ritimharitası gazlanamaz', + 'owner' => 'Kendi ritimharitanı gazlayamazsın.', ], 'timestamp' => [ - 'exceeds_beatmapset_length' => 'Belirtilen zaman damgası beatmap\'in uzunluğunu aşmakta.', + 'exceeds_beatmapset_length' => 'Belirtilen zaman damgası ritimharitasının uzunluğunu aşmakta.', 'negative' => "Zaman damgası negatif olamaz.", ], ], @@ -72,8 +72,8 @@ ], 'post' => [ - 'beatmapset_post_no_delete' => 'Beatmap metaveri gönderisinin silinmesi yasaktır.', - 'beatmapset_post_no_edit' => 'Beatmap metaveri gönderisini düzenlemek yasaktır.', + 'beatmapset_post_no_delete' => 'Ritimharitası metaveri gönderisinin silinmesi yasaktır.', + 'beatmapset_post_no_edit' => 'Ritimharitası metaveri gönderisini düzenlemek yasaktır.', 'first_post_no_delete' => 'Başlangıç gönderisi silinemez', 'missing_topic' => 'Gönderinin konusu eksik', 'only_quote' => 'Cevabınız sadece bir alıntı içeriyor.', @@ -174,7 +174,7 @@ ], 'user_report' => [ - 'no_ranked_beatmapset' => 'Dereceli beatmapler bildirilemez', + 'no_ranked_beatmapset' => 'Dereceli ritimharitaları bildirilemez', 'not_in_channel' => 'Bu kanalda değilsiniz.', 'reason_not_valid' => ':reason sebebi bu rapor türü için geçerli değil.', 'self' => "Kendinizi raporlayamazsınız!", diff --git a/resources/lang/tr/notifications.php b/resources/lang/tr/notifications.php index 70aa6e527af..a3cb80cbbee 100644 --- a/resources/lang/tr/notifications.php +++ b/resources/lang/tr/notifications.php @@ -15,7 +15,7 @@ 'action_type' => [ '_' => 'hepsi', - 'beatmapset' => 'haritalar', + 'beatmapset' => 'ritimharitası', 'build' => 'sürümler', 'channel' => 'sohbet', 'forum_topic' => 'forum', @@ -26,7 +26,7 @@ 'filters' => [ '_' => 'hepsi', 'user' => 'profil', - 'beatmapset' => 'beatmapler', + 'beatmapset' => 'ritimharitaları', 'forum_topic' => 'forum', 'news_post' => 'gelişmeler', 'build' => 'sürümler', @@ -35,17 +35,17 @@ 'item' => [ 'beatmapset' => [ - '_' => 'Beatmap', + '_' => 'Ritimharitası', 'beatmap_owner_change' => [ - '_' => 'Konuk zorluk', - 'beatmap_owner_change' => 'Artık ":title" beatmapindeki ":beatmap" zorluğunun sahibisiniz', + '_' => 'Konuk zorluğu', + 'beatmap_owner_change' => 'Artık ":title" ritimharitasındaki ":beatmap" zorluğunun sahibisiniz', 'beatmap_owner_change_compact' => 'Artık ":beatmap" zorluğunun sahibisiniz', ], 'beatmapset_discussion' => [ - '_' => 'Beatmap tartışması', - 'beatmapset_discussion_lock' => '":title" setinin tartışması kilitlendi', + '_' => 'Ritimharitası tartışması', + 'beatmapset_discussion_lock' => '":title" tartışması kilitlendi', 'beatmapset_discussion_lock_compact' => 'Tartışma kilitlenmiş', 'beatmapset_discussion_post_new' => '":title" setinde :username tarafından yeni bir gönderi mevcut: ":content"', 'beatmapset_discussion_post_new_empty' => '":title" setinde :username tarafından yeni gönderi', @@ -57,14 +57,14 @@ 'beatmapset_discussion_unlock_compact' => 'Tartışmanın kilidi kaldırılmış', 'review_count' => [ - 'praises' => '', - 'problems' => '', - 'suggestions' => '', + 'praises' => ':count_delimited övgü|:count_delimited övgüler', + 'problems' => ':count_delimited sorun|:count_delimited sorunlar', + 'suggestions' => ':count_delimited öneri|:count_delimited öneriler', ], ], 'beatmapset_problem' => [ - '_' => 'Nitelikli Beatmap sorunu', + '_' => 'Nitelikli Ritimharitası sorunu', 'beatmapset_discussion_qualified_problem' => ':username tarafından bildirildi ":title": ":content"', 'beatmapset_discussion_qualified_problem_empty' => ':username tarafından bildirildi ":title"', 'beatmapset_discussion_qualified_problem_compact' => ':username tarafından rapor edildi: ":content"', @@ -72,9 +72,9 @@ ], 'beatmapset_state' => [ - '_' => 'Beatmap durumu değişti', + '_' => 'Ritimharitası durumu değişti', 'beatmapset_disqualify' => '":title" diskalifiye edildi', - 'beatmapset_disqualify_compact' => 'Beatmap diskalifiye edildi', + 'beatmapset_disqualify_compact' => 'Ritimharitası diskalifiye edildi', 'beatmapset_love' => '":title" sevilenlere yükseltildi', 'beatmapset_love_compact' => 'Beatmap sevilenlere yükseltildi', 'beatmapset_nominate' => '":title" aday gösterildi', @@ -82,9 +82,9 @@ 'beatmapset_qualify' => '":title" yeterli aday gösterimi aldı ve derecelendirme sırasına girdi', 'beatmapset_qualify_compact' => 'Beatmap derecelendirme sırasına girdi', 'beatmapset_rank' => '":title" dereceli oldu', - 'beatmapset_rank_compact' => 'Beatmap dereceli oldu', + 'beatmapset_rank_compact' => 'Ritimharitası dereceli oldu', 'beatmapset_remove_from_loved' => '":title" Sevilenlerden çıkarıldı', - 'beatmapset_remove_from_loved_compact' => 'Beatmap Sevilenlerden çıkarıldı', + 'beatmapset_remove_from_loved_compact' => 'Ritimharitası Sevilenler\'den çıkarıldı', 'beatmapset_reset_nominations' => '":title" setinin adaylığı sıfırlandı', 'beatmapset_reset_nominations_compact' => 'Adaylık sıfırlandı', ], @@ -161,14 +161,14 @@ 'user' => [ 'user_beatmapset_new' => [ - '_' => 'Yeni beatmap', + '_' => 'Yeni ritimharitası', - 'user_beatmapset_new' => ':username tarafından yeni beatmap ":title"', - 'user_beatmapset_new_compact' => 'Yeni beatmap ":title"', - 'user_beatmapset_new_group' => ' :username tarafından yapılmış yeni beatmapler', + 'user_beatmapset_new' => ':username tarafından yeni ritimharitası ":title"', + 'user_beatmapset_new_compact' => 'Yeni ritimharitası ":title"', + 'user_beatmapset_new_group' => ' :username tarafından yapılmış yeni ritimharitaları', - 'user_beatmapset_revive' => '":title" adlı beatmap :username tarafından hayata geri döndürüldü', - 'user_beatmapset_revive_compact' => '":title" adlı beatmap hayata geri döndürüldü', + 'user_beatmapset_revive' => '":title" adlı ritimharitası :username tarafından hayata geri döndürüldü', + 'user_beatmapset_revive_compact' => '":title" adlı ritimharitası hayata geri döndürüldü', ], ], @@ -187,7 +187,7 @@ 'mail' => [ 'beatmapset' => [ 'beatmap_owner_change' => [ - 'beatmap_owner_change' => 'Artık ":title" beatmapinin bir konuğusunuz', + 'beatmap_owner_change' => 'Artık ":title" ritimharitasının bir konuğusunuz', ], 'beatmapset_discussion' => [ @@ -211,7 +211,7 @@ ], 'comment' => [ - 'comment_new' => '":title" beatmapinde yeni yorumlar mevcut', + 'comment_new' => '":title" ritimharitasında yeni yorumlar mevcut', ], ], @@ -250,8 +250,8 @@ ], 'user_beatmapset_new' => [ - 'user_beatmapset_new' => ':username yeni beatmapler yaptı', - 'user_beatmapset_revive' => ':username beatmap\'leri hayata geri döndürdü', + 'user_beatmapset_new' => ':username yeni ritimharitaları yaptı', + 'user_beatmapset_revive' => ':username ritimharitalarını hayata geri döndürdü', ], ], ], diff --git a/resources/lang/tr/page_title.php b/resources/lang/tr/page_title.php index be80aa564c9..a47a2a48a80 100644 --- a/resources/lang/tr/page_title.php +++ b/resources/lang/tr/page_title.php @@ -35,24 +35,24 @@ '_' => 'featured artist\'ler', ], 'beatmap_discussion_posts_controller' => [ - '_' => 'beatmap tartışma gönderileri', + '_' => 'ritimharitası tartışma gönderileri', ], 'beatmap_discussions_controller' => [ - '_' => 'beatmap tartışmaları', + '_' => 'ritimharitası tartışmaları', ], 'beatmap_packs_controller' => [ - '_' => 'beatmap paketleri', + '_' => 'ritimharitası paketleri', ], 'beatmapset_discussion_votes_controller' => [ - '_' => 'beatmap tartışma oylamaları', + '_' => 'ritimharitası tartışma oylamaları', ], 'beatmapset_events_controller' => [ - '_' => 'beatmap geçmişi', + '_' => 'ritimharitası geçmişi', ], 'beatmapsets_controller' => [ - 'discussion' => 'beatmap tartışma', - 'index' => 'beatmap kataloğu', - 'show' => 'beatmap bilgisi', + 'discussion' => 'ritimharitası tartışması', + 'index' => 'ritimharitası kataloğu', + 'show' => 'ritimharitası bilgisi', ], 'changelog_controller' => [ '_' => 'değişiklik kayıtları', diff --git a/resources/lang/tr/quick_search.php b/resources/lang/tr/quick_search.php index 3d85227b7ac..3d0170b60e8 100644 --- a/resources/lang/tr/quick_search.php +++ b/resources/lang/tr/quick_search.php @@ -5,7 +5,7 @@ return [ 'mode' => [ - 'beatmapset' => 'Beatmap', + 'beatmapset' => 'Ritimharitası', 'forum_post' => 'Forum', 'other' => 'Diğer', 'user' => 'Oyuncu', diff --git a/resources/lang/tr/report.php b/resources/lang/tr/report.php index 58ae6f4366d..2c308af31b3 100644 --- a/resources/lang/tr/report.php +++ b/resources/lang/tr/report.php @@ -6,7 +6,7 @@ return [ 'beatmapset' => [ 'button' => 'Bildir', - 'title' => ':username kullanıcısının beatmapi bildirilsin mi?', + 'title' => ':username kullanıcısının ritimharitası bildirilsin mi?', ], 'beatmapset_discussion_post' => [ diff --git a/resources/lang/tr/store.php b/resources/lang/tr/store.php index d0142b9740a..430b8401289 100644 --- a/resources/lang/tr/store.php +++ b/resources/lang/tr/store.php @@ -49,15 +49,15 @@ ], 'discount' => '%:percent kazanın', - 'free' => '', + 'free' => 'ücretsiz!', 'invoice' => [ 'contact' => 'İletişim:', 'date' => 'Tarih:', 'echeck_delay' => 'Ödemenizin bir eCheck olması nedeniyle, ödemenizin PayPal\'dan temizlenmesi için 10 ekstra günü göz önüne alın!', 'hide_from_activity' => 'Bu siparişteki osu!supporter etiketleri yakın zamandaki etkinliklerinizde gösterilmez.', - 'sent_via' => '', - 'shipping_to' => '', + 'sent_via' => 'Üzerinden gönderildi:', + 'shipping_to' => 'Teslimat adresi:', 'title' => 'Fatura', 'title_compact' => 'fatura', @@ -65,21 +65,21 @@ 'cancelled' => [ 'title' => 'Siparişiniz iptal edildi', 'line_1' => [ - '_' => "", - 'link_text' => '', + '_' => "İptal talebinde bulunmadıysanız lütfen sipariş numaranızı (#:order_number) belirterek iletişime geçin :link.", + 'link_text' => 'osu!store yardım merkezi', ], ], 'delivered' => [ 'title' => 'Siparişiniz teslim edildi! İyi günlerde kullanmanız dileğiyle!', 'line_1' => [ '_' => 'Satın alımınızla ilgili bir problem yaşıyorsanız,lütfen :link ile görüşün.', - 'link_text' => '', + 'link_text' => 'osu!store yardım merkezi', ], ], 'prepared' => [ 'title' => 'Siparişiniz hazılrlanıyor!', - 'line_1' => '', - 'line_2' => '', + 'line_1' => 'Lütfen paketinizin kargoya verilmesi için biraz daha bekleyin. Sipariş işlenip gönderildikten sonra takip bilgileri burada görünecektir. Bu süreç, ne kadar meşgul olduğumuza bağlı olarak 5 güne kadar sürebilir (genellikle daha az!).', + 'line_2' => 'Tüm siparişleri, ağırlık ve değere bağlı olarak çeşitli nakliye hizmetleri kullanarak Japonya\'dan gönderiyoruz. Siparişi gönderdikten sonra bu alan ayrıntılarla güncellenecektir.', ], 'processing' => [ 'title' => 'Ödemeniz henüz onaylanmadı!', @@ -91,9 +91,9 @@ ], 'shipped' => [ 'title' => 'Siparişiniz kargoya verildi!', - 'tracking_details' => '', + 'tracking_details' => 'Takip ayrıntıları şöyle:', 'no_tracking_details' => [ - '_' => "", + '_' => "Paketinizi uçak kargosu yoluyla gönderdiğimiz için takip ayrıntılarına sahip değiliz, ancak paketinizi 1-3 hafta içinde almayı bekleyebilirsin. Avrupa'da bazen gümrükler bizim kontrolümüz dışında siparişi geciktirebilir. Herhangi bir endişen varsa lütfen sana gelen sipariş onay e-postasını yanıtla :link.", 'link_text' => 'bize bir e-mail yollayın', ], ], @@ -108,17 +108,17 @@ 'no_orders' => 'Görüntülenecek sipariş yok.', 'paid_on' => 'Sipariş verme tarihi :date', 'resume' => 'Sepete Dön', - 'shipping_and_handling' => '', + 'shipping_and_handling' => 'Nakliye ve Taşıma', 'shopify_expired' => 'Bu sipariş için ödeme bağlantısının süresi doldu.', 'subtotal' => 'Ara toplam', 'total' => 'Toplam', 'details' => [ - 'order_number' => '', - 'payment_terms' => '', + 'order_number' => 'Sipariş #', + 'payment_terms' => 'Ödeme koşulları', 'salesperson' => 'Satış Temsilcisi', 'shipping_method' => 'Gönderim Yolu', - 'shipping_terms' => '', + 'shipping_terms' => 'Nakliye Koşulları', 'title' => 'Sipariş Detayları', ], @@ -157,7 +157,7 @@ 'thanks' => [ 'title' => 'Siparişiniz için teşekkür ederiz!', 'line_1' => [ - '_' => '', + '_' => 'Yakında bir onay e-postası alacaksın. Soruların varsa lütfen :link!', 'link_text' => 'bizimle iletişime geçin', ], ], @@ -193,7 +193,7 @@ 'username_change' => [ 'check' => 'Geçerliliğini kontrol etmek için bir kullanıcı adı girin!', 'checking' => ':username geçerliliği kontrol ediliyor...', - 'placeholder' => '', + 'placeholder' => 'İstenen Kullanıcı Adı', 'label' => 'Yeni kullanıcı adı', 'current' => 'Şu anki kullanıcı adınız ":username".', diff --git a/resources/lang/tr/users.php b/resources/lang/tr/users.php index 5292bfb1fdd..4700955a881 100644 --- a/resources/lang/tr/users.php +++ b/resources/lang/tr/users.php @@ -84,7 +84,7 @@ 'opening' => 'Hesabını dondurmaya sebebiyet verebilecek birtakım sebepler var:', 'tos' => [ - '_' => 'Siz, :community_rules ya da :tos kurallarından bir veya daha fazlasını ihlal ettiniz.', + '_' => ':community_rules ya da :tos kurallarından bir veya daha fazlasını ihlal ettin.', 'community_rules' => 'topluluk kuralları', 'tos' => 'hizmet kullanım şartları', ], @@ -109,7 +109,7 @@ 'failed' => 'Hatalı giriş', 'forgot' => 'Şifrenizi mi unuttunuz?', 'info' => 'Devam etmek için lütfen giriş yapınız', - 'invalid_captcha' => 'Captcha geçersiz, sayfayı yenileyip tekrar deneyin.', + 'invalid_captcha' => 'Çok fazla hatalı giriş denemesi, CAPTCHA\'yı tamamlayıp tekrar dene. (CAPTCHA gözükmüyorsa sayfayı yenile)', 'locked_ip' => 'IP adresiniz kilitli. Lütfen birkaç dakika bekleyin.', 'password' => 'Şifre', 'register' => "osu! hesabınız yok mu? Yeni bir tane oluşturun", @@ -124,13 +124,13 @@ ], 'ogp' => [ - 'modding_description' => '', - 'modding_description_empty' => '', + 'modding_description' => 'Ritimharitaları: :counts', + 'modding_description_empty' => 'Kullanıcının herhangi bir ritimharitası yok...', 'description' => [ - '_' => '', - 'country' => '', - 'global' => '', + '_' => 'Derece (:ruleset): :global | :country', + 'country' => 'Ülke :rank', + 'global' => 'Küresel :rank', ], ], @@ -170,7 +170,7 @@ ], 'restricted_banner' => [ 'title' => 'Hesabınız kısıtlandı!', - 'message' => 'Kısıtlanmışken, diğer oyuncularla etkileşime geçemeyecek ve skorlarınızı sadece siz görebileceksiniz. Bu genellikle otomatik olan bir işlemin sonucudur ve 24 saat içerisinde kalkabilir. Kısıtlamanızın açılması için başvurmak istiyorsanız, lütfen destek hattıyla iletişime geçin.', + 'message' => 'Kısıtlanmışken, diğer oyuncularla etkileşime geçemezsin ve skorların sadece sana gözükür. Bu genellikle otomatik bir sürecin sonucudur ve genellikle 24 saat içinde kaldırılır. :link', 'message_link' => 'Daha fazla bilgi için bu sayfaya göz atın.', ], 'show' => [ @@ -235,25 +235,25 @@ 'title' => 'Beatmapler', 'favourite' => [ - 'title' => 'Favori Beatmapler', + 'title' => 'Favori Ritimharitaları', ], 'graveyard' => [ - 'title' => 'Mezarlıktaki Beatmapler', + 'title' => 'Mezarlıktaki Ritimharitaları', ], 'guest' => [ - 'title' => 'Konuk Olarak Katıldığı Beatmapler', + 'title' => 'Konuk Katılımı Ritimharitaları', ], 'loved' => [ - 'title' => 'Sevilen Beatmapler', + 'title' => 'Sevilen Ritimharitaları', ], 'nominated' => [ - 'title' => 'Aday Gösterilen Dereceli Beatmapler', + 'title' => 'Aday Gösterilen Dereceli Ritimharitaları', ], 'pending' => [ - 'title' => 'Beklemedeki Beatmapler', + 'title' => 'Beklemedeki Ritimharitaları', ], 'ranked' => [ - 'title' => 'Dereceli & Onaylı Beatmapler', + 'title' => 'Dereceli Ritimharitaları', ], ], 'discussions' => [ @@ -331,7 +331,7 @@ ], 'total_info' => [ - '_' => 'Kullanıcının beatmap modlamaya yaptığı katkının miktarına bağlıdır. Daha fazla bilgi için :link bakınız.', + '_' => 'Kullanıcının ritimharitası moderasyonuna yaptığı katkının miktarına bağlıdır. Daha fazla bilgi için :link bakınız.', 'link' => 'bu sayfaya', ], ], @@ -462,10 +462,10 @@ 'total_hits' => 'Toplam Vuruş', 'total_score' => 'Toplam Skor', // modding stats - 'graveyard_beatmapset_count' => 'Mezarlıktaki Beatmapler', - 'loved_beatmapset_count' => 'Sevilen Beatmapler', - 'pending_beatmapset_count' => 'Onay Bekleyen Beatmapler', - 'ranked_beatmapset_count' => 'Dereceli ve Onaylanmış Beatmapler', + 'graveyard_beatmapset_count' => 'Mezarlıktaki Ritimharitaları', + 'loved_beatmapset_count' => 'Sevilen Ritimharitaları', + 'pending_beatmapset_count' => 'Onay Bekleyen Ritimharitaları', + 'ranked_beatmapset_count' => 'Dereceli Ritimharitaları', ], ], diff --git a/resources/lang/zh-tw/accounts.php b/resources/lang/zh-tw/accounts.php index c386e756daf..d38e6072563 100644 --- a/resources/lang/zh-tw/accounts.php +++ b/resources/lang/zh-tw/accounts.php @@ -147,7 +147,7 @@ ], 'verification_completed' => [ - 'text' => '您可以關閉此選項/視窗', + 'text' => '您現在可以關閉此分頁/視窗', 'title' => '驗證已經完成', ], diff --git a/resources/lang/zh-tw/store.php b/resources/lang/zh-tw/store.php index 0298c6cef8d..c7488a1dcc3 100644 --- a/resources/lang/zh-tw/store.php +++ b/resources/lang/zh-tw/store.php @@ -90,8 +90,8 @@ ], ], 'shipped' => [ - 'title' => '', - 'tracking_details' => '', + 'title' => '您的訂單已出貨!', + 'tracking_details' => '物流追蹤詳情如下:', 'no_tracking_details' => [ '_' => "", 'link_text' => '向我們發送電子郵件', @@ -119,7 +119,7 @@ 'salesperson' => '', 'shipping_method' => '運送方式', 'shipping_terms' => '', - 'title' => '', + 'title' => '訂單詳情:', ], 'item' => [ diff --git a/resources/lang/zh-tw/users.php b/resources/lang/zh-tw/users.php index eef78b6adeb..e863b7c9f33 100644 --- a/resources/lang/zh-tw/users.php +++ b/resources/lang/zh-tw/users.php @@ -124,7 +124,7 @@ ], 'ogp' => [ - 'modding_description' => '', + 'modding_description' => '圖譜: :counts', 'modding_description_empty' => '', 'description' => [ From fa433d6ecc644b6926cd6d01563627efb764b456 Mon Sep 17 00:00:00 2001 From: nanaya Date: Sun, 24 Dec 2023 01:06:31 +0900 Subject: [PATCH 096/102] Fix old file url call --- app/Jobs/Notifications/ForumTopicReply.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/Notifications/ForumTopicReply.php b/app/Jobs/Notifications/ForumTopicReply.php index 237ec3fc6d0..4fbbb549572 100644 --- a/app/Jobs/Notifications/ForumTopicReply.php +++ b/app/Jobs/Notifications/ForumTopicReply.php @@ -50,7 +50,7 @@ public function getDetails(): array return [ 'title' => $this->post->topic->topic_title, 'post_id' => $this->post->getKey(), - 'cover_url' => optional($this->post->topic->cover)->fileUrl(), + 'cover_url' => $this->post->topic->cover?->file()->url(), ]; } From 081776dc8d7f25ad20331d65434871b9814454a5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Dec 2023 04:48:14 +0900 Subject: [PATCH 097/102] Update translations from crowdin --- resources/lang/pl/store.php | 4 +- resources/lang/ru/authorization.php | 2 +- resources/lang/ru/beatmap_discussions.php | 2 +- resources/lang/ru/beatmaps.php | 4 +- resources/lang/ru/beatmapsets.php | 2 +- resources/lang/ru/comments.php | 2 +- resources/lang/ru/layout.php | 2 +- resources/lang/tr/accounts.php | 24 +++++------ resources/lang/tr/api.php | 8 ++-- resources/lang/tr/artist.php | 2 +- resources/lang/tr/authorization.php | 4 +- resources/lang/tr/beatmap_discussions.php | 6 +-- resources/lang/tr/beatmaps.php | 30 +++++++------- resources/lang/tr/beatmapset_events.php | 6 +-- resources/lang/tr/beatmapset_watches.php | 4 +- resources/lang/tr/beatmapsets.php | 34 +++++++-------- resources/lang/tr/comments.php | 4 +- resources/lang/tr/community.php | 26 ++++++------ resources/lang/tr/contest.php | 4 +- resources/lang/tr/errors.php | 2 +- resources/lang/tr/events.php | 8 ++-- resources/lang/tr/follows.php | 6 +-- resources/lang/tr/home.php | 18 ++++---- resources/lang/tr/layout.php | 8 ++-- resources/lang/tr/mail.php | 22 +++++----- resources/lang/tr/matches.php | 2 +- resources/lang/tr/model_validation.php | 22 +++++----- resources/lang/tr/notifications.php | 50 +++++++++++------------ resources/lang/tr/page_title.php | 16 ++++---- resources/lang/tr/quick_search.php | 2 +- resources/lang/tr/report.php | 2 +- resources/lang/tr/store.php | 32 +++++++-------- resources/lang/tr/users.php | 40 +++++++++--------- 33 files changed, 200 insertions(+), 200 deletions(-) diff --git a/resources/lang/pl/store.php b/resources/lang/pl/store.php index d1a9c486542..5f7553c3e20 100644 --- a/resources/lang/pl/store.php +++ b/resources/lang/pl/store.php @@ -119,7 +119,7 @@ 'salesperson' => '', 'shipping_method' => '', 'shipping_terms' => '', - 'title' => '', + 'title' => 'Szczegóły zamówienia', ], 'item' => [ @@ -151,7 +151,7 @@ 'paid' => 'Opłacone', 'processing' => 'Oczekiwanie na potwierdzenie', 'shipped' => 'W transporcie', - 'title' => '', + 'title' => 'Status zamówienia', ], 'thanks' => [ diff --git a/resources/lang/ru/authorization.php b/resources/lang/ru/authorization.php index fc99a78f93d..3aeedd7e7e6 100644 --- a/resources/lang/ru/authorization.php +++ b/resources/lang/ru/authorization.php @@ -5,7 +5,7 @@ return [ 'play_more' => 'Может, лучше в osu! поиграете?', - 'require_login' => 'Войдите для продолжения.', + 'require_login' => 'Войдите, чтобы оставить своё мнение', 'require_verification' => 'Пожалуйста, подтвердите свой аккаунт.', 'restricted' => "Это нельзя сделать, пока ваши права ограничены.", 'silenced' => "Это сделать нельзя, пока Вы заглушены.", diff --git a/resources/lang/ru/beatmap_discussions.php b/resources/lang/ru/beatmap_discussions.php index c052086466d..135877c0e58 100644 --- a/resources/lang/ru/beatmap_discussions.php +++ b/resources/lang/ru/beatmap_discussions.php @@ -68,7 +68,7 @@ 'reply' => [ 'open' => [ - 'guest' => 'Войдите, чтобы ответить', + 'guest' => 'Войдите в аккаунт, чтобы ответить', 'user' => 'Ответить', ], ], diff --git a/resources/lang/ru/beatmaps.php b/resources/lang/ru/beatmaps.php index beca52dec72..a3aa413c913 100644 --- a/resources/lang/ru/beatmaps.php +++ b/resources/lang/ru/beatmaps.php @@ -26,7 +26,7 @@ 'message_type_select' => 'Выбрать тип комментария', 'reply_notice' => 'Нажмите Enter, чтобы ответить.', 'reply_placeholder' => 'Напишите ответ', - 'require-login' => 'Пожалуйста, войдите в аккаунт, чтобы оставить сообщение или ответить', + 'require-login' => 'Пожалуйста, войдите в аккаунт, чтобы оставить отзыв', 'resolved' => 'Решено', 'restore' => 'восстановить', 'show_deleted' => 'Показать удалённые', @@ -233,7 +233,7 @@ 'listing' => [ 'search' => [ 'prompt' => 'введите ключевые слова...', - 'login_required' => 'Войдите, чтобы искать.', + 'login_required' => 'Войдите в аккаунт, чтобы начать поиск', 'options' => 'Больше настроек поиска', 'supporter_filter' => 'Фильтрация по критерию :filters требует наличия тега osu!supporter', 'not-found' => 'нет результатов', diff --git a/resources/lang/ru/beatmapsets.php b/resources/lang/ru/beatmapsets.php index 68069d9ac2b..8164e5d2056 100644 --- a/resources/lang/ru/beatmapsets.php +++ b/resources/lang/ru/beatmapsets.php @@ -72,7 +72,7 @@ 'details' => [ 'by_artist' => 'от :artist', 'favourite' => 'добавить в избранные', - 'favourite_login' => 'войдите, чтобы добавить эту карту в избранные', + 'favourite_login' => 'войдите в аккаунт, чтобы добавить эту карту в избранные', 'logged-out' => 'вы должны войти, чтобы начать скачивать карты!', 'mapped_by' => 'автор :mapper', 'mapped_by_guest' => 'гостевая сложность от :mapper', diff --git a/resources/lang/ru/comments.php b/resources/lang/ru/comments.php index 65f9ffaf358..cd14005e67d 100644 --- a/resources/lang/ru/comments.php +++ b/resources/lang/ru/comments.php @@ -33,7 +33,7 @@ ], 'guest_button' => [ - 'new' => 'Войдите, чтобы комментировать', + 'new' => 'Войдите, чтобы прокомментировать', 'reply' => 'Войдите, чтобы ответить', ], diff --git a/resources/lang/ru/layout.php b/resources/lang/ru/layout.php index cf0a0458ae9..0062a90a300 100644 --- a/resources/lang/ru/layout.php +++ b/resources/lang/ru/layout.php @@ -174,7 +174,7 @@ 'login' => [ 'forgot' => "Я забыл свои данные", 'password' => 'пароль', - 'title' => 'Войдите, чтобы продолжить', + 'title' => 'Вход', 'username' => 'никнейм', 'error' => [ diff --git a/resources/lang/tr/accounts.php b/resources/lang/tr/accounts.php index a7188444507..e0e2b59d090 100644 --- a/resources/lang/tr/accounts.php +++ b/resources/lang/tr/accounts.php @@ -63,21 +63,21 @@ ], 'github_user' => [ - 'info' => "osu!'nun açık kaynak depolarına katkıda bulunuyorsan GitHub hesabını buraya bağlamak, değişiklik günlüğü girişlerini osu! profilinle ilişkilendirecektir. osu!'ya katkı geçmişi olmayan GitHub hesapları bağlanamaz.", + 'info' => "", 'link' => 'GitHub Hesabını Bağla', 'title' => 'GitHub', 'unlink' => 'GitHub Hesabının bağlantısını Kaldır', 'error' => [ - 'already_linked' => 'Bu GitHub hesabı zaten farklı bir kullanıcıya bağlı.', - 'no_contribution' => 'osu! depolarında herhangi bir katkı geçmişi olmayan GitHub hesabı bağlanamıyor.', - 'unverified_email' => 'Lütfen GitHub\'da e-posta adresini doğrula ve ardından hesabını bağlamayı tekrar dene.', + 'already_linked' => '', + 'no_contribution' => '', + 'unverified_email' => '', ], ], 'notifications' => [ - 'beatmapset_discussion_qualified_problem' => 'doğrulanmış ritimharitalarının belirtilen modlardaki yeni sorunlarının bildirimlerini al', - 'beatmapset_disqualify' => 'belirtilen modların ritimharitaları diskalifiye edildiğinde bildirim al', + 'beatmapset_discussion_qualified_problem' => 'Doğrulanmış beatmapler\'in belirtilen modlardaki yeni sorunlarının bildirimlerini al', + 'beatmapset_disqualify' => 'belirtilen modların beatmapleri diskalifiye edildiğinde bildirim al', 'comment_reply' => 'yorumlarına yapılan yanıtlar için bildirim al', 'title' => 'Bildirimler', 'topic_auto_subscribe' => 'oluşturduğunuz yeni forum başlıklarında bildirimleri otomatik olarak etkinleştir', @@ -85,12 +85,12 @@ 'options' => [ '_' => 'bildirim seçenekleri', 'beatmap_owner_change' => 'konuk zorluk', - 'beatmapset:modding' => 'ritimharitası modlama', + 'beatmapset:modding' => 'beatmap modlama', 'channel_message' => 'özel sohbet mesajları', 'comment_new' => 'yeni yorumlar', 'forum_topic_reply' => 'konu yanıtı', 'mail' => 'posta', - 'mapping' => 'ritimharitası yaratıcısı', + 'mapping' => 'beatmap mapper', 'push' => 'anlık', 'user_achievement_unlock' => 'kullanıcı madalyası açıldı', ], @@ -98,17 +98,17 @@ 'oauth' => [ 'authorized_clients' => 'izin verilen istemciler', - 'own_clients' => 'sana ait istemciler', + 'own_clients' => 'size ait istemciler', 'title' => 'OAuth', ], 'options' => [ - 'beatmapset_show_nsfw' => 'ritimharitalarındaki müstehcen içerikler için uyarıları gizle', - 'beatmapset_title_show_original' => 'ritimharitası metaverisini orijinal dilinde göster', + 'beatmapset_show_nsfw' => 'beatmaplerdeki müstehcen içerikler için uyarıları gizle', + 'beatmapset_title_show_original' => 'beatmap metaverisini orijinal dilinde göster', 'title' => 'Seçenekler', 'beatmapset_download' => [ - '_' => 'varsayılan ritimharitası indirme tipi', + '_' => 'varsayılan beatmap indirme tipi', 'all' => 'eğer varsa video ile beraber', 'direct' => 'osu!direct\'de aç', 'no_video' => 'video olmadan', diff --git a/resources/lang/tr/api.php b/resources/lang/tr/api.php index 041606e4e38..648cde803e9 100644 --- a/resources/lang/tr/api.php +++ b/resources/lang/tr/api.php @@ -17,9 +17,9 @@ 'identify' => 'Kim olduğunuzu ve herkese açık profilinizi görüntüleyebilir.', 'chat' => [ - 'read' => 'Senin adına mesajları oku.', - 'write' => 'Senin adına mesaj gönder.', - 'write_manage' => 'Kanallara senin adına katıl ve ayrıl.', + 'read' => 'Sizin adınıza mesajları okuyun.', + 'write' => 'Sizin adınıza mesaj gönderebilir.', + 'write_manage' => 'Kanallara sizin adınıza katılın ve ayrılın.', ], 'forum' => [ @@ -30,6 +30,6 @@ 'read' => 'Kimi takip ettiğinizi görebilir.', ], - 'public' => 'Herkese açık verileri senin adına oku.', + 'public' => 'Herkese açık verilerinizi sizin adınıza okuyabilir.', ], ]; diff --git a/resources/lang/tr/artist.php b/resources/lang/tr/artist.php index 7eb12a2e854..34fefe33738 100644 --- a/resources/lang/tr/artist.php +++ b/resources/lang/tr/artist.php @@ -22,7 +22,7 @@ ], 'links' => [ - 'beatmaps' => 'osu! Ritimharitaları', + 'beatmaps' => 'osu! beatmapleri', 'osu' => 'osu! profili', 'site' => 'Resmi Website', ], diff --git a/resources/lang/tr/authorization.php b/resources/lang/tr/authorization.php index 27ac4ac9a34..b2b968fa04a 100644 --- a/resources/lang/tr/authorization.php +++ b/resources/lang/tr/authorization.php @@ -27,7 +27,7 @@ ], 'store' => [ - 'mapper_note_wrong_user' => 'Yalnızca ritimharitası sahibi ya da aday gösterici/NAT grup üyesi ritimharitası yaratıcısı notu gönderebilir.', + 'mapper_note_wrong_user' => 'Yalnızca beatmap sahibi ya da aday gösterici/NAT grup üyesi mapper notu gönderebilir.', ], 'vote' => [ @@ -53,7 +53,7 @@ ], 'beatmapset' => [ - 'discussion_locked' => 'Bu ritimharitası, tartışma için kilitlenmiştir.', + 'discussion_locked' => 'Bu harita tartışma için kilitlenmiştir.', 'metadata' => [ 'nominated' => 'Aday gösterilen bir mapin metaverisini değiştiremezsiniz. Hatalı ayarlandığını düşünüyorsanız bir BN ya da NAT üyesiyle iletişime geçiniz.', diff --git a/resources/lang/tr/beatmap_discussions.php b/resources/lang/tr/beatmap_discussions.php index 55492d5f5b2..34f52123997 100644 --- a/resources/lang/tr/beatmap_discussions.php +++ b/resources/lang/tr/beatmap_discussions.php @@ -24,14 +24,14 @@ 'form' => [ '_' => 'Ara', 'deleted' => 'Silinmiş tartışmaları dahil et', - 'mode' => 'Ritimharitası modu', + 'mode' => 'Beatmap modu', 'only_unresolved' => 'Sadece çözülmemiş tartışmaları göster', - 'show_review_embeds' => 'İnceleme gönderilerini göster', + 'show_review_embeds' => '', 'types' => 'Mesaj türü', 'username' => 'Kullanıcı adı', 'beatmapset_status' => [ - '_' => 'Ritimharitası Durumu', + '_' => 'Beatmap Durumu', 'all' => 'Tümü', 'disqualified' => 'Diskalifiye edildi', 'never_qualified' => 'Niteliklendirilmedi', diff --git a/resources/lang/tr/beatmaps.php b/resources/lang/tr/beatmaps.php index 370e795b499..73cab335fcb 100644 --- a/resources/lang/tr/beatmaps.php +++ b/resources/lang/tr/beatmaps.php @@ -21,7 +21,7 @@ 'guest' => ':user kullanıcısının konuk zorluğu', 'kudosu_denied' => 'Kudosu almaktan mahrum bırakıldı.', 'message_placeholder_deleted_beatmap' => 'Bu zorluk seviyesi silindi o yüzden hakkında daha fazla tartışılamaz.', - 'message_placeholder_locked' => 'Bu ritimharitası için tartışma devre dışı bırakıldı.', + 'message_placeholder_locked' => 'Bu beatmap için tartışma devre dışı bırakıldı.', 'message_placeholder_silenced' => "Susturulduğunuzda tartışma gönderisi gönderemezsiniz.", 'message_type_select' => 'Yorum Türünü Seçin', 'reply_notice' => 'Cevaplamak için Enter tuşuna basın.', @@ -153,8 +153,8 @@ 'approved' => 'Bu beatmap :date tarihinde onaylandı!', 'graveyard' => "Bu beatmap :date tarihinden beri güncellenmedi ve büyük ihtimalle yaratıcısı tarafından terk edildi...", 'loved' => 'Bu beatmap :date tarihinde sevilenler kategorisine eklendi!', - 'ranked' => 'Bu ritimharitası :date tarihinde dereceli oldu!', - 'wip' => 'Dikkat: Bu ritimharitası yaratıcısı tarafından yapım aşamasında olarak işaretlendi.', + 'ranked' => 'Bu beatmap :date tarihinde dereceli oldu!', + 'wip' => 'Dikkat: Bu beatmap yaratıcısı tarafından yapım aşamasında olarak işaretlendi.', ], 'votes' => [ @@ -170,11 +170,11 @@ ], 'hype' => [ - 'button' => 'Ritimharitasını Gazla!', + 'button' => 'Beatmapi Gazla!', 'button_done' => 'Çoktan Gazlandı!', 'confirm' => "Emin misiniz? Bu işlem kalan :n adet gaz hakkından birini kullanacak ve geriye alınamayacak.", - 'explanation' => 'Bu ritimharitasını, aday gösterilmesi ve dereceli olması için daha görünür yapmak için gazla!', - 'explanation_guest' => 'Bu ritimharitasının aday gösterilmesi ve dereceli olması için daha görünür yapmak için gazlamak için giriş yap!', + 'explanation' => 'Bu beatmapi aday gösterilmesi ve dereceli olması için daha görünür yapmak için gazla!', + 'explanation_guest' => 'Bu beatmapi aday gösterilmesi ve dereceli olması için daha görünür yapmak için gazlamak için giriş yap!', 'new_time' => "Bir sonraki gaz :new_time tarihinde gelecek.", 'remaining' => ':remaining gazınız kaldı.', 'required_text' => 'Gaz: :current/:required', @@ -187,11 +187,11 @@ ], 'nominations' => [ - 'already_nominated' => 'Bu ritimharitasını zaten aday gösterdiniz.', - 'cannot_nominate' => 'Bu ritimharitası oyun modunu aday gösteremezsiniz.', + 'already_nominated' => 'Bu beatmapi zaten aday gösterdiniz.', + 'cannot_nominate' => 'Bu beatmap oyun modunu aday gösteremezsiniz.', 'delete' => 'Sil', - 'delete_own_confirm' => 'Emin misin? Ritimharitası silinecek ve profiline yönlendirileceksin.', - 'delete_other_confirm' => 'Emin misin? Ritimharitası silinecek ve kullanıcının profiline yönlendirileceksin.', + 'delete_own_confirm' => 'Emin misin? Beatmap silinecek ve profiline yönlendirileceksin.', + 'delete_other_confirm' => 'Emin misin? Beatmap silinecek ve kullanıcının profiline yönlendirileceksin.', 'disqualification_prompt' => 'Diskalifiye sebebi nedir?', 'disqualified_at' => ':time_ago: diskalifiye edildi (:reason).', 'disqualified_no_reason' => 'bir sebep belirtilmedi', @@ -199,7 +199,7 @@ 'incorrect_state' => 'Bu eylemi gerçekleştirirken bir hata oluştu, sayfayı yenilemeyi deneyin.', 'love' => 'Sevilenlere ekle', 'love_choose' => 'Sevilen\'lere eklenecek zorluğu seçin', - 'love_confirm' => 'Bu ritimharitasını seviyor musun?', + 'love_confirm' => 'Bu beatmapi seviyor musun?', 'nominate' => 'Aday Göster', 'nominate_confirm' => 'Beatmap aday gösterilsin mi?', 'nominated_by' => ':users tarafından aday gösterildi', @@ -224,9 +224,9 @@ ], 'reset_confirm' => [ - 'disqualify' => 'Emin misin? Bu, ritimharitasının nitelikli olmasını önleyecek ve aday gösterme sürecini sıfırlayacak.', + 'disqualify' => 'Emin misiniz? Bu, beatmapin nitelikli olmasını önleyecek ve aday gösterme sürecini sıfırlayacak.', 'nomination_reset' => 'Emin misin? Yeni bir sorun bildirmek aday gösterme sürecini sıfırlayacaktır.', - 'problem_warning' => 'Bu ritimharitasındaki sorunu bildireceğinden emin misin? Bu, ritimharitası adaylarını uyaracaktır.', + 'problem_warning' => 'Bu beatmap\'teki sorunu bildireceğinizden emin misiniz? Bu, Beatmap adaylarını uyaracaktır.', ], ], @@ -268,11 +268,11 @@ ], ], 'general' => [ - 'converts' => 'Dönüştürülmüş ritimharitalarını dahil et', + 'converts' => 'Dönüştürülmüş beatmapleri dahil et', 'featured_artists' => 'Featured artist\'ler', 'follows' => 'Abone olunan mapperlar', 'recommended' => 'Önerilen zorluk seviyesi', - 'spotlights' => 'Öne çıkan ritimharitaları', + 'spotlights' => 'Öne çıkan beatmapler', ], 'mode' => [ 'all' => 'Hepsi', diff --git a/resources/lang/tr/beatmapset_events.php b/resources/lang/tr/beatmapset_events.php index 84e96b9044d..7547ac13b85 100644 --- a/resources/lang/tr/beatmapset_events.php +++ b/resources/lang/tr/beatmapset_events.php @@ -8,11 +8,11 @@ 'approve' => 'Onaylı.', 'beatmap_owner_change' => ':beatmap zorluğunun sahibi :new_user kullanıcısı ile değiştirildi.', 'discussion_delete' => 'Moderatör :discussion tartışmasını sildi.', - 'discussion_lock' => 'Bu ritimharitası için tartışma devre dışı bırakıldı. (:text)', + 'discussion_lock' => 'Bu beatmap için tartışma sağlandı', 'discussion_post_delete' => ':discussion tartışmasındaki gönderi Moderatör tarafından silindi.', 'discussion_post_restore' => ':discussion tartışmasındaki gönderi Moderatör tarafından restore edildi.', 'discussion_restore' => ':discussion tartışması moderatör tarafından restore edildi.', - 'discussion_unlock' => 'Bu ritimharitası için tartışma aktif edildi.', + 'discussion_unlock' => 'Bu beatmap için tartışma sağlandı.', 'disqualify' => ':user tarafından diskalifiye edildi. Sebep: :discussion (:text).', 'disqualify_legacy' => ':user tarafından diskalifiye edildi. Sebep: :text.', 'genre_edit' => 'Tür :old dan :new ile değiştirildi.', @@ -31,7 +31,7 @@ 'nomination_reset_received' => ':user tarafından gerçekleştirilen aday gösterme :source_user tarafından sıfırlandı (:text)', 'nomination_reset_received_profile' => 'Adaylık :user tarafından sıfırlandı (:text)', 'offset_edit' => 'Çevrimiçi ofset :old dan :new e değiştirildi.', - 'qualify' => 'Bu ritimharitası gerekli aday gösterilme miktarına ulaştı ve nitelikli oldu.', + 'qualify' => 'Bu beatmap gerekli aday gösterilme miktarına ulaştı ve nitelikli oldu.', 'rank' => 'Dereceli.', 'remove_from_loved' => ':user tarafından Sevilenlerden çıkarıldı (:text)', 'tags_edit' => 'Etiketler ":old" dan ":new" ile değiştirildi.', diff --git a/resources/lang/tr/beatmapset_watches.php b/resources/lang/tr/beatmapset_watches.php index 468ab6e8b95..1428471aa21 100644 --- a/resources/lang/tr/beatmapset_watches.php +++ b/resources/lang/tr/beatmapset_watches.php @@ -9,8 +9,8 @@ 'title_compact' => 'modlama izleme listesi', 'counts' => [ - 'total' => 'İzlenen ritimharitaları', - 'unread' => 'Yeni gelişmelere sahip ritimharitaları', + 'total' => 'İzlenen beatmapler', + 'unread' => 'Yeni gelişmelere sahip beatmapler', ], 'table' => [ diff --git a/resources/lang/tr/beatmapsets.php b/resources/lang/tr/beatmapsets.php index f786200e105..cf2c48ce791 100644 --- a/resources/lang/tr/beatmapsets.php +++ b/resources/lang/tr/beatmapsets.php @@ -12,7 +12,7 @@ ], 'cover' => [ - 'deleted' => 'Silinmiş ritimharitası', + 'deleted' => 'Silinmiş beatmap', ], 'download' => [ @@ -24,12 +24,12 @@ ], 'index' => [ - 'title' => 'Ritimharitası Kataloğu', + 'title' => 'Beatmap Kataloğu', 'guest_title' => 'Beatmapler', ], 'panel' => [ - 'empty' => 'ritimharitası yok', + 'empty' => 'beatmap yok', 'download' => [ 'all' => 'indir', @@ -40,14 +40,14 @@ ], 'nominate' => [ - 'hybrid_requires_modes' => 'Karma bir ritimharitası, adaylık için en az bir oyun modu seçmenizi gerektirir.', + 'hybrid_requires_modes' => 'Karma bir beatmap seti, adaylık için en az bir oyun modu seçmenizi gerektirir.', 'incorrect_mode' => ':mode modunu aday göstermek için izniniz yok.', 'full_bn_required' => 'Bu niteliklendirme aday gösterimini gerçekleştirebilmeniz için asil aday gösterici olmanız gerekmektedir.', 'too_many' => 'Adaylık şartı zaten yerine getirildi.', 'dialog' => [ - 'confirmation' => 'Bu ritimharitasını aday göstermek istediğinize emin misiniz?', - 'header' => 'Ritimharitasını aday gösterin', + 'confirmation' => 'Bu beatmapi aday göstermek istediğinize emin misiniz?', + 'header' => 'Beatmap aday gösterin', 'hybrid_warning' => 'not: sadece bir kez aday gösterebilirsiniz, bu yüzden lütfen istediğiniz tüm oyun modlarını aday gösterdiğinizden emin olun', 'which_modes' => 'Hangi modlar için aday gösterilsin?', ], @@ -65,18 +65,18 @@ ], 'deleted_banner' => [ - 'title' => 'Bu ritimharitası silindi.', + 'title' => 'Bu beatmap silindi.', 'message' => '(bunu sadece moderatörler görebilir)', ], 'details' => [ 'by_artist' => ':artist tarafından', - 'favourite' => 'ritimharitasını favorilere ekle', - 'favourite_login' => 'ritimharitasını favorilere eklemek için giriş yap', + 'favourite' => 'Beatmap setini favorilere ekle', + 'favourite_login' => 'Beatmapi favorilere eklemek için giriş yap', 'logged-out' => 'Herhangi bir beatmapi indirmeden önce giriş yapmalısınız!', 'mapped_by' => ':mapper tarafından yapıldı', 'mapped_by_guest' => ':mapper tarafından konuk zorluk', - 'unfavourite' => 'ritimharitasını favorilerden çıkar', + 'unfavourite' => 'Beatmap setini favorilerden çıkar', 'updated_timeago' => 'son güncelleme: :timeago', 'download' => [ @@ -102,7 +102,7 @@ ], 'favourites' => [ - 'limit_reached' => 'Favorilerinizde çok fazla ritimharitası var! Lütfen birkaç tanesini çıkarıp tekrar deneyin.', + 'limit_reached' => 'Favorilerinizde çok fazla beatmap\'iniz var! Lütfen devam etmeden önce birini çıkartın.', ], 'hype' => [ @@ -123,7 +123,7 @@ ], 'report' => [ - '_' => 'Eğer bu ritimharitasında bir sorun bulduysanız, takımı uyarmak için lütfen :link bildirin.', + '_' => 'Eğer bu beatmapte bir sorun bulduysanız, takımı uyarmak için lütfen :link bildirin.', 'button' => 'Sorun Bildir', 'link' => 'buradan', ], @@ -139,19 +139,19 @@ 'offset' => 'Çevrimiçi ofset', 'points-of-failure' => 'Başarısız Olunan Kısımlar', 'source' => 'Kaynak', - 'storyboard' => 'Bu ritimharitası arkaplan animasyonu içeriyor', + 'storyboard' => 'Bu beatmap storyboard içeriyor', 'success-rate' => 'Başarı Oranı', 'tags' => 'Etiketler', - 'video' => 'Bu ritimharitası video içeriyor', + 'video' => 'Bu beatmap video içeriyor', ], 'nsfw_warning' => [ - 'details' => 'Bu ritimharitası müstehcen, ofansif, veya rahatsız edici içerik içeriyor. Yine de görüntülemek istiyor musun?', + 'details' => 'Bu beatmap müstehcen, ofansif, veya rahatsız edici içerik içermektedir. Yine de görüntülemek istiyor musunuz?', 'title' => 'Müstehcen İçerik', 'buttons' => [ 'disable' => 'Uyarıyı devre dışı bırak', - 'listing' => 'Ritimharitası kataloğu', + 'listing' => 'Beatmap kataloğu', 'show' => 'Göster', ], ], @@ -185,7 +185,7 @@ 'friend' => 'Hiçbir arkadaşın henüz bu mapte bir skora sahip değil!', 'global' => 'Henüz skor yok. Biraz skor yapmaya ne dersin?', 'loading' => 'Skorlar yükleniyor...', - 'unranked' => 'Derecesiz ritimharitası.', + 'unranked' => 'Derecelendirilmemiş beatmap.', ], 'score' => [ 'first' => 'Lider', diff --git a/resources/lang/tr/comments.php b/resources/lang/tr/comments.php index 2be9ad83f41..e190a9cfd48 100644 --- a/resources/lang/tr/comments.php +++ b/resources/lang/tr/comments.php @@ -17,7 +17,7 @@ 'title' => 'Yorumlar', 'commentable_name' => [ - 'beatmapset' => 'Ritimharitası', + 'beatmapset' => 'Beatmap', 'build' => 'Değişiklik kayıtları', 'news_post' => 'Haberler', '_deleted' => 'Silinmiş Öge', @@ -44,7 +44,7 @@ ], 'ogp' => [ - 'title' => 'yorumlayan :user', + 'title' => '', ], 'placeholder' => [ diff --git a/resources/lang/tr/community.php b/resources/lang/tr/community.php index 699f07270c9..d1ca886f62f 100644 --- a/resources/lang/tr/community.php +++ b/resources/lang/tr/community.php @@ -24,12 +24,12 @@ ], 'featured-artists' => [ 'title' => 'Featured Artist\'ler', - 'description' => 'Senin desteğinle, daha çok müzisyen ile iletişim kurabilir ve onların güzel şarkılarını osu! için lisanslayabiliriz!', + 'description' => 'Sizin desteğinizle, daha çok müzisyen ile iletişim kurabilir ve onların güzel şarkılarını osu! için lisanslayabiliriz!', 'link_text' => 'Güncel listeyi görüntüleyin »', ], 'ads' => [ 'title' => 'osu!\'nun kendi kendine devam etmesini sağlayın', - 'description' => 'Senin katkıların oyunun özgür, reklamlardan ve sponsorlardan tamamen bağımsız kalmasına yardımcı olur.', + 'description' => 'Sizin katkılarınız oyunun özgür, reklamlardan ve sponsorlardan tamamen bağımsız kalmasına yardımcı olur.', ], 'tournaments' => [ 'title' => 'Resmi Turnuvalar', @@ -46,12 +46,12 @@ 'title' => 'Öyle mi? Neler alacağım?!', 'osu_direct' => [ 'title' => 'osu!direct', - 'description' => 'Oyundan çıkmaya gerek kalmadan hızlıca ritimharitalarını arayıp indirebilirsin.', + 'description' => 'Oyundan çıkmaya gerek kalmadan hızlıca beatmapleri arayıp indirebilirsin.', ], 'friend_ranking' => [ 'title' => 'Arkadaş Sıralaması', - 'description' => "Hem oyun içinde hem de websitede, bir ritimharitası sıralamasında arkadaşlarınız ile karşılaştırıldığında nasıl olduğunuzu görün.", + 'description' => "Hem oyun içinde hem de websitede, bir beatmapin sıralamasında arkadaşlarınız ile karşılaştırıldığında nasıl olduğunuzu görün.", ], 'country_ranking' => [ @@ -66,12 +66,12 @@ 'auto_downloads' => [ 'title' => 'Otomatik İndirme', - 'description' => 'Çok oyunculu oyunlardayken, başkalarını seyrederken, veya sohbetteki linklere tıkladığınızda ritimharitaları otomatik olarak indirilir!', + 'description' => 'Çok oyunculu oyunlardayken, başkalarını seyrederken, veya sohbetteki linklere tıkladığınızda beatmapler otomatik olarak indirilir!', ], 'upload_more' => [ 'title' => 'Daha Fazla Yükle', - 'description' => 'Maksimum 10 olmak üzere fazladan (dereceli ritimharitası başına) beklemede ritimharitası yuvası.', + 'description' => 'Maksimum 10 olmak üzere fazladan (dereceli beatmap başına) beklemede beatmap yuvası.', ], 'early_access' => [ @@ -85,8 +85,8 @@ ], 'beatmap_filters' => [ - 'title' => 'Ritimharitası Filtreleri', - 'description' => 'Ritimharitası aramalarını oynanmış, oynanmamış ya da elde edilmiş dereceye göre filtreleyebilme.', + 'title' => 'Beatmap Filtreleri', + 'description' => 'Beatmap aramalarınızı oynanmış, oynanmamış ya da (eğer varsa) elde edilmiş dereceye göre filtreleme.', ], 'yellow_fellow' => [ @@ -101,7 +101,7 @@ 'change_username' => [ 'title' => 'Kullanıcı Adı Değiştirme', - 'description' => 'Tek seferlik isim değiştirme hakkı ilk supporter satın alımın ile birlikte ücretsiz verilir.', + 'description' => 'Tek seferlik isim değiştirme hakkı ilk supporter satın alımınız ile birlikte ücretsiz verilir.', ], 'skinnables' => [ @@ -116,20 +116,20 @@ 'sort_options' => [ 'title' => 'Sıralama Seçenekleri', - 'description' => 'Oyun içinde ritimharitalarının ülke/arkadaş/moda göre sıralamalarını görme yeteneği.', + 'description' => 'Oyun içinde beatmaplerin ülke/arkadaş/moda göre sıralamalarını görme yeteneği.', ], 'more_favourites' => [ 'title' => 'Daha Fazla Favori', - 'description' => 'Favorine ekleyebileceğin maksimum ritimharitası sayısı :normally → :supporter olarak yükseltilir.', + 'description' => 'Favorine ekleyebileceğin maksimum beatmap sayısı :normally → :supporter olarak yükseltilir.', ], 'more_friends' => [ 'title' => 'Daha Fazla Arkadaş', 'description' => 'Ekleyebileceğin maksimum arkadaş sayısı :normally → :supporter olarak yükseltilir.', ], 'more_beatmaps' => [ - 'title' => 'Daha Fazla Ritimharitası Yükle', - 'description' => 'Aynı anda kaç tane bekleyen ritimharitasına sahip olabileceğiniz, temel değer artı halihazırda sahip olduğunuz her dereceli ritimharitası için ek bir bonusla hesaplanır (bir limite kadar).

Normalde bu, dereceli ritimharitası başına :base artı :bonus şeklindedir. (:bonus_max kadar). osu!supporter ile bu, dereceli ritimharitası başına :supporter_base artı :supporter_bonus olur. (:supporter_bonus_max kadar).', + 'title' => 'Daha Fazla Beatmap Yükle', + 'description' => 'Ne kadar ranked olmayan beatmaplere sahip olabileceğin, temel bir değere ek olarak, ne kadar ranked beatmap sahip olmuşluğun varsa eklenerek belirlenir (bir sınıra kadar).
Normalde bu her bir ranked map için fazladan 4 tane daha fazla ranked olmayan beatmap hakkına erişirsin (2\'ye kadar). Destekçilik ile bu 1 ranked beatmap için 8 e çıkar (12\'ye kadar).
', ], 'friend_filtering' => [ 'title' => 'Arkadaş Sıralamaları', diff --git a/resources/lang/tr/contest.php b/resources/lang/tr/contest.php index 3b74820c968..f26307a570d 100644 --- a/resources/lang/tr/contest.php +++ b/resources/lang/tr/contest.php @@ -19,7 +19,7 @@ 'show_voted_only' => 'Oy verilenleri göster', 'best_of' => [ - 'none_played' => "Bu yarışma için geçerli olan hiçbir ritimharitasını oynamamışsınız!", + 'none_played' => "Bu yarışma için geçerli olan hiçbir beatmapi oynamamışsınız!", ], 'button' => [ @@ -34,7 +34,7 @@ 'requirement' => [ 'playlist_beatmapsets' => [ - 'incomplete_play' => 'Oylama yapabilmen için belirli oynatma listelerindeki bütün ritimharitalarını oynaman gerekiyor', + 'incomplete_play' => 'Oylama yapabilmek için belirli playlistlerdeki bütün haritaları oynamanız gerekmektedir', ], ], ], diff --git a/resources/lang/tr/errors.php b/resources/lang/tr/errors.php index 4fbd207772b..87ca4f94556 100644 --- a/resources/lang/tr/errors.php +++ b/resources/lang/tr/errors.php @@ -23,7 +23,7 @@ ], 'beatmaps' => [ 'invalid_mode' => 'Geçersiz mod seçildi.', - 'standard_converts_only' => 'Bu ritimharitası zorluğunda seçilen modda şuanda skor mevcut değil.', + 'standard_converts_only' => 'Bu beatmap zorluğunda seçilen mod\'da şuanda skor mevcut değil.', ], 'checkout' => [ 'generic' => 'Checkout\'unuzu hazırlarken bir hata oluştu.', diff --git a/resources/lang/tr/events.php b/resources/lang/tr/events.php index 4bf819f7713..91e6b30e042 100644 --- a/resources/lang/tr/events.php +++ b/resources/lang/tr/events.php @@ -9,11 +9,11 @@ 'beatmapset_approve' => ':user tarafından yapılan :beatmapset :approval!', 'beatmapset_delete' => ':beatmapset silindi.', 'beatmapset_revive' => ':beatmapset :user tarafından ebedi uykusundan uyandırıldı.', - 'beatmapset_update' => ':user ":beatmapset" ritimharitasını güncelledi', - 'beatmapset_upload' => ':user yeni bir ritimharitası oluşturdu ":beatmapset"', + 'beatmapset_update' => ':user ":beatmapset" beatmapini güncelledi', + 'beatmapset_upload' => ':user yeni bir beatmap oluşturdu ":beatmapset"', 'empty' => "Bu kullanıcı son zamanlarda kayda değer bir şey yapmamış!", - 'rank' => ':user, :beatmap (:mode) ritimharitasında #:rank sıralamaya ulaştı', - 'rank_lost' => ':user :beatmap (:mode) ritimharitasında birinciliği kaybetti', + 'rank' => ':user :beatmap (:mode) beatmapinde #:rank sıralamaya ulaştı', + 'rank_lost' => ':user :beatmap (:mode) beatmapinde birinciliği kaybetti', 'user_support_again' => ':user bir kez daha osu!\'yu desteklemeyi seçti - cömertliğinden dolayı teşekkürler!', 'user_support_first' => ':user osu! supporter satın aldı - cömertliğinden dolayı teşekkür ederiz!', 'user_support_gift' => ':user osu!supporter hediyesi aldı!', diff --git a/resources/lang/tr/follows.php b/resources/lang/tr/follows.php index f6820ce8b1c..3bd83c88978 100644 --- a/resources/lang/tr/follows.php +++ b/resources/lang/tr/follows.php @@ -28,11 +28,11 @@ 'followers' => 'mapping aboneleri', 'page_title' => 'mapper izleme listesi', 'title' => 'mapper', - 'to_0' => 'bu kullanıcı yeni bir ritimharitası yüklediğinde bana bildirmeyi bırak', - 'to_1' => 'bu kullanıcı yeni bir ritimharitası yüklediğinde bana bildir', + 'to_0' => 'bu kullanıcı yeni bir beatmap yüklediğinde bana bildirmeyi bırak', + 'to_1' => 'bu kullanıcı yeni bir beatmap yüklediğinde bana bildir', ], 'modding' => [ - 'title' => 'ritimharitası tartışması', + 'title' => 'beatmap tartışması', ], ]; diff --git a/resources/lang/tr/home.php b/resources/lang/tr/home.php index c713dd54b38..2d90d7ac66c 100644 --- a/resources/lang/tr/home.php +++ b/resources/lang/tr/home.php @@ -27,10 +27,10 @@ 'title' => 'Ara', 'beatmapset' => [ - 'login_required' => 'Ritimharitalarını aramak için giriş yapın', - 'more' => ':count tane daha ritimharitası arama sonucu', - 'more_simple' => 'Daha fazla ritimharitası arama sonucu gör', - 'title' => 'Ritimharitaları', + 'login_required' => 'Beatmapleri aramak için giriş yapın', + 'more' => ':count tane daha beatmap arama sonucu', + 'more_simple' => 'Daha fazla beatmap arama sonucu gör', + 'title' => 'Beatmapler', ], 'forum_post' => [ @@ -51,7 +51,7 @@ 'mode' => [ 'all' => 'hepsi', - 'beatmapset' => 'ritimharitası', + 'beatmapset' => 'beatmap', 'forum_post' => 'forum', 'user' => 'oyuncu', 'wiki_page' => 'wiki', @@ -111,9 +111,9 @@ 'description' => 'yükleyiciyi indirmek için yukarıdaki düğmeye tıklayın, sonra çalıştırın!', ], 'beatmaps' => [ - 'title' => 'ritimharitaları edinin', + 'title' => 'beatmap edinin', 'description' => [ - '_' => 'Kullanıcılar tarafından oluşturulmuş zengin ritimharitası kütüphanesine:browse göz at ve oynamaya başla!', + '_' => 'Kullanıcılar tarafından oluşturulmuş engin beatmap kütüphanesine :browse ve oynamaya başla!', 'browse' => 'göz at', ], ], @@ -134,8 +134,8 @@ ], ], 'beatmaps' => [ - 'new' => 'Yeni Dereceli Ritimharitaları', - 'popular' => 'Popüler Ritimharitaları', + 'new' => 'Yeni Dereceli Beatmapler', + 'popular' => 'Popüler Beatmapler', 'by_user' => ':user tarafından', ], 'buttons' => [ diff --git a/resources/lang/tr/layout.php b/resources/lang/tr/layout.php index 2b92d57e1df..ff3be9ac7d1 100644 --- a/resources/lang/tr/layout.php +++ b/resources/lang/tr/layout.php @@ -14,8 +14,8 @@ 'header' => [ 'admin' => [ - 'beatmapset' => 'ritimharitası seti', - 'beatmapset_covers' => 'ritimharitası seti kapakları', + 'beatmapset' => 'beatmap seti', + 'beatmapset_covers' => 'beatmap seti kapakları', 'contest' => 'yarışma', 'contests' => 'yarışmalar', 'root' => 'konsol', @@ -67,7 +67,7 @@ 'menu' => [ 'beatmaps' => [ - '_' => 'ritimharitaları', + '_' => 'beatmapler', ], 'community' => [ '_' => 'topluluk', @@ -98,7 +98,7 @@ '_' => 'Genel', 'home' => 'Anasayfa', 'changelog-index' => 'Değişiklikler', - 'beatmaps' => 'Ritimharitası Kataloğu', + 'beatmaps' => 'Beatmap Kataloğu', 'download' => 'osu!\'yu indir!', ], 'help' => [ diff --git a/resources/lang/tr/mail.php b/resources/lang/tr/mail.php index dc03bc7ce95..cf0931b59ef 100644 --- a/resources/lang/tr/mail.php +++ b/resources/lang/tr/mail.php @@ -5,9 +5,9 @@ return [ 'beatmapset_update_notice' => [ - 'new' => 'Sadece sana son girdiğinden beri ":title" ritimharitarında yeni bir güncelleme olduğunu bildiriyoruz.', - 'subject' => '":title" ritimharitasında için yeni bir güncelleme', - 'unwatch' => 'Artık bu ritimharitasını izlemek istemiyorsan, yukarıdaki sayfada veya modlama izleme listesi sayfasında bulunan "İzlemeyi Bırak" bağlantısına tıklayabilirsin:', + 'new' => 'Sadece sana son girdiğinden beri ":title" beatmap\'inde yeni bir güncelleme olduğunu bildiriyoruz.', + 'subject' => '":title" beatmapi için yeni bir güncelleme', + 'unwatch' => 'Artık bu beatmap\'i izlemek istemiyorsan, yukarıdaki sayfada veya modlama izleme listesi sayfasında bulunan "İzlemeyi Bırak" bağlantısına tıklayabilirsin:', 'visit' => 'Tartışma sayfasını buradan ziyaret edin:', ], @@ -15,15 +15,15 @@ 'closing' => 'Saygılarımızla,', 'hello' => 'Selam :user,', 'report' => 'Eğer böyle bir değişiklik talep etmediyseniz lütfen DERHAL bu e-postayı yanıtlayın.', - 'ignore' => 'Eğer bunu isteyen sen değilsen, bu mesajı görmezden gelebilirsin.', + 'ignore' => 'Eğer bunu isteyen siz değilseniz, bu mesajı görmezden gelebilirsiniz.', ], 'donation_thanks' => [ 'benefit_more' => 'Zaman içinde daha fazla yeni supporter ayrıcalığı da eklenecek bu arada!', - 'feedback' => "Eğer herhangi bir sorun veya geribildirimin varsa, bu e-postaya cevap yazmaktan çekinmeyin; Sana en kısa zamanda geri döneceğim!", - 'keep_free' => 'Senin gibi insanlar sayesinde osu!, oyunu ve topluluğu akıcı bir şekilde hiçbir reklam veya zorla ödeme olmadan oyunu devam ettirebiliyor.', + 'feedback' => "Eğer herhangi bir sorunuz veya geribildiriminiz varsa, bu postaya cevap yazmaktan çekinmeyin; Size en kısa zamanda geri döneceğim!", + 'keep_free' => 'Sizin gibi insanlar sayesinde osu!, oyunu ve topluluğu akıcı bir şekilde hiçbir reklam veya zorla ödeme olmadan oyunu devam ettirebiliyor.', 'keep_running' => 'Senin katkın osu!\'yu :minutes kadardır ayakta tutuyor. Fazla görünmüyor olabilir ama damlaya damlaya göl olur :).', - 'subject' => 'Teşekkürler, osu! seni seviyor <3', + 'subject' => 'Teşekkürler, osu! sizi seviyor <3', 'translation' => 'Metnin topluluk tarafından sağlanan bilgi amaçlı çevirisi aşağıdaki gibidir:', 'benefit' => [ @@ -66,9 +66,9 @@ 'anonymous_gift_maybe_not' => 'Ama muhtemelen kim olduğunu biliyorsun ;).', 'duration' => 'Onun sayesinde, sonraki :duration boyunca osu!direct\'e ve diğer osu!supporter ayrıcalıklarına sahip olacaksın.', 'features' => 'Bu avantajlar hakkında daha fazla detaylı bilgiye buradan ulaşabilirsiniz:', - 'gifted' => 'Birisi sana az önce bir osu!supporter etiketi hediye etti!', - 'gift_message' => 'Bu etiketi hediye eden kişi sana bir mesaj bıraktı:', - 'subject' => 'Sana bir osu!supporter etiketi verildi!', + 'gifted' => 'Birisi size az önce bir osu!supporter etiketi hediye etti!', + 'gift_message' => 'Bu etiketi hediye eden kişi size bir mesaj bıraktı:', + 'subject' => 'Size bir osu! Destekçisi etiketi verildi!', ], 'user_email_updated' => [ @@ -100,7 +100,7 @@ 'code' => 'Doğrulama kodun:', 'code_hint' => 'Kodu boşluk bırakarak ya da bırakmadan girebilirsiniz.', 'link' => 'Alternatif olarak, doğrulamayı bitirmek için bu bağlantıya da gidebilirsin:', - 'report' => 'Eğer böyle bir istemde bulunmadıysan, hesabın tehlikede olabilir, lütfen HEMEN YANITLA.', + 'report' => 'Eğer siz böyle bir istemde bulunmadıysanız, hesabınız tehlikede olabileceğinden lütfen HEMEN YANITLAYIN. ', 'subject' => 'osu! hesap doğrulama', 'action_from' => [ diff --git a/resources/lang/tr/matches.php b/resources/lang/tr/matches.php index 655695b5e08..5c0119c13f8 100644 --- a/resources/lang/tr/matches.php +++ b/resources/lang/tr/matches.php @@ -5,7 +5,7 @@ return [ 'match' => [ - 'beatmap-deleted' => 'silinmiş ritimharitası', + 'beatmap-deleted' => 'silinmiş beatmap', 'failed' => 'BAŞARISIZ', 'header' => 'Çok Oyunculu Maçlar', 'in-progress' => '(devam eden maç)', diff --git a/resources/lang/tr/model_validation.php b/resources/lang/tr/model_validation.php index d7b1909853f..4937eedeb75 100644 --- a/resources/lang/tr/model_validation.php +++ b/resources/lang/tr/model_validation.php @@ -12,11 +12,11 @@ 'wrong_confirmation' => 'Doğrulama eşleşmiyor.', 'beatmapset_discussion' => [ - 'beatmap_missing' => 'Zaman damgası belirtildi, ancak ritimharitası eksik.', - 'beatmapset_no_hype' => "Ritimharitası gazlanamaz.", + 'beatmap_missing' => 'Zaman damgası belirtildi, ancak beatmap eksik.', + 'beatmapset_no_hype' => "Beatmap gazlanamaz.", 'hype_requires_null_beatmap' => 'Gaz, Genel (tüm zorluklar) sekmesinde verilmelidir.', 'invalid_beatmap_id' => 'Yanlış zorluk belirtildi.', - 'invalid_beatmapset_id' => 'Yanlış ritimharitası belirtildi.', + 'invalid_beatmapset_id' => 'Yanlış beatmap belirtildi.', 'locked' => 'Tartışma kilitli.', 'attributes' => [ @@ -25,16 +25,16 @@ ], 'hype' => [ - 'discussion_locked' => "Bu ritimharitası şu anda tartışmaya kapalıdır ve gazlanamaz", + 'discussion_locked' => "Bu beatmap şu anda tartışmaya kapalıdır ve gazlanamaz", 'guest' => 'Gazlamak giriş yapmalısın.', - 'hyped' => 'Bu ritimharitasını çoktan gazladın.', + 'hyped' => 'Bu beatmapi çoktan gazladın.', 'limit_exceeded' => 'Bütün gazını kullandın.', - 'not_hypeable' => 'Bu ritimharitası gazlanamaz', - 'owner' => 'Kendi ritimharitanı gazlayamazsın.', + 'not_hypeable' => 'Bu beatmap gazlanamaz', + 'owner' => 'Kendi beatmapini gazlayamazsın.', ], 'timestamp' => [ - 'exceeds_beatmapset_length' => 'Belirtilen zaman damgası ritimharitasının uzunluğunu aşmakta.', + 'exceeds_beatmapset_length' => 'Belirtilen zaman damgası beatmap\'in uzunluğunu aşmakta.', 'negative' => "Zaman damgası negatif olamaz.", ], ], @@ -72,8 +72,8 @@ ], 'post' => [ - 'beatmapset_post_no_delete' => 'Ritimharitası metaveri gönderisinin silinmesi yasaktır.', - 'beatmapset_post_no_edit' => 'Ritimharitası metaveri gönderisini düzenlemek yasaktır.', + 'beatmapset_post_no_delete' => 'Beatmap metaveri gönderisinin silinmesi yasaktır.', + 'beatmapset_post_no_edit' => 'Beatmap metaveri gönderisini düzenlemek yasaktır.', 'first_post_no_delete' => 'Başlangıç gönderisi silinemez', 'missing_topic' => 'Gönderinin konusu eksik', 'only_quote' => 'Cevabınız sadece bir alıntı içeriyor.', @@ -174,7 +174,7 @@ ], 'user_report' => [ - 'no_ranked_beatmapset' => 'Dereceli ritimharitaları bildirilemez', + 'no_ranked_beatmapset' => 'Dereceli beatmapler bildirilemez', 'not_in_channel' => 'Bu kanalda değilsiniz.', 'reason_not_valid' => ':reason sebebi bu rapor türü için geçerli değil.', 'self' => "Kendinizi raporlayamazsınız!", diff --git a/resources/lang/tr/notifications.php b/resources/lang/tr/notifications.php index a3cb80cbbee..b2caf09edc4 100644 --- a/resources/lang/tr/notifications.php +++ b/resources/lang/tr/notifications.php @@ -15,7 +15,7 @@ 'action_type' => [ '_' => 'hepsi', - 'beatmapset' => 'ritimharitası', + 'beatmapset' => 'haritalar', 'build' => 'sürümler', 'channel' => 'sohbet', 'forum_topic' => 'forum', @@ -26,7 +26,7 @@ 'filters' => [ '_' => 'hepsi', 'user' => 'profil', - 'beatmapset' => 'ritimharitaları', + 'beatmapset' => 'haritalar', 'forum_topic' => 'forum', 'news_post' => 'gelişmeler', 'build' => 'sürümler', @@ -35,17 +35,17 @@ 'item' => [ 'beatmapset' => [ - '_' => 'Ritimharitası', + '_' => 'Harita', 'beatmap_owner_change' => [ - '_' => 'Konuk zorluğu', - 'beatmap_owner_change' => 'Artık ":title" ritimharitasındaki ":beatmap" zorluğunun sahibisiniz', + '_' => 'Konuk zorluk', + 'beatmap_owner_change' => 'Artık ":title" beatmapindeki ":beatmap" zorluğunun sahibisiniz', 'beatmap_owner_change_compact' => 'Artık ":beatmap" zorluğunun sahibisiniz', ], 'beatmapset_discussion' => [ - '_' => 'Ritimharitası tartışması', - 'beatmapset_discussion_lock' => '":title" tartışması kilitlendi', + '_' => 'Beatmap tartışması', + 'beatmapset_discussion_lock' => '":title" setinin tartışması kilitlendi', 'beatmapset_discussion_lock_compact' => 'Tartışma kilitlenmiş', 'beatmapset_discussion_post_new' => '":title" setinde :username tarafından yeni bir gönderi mevcut: ":content"', 'beatmapset_discussion_post_new_empty' => '":title" setinde :username tarafından yeni gönderi', @@ -57,14 +57,14 @@ 'beatmapset_discussion_unlock_compact' => 'Tartışmanın kilidi kaldırılmış', 'review_count' => [ - 'praises' => ':count_delimited övgü|:count_delimited övgüler', - 'problems' => ':count_delimited sorun|:count_delimited sorunlar', - 'suggestions' => ':count_delimited öneri|:count_delimited öneriler', + 'praises' => '', + 'problems' => '', + 'suggestions' => '', ], ], 'beatmapset_problem' => [ - '_' => 'Nitelikli Ritimharitası sorunu', + '_' => 'Nitelikli Beatmap sorunu', 'beatmapset_discussion_qualified_problem' => ':username tarafından bildirildi ":title": ":content"', 'beatmapset_discussion_qualified_problem_empty' => ':username tarafından bildirildi ":title"', 'beatmapset_discussion_qualified_problem_compact' => ':username tarafından rapor edildi: ":content"', @@ -72,9 +72,9 @@ ], 'beatmapset_state' => [ - '_' => 'Ritimharitası durumu değişti', + '_' => 'Beatmap durumu değişti', 'beatmapset_disqualify' => '":title" diskalifiye edildi', - 'beatmapset_disqualify_compact' => 'Ritimharitası diskalifiye edildi', + 'beatmapset_disqualify_compact' => 'Beatmap diskalifiye edildi', 'beatmapset_love' => '":title" sevilenlere yükseltildi', 'beatmapset_love_compact' => 'Beatmap sevilenlere yükseltildi', 'beatmapset_nominate' => '":title" aday gösterildi', @@ -82,9 +82,9 @@ 'beatmapset_qualify' => '":title" yeterli aday gösterimi aldı ve derecelendirme sırasına girdi', 'beatmapset_qualify_compact' => 'Beatmap derecelendirme sırasına girdi', 'beatmapset_rank' => '":title" dereceli oldu', - 'beatmapset_rank_compact' => 'Ritimharitası dereceli oldu', + 'beatmapset_rank_compact' => 'Beatmap dereceli oldu', 'beatmapset_remove_from_loved' => '":title" Sevilenlerden çıkarıldı', - 'beatmapset_remove_from_loved_compact' => 'Ritimharitası Sevilenler\'den çıkarıldı', + 'beatmapset_remove_from_loved_compact' => 'Beatmap Sevilenlerden çıkarıldı', 'beatmapset_reset_nominations' => '":title" setinin adaylığı sıfırlandı', 'beatmapset_reset_nominations_compact' => 'Adaylık sıfırlandı', ], @@ -161,14 +161,14 @@ 'user' => [ 'user_beatmapset_new' => [ - '_' => 'Yeni ritimharitası', + '_' => 'Yeni beatmap', - 'user_beatmapset_new' => ':username tarafından yeni ritimharitası ":title"', - 'user_beatmapset_new_compact' => 'Yeni ritimharitası ":title"', - 'user_beatmapset_new_group' => ' :username tarafından yapılmış yeni ritimharitaları', + 'user_beatmapset_new' => ':username tarafından yeni beatmap ":title"', + 'user_beatmapset_new_compact' => 'Yeni beatmap ":title"', + 'user_beatmapset_new_group' => ' :username tarafından yapılmış yeni beatmapler', - 'user_beatmapset_revive' => '":title" adlı ritimharitası :username tarafından hayata geri döndürüldü', - 'user_beatmapset_revive_compact' => '":title" adlı ritimharitası hayata geri döndürüldü', + 'user_beatmapset_revive' => '":title" adlı beatmap :username tarafından hayata geri döndürüldü', + 'user_beatmapset_revive_compact' => '":title" adlı beatmap hayata geri döndürüldü', ], ], @@ -187,7 +187,7 @@ 'mail' => [ 'beatmapset' => [ 'beatmap_owner_change' => [ - 'beatmap_owner_change' => 'Artık ":title" ritimharitasının bir konuğusunuz', + 'beatmap_owner_change' => 'Artık ":title" beatmapinin bir konuğusunuz', ], 'beatmapset_discussion' => [ @@ -211,7 +211,7 @@ ], 'comment' => [ - 'comment_new' => '":title" ritimharitasında yeni yorumlar mevcut', + 'comment_new' => '":title" beatmapinde yeni yorumlar mevcut', ], ], @@ -250,8 +250,8 @@ ], 'user_beatmapset_new' => [ - 'user_beatmapset_new' => ':username yeni ritimharitaları yaptı', - 'user_beatmapset_revive' => ':username ritimharitalarını hayata geri döndürdü', + 'user_beatmapset_new' => ':username yeni beatmapler yaptı', + 'user_beatmapset_revive' => ':username beatmap\'leri hayata geri döndürdü', ], ], ], diff --git a/resources/lang/tr/page_title.php b/resources/lang/tr/page_title.php index a47a2a48a80..be80aa564c9 100644 --- a/resources/lang/tr/page_title.php +++ b/resources/lang/tr/page_title.php @@ -35,24 +35,24 @@ '_' => 'featured artist\'ler', ], 'beatmap_discussion_posts_controller' => [ - '_' => 'ritimharitası tartışma gönderileri', + '_' => 'beatmap tartışma gönderileri', ], 'beatmap_discussions_controller' => [ - '_' => 'ritimharitası tartışmaları', + '_' => 'beatmap tartışmaları', ], 'beatmap_packs_controller' => [ - '_' => 'ritimharitası paketleri', + '_' => 'beatmap paketleri', ], 'beatmapset_discussion_votes_controller' => [ - '_' => 'ritimharitası tartışma oylamaları', + '_' => 'beatmap tartışma oylamaları', ], 'beatmapset_events_controller' => [ - '_' => 'ritimharitası geçmişi', + '_' => 'beatmap geçmişi', ], 'beatmapsets_controller' => [ - 'discussion' => 'ritimharitası tartışması', - 'index' => 'ritimharitası kataloğu', - 'show' => 'ritimharitası bilgisi', + 'discussion' => 'beatmap tartışma', + 'index' => 'beatmap kataloğu', + 'show' => 'beatmap bilgisi', ], 'changelog_controller' => [ '_' => 'değişiklik kayıtları', diff --git a/resources/lang/tr/quick_search.php b/resources/lang/tr/quick_search.php index 3d0170b60e8..3d85227b7ac 100644 --- a/resources/lang/tr/quick_search.php +++ b/resources/lang/tr/quick_search.php @@ -5,7 +5,7 @@ return [ 'mode' => [ - 'beatmapset' => 'Ritimharitası', + 'beatmapset' => 'Beatmap', 'forum_post' => 'Forum', 'other' => 'Diğer', 'user' => 'Oyuncu', diff --git a/resources/lang/tr/report.php b/resources/lang/tr/report.php index 2c308af31b3..58ae6f4366d 100644 --- a/resources/lang/tr/report.php +++ b/resources/lang/tr/report.php @@ -6,7 +6,7 @@ return [ 'beatmapset' => [ 'button' => 'Bildir', - 'title' => ':username kullanıcısının ritimharitası bildirilsin mi?', + 'title' => ':username kullanıcısının beatmapi bildirilsin mi?', ], 'beatmapset_discussion_post' => [ diff --git a/resources/lang/tr/store.php b/resources/lang/tr/store.php index 430b8401289..d0142b9740a 100644 --- a/resources/lang/tr/store.php +++ b/resources/lang/tr/store.php @@ -49,15 +49,15 @@ ], 'discount' => '%:percent kazanın', - 'free' => 'ücretsiz!', + 'free' => '', 'invoice' => [ 'contact' => 'İletişim:', 'date' => 'Tarih:', 'echeck_delay' => 'Ödemenizin bir eCheck olması nedeniyle, ödemenizin PayPal\'dan temizlenmesi için 10 ekstra günü göz önüne alın!', 'hide_from_activity' => 'Bu siparişteki osu!supporter etiketleri yakın zamandaki etkinliklerinizde gösterilmez.', - 'sent_via' => 'Üzerinden gönderildi:', - 'shipping_to' => 'Teslimat adresi:', + 'sent_via' => '', + 'shipping_to' => '', 'title' => 'Fatura', 'title_compact' => 'fatura', @@ -65,21 +65,21 @@ 'cancelled' => [ 'title' => 'Siparişiniz iptal edildi', 'line_1' => [ - '_' => "İptal talebinde bulunmadıysanız lütfen sipariş numaranızı (#:order_number) belirterek iletişime geçin :link.", - 'link_text' => 'osu!store yardım merkezi', + '_' => "", + 'link_text' => '', ], ], 'delivered' => [ 'title' => 'Siparişiniz teslim edildi! İyi günlerde kullanmanız dileğiyle!', 'line_1' => [ '_' => 'Satın alımınızla ilgili bir problem yaşıyorsanız,lütfen :link ile görüşün.', - 'link_text' => 'osu!store yardım merkezi', + 'link_text' => '', ], ], 'prepared' => [ 'title' => 'Siparişiniz hazılrlanıyor!', - 'line_1' => 'Lütfen paketinizin kargoya verilmesi için biraz daha bekleyin. Sipariş işlenip gönderildikten sonra takip bilgileri burada görünecektir. Bu süreç, ne kadar meşgul olduğumuza bağlı olarak 5 güne kadar sürebilir (genellikle daha az!).', - 'line_2' => 'Tüm siparişleri, ağırlık ve değere bağlı olarak çeşitli nakliye hizmetleri kullanarak Japonya\'dan gönderiyoruz. Siparişi gönderdikten sonra bu alan ayrıntılarla güncellenecektir.', + 'line_1' => '', + 'line_2' => '', ], 'processing' => [ 'title' => 'Ödemeniz henüz onaylanmadı!', @@ -91,9 +91,9 @@ ], 'shipped' => [ 'title' => 'Siparişiniz kargoya verildi!', - 'tracking_details' => 'Takip ayrıntıları şöyle:', + 'tracking_details' => '', 'no_tracking_details' => [ - '_' => "Paketinizi uçak kargosu yoluyla gönderdiğimiz için takip ayrıntılarına sahip değiliz, ancak paketinizi 1-3 hafta içinde almayı bekleyebilirsin. Avrupa'da bazen gümrükler bizim kontrolümüz dışında siparişi geciktirebilir. Herhangi bir endişen varsa lütfen sana gelen sipariş onay e-postasını yanıtla :link.", + '_' => "", 'link_text' => 'bize bir e-mail yollayın', ], ], @@ -108,17 +108,17 @@ 'no_orders' => 'Görüntülenecek sipariş yok.', 'paid_on' => 'Sipariş verme tarihi :date', 'resume' => 'Sepete Dön', - 'shipping_and_handling' => 'Nakliye ve Taşıma', + 'shipping_and_handling' => '', 'shopify_expired' => 'Bu sipariş için ödeme bağlantısının süresi doldu.', 'subtotal' => 'Ara toplam', 'total' => 'Toplam', 'details' => [ - 'order_number' => 'Sipariş #', - 'payment_terms' => 'Ödeme koşulları', + 'order_number' => '', + 'payment_terms' => '', 'salesperson' => 'Satış Temsilcisi', 'shipping_method' => 'Gönderim Yolu', - 'shipping_terms' => 'Nakliye Koşulları', + 'shipping_terms' => '', 'title' => 'Sipariş Detayları', ], @@ -157,7 +157,7 @@ 'thanks' => [ 'title' => 'Siparişiniz için teşekkür ederiz!', 'line_1' => [ - '_' => 'Yakında bir onay e-postası alacaksın. Soruların varsa lütfen :link!', + '_' => '', 'link_text' => 'bizimle iletişime geçin', ], ], @@ -193,7 +193,7 @@ 'username_change' => [ 'check' => 'Geçerliliğini kontrol etmek için bir kullanıcı adı girin!', 'checking' => ':username geçerliliği kontrol ediliyor...', - 'placeholder' => 'İstenen Kullanıcı Adı', + 'placeholder' => '', 'label' => 'Yeni kullanıcı adı', 'current' => 'Şu anki kullanıcı adınız ":username".', diff --git a/resources/lang/tr/users.php b/resources/lang/tr/users.php index 4700955a881..5292bfb1fdd 100644 --- a/resources/lang/tr/users.php +++ b/resources/lang/tr/users.php @@ -84,7 +84,7 @@ 'opening' => 'Hesabını dondurmaya sebebiyet verebilecek birtakım sebepler var:', 'tos' => [ - '_' => ':community_rules ya da :tos kurallarından bir veya daha fazlasını ihlal ettin.', + '_' => 'Siz, :community_rules ya da :tos kurallarından bir veya daha fazlasını ihlal ettiniz.', 'community_rules' => 'topluluk kuralları', 'tos' => 'hizmet kullanım şartları', ], @@ -109,7 +109,7 @@ 'failed' => 'Hatalı giriş', 'forgot' => 'Şifrenizi mi unuttunuz?', 'info' => 'Devam etmek için lütfen giriş yapınız', - 'invalid_captcha' => 'Çok fazla hatalı giriş denemesi, CAPTCHA\'yı tamamlayıp tekrar dene. (CAPTCHA gözükmüyorsa sayfayı yenile)', + 'invalid_captcha' => 'Captcha geçersiz, sayfayı yenileyip tekrar deneyin.', 'locked_ip' => 'IP adresiniz kilitli. Lütfen birkaç dakika bekleyin.', 'password' => 'Şifre', 'register' => "osu! hesabınız yok mu? Yeni bir tane oluşturun", @@ -124,13 +124,13 @@ ], 'ogp' => [ - 'modding_description' => 'Ritimharitaları: :counts', - 'modding_description_empty' => 'Kullanıcının herhangi bir ritimharitası yok...', + 'modding_description' => '', + 'modding_description_empty' => '', 'description' => [ - '_' => 'Derece (:ruleset): :global | :country', - 'country' => 'Ülke :rank', - 'global' => 'Küresel :rank', + '_' => '', + 'country' => '', + 'global' => '', ], ], @@ -170,7 +170,7 @@ ], 'restricted_banner' => [ 'title' => 'Hesabınız kısıtlandı!', - 'message' => 'Kısıtlanmışken, diğer oyuncularla etkileşime geçemezsin ve skorların sadece sana gözükür. Bu genellikle otomatik bir sürecin sonucudur ve genellikle 24 saat içinde kaldırılır. :link', + 'message' => 'Kısıtlanmışken, diğer oyuncularla etkileşime geçemeyecek ve skorlarınızı sadece siz görebileceksiniz. Bu genellikle otomatik olan bir işlemin sonucudur ve 24 saat içerisinde kalkabilir. Kısıtlamanızın açılması için başvurmak istiyorsanız, lütfen destek hattıyla iletişime geçin.', 'message_link' => 'Daha fazla bilgi için bu sayfaya göz atın.', ], 'show' => [ @@ -235,25 +235,25 @@ 'title' => 'Beatmapler', 'favourite' => [ - 'title' => 'Favori Ritimharitaları', + 'title' => 'Favori Beatmapler', ], 'graveyard' => [ - 'title' => 'Mezarlıktaki Ritimharitaları', + 'title' => 'Mezarlıktaki Beatmapler', ], 'guest' => [ - 'title' => 'Konuk Katılımı Ritimharitaları', + 'title' => 'Konuk Olarak Katıldığı Beatmapler', ], 'loved' => [ - 'title' => 'Sevilen Ritimharitaları', + 'title' => 'Sevilen Beatmapler', ], 'nominated' => [ - 'title' => 'Aday Gösterilen Dereceli Ritimharitaları', + 'title' => 'Aday Gösterilen Dereceli Beatmapler', ], 'pending' => [ - 'title' => 'Beklemedeki Ritimharitaları', + 'title' => 'Beklemedeki Beatmapler', ], 'ranked' => [ - 'title' => 'Dereceli Ritimharitaları', + 'title' => 'Dereceli & Onaylı Beatmapler', ], ], 'discussions' => [ @@ -331,7 +331,7 @@ ], 'total_info' => [ - '_' => 'Kullanıcının ritimharitası moderasyonuna yaptığı katkının miktarına bağlıdır. Daha fazla bilgi için :link bakınız.', + '_' => 'Kullanıcının beatmap modlamaya yaptığı katkının miktarına bağlıdır. Daha fazla bilgi için :link bakınız.', 'link' => 'bu sayfaya', ], ], @@ -462,10 +462,10 @@ 'total_hits' => 'Toplam Vuruş', 'total_score' => 'Toplam Skor', // modding stats - 'graveyard_beatmapset_count' => 'Mezarlıktaki Ritimharitaları', - 'loved_beatmapset_count' => 'Sevilen Ritimharitaları', - 'pending_beatmapset_count' => 'Onay Bekleyen Ritimharitaları', - 'ranked_beatmapset_count' => 'Dereceli Ritimharitaları', + 'graveyard_beatmapset_count' => 'Mezarlıktaki Beatmapler', + 'loved_beatmapset_count' => 'Sevilen Beatmapler', + 'pending_beatmapset_count' => 'Onay Bekleyen Beatmapler', + 'ranked_beatmapset_count' => 'Dereceli ve Onaylanmış Beatmapler', ], ], From 5fc469ad2ed3073d6a162e18ce5fc2d0f98933ec Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 22 Dec 2023 18:49:08 +0900 Subject: [PATCH 098/102] Add toggle for legacy score only view --- app/Http/Controllers/AccountController.php | 1 + app/Libraries/Search/ScoreSearchParams.php | 32 ++++++++++++--------- app/Models/UserProfileCustomization.php | 12 ++++++++ app/Transformers/UserCompactTransformer.php | 1 + 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 5ecd343603f..b02945d1851 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -257,6 +257,7 @@ public function updateOptions() 'comments_sort:string', 'extras_order:string[]', 'forum_posts_show_deleted:bool', + 'legacy_score_only:bool', 'profile_cover_expanded:bool', 'user_list_filter:string', 'user_list_sort:string', diff --git a/app/Libraries/Search/ScoreSearchParams.php b/app/Libraries/Search/ScoreSearchParams.php index 9ad2d4bc5ea..dc99bd1b6a3 100644 --- a/app/Libraries/Search/ScoreSearchParams.php +++ b/app/Libraries/Search/ScoreSearchParams.php @@ -11,12 +11,27 @@ use App\Libraries\Elasticsearch\Sort; use App\Models\Solo\Score; use App\Models\User; +use App\Models\UserProfileCustomization; class ScoreSearchParams extends SearchParams { const VALID_TYPES = ['global', 'country', 'friend']; const DEFAULT_TYPE = 'global'; + public ?array $beatmapIds = null; + public ?Score $beforeScore = null; + public ?int $beforeTotalScore = null; + public ?array $excludeMods = null; + public ?bool $isLegacy = null; + public ?array $mods = null; + public ?int $rulesetId = null; + public $size = 50; + public ?User $user = null; + public ?int $userId = null; + + private ?string $countryCode = null; + private string $type = self::DEFAULT_TYPE; + public static function fromArray(array $rawParams): static { $params = new static(); @@ -39,19 +54,10 @@ public static function fromArray(array $rawParams): static return $params; } - public ?array $beatmapIds = null; - public ?Score $beforeScore = null; - public ?int $beforeTotalScore = null; - public ?array $excludeMods = null; - public ?bool $isLegacy = null; - public ?array $mods = null; - public ?int $rulesetId = null; - public $size = 50; - public ?User $user = null; - public ?int $userId = null; - - private ?string $countryCode = null; - private string $type = self::DEFAULT_TYPE; + public static function showLegacyForUser(?User $user): bool + { + return $user?->userProfileCustomization?->legacy_score_only ?? UserProfileCustomization::DEFAULT_LEGACY_ONLY_ATTRIBUTE; + } public function getCountryCode(): string { diff --git a/app/Models/UserProfileCustomization.php b/app/Models/UserProfileCustomization.php index cc567cced5d..e7cf6ac4d94 100644 --- a/app/Models/UserProfileCustomization.php +++ b/app/Models/UserProfileCustomization.php @@ -43,6 +43,8 @@ class UserProfileCustomization extends Model 'views' => ['all' => ['card', 'list', 'brick'], 'default' => 'card'], ]; + private const DEFAULT_LEGACY_ONLY_ATTRIBUTE = true; + public $incrementing = false; protected $casts = [ @@ -194,6 +196,16 @@ public function setForumPostsShowDeletedAttribute($value) $this->setOption('forum_posts_show_deleted', get_bool($value)); } + public function getLegacyScoreOnlyAttribute(): bool + { + return $this->options['legacy_score_only'] ?? static::DEFAULT_LEGACY_ONLY_ATTRIBUTE; + } + + public function setLegacyScoreOnlyAttribute($value): void + { + $this->setOption('legacy_score_only', get_bool($value)); + } + public function getUserListFilterAttribute() { return $this->options['user_list_filter'] ?? static::USER_LIST['filters']['default']; diff --git a/app/Transformers/UserCompactTransformer.php b/app/Transformers/UserCompactTransformer.php index 4df771e6390..ee2766d4705 100644 --- a/app/Transformers/UserCompactTransformer.php +++ b/app/Transformers/UserCompactTransformer.php @@ -450,6 +450,7 @@ public function includeUserPreferences(User $user) 'beatmapset_title_show_original', 'comments_show_deleted', 'forum_posts_show_deleted', + 'legacy_score_only', 'profile_cover_expanded', 'user_list_filter', 'user_list_sort', From a583b4344dd9d2e5401afc80fa33df7148079558 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 25 Dec 2023 21:55:22 +0900 Subject: [PATCH 099/102] Update indexer docker setup --- docker-compose.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ad823c25b1c..01995066de4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -145,8 +145,8 @@ services: - "${NGINX_PORT:-8080}:80" score-indexer: - image: pppy/osu-elastic-indexer - command: ["queue", "watch", "--set-current"] + image: pppy/osu-elastic-indexer:master + command: ["queue", "watch"] depends_on: redis: condition: service_healthy @@ -159,8 +159,8 @@ services: SCHEMA: "${SCHEMA:-1}" score-indexer-test: - image: pppy/osu-elastic-indexer - command: ["queue", "watch", "--set-current"] + image: pppy/osu-elastic-indexer:master + command: ["queue", "watch"] depends_on: redis: condition: service_healthy From 1cd927cc4bce4ae34677cd468d84c8b7574d4eb8 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 25 Dec 2023 22:42:24 +0900 Subject: [PATCH 100/102] Add correct scope for beatmap pack subquery --- app/Models/Beatmapset.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Models/Beatmapset.php b/app/Models/Beatmapset.php index 0c4d19984fa..61742f267ba 100644 --- a/app/Models/Beatmapset.php +++ b/app/Models/Beatmapset.php @@ -307,11 +307,12 @@ public function scopeWithPackTags(Builder $query): Builder $packItemBeatmapsetIdColumn = (new BeatmapPackItem())->qualifyColumn('beatmapset_id'); $packQuery = BeatmapPack ::selectRaw("GROUP_CONCAT({$packTagColumn} SEPARATOR ',')") + ->default() ->whereRelation( 'items', - DB::raw("{$packItemBeatmapsetIdColumn}"), - DB::raw("{$idColumn}"), - )->toSql(); + DB::raw($packItemBeatmapsetIdColumn), + DB::raw($idColumn), + )->toRawSql(); return $query ->select('*') From 785701ee4387345133bd866e360699057e28f442 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 26 Dec 2023 16:57:14 +0900 Subject: [PATCH 101/102] The const used somewhere else --- app/Models/UserProfileCustomization.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/UserProfileCustomization.php b/app/Models/UserProfileCustomization.php index e7cf6ac4d94..1ff55c566f6 100644 --- a/app/Models/UserProfileCustomization.php +++ b/app/Models/UserProfileCustomization.php @@ -37,14 +37,14 @@ class UserProfileCustomization extends Model const BEATMAPSET_DOWNLOAD = ['all', 'no_video', 'direct']; + const DEFAULT_LEGACY_ONLY_ATTRIBUTE = true; + const USER_LIST = [ 'filters' => ['all' => ['all', 'online', 'offline'], 'default' => 'all'], 'sorts' => ['all' => ['last_visit', 'rank', 'username'], 'default' => 'last_visit'], 'views' => ['all' => ['card', 'list', 'brick'], 'default' => 'card'], ]; - private const DEFAULT_LEGACY_ONLY_ATTRIBUTE = true; - public $incrementing = false; protected $casts = [ From 6ef9835cfbca46d808b9ca3b05d92326cfcc41cb Mon Sep 17 00:00:00 2001 From: peppy Date: Thu, 28 Dec 2023 10:52:30 +0000 Subject: [PATCH 102/102] Update mod definitions --- database/mods.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/database/mods.json b/database/mods.json index 0fb0df78b26..ed40b0dc4cc 100644 --- a/database/mods.json +++ b/database/mods.json @@ -37,7 +37,7 @@ "SD", "PF", "AC", - "AP" + "CN" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -140,8 +140,7 @@ "IncompatibleMods": [ "NF", "PF", - "TP", - "AP" + "TP" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -165,8 +164,7 @@ "IncompatibleMods": [ "NF", "SD", - "AC", - "AP" + "AC" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -353,8 +351,7 @@ "IncompatibleMods": [ "EZ", "NF", - "PF", - "AP" + "PF" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -605,6 +602,7 @@ "Type": "Automation", "Settings": [], "IncompatibleMods": [ + "NF", "AL", "SG", "AT", @@ -650,10 +648,6 @@ "Type": "Automation", "Settings": [], "IncompatibleMods": [ - "NF", - "SD", - "PF", - "AC", "AT", "CN", "RX", @@ -1214,7 +1208,8 @@ "IncompatibleMods": [ "SD", "PF", - "AC" + "AC", + "CN" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -1616,6 +1611,7 @@ "Type": "Automation", "Settings": [], "IncompatibleMods": [ + "NF", "SG", "AT", "CN", @@ -1848,7 +1844,8 @@ "IncompatibleMods": [ "SD", "PF", - "AC" + "AC", + "CN" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -2216,6 +2213,7 @@ "Type": "Automation", "Settings": [], "IncompatibleMods": [ + "NF", "AT", "CN", "RX" @@ -2441,7 +2439,8 @@ "IncompatibleMods": [ "SD", "PF", - "AC" + "AC", + "CN" ], "RequiresConfiguration": false, "UserPlayable": true, @@ -3137,6 +3136,7 @@ "Type": "Automation", "Settings": [], "IncompatibleMods": [ + "NF", "AT", "CN", "AS"