";
}
public function parseBoxHelperSuffix()
@@ -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/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/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');
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/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/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/Opengraph/Forum/ForumOpengraph.php b/app/Libraries/Opengraph/Forum/ForumOpengraph.php
index 6d730161cc4..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?->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..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?->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/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 14bb56bb522..f0715e9e56d 100644
--- a/app/Libraries/OsuAuthorize.php
+++ b/app/Libraries/OsuAuthorize.php
@@ -539,7 +539,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);
}
@@ -672,7 +672,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';
}
@@ -939,7 +939,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);
}
@@ -988,7 +988,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);
}
@@ -1424,7 +1424,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';
}
@@ -1529,14 +1529,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';
}
@@ -1799,7 +1799,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';
}
@@ -1946,7 +1946,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';
}
@@ -2158,13 +2158,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
deleted file mode 100644
index 1191a7e1789..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 config('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/RouteSection.php b/app/Libraries/RouteSection.php
index af03c091baf..aac4a727a9b 100644
--- a/app/Libraries/RouteSection.php
+++ b/app/Libraries/RouteSection.php
@@ -140,32 +140,27 @@ class RouteSection
],
];
- public function getCurrent($key = null)
+ public function getCurrent(): array
{
- $data = request()->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()
{
- $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 +177,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 +185,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',
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..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(
- config('osu.elasticsearch.prefix').'solo_scores',
+ $GLOBALS['cfg']['osu']['elasticsearch']['prefix'].'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
@@ -116,17 +116,19 @@ 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:{$schema}", ...$values);
}
}
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/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/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 039b75504f8..2ad89ab2bc5 100644
--- a/app/Libraries/Session/SessionManager.php
+++ b/app/Libraries/Session/SessionManager.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 App\Libraries\Session;
class SessionManager extends \Illuminate\Session\SessionManager
@@ -15,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 7a2e07307da..57f82b936f1 100644
--- a/app/Libraries/Session/Store.php
+++ b/app/Libraries/Session/Store.php
@@ -3,172 +3,121 @@
// 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 App\Interfaces\SessionVerificationInterface;
+use Illuminate\Redis\Connections\PhpRedisConnection;
+use Illuminate\Session\Store as BaseStore;
+use Illuminate\Support\Arr;
use Jenssegers\Agent\Agent;
-use LaravelRedis as Redis;
-class Store extends \Illuminate\Session\Store
+class Store extends BaseStore implements SessionVerificationInterface
{
- const SESSION_ID_LENGTH = 40;
+ private const PREFIX = 'sessions:';
- public static function destroy($userId, ?string $excludedSessionId = null)
+ public static function batchDelete(?int $userId, ?array $ids = null): void
{
- if (!static::isUsingRedis()) {
+ $ids ??= static::ids($userId);
+
+ if (empty($ids)) {
return;
}
- $keys = static::keys($userId);
- if ($excludedSessionId !== null) {
- $keys = array_filter($keys, fn ($key) => $key !== $excludedSessionId);
+ $currentSession = \Session::instance();
+ if (in_array($currentSession->getId(), $ids, true)) {
+ $currentSession->flush();
}
- UserSessionEvent::newLogout($userId, $keys)->broadcast();
- Redis::del(array_merge([static::listKey($userId)], $keys));
- }
-
- public static function isUsingRedis()
- {
- return config('session.driver') === 'redis';
- }
-
- /**
- * Get the redis key prefix for the given user (excluding cache prefix).
- *
- * @return string
- */
- public static function keyPrefix($userId)
- {
- return 'sessions:'.($userId ?? 'guest');
- }
- public static function keys($userId)
- {
- if (!static::isUsingRedis()) {
- return [];
+ $redis = self::redis();
+ $redis->del($ids);
+ if ($userId !== null) {
+ $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, $idsForEvent)->broadcast();
}
-
- 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)
+ public static function findForVerification(string $id): static
{
- return config('cache.prefix').':'.static::keyPrefix($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,
- ];
+ return static::findOrNew($id);
}
- public static function removeFullId($userId, $fullId)
+ public static function findOrNew(?string $id = null): static
{
- static::removeKey($userId, config('cache.prefix').':'.$fullId);
- }
+ if ($id !== null) {
+ $currentSession = \Session::instance();
- public static function removeKey($userId, $key)
- {
- if (!static::isUsingRedis()) {
- return;
+ if ($currentSession->getId() === $id) {
+ return $currentSession;
+ }
}
- if ($userId === null) {
- $userId = static::parseKey($key)['userId'];
+ $ret = (new SessionManager(\App::getInstance()))->instance();
+ if ($id !== null) {
+ $ret->setId($id);
}
+ $ret->start();
- UserSessionEvent::newLogout($userId, [$key])->broadcast();
- Redis::srem(static::listKey($userId), $key);
- Redis::del($key);
+ return $ret;
}
- /**
- * Destroys a session owned by the current user that is identified by the given id.
- *
- * @return bool
- */
- public function destroyUserSession($sessionId)
+ public static function ids(?int $userId): array
{
- if (Auth::check()) {
- $userId = Auth::user()->user_id;
- $fullSessionId = static::keyPrefix($userId).':'.$sessionId;
- $this->handler->destroy($fullSessionId);
-
- static::removeFullId($userId, $fullSessionId);
-
- return true;
- }
-
- return false;
+ return $userId === null
+ ? []
+ : array_map(
+ // The ids were previously stored with prefix.
+ fn ($id) => str_starts_with($id, 'osu-next:') ? substr($id, 9) : $id,
+ self::redis()->smembers(self::listKey($userId)),
+ );
}
- /**
- * Return whether the given id matches the current session's id.
- *
- * @return bool
- */
- public function isCurrentSession($sessionId)
+ public static function keyForEvent(string $id): string
{
- return $this->getIdWithoutKeyPrefix() === $this->stripKeyPrefix($sessionId);
+ // TODO: use config's database.redis.session.prefix (also in notification-server)
+ return "osu-next:{$id}";
}
- /**
- * Returns whether the current session is a guest session based on the key prefix of the session id.
- *
- * @return bool
- */
- public function isGuestSession()
+ public static function keysForEvent(array $ids): array
{
- return starts_with($this->getId(), static::keyPrefix(null).':');
+ return array_map(static::keyForEvent(...), $ids);
}
- public function currentUserSessions()
+ public static function sessions(int $userId): array
{
- 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)),
+ self::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;
@@ -176,114 +125,139 @@ 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 config('cache.prefix').':'.$this->getId();
+ return \LaravelRedis::connection($GLOBALS['cfg']['session']['connection']);
+ }
+
+ 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());
}
/**
- * 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 $this;
+ }
+ public function isValidId($id)
+ {
+ // Overridden to allow prefixed id
return is_string($id);
}
- public function getIdWithoutKeyPrefix()
+ public function isVerified(): bool
+ {
+ return $this->attributes['verified'] ?? false;
+ }
+
+ public function markVerified(): void
{
- return $this->stripKeyPrefix($this->getId());
+ $this->attributes['verified'] = true;
+ $this->save();
}
/**
- * 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, 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 : $GLOBALS['cfg']['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) {
+ self::redis()->sadd(self::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.
+ // 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;
}
- /**
- * 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 self::PREFIX
+ .($userId ?? 'guest')
+ .':'
+ .parent::generateSessionId();
}
/**
@@ -294,7 +268,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));
@@ -307,14 +280,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/SessionVerification/Controller.php b/app/Libraries/SessionVerification/Controller.php
new file mode 100644
index 00000000000..0333f65b192
--- /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 = Helper::currentUserOrFail();
+ $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, Helper::currentUserOrFail());
+
+ return response(['message' => osu_trans('user_verification.errors.reissued')], 200);
+ }
+
+ public static function verify()
+ {
+ $key = strtr(get_string(\Request::input('verification_key')) ?? '', [' ' => '']);
+ $user = Helper::currentUserOrFail();
+ $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, $state);
+
+ 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, $state);
+ }
+
+ 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..aa44cf8c374
--- /dev/null
+++ b/app/Libraries/SessionVerification/Helper.php
@@ -0,0 +1,64 @@
+. 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 currentUserOrFail(): 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)) {
+ 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(
+ "{$GLOBALS['cfg']['datadog-helper']['prefix_web']}.verification.attempts",
+ 1,
+ compact('reason', 'source', 'type')
+ );
+ }
+
+ 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
new file mode 100644
index 00000000000..1f9b0133f15
--- /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 CarbonImmutable $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($GLOBALS['cfg']['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($this->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 >= $GLOBALS['cfg']['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/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/Uploader.php b/app/Libraries/Uploader.php
new file mode 100644
index 00000000000..34c8ce4a850
--- /dev/null
+++ b/app/Libraries/Uploader.php
@@ -0,0 +1,114 @@
+. 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 const DEFAULT_MAX_FILESIZE = 10_000_000;
+
+ 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'] ?? static::DEFAULT_MAX_FILESIZE,
+ );
+ $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/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/Cover.php b/app/Libraries/User/Cover.php
new file mode 100644
index 00000000000..b008e8e1045
--- /dev/null
+++ b/app/Libraries/User/Cover.php
@@ -0,0 +1,93 @@
+. 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
+{
+ const CUSTOM_COVER_MAX_DIMENSIONS = [2400, 640];
+
+ 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/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/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/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
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 61c336ee09a..00000000000
--- a/app/Libraries/UserVerificationState.php
+++ /dev/null
@@ -1,158 +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\SessionManager;
-use App\Models\User;
-
-class UserVerificationState
-{
- protected $user;
-
- private $session;
-
- public static function fromCurrentRequest()
- {
- return new static(auth()->user(), session());
- }
-
- 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)
- {
- $session = new SessionManager(app());
- $session->setId($params['sessionId']);
- $session->start();
-
- return new static(User::find($params['userId']), $session);
- }
-
- 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;
- }
- }
-
- 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->getKey())->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/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/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/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/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();
diff --git a/app/Models/Beatmapset.php b/app/Models/Beatmapset.php
index 4a04566ec7f..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('*')
@@ -349,7 +350,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 +468,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 +585,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 +1072,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 +1131,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 +1241,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/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/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/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/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 d04ddb8f140..8e54716b6b7 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`.
*
@@ -124,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']);
};
}
@@ -230,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)
@@ -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/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/Multiplayer/UserScoreAggregate.php b/app/Models/Multiplayer/UserScoreAggregate.php
index bc3a6998c75..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;
}
@@ -202,7 +212,7 @@ public function userRank()
private function updateUserTotal(ScoreLink $currentScoreLink, PlaylistItemUserHighScore $prev)
{
- if ($prev->exists) {
+ if ($prev->score_id !== null) {
$this->total_score -= $prev->total_score;
$this->accuracy -= $prev->accuracy;
$this->pp -= $prev->pp;
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 de0060a1b7f..a639f9e63eb 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.
@@ -83,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/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/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 5a74a042819..6b4632a30a2 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',
@@ -146,18 +150,17 @@ public function getAttribute($key)
'beatmap_id',
'id',
'ruleset_id',
+ 'unix_updated_at',
'user_id' => $this->getRawAttribute($key),
'data' => $this->getClassCastableAttributeValue($key, $this->getRawAttribute($key)),
'has_replay',
- 'preserve' => (bool) $this->getRawAttribute($key),
-
- 'created_at',
- 'updated_at' => $this->getTimeFast($key),
+ 'preserve',
+ 'ranked' => (bool) $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,
@@ -184,7 +187,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());
}
@@ -215,7 +218,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 +237,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/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/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);
+ }
+}
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 04a34a07aa9..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;
});
}
@@ -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')
@@ -1831,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,
@@ -1973,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)
@@ -2081,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/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..1ff55c566f6 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;
/**
@@ -35,6 +37,8 @@ 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'],
@@ -49,7 +53,7 @@ class UserProfileCustomization extends Model
];
protected $primaryKey = 'user_id';
- private $cover;
+ private Uploader $customCover;
public static function repairExtrasOrder($value)
{
@@ -67,22 +71,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 +173,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;
@@ -195,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'];
@@ -268,6 +279,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' => Cover::CUSTOM_COVER_MAX_DIMENSIONS]],
+ );
+ }
+
+ public function cover()
+ {
+ return new Cover($this);
+ }
+
private function setOption($key, $value)
{
$this->options ??= [];
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/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/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/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/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/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..ee2766d4705 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(),
]);
}
@@ -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',
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/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 dbfe75eacf5..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,21 +463,16 @@ function log_error($exception)
{
Log::error($exception);
- if (config('sentry.dsn')) {
+ if ($GLOBALS['cfg']['sentry']['dsn']) {
Sentry::captureException($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')
@@ -528,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)
@@ -550,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);
@@ -559,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) {
@@ -573,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;
@@ -770,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
@@ -842,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) {
@@ -1049,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;
@@ -1065,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 = '')
@@ -1753,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/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",
diff --git a/config/cache.php b/config/cache.php
index 98f45767b86..1a182c5f3e4 100644
--- a/config/cache.php
+++ b/config/cache.php
@@ -13,7 +13,7 @@
|
*/
- 'default' => env('CACHE_DRIVER', 'file'),
+ 'default' => env('CACHE_DRIVER', 'redis'),
/*
|--------------------------------------------------------------------------
@@ -77,6 +77,6 @@
|
*/
- 'prefix' => 'osu-next',
+ 'prefix' => null,
];
diff --git a/config/database.php b/config/database.php
index 2102aef0463..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,15 +143,10 @@
'database' => get_int(env('CACHE_REDIS_DB')) ?? 0,
'password' => presence(env('CACHE_REDIS_PASSWORD')) ?? presence(env('REDIS_PASSWORD')),
'persistent' => true,
+ '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 +156,10 @@
'persistent' => true,
],
+ 'session' => [
+ ...$redisDefault,
+ 'prefix' => $redisCachePrefix,
+ ],
],
];
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 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 @@
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/config/session.php b/config/session.php
index 2da7990bb91..1957716d6d0 100644
--- a/config/session.php
+++ b/config/session.php
@@ -16,7 +16,7 @@
|
*/
- 'driver' => env('SESSION_DRIVER', 'file'),
+ 'driver' => env('SESSION_DRIVER', 'redis'),
/*
|--------------------------------------------------------------------------
@@ -71,7 +71,7 @@
|
*/
- 'connection' => null,
+ 'connection' => 'session',
/*
|--------------------------------------------------------------------------
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/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..a66b05eb14c
--- /dev/null
+++ b/database/migrations/2023_11_27_173516_add_video_url_on_artists.php
@@ -0,0 +1,31 @@
+. 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;
+
+return new class extends Migration
+{
+ /**
+ * Run the migrations.
+ */
+ public function up(): void
+ {
+ Schema::table('artists', function (Blueprint $table) {
+ $table->string('video_url')->nullable();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('artists', function (Blueprint $table) {
+ $table->dropColumn('video_url');
+ });
+ }
+};
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();
+ }
+};
diff --git a/database/mods.json b/database/mods.json
index d40e14a5430..ed40b0dc4cc 100644
--- a/database/mods.json
+++ b/database/mods.json
@@ -37,8 +37,7 @@
"SD",
"PF",
"AC",
- "RX",
- "AP"
+ "CN"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -141,9 +140,7 @@
"IncompatibleMods": [
"NF",
"PF",
- "TP",
- "RX",
- "AP"
+ "TP"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -167,9 +164,7 @@
"IncompatibleMods": [
"NF",
"SD",
- "AC",
- "RX",
- "AP"
+ "AC"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -356,9 +351,7 @@
"IncompatibleMods": [
"EZ",
"NF",
- "PF",
- "RX",
- "AP"
+ "PF"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -475,6 +468,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": [
@@ -603,6 +602,7 @@
"Type": "Automation",
"Settings": [],
"IncompatibleMods": [
+ "NF",
"AL",
"SG",
"AT",
@@ -628,10 +628,6 @@
"Type": "Automation",
"Settings": [],
"IncompatibleMods": [
- "NF",
- "SD",
- "PF",
- "AC",
"AL",
"SG",
"AT",
@@ -652,10 +648,6 @@
"Type": "Automation",
"Settings": [],
"IncompatibleMods": [
- "NF",
- "SD",
- "PF",
- "AC",
"AT",
"CN",
"RX",
@@ -1217,7 +1209,7 @@
"SD",
"PF",
"AC",
- "RX"
+ "CN"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -1318,8 +1310,7 @@
],
"IncompatibleMods": [
"NF",
- "PF",
- "RX"
+ "PF"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -1343,8 +1334,7 @@
"IncompatibleMods": [
"NF",
"SD",
- "AC",
- "RX"
+ "AC"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -1480,8 +1470,7 @@
],
"IncompatibleMods": [
"NF",
- "PF",
- "RX"
+ "PF"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -1622,6 +1611,7 @@
"Type": "Automation",
"Settings": [],
"IncompatibleMods": [
+ "NF",
"SG",
"AT",
"CN",
@@ -1641,10 +1631,6 @@
"Type": "Automation",
"Settings": [],
"IncompatibleMods": [
- "NF",
- "SD",
- "PF",
- "AC",
"SG",
"AT",
"CN"
@@ -1859,7 +1845,7 @@
"SD",
"PF",
"AC",
- "RX"
+ "CN"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -1958,8 +1944,7 @@
],
"IncompatibleMods": [
"NF",
- "PF",
- "RX"
+ "PF"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -1983,8 +1968,7 @@
"IncompatibleMods": [
"NF",
"SD",
- "AC",
- "RX"
+ "AC"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -2119,8 +2103,7 @@
"IncompatibleMods": [
"EZ",
"NF",
- "PF",
- "RX"
+ "PF"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -2230,6 +2213,7 @@
"Type": "Automation",
"Settings": [],
"IncompatibleMods": [
+ "NF",
"AT",
"CN",
"RX"
@@ -2247,10 +2231,6 @@
"Type": "Automation",
"Settings": [],
"IncompatibleMods": [
- "NF",
- "SD",
- "PF",
- "AC",
"AT",
"CN"
],
@@ -2459,7 +2439,8 @@
"IncompatibleMods": [
"SD",
"PF",
- "AC"
+ "AC",
+ "CN"
],
"RequiresConfiguration": false,
"UserPlayable": true,
@@ -3155,6 +3136,7 @@
"Type": "Automation",
"Settings": [],
"IncompatibleMods": [
+ "NF",
"AT",
"CN",
"AS"
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/docker-compose.yml b/docker-compose.yml
index eb65755916f..01995066de4 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:
@@ -147,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
@@ -161,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
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/resources/css/bem/artist.less b/resources/css/bem/artist.less
index 4d1d3a9fb9c..8bbeb9111b0 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,24 @@
}
}
- &__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-top: 20px;
+ aspect-ratio: 16 / 9;
+ width: 100%;
+ border-radius: @border-radius-large;
+ overflow: hidden;
}
&__white-link {
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;
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;
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/beatmapsets-show/header.tsx b/resources/js/beatmapsets-show/header.tsx
index b3124acbda5..8dbc6034909 100644
--- a/resources/js/beatmapsets-show/header.tsx
+++ b/resources/js/beatmapsets-show/header.tsx
@@ -352,13 +352,23 @@ export default class Header extends React.Component {
);
}
+ private statusToWikiLink(status: string): string {
+ let fragment: string;
+ if (status === 'wip' || status === 'pending') {
+ fragment = 'wip-and-pending';
+ } else {
+ fragment = status;
+ }
+ return wikiUrl(`Beatmap/Category#${fragment}`);
+ }
+
private readonly updateFavouritePopup = () => {
if (!this.hoveredFavouriteIcon) {
return;
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/js/profile-page/cover.tsx b/resources/js/profile-page/cover.tsx
index da2f5591c48..b608920468b 100644
--- a/resources/js/profile-page/cover.tsx
+++ b/resources/js/profile-page/cover.tsx
@@ -126,9 +126,9 @@ export default class Cover extends React.Component {
return (
<>
{this.props.user.is_supporter &&
-
+
{times(this.props.user.support_level ?? 0, (i) => )}
-
+
}
>
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/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/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/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/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/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/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/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 cf4e9930c50..0ec2d80016e 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' => 'Rankattu',
],
'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..f216348433f 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' => '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',
],
],
],
@@ -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_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/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..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',
@@ -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,12 +203,12 @@
'drain' => 'Terveyden valutus',
'accuracy' => 'Tarkkuus',
'ar' => 'Lähestymisnopeus',
- 'stars' => 'Vaikeustaso',
+ 'stars' => 'Tähtiluokitus',
'total_length' => 'Pituus',
'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/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..bfed28e116c 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',
@@ -113,7 +113,7 @@
],
'input' => [
- 'search' => 'etsi...',
+ 'search' => 'hae...',
],
'pagination' => [
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/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 487a0b1d8fb..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' => 'hyväksytty',
+ 'ranked' => 'rankattu',
],
'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/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 a28c8f39479..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',
],
@@ -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,13 +134,13 @@
],
],
'beatmaps' => [
- 'new' => 'Uudet Hyväksytyt Beatmapit',
+ 'new' => 'Uudet rankatut rytmikartat',
'popular' => 'Suositut rytmikartat',
'by_user' => 'tehnyt :user',
],
'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 d4b1d3b10f2..57c6cee5b40 100644
--- a/resources/lang/fi/layout.php
+++ b/resources/lang/fi/layout.php
@@ -67,7 +67,7 @@
'menu' => [
'beatmaps' => [
- '_' => 'beatmapit',
+ '_' => 'rytmikartat',
],
'community' => [
'_' => 'yhteisö',
@@ -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/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/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 001fa1e7856..df74fc03043 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',
@@ -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/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/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/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..c0d35a450ab 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/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/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/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/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/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/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/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/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/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 f5c595b2193..5f7553c3e20 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',
@@ -49,21 +49,21 @@
],
'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' => [
'cancelled' => [
- 'title' => '',
+ 'title' => 'Twoje zamówienie zostało anulowane',
'line_1' => [
'_' => "",
'link_text' => '',
@@ -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' => [
@@ -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/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..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' => "Это сделать нельзя, пока Вы заглушены.",
@@ -53,7 +53,7 @@
],
'beatmapset' => [
- 'discussion_locked' => 'Обсуждение этой карты закрыто.',
+ 'discussion_locked' => 'Возможность обсуждения этой карты закрыта.',
'metadata' => [
'nominated' => 'Вы не можете изменить метаданные номинируемой карты. В случае ошибок свяжитесь с номнатором или членом NAT.',
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 1235899a919..135877c0e58 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' => 'Рейтинговая',
],
@@ -68,15 +68,15 @@
'reply' => [
'open' => [
- 'guest' => 'Войдите, чтобы ответить',
+ 'guest' => 'Войдите в аккаунт, чтобы ответить',
'user' => 'Ответить',
],
],
'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..a3aa413c913 100644
--- a/resources/lang/ru/beatmaps.php
+++ b/resources/lang/ru/beatmaps.php
@@ -21,12 +21,12 @@
'guest' => 'Гостевая сложность от :user',
'kudosu_denied' => 'Отказано в получении кудосу.',
'message_placeholder_deleted_beatmap' => 'Эта сложность была удалена, и поэтому обсуждать её больше нельзя.',
- 'message_placeholder_locked' => 'Обсуждение этой карты было отключено.',
+ 'message_placeholder_locked' => 'Возможность обсуждения этой карты закрыта.',
'message_placeholder_silenced' => "Запрещено писать посты в обсуждении, пока вы заглушены.",
'message_type_select' => 'Выбрать тип комментария',
'reply_notice' => 'Нажмите Enter, чтобы ответить.',
'reply_placeholder' => 'Напишите ответ',
- 'require-login' => 'Пожалуйста, войдите в аккаунт, чтобы оставить сообщение или ответить',
+ 'require-login' => 'Пожалуйста, войдите в аккаунт, чтобы оставить отзыв',
'resolved' => 'Решено',
'restore' => 'восстановить',
'show_deleted' => 'Показать удалённые',
@@ -62,7 +62,7 @@
'message_placeholder' => [
'general' => 'Оставьте отзыв в Общее (:version)',
'generalAll' => 'Оставьте отзыв в Общее (все сложности)',
- 'review' => 'Напишите рецензию',
+ 'review' => 'Начните печатать',
'timeline' => 'Сообщите о тайм-коде в сложности :version',
],
@@ -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/beatmapset_events.php b/resources/lang/ru/beatmapset_events.php
index be1b22bcf8e..a48ca28bd90 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' => 'Обсуждение для этой карты было включено.',
- 'disqualify' => 'Дисквалифицирована :user. Причина: :discussion (:text).',
- 'disqualify_legacy' => 'Дисквалифицирована :user. Причина: :text.',
+ 'discussion_unlock' => 'Возможность обсуждения этой карты снова открыта.',
+ 'disqualify' => 'Получена дисквалификация от :user. Причина: :discussion (: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/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 5d7358ae401..cd14005e67d 100644
--- a/resources/lang/ru/comments.php
+++ b/resources/lang/ru/comments.php
@@ -33,7 +33,7 @@
],
'guest_button' => [
- 'new' => 'Войдите, чтобы комментировать',
+ 'new' => 'Войдите, чтобы прокомментировать',
'reply' => 'Войдите, чтобы ответить',
],
@@ -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..0062a90a300 100644
--- a/resources/lang/ru/layout.php
+++ b/resources/lang/ru/layout.php
@@ -174,11 +174,11 @@
'login' => [
'forgot' => "Я забыл свои данные",
'password' => 'пароль',
- 'title' => 'Войдите, чтобы продолжить',
+ 'title' => 'Вход',
'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..57beafebd6c 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 предложений',
],
],
@@ -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/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..e0e2b59d090 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' => '',
@@ -76,7 +76,7 @@
],
'notifications' => [
- 'beatmapset_discussion_qualified_problem' => 'belirtilen modlardaki nitelikli maplerin yeni sorunlarında 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',
diff --git a/resources/lang/tr/beatmaps.php b/resources/lang/tr/beatmaps.php
index 6072b3c932e..73cab335fcb 100644
--- a/resources/lang/tr/beatmaps.php
+++ b/resources/lang/tr/beatmaps.php
@@ -174,7 +174,7 @@
'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_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',
diff --git a/resources/lang/tr/beatmapset_watches.php b/resources/lang/tr/beatmapset_watches.php
index ae00fdfcafd..1428471aa21 100644
--- a/resources/lang/tr/beatmapset_watches.php
+++ b/resources/lang/tr/beatmapset_watches.php
@@ -6,7 +6,7 @@
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',
diff --git a/resources/lang/tr/notifications.php b/resources/lang/tr/notifications.php
index 70aa6e527af..b2caf09edc4 100644
--- a/resources/lang/tr/notifications.php
+++ b/resources/lang/tr/notifications.php
@@ -26,7 +26,7 @@
'filters' => [
'_' => 'hepsi',
'user' => 'profil',
- 'beatmapset' => 'beatmapler',
+ 'beatmapset' => 'haritalar',
'forum_topic' => 'forum',
'news_post' => 'gelişmeler',
'build' => 'sürümler',
@@ -35,7 +35,7 @@
'item' => [
'beatmapset' => [
- '_' => 'Beatmap',
+ '_' => 'Harita',
'beatmap_owner_change' => [
'_' => 'Konuk zorluk',
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/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 21a7480bf2c..c7488a1dcc3 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' => '',
],
@@ -90,11 +90,11 @@
],
],
'shipped' => [
- 'title' => '',
- 'tracking_details' => '',
+ 'title' => '您的訂單已出貨!',
+ 'tracking_details' => '物流追蹤詳情如下:',
'no_tracking_details' => [
'_' => "",
- 'link_text' => '',
+ 'link_text' => '向我們發送電子郵件',
],
],
],
@@ -110,16 +110,16 @@
'resume' => '繼續結賬',
'shipping_and_handling' => '',
'shopify_expired' => '此訂單的結帳網址已經過期。',
- 'subtotal' => '',
- 'total' => '',
+ 'subtotal' => '小計',
+ 'total' => '總計',
'details' => [
'order_number' => '',
'payment_terms' => '',
'salesperson' => '',
- 'shipping_method' => '',
+ 'shipping_method' => '運送方式',
'shipping_terms' => '',
- 'title' => '',
+ 'title' => '訂單詳情:',
],
'item' => [
@@ -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-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' => [
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',
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"
# 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}}"
// 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 @@
+ @if ($isSupporter)
This is a private link for osu!supporters. Please do not share it.
If you want to share access to the iOS beta with other users, link them to this page instead.
-
+ @else
Note that we may reset this link every few months to allow new users to test.
(because Apple has a limit on how many testers can be added)
- @if (!Auth::user())
+ @if ($user === null)
If you are an osu!supporter, please login for a more permanent link.
@endif
-