Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions Classes/Service/UsageService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,18 @@
use DeepL\Usage;
use TYPO3\CMS\Backend\Toolbar\Enumeration\InformationStatus;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Localization\Locales;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use WebVision\Deepltranslate\Core\ClientInterface;
use WebVision\Deepltranslate\Core\Event\Listener\UsageToolBarEventListener;
use WebVision\Deepltranslate\Core\Hooks\UsageProcessAfterFinishHook;

final class UsageService implements UsageServiceInterface
{
protected ClientInterface $client;

public function __construct(
ClientInterface $client
private readonly ClientInterface $client,
private readonly Locales $locales
) {
$this->client = $client;
}

public function getCurrentUsage(): ?Usage
Expand Down Expand Up @@ -61,14 +60,16 @@ public function isTranslateLimitExceeded(): bool
*/
public function formatNumber(int $number)
{
$language = 'en';
$language = 'default';
if ($this->getBackendUser() !== null) {
$uc = $this->getBackendUser()->uc;
if (is_array($uc) && array_key_exists('lang', $uc)) {
$language = $uc['lang'];
}
}
$numberFormatter = new \NumberFormatter($language, \NumberFormatter::DECIMAL);

$locale = $this->locales->createLocale($language);
$numberFormatter = new \NumberFormatter($locale->getLanguageCode(), \NumberFormatter::DECIMAL);
return $numberFormatter->format($number);
}

Expand Down
6 changes: 6 additions & 0 deletions Tests/Functional/Services/Fixtures/Pages.csv
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ pages,,,,,
tt_content,
,uid,pid,header,CType,bodytext
,3,1,"DeepL-Functional-Test Element","text",""
"be_users"
,"uid","pid","tstamp","username","password","admin","disable","starttime","endtime","options","crdate","workspace_perms","deleted","TSconfig","lastlogin","workspace_id","uc"
# The password is "password"
# The user has a broken/outdated uc lang configuration. This is required testing the behaviour of #486
,1,0,1366642540,"admin","$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1",1,0,0,0,0,1366642540,1,0,,1371033743,0,"a:19:{s:10:""moduleData"";a:7:{s:28:""dashboard/current_dashboard/"";s:40:""764f4d1012c7b870a98ffd1e8dd3ff5e133cb451"";s:9:""scheduler"";a:1:{s:6:""action"";s:16:""scheduler_manage"";}s:13:""system_config"";a:1:{s:4:""tree"";s:3:""tca"";}s:10:""web_layout"";a:3:{s:8:""function"";s:1:""2"";s:8:""language"";s:1:""2"";s:10:""showHidden"";b:1;}s:10:""FormEngine"";a:2:{i:0;a:2:{s:32:""c31c3d00814edbf9b2ddab640af3f55d"";a:5:{i:0;s:116:""Bacon ipsum dolor sit strong amet capicola jerky pork chop rump shoulder shank. Shankle strip steak pig salami link."";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:14;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:34:""&edit%5Btt_content%5D%5B14%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:14;s:3:""pid"";i:10;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:99:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=10#element-tt_content-14"";}s:32:""c312013d83c1a6ad7fec8b36a37ba3c8"";a:5:{i:0;s:25:""TYPO3 Styleguide Frontend"";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:1;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:33:""&edit%5Btt_content%5D%5B1%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:1;s:3:""pid"";i:1;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:98:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=1&#element-tt_content-1"";}}i:1;s:32:""d63be24a7702dd6c8c0504bfe838a532"";}s:57:""TYPO3\CMS\Backend\Utility\BackendUtility::getUpdateSignal"";a:0:{}s:16:""opendocs::recent"";a:5:{s:32:""d63be24a7702dd6c8c0504bfe838a532"";a:5:{i:0;s:120:""Bacon ipsum dolor sit strong amet capicola jerky pork chop rump shoulder shank. Haxe Streifen Steak Schwein Salami Link."";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:44;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:34:""&edit%5Btt_content%5D%5B44%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:44;s:3:""pid"";i:8;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:99:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=8&#element-tt_content-44"";}s:32:""ffbd6ae78a9aa555f88d6295c30fb80c"";a:5:{i:0;s:116:""Bacon ipsum dolor sit strong amet capicola jerky pork chop rump shoulder shank. Shankle strip steak pig salami link."";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:10;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:34:""&edit%5Btt_content%5D%5B10%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:10;s:3:""pid"";i:8;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:98:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=8#element-tt_content-10"";}s:32:""f3a80bc04cdfd6ed305676c6deecde13"";a:5:{i:0;s:25:""TYPO3 Styleguide Frontend"";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:43;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:34:""&edit%5Btt_content%5D%5B43%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:43;s:3:""pid"";i:1;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:70:""/typo3/module/dashboard?token=dcec9d55204841dc643c2622b1dd11306044d7fa"";}s:32:""c312013d83c1a6ad7fec8b36a37ba3c8"";a:5:{i:0;s:25:""TYPO3 Styleguide Frontend"";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:1;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:33:""&edit%5Btt_content%5D%5B1%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:1;s:3:""pid"";i:1;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:97:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=1#element-tt_content-1"";}s:32:""9b967901d6c9df7fbe10e9cd1eacc0fe"";a:5:{i:0;s:24:""styleguide frontend demo"";i:1;a:5:{s:4:""edit"";a:1:{s:5:""pages"";a:1:{i:1;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";a:1:{s:5:""pages"";a:1:{s:16:""sys_language_uid"";s:1:""0"";}}s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:76:""&edit%5Bpages%5D%5B1%5D=edit&overrideVals%5Bpages%5D%5Bsys_language_uid%5D=0"";i:3;a:5:{s:5:""table"";s:5:""pages"";s:3:""uid"";i:1;s:3:""pid"";i:0;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:217:""/typo3/record/edit?token=ae076486b94686606614f90d8a155ec1f785183e&edit%5Btt_content%5D%5B14%5D=edit&returnUrl=/typo3/module/web/layout?token%3D2fb2757ce2a0f7275162273a7363c3cdf5ae31e0%26id%3D10%23element-tt_content-14"";}}}s:14:""emailMeAtLogin"";i:0;s:8:""titleLen"";s:2:""50"";s:20:""edit_docModuleUpload"";i:1;s:15:""moduleSessionID"";a:7:{s:28:""dashboard/current_dashboard/"";s:40:""e47ba98e40d443d825f5d08a6545e37bbc86bac5"";s:9:""scheduler"";s:40:""e47ba98e40d443d825f5d08a6545e37bbc86bac5"";s:13:""system_config"";s:40:""e47ba98e40d443d825f5d08a6545e37bbc86bac5"";s:10:""web_layout"";s:40:""e47ba98e40d443d825f5d08a6545e37bbc86bac5"";s:10:""FormEngine"";s:40:""ac1694175250c17ad2c05ef590e41376512745be"";s:57:""TYPO3\CMS\Backend\Utility\BackendUtility::getUpdateSignal"";s:40:""75d90be2aa2bf0625bafeee69c3fdd82f726db12"";s:16:""opendocs::recent"";s:40:""ac1694175250c17ad2c05ef590e41376512745be"";}s:8:""realName"";s:0:"""";s:5:""email"";s:0:"""";s:8:""password"";s:0:"""";s:9:""password2"";s:0:"""";s:6:""avatar"";s:0:"""";s:4:""lang"";s:7:""default"";s:11:""startModule"";s:0:"""";s:25:""showHiddenFilesAndFolders"";i:0;s:10:""copyLevels"";s:0:"""";s:18:""resetConfiguration"";s:0:"""";s:12:""mfaProviders"";s:0:"""";s:18:""backendTitleFormat"";s:10:""titleFirst"";s:11:""colorScheme"";s:4:""auto"";s:5:""theme"";s:6:""modern"";}"
,2,0,1366642540,"admin","$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1",1,0,0,0,0,1366642540,1,0,,1371033743,0,"a:19:{s:10:""moduleData"";a:7:{s:28:""dashboard/current_dashboard/"";s:40:""764f4d1012c7b870a98ffd1e8dd3ff5e133cb451"";s:9:""scheduler"";a:1:{s:6:""action"";s:16:""scheduler_manage"";}s:13:""system_config"";a:1:{s:4:""tree"";s:3:""tca"";}s:10:""web_layout"";a:3:{s:8:""function"";s:1:""2"";s:8:""language"";s:1:""2"";s:10:""showHidden"";b:1;}s:10:""FormEngine"";a:2:{i:0;a:2:{s:32:""c31c3d00814edbf9b2ddab640af3f55d"";a:5:{i:0;s:116:""Bacon ipsum dolor sit strong amet capicola jerky pork chop rump shoulder shank. Shankle strip steak pig salami link."";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:14;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:34:""&edit%5Btt_content%5D%5B14%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:14;s:3:""pid"";i:10;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:99:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=10#element-tt_content-14"";}s:32:""c312013d83c1a6ad7fec8b36a37ba3c8"";a:5:{i:0;s:25:""TYPO3 Styleguide Frontend"";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:1;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:33:""&edit%5Btt_content%5D%5B1%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:1;s:3:""pid"";i:1;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:98:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=1&#element-tt_content-1"";}}i:1;s:32:""d63be24a7702dd6c8c0504bfe838a532"";}s:57:""TYPO3\CMS\Backend\Utility\BackendUtility::getUpdateSignal"";a:0:{}s:16:""opendocs::recent"";a:5:{s:32:""d63be24a7702dd6c8c0504bfe838a532"";a:5:{i:0;s:120:""Bacon ipsum dolor sit strong amet capicola jerky pork chop rump shoulder shank. Haxe Streifen Steak Schwein Salami Link."";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:44;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:34:""&edit%5Btt_content%5D%5B44%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:44;s:3:""pid"";i:8;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:99:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=8&#element-tt_content-44"";}s:32:""ffbd6ae78a9aa555f88d6295c30fb80c"";a:5:{i:0;s:116:""Bacon ipsum dolor sit strong amet capicola jerky pork chop rump shoulder shank. Shankle strip steak pig salami link."";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:10;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:34:""&edit%5Btt_content%5D%5B10%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:10;s:3:""pid"";i:8;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:98:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=8#element-tt_content-10"";}s:32:""f3a80bc04cdfd6ed305676c6deecde13"";a:5:{i:0;s:25:""TYPO3 Styleguide Frontend"";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:43;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:34:""&edit%5Btt_content%5D%5B43%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:43;s:3:""pid"";i:1;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:70:""/typo3/module/dashboard?token=dcec9d55204841dc643c2622b1dd11306044d7fa"";}s:32:""c312013d83c1a6ad7fec8b36a37ba3c8"";a:5:{i:0;s:25:""TYPO3 Styleguide Frontend"";i:1;a:5:{s:4:""edit"";a:1:{s:10:""tt_content"";a:1:{i:1;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";N;s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:33:""&edit%5Btt_content%5D%5B1%5D=edit"";i:3;a:5:{s:5:""table"";s:10:""tt_content"";s:3:""uid"";i:1;s:3:""pid"";i:1;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:97:""/typo3/module/web/layout?token=2fb2757ce2a0f7275162273a7363c3cdf5ae31e0&id=1#element-tt_content-1"";}s:32:""9b967901d6c9df7fbe10e9cd1eacc0fe"";a:5:{i:0;s:24:""styleguide frontend demo"";i:1;a:5:{s:4:""edit"";a:1:{s:5:""pages"";a:1:{i:1;s:4:""edit"";}}s:7:""defVals"";N;s:12:""overrideVals"";a:1:{s:5:""pages"";a:1:{s:16:""sys_language_uid"";s:1:""0"";}}s:11:""columnsOnly"";N;s:6:""noView"";N;}i:2;s:76:""&edit%5Bpages%5D%5B1%5D=edit&overrideVals%5Bpages%5D%5Bsys_language_uid%5D=0"";i:3;a:5:{s:5:""table"";s:5:""pages"";s:3:""uid"";i:1;s:3:""pid"";i:0;s:3:""cmd"";s:4:""edit"";s:12:""deleteAccess"";b:1;}i:4;s:217:""/typo3/record/edit?token=ae076486b94686606614f90d8a155ec1f785183e&edit%5Btt_content%5D%5B14%5D=edit&returnUrl=/typo3/module/web/layout?token%3D2fb2757ce2a0f7275162273a7363c3cdf5ae31e0%26id%3D10%23element-tt_content-14"";}}}s:14:""emailMeAtLogin"";i:0;s:8:""titleLen"";s:2:""50"";s:20:""edit_docModuleUpload"";i:1;s:15:""moduleSessionID"";a:7:{s:28:""dashboard/current_dashboard/"";s:40:""e47ba98e40d443d825f5d08a6545e37bbc86bac5"";s:9:""scheduler"";s:40:""e47ba98e40d443d825f5d08a6545e37bbc86bac5"";s:13:""system_config"";s:40:""e47ba98e40d443d825f5d08a6545e37bbc86bac5"";s:10:""web_layout"";s:40:""e47ba98e40d443d825f5d08a6545e37bbc86bac5"";s:10:""FormEngine"";s:40:""ac1694175250c17ad2c05ef590e41376512745be"";s:57:""TYPO3\CMS\Backend\Utility\BackendUtility::getUpdateSignal"";s:40:""75d90be2aa2bf0625bafeee69c3fdd82f726db12"";s:16:""opendocs::recent"";s:40:""ac1694175250c17ad2c05ef590e41376512745be"";}s:8:""realName"";s:0:"""";s:5:""email"";s:0:"""";s:8:""password"";s:0:"""";s:9:""password2"";s:0:"""";s:6:""avatar"";s:0:"""";s:4:""lang"";s:2:""de"";s:11:""startModule"";s:0:"""";s:25:""showHiddenFilesAndFolders"";i:0;s:10:""copyLevels"";s:0:"""";s:18:""resetConfiguration"";s:0:"""";s:12:""mfaProviders"";s:0:"""";s:18:""backendTitleFormat"";s:10:""titleFirst"";s:11:""colorScheme"";s:4:""auto"";s:5:""theme"";s:6:""modern"";}"
36 changes: 36 additions & 0 deletions Tests/Functional/Services/UsageServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use DeepL\Usage;
use DeepL\UsageDetail;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use WebVision\Deepltranslate\Core\Service\DeeplService;
use WebVision\Deepltranslate\Core\Service\ProcessingInstruction;
Expand Down Expand Up @@ -104,4 +105,39 @@ public function checkHTMLMarkupsIsNotPartOfLimit(): void
static::assertInstanceOf(UsageDetail::class, $character);
static::assertEquals(strlen($translateContent), $character->count);
}

public static function numberFormatterLocalesDataProvider(): \Generator
{
yield 'Default formats to english' => [
'user' => 1,
'number' => 20000,
'expectedFormat' => '20,000',
];
yield 'BE uc lang "de" formats german' => [
'user' => 2,
'number' => 93254850,
'expectedFormat' => '93.254.850',
];
}
/**
* This test ensures that in PHP >=8.4 the NumberFormatter works correctly.
* With migrated TYPO3 data there is the possibility that uc['lang'] is set to 'default',
* which is no correct format for a locale the number formatter accepts. THis will lead
* to an error during initialisation.
*/
#[Test]
#[DataProvider('numberFormatterLocalesDataProvider')]
public function numberFormatRespectsLocalesAndDefault(
int $user,
int $number,
string $expectedFormat
): void {
$this->importCSVDataSet(__DIR__ . '/Fixtures/Pages.csv');
$this->setUpBackendUser($user);
/** @var UsageService $usageService */
$usageService = $this->get(UsageService::class);

$formatted = $usageService->formatNumber($number);
static::assertEquals($expectedFormat, $formatted);
}
}