From c398aa2b694ff53a5459b8e987cc2e9404fb3202 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 19 Apr 2020 06:51:40 +0200 Subject: [PATCH] Add support for British English and allow the user to set a locale. --- .../Report/Audit/MonthReportGenerator.php | 6 +++--- .../Controllers/Chart/AccountController.php | 3 ++- app/Http/Controllers/Chart/BillController.php | 3 ++- .../Controllers/Chart/BudgetController.php | 4 ++-- .../Controllers/Chart/PiggyBankController.php | 5 +++-- .../Controllers/Chart/ReportController.php | 3 ++- app/Http/Controllers/Controller.php | 9 +++++---- .../Controllers/Json/RecurrenceController.php | 3 ++- .../Controllers/PreferencesController.php | 20 ++++++++++++++++++- app/Http/Middleware/Range.php | 17 ++++++++-------- app/Models/AccountMeta.php | 2 +- app/Models/Tag.php | 7 ------- app/Support/Amount.php | 8 +++++--- .../Http/Controllers/ChartGeneration.php | 3 ++- app/Support/Navigation.php | 10 ++++++---- app/Support/Steam.php | 13 ++++++++++++ config/firefly.php | 4 +++- 17 files changed, 78 insertions(+), 42 deletions(-) diff --git a/app/Generator/Report/Audit/MonthReportGenerator.php b/app/Generator/Report/Audit/MonthReportGenerator.php index 55757386c3..6ccd228b27 100644 --- a/app/Generator/Report/Audit/MonthReportGenerator.php +++ b/app/Generator/Report/Audit/MonthReportGenerator.php @@ -154,14 +154,14 @@ class MonthReportGenerator implements ReportGeneratorInterface $journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date'); } - + $locale = app('steam')->getLocale(); $return = [ 'journals' => $journals, 'currency' => $currency, 'exists' => count($journals) > 0, - 'end' => $this->end->formatLocalized((string) trans('config.month_and_day')), + 'end' => $this->end->formatLocalized((string) trans('config.month_and_day', [], $locale)), 'endBalance' => app('steam')->balance($account, $this->end), - 'dayBefore' => $date->formatLocalized((string) trans('config.month_and_day')), + 'dayBefore' => $date->formatLocalized((string) trans('config.month_and_day', [], $locale)), 'dayBeforeBalance' => $dayBeforeBalance, ]; diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index d6d1b4e786..3abf3d7399 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -571,6 +571,7 @@ class AccountController extends Controller */ private function periodByCurrency(Carbon $start, Carbon $end, Account $account, TransactionCurrency $currency): array { + $locale = app('steam')->getLocale(); $step = $this->calculateStep($start, $end); $result = [ 'label' => sprintf('%s (%s)', $account->name, $currency->symbol), @@ -582,7 +583,7 @@ class AccountController extends Controller switch ($step) { case '1D': // per day the entire period, balance for every day. - $format = (string) trans('config.month_and_day'); + $format = (string) trans('config.month_and_day', [], $locale); $range = app('steam')->balanceInRange($account, $start, $end, $currency); $previous = array_values($range)[0]; while ($end >= $current) { diff --git a/app/Http/Controllers/Chart/BillController.php b/app/Http/Controllers/Chart/BillController.php index b817da0147..d3d26048d4 100644 --- a/app/Http/Controllers/Chart/BillController.php +++ b/app/Http/Controllers/Chart/BillController.php @@ -111,6 +111,7 @@ class BillController extends Controller if ($cache->has()) { return response()->json($cache->get()); // @codeCoverageIgnore } + $locale = app('steam')->getLocale(); /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -131,7 +132,7 @@ class BillController extends Controller ]; foreach ($journals as $journal) { - $date = $journal['date']->formatLocalized((string) trans('config.month_and_day')); + $date = $journal['date']->formatLocalized((string) trans('config.month_and_day', [], $locale)); $chartData[0]['entries'][$date] = $bill->amount_min; // minimum amount of bill $chartData[1]['entries'][$date] = $bill->amount_max; // maximum amount of bill diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php index 19a80b2b1a..bd16c0b582 100644 --- a/app/Http/Controllers/Chart/BudgetController.php +++ b/app/Http/Controllers/Chart/BudgetController.php @@ -179,14 +179,14 @@ class BudgetController extends Controller if ($cache->has()) { return response()->json($cache->get()); // @codeCoverageIgnore } - + $locale = app('steam')->getLocale(); $entries = []; $amount = $budgetLimit->amount; $budgetCollection = new Collection([$budget]); while ($start <= $end) { $spent = $this->opsRepository->spentInPeriod($budgetCollection, new Collection, $start, $start); $amount = bcadd($amount, $spent); - $format = $start->formatLocalized((string)trans('config.month_and_day')); + $format = $start->formatLocalized((string)trans('config.month_and_day', [], $locale)); $entries[$format] = $amount; $start->addDay(); diff --git a/app/Http/Controllers/Chart/PiggyBankController.php b/app/Http/Controllers/Chart/PiggyBankController.php index 72a96d43b7..2d3246195a 100644 --- a/app/Http/Controllers/Chart/PiggyBankController.php +++ b/app/Http/Controllers/Chart/PiggyBankController.php @@ -76,6 +76,7 @@ class PiggyBankController extends Controller } $set = $repository->getEvents($piggyBank); $set = $set->reverse(); + $locale =app('steam')->getLocale(); // get first event or start date of piggy bank or today $startDate = $piggyBank->start_date ?? new Carbon; @@ -99,7 +100,7 @@ class PiggyBankController extends Controller } ); $currentSum = $filtered->sum('amount'); - $label = $oldest->formatLocalized((string) trans('config.month_and_day')); + $label = $oldest->formatLocalized((string) trans('config.month_and_day', [], $locale)); $chartData[$label] = $currentSum; $oldest = app('navigation')->addPeriod($oldest, $step, 0); } @@ -110,7 +111,7 @@ class PiggyBankController extends Controller } ); $finalSum = $finalFiltered->sum('amount'); - $finalLabel = $today->formatLocalized((string) trans('config.month_and_day')); + $finalLabel = $today->formatLocalized((string) trans('config.month_and_day', [], $locale)); $chartData[$finalLabel] = $finalSum; $data = $this->generator->singleSet($piggyBank->name, $chartData); diff --git a/app/Http/Controllers/Chart/ReportController.php b/app/Http/Controllers/Chart/ReportController.php index 79e3d65a7c..e9a9c4d1e8 100644 --- a/app/Http/Controllers/Chart/ReportController.php +++ b/app/Http/Controllers/Chart/ReportController.php @@ -79,6 +79,7 @@ class ReportController extends Controller if ($cache->has()) { return response()->json($cache->get()); // @codeCoverageIgnore } + $locale = app('steam')->getLocale(); $current = clone $start; $chartData = []; /** @var NetWorthInterface $helper */ @@ -110,7 +111,7 @@ class ReportController extends Controller /** @var array $netWorthItem */ foreach ($result as $netWorthItem) { $currencyId = $netWorthItem['currency']->id; - $label = $current->formatLocalized((string) trans('config.month_and_day')); + $label = $current->formatLocalized((string) trans('config.month_and_day', [], $locale)); if (!isset($chartData[$currencyId])) { $chartData[$currencyId] = [ 'label' => 'Net worth in ' . $netWorthItem['currency']->name, diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 9d69241442..04807b3468 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -85,15 +85,16 @@ class Controller extends BaseController $this->middleware( function ($request, $next) { + $locale = app('steam')->getLocale(); // translations for specific strings: - $this->monthFormat = (string) trans('config.month'); - $this->monthAndDayFormat = (string) trans('config.month_and_day'); - $this->dateTimeFormat = (string) trans('config.date_time'); + $this->monthFormat = (string) trans('config.month', [], $locale); + $this->monthAndDayFormat = (string) trans('config.month_and_day', [], $locale); + $this->dateTimeFormat = (string) trans('config.date_time', [], $locale); // get shown-intro-preference: if (auth()->check()) { $language = app('steam')->getLanguage(); - $locale = app('steam')->getLanguage(); + $locale = app('steam')->getLocale(); $page = $this->getPageName(); $shownDemo = $this->hasSeenDemo(); app('view')->share('language', $language); diff --git a/app/Http/Controllers/Json/RecurrenceController.php b/app/Http/Controllers/Json/RecurrenceController.php index e8ffc0e795..a747aa04ed 100644 --- a/app/Http/Controllers/Json/RecurrenceController.php +++ b/app/Http/Controllers/Json/RecurrenceController.php @@ -151,6 +151,7 @@ class RecurrenceController extends Controller $today = Carbon::now()->startOfDay(); $date = Carbon::createFromFormat('Y-m-d', $string)->startOfDay(); $preSelected = (string) $request->get('pre_select'); + $locale = app('steam')->getLocale(); Log::debug(sprintf('date = %s, today = %s. date > today? %s', $date->toAtomString(), $today->toAtomString(), var_export($date > $today, true))); Log::debug(sprintf('past = true? %s', var_export('true' === (string) $request->get('past'), true))); @@ -163,7 +164,7 @@ class RecurrenceController extends Controller $dayOfWeek = (string) trans(sprintf('config.dow_%s', $date->dayOfWeekIso)); $ndom = sprintf('ndom,%s,%s', $date->weekOfMonth, $date->dayOfWeekIso); $yearly = sprintf('yearly,%s', $date->format('Y-m-d')); - $yearlyDate = $date->formatLocalized((string) trans('config.month_and_day_no_year')); + $yearlyDate = $date->formatLocalized((string) trans('config.month_and_day_no_year', [], $locale)); $result = [ 'daily' => ['label' => (string) trans('firefly.recurring_daily'), 'selected' => 0 === strpos($preSelected, 'daily')], $weekly => ['label' => (string) trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]), diff --git a/app/Http/Controllers/PreferencesController.php b/app/Http/Controllers/PreferencesController.php index bd5d8f9a58..b3a161cb41 100644 --- a/app/Http/Controllers/PreferencesController.php +++ b/app/Http/Controllers/PreferencesController.php @@ -31,6 +31,7 @@ use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Routing\Redirector; use Illuminate\View\View; +use JsonException; /** * Class PreferencesController. @@ -90,8 +91,9 @@ class PreferencesController extends Controller $viewRange = $viewRangePref->data; $frontPageAccounts = app('preferences')->get('frontPageAccounts', $accountIds); - $language = app('preferences')->get('language', config('firefly.default_language', 'en_US'))->data; + $language = app('steam')->getLanguage(); $languages = config('firefly.languages'); + $locale = app('preferences')->get('locale', config('firefly.default_locale', 'equal'))->data; $listPageSize = app('preferences')->get('listPageSize', 50)->data; $customFiscalYear = app('preferences')->get('customFiscalYear', 0)->data; $fiscalYearStartStr = app('preferences')->get('fiscalYearStart', '01-01')->data; @@ -100,6 +102,15 @@ class PreferencesController extends Controller ksort($languages); + // list of locales also has "equal" which makes it equal to whatever the language is. + + try { + $locales = json_decode(file_get_contents(resource_path(sprintf('lang/%s/locales.json', $language))), true, 512, JSON_THROW_ON_ERROR); + } catch (JsonException $e) { + Log::error($e->getMessage()); + $locales = []; + } + $locales = ['equal' => (string) trans('firefly.equal_to_language')] + $locales; // an important fallback is that the frontPageAccount array gets refilled automatically // when it turns up empty. if (0 === count($frontPageAccounts->data)) { @@ -113,6 +124,8 @@ class PreferencesController extends Controller 'groupedAccounts', 'frontPageAccounts', 'languages', + 'locales', + 'locale', 'tjOptionalFields', 'viewRange', 'customFiscalYear', @@ -172,6 +185,11 @@ class PreferencesController extends Controller session()->flash('info', 'All translations are supplied by volunteers. There might be errors and mistakes. I appreciate your feedback.'); } + // same for locale: + /** @var Preference $currentLocale */ + $locale = $request->get('locale'); + app('preferences')->set('locale', $locale); + // optional fields for transactions: $setOptions = $request->get('tj'); $optionalTj = [ diff --git a/app/Http/Middleware/Range.php b/app/Http/Middleware/Range.php index 226addbfca..b8a0ca8780 100644 --- a/app/Http/Middleware/Range.php +++ b/app/Http/Middleware/Range.php @@ -76,15 +76,14 @@ class Range { // get locale preference: $language = app('steam')->getLanguage(); - //$locale = $this->getLocale(); + $locale = app('steam')->getLocale(); App::setLocale($language); - Carbon::setLocale(substr($language, 0, 2)); + Carbon::setLocale(substr($locale, 0, 2)); - $locale = explode(',', (string) trans('config.locale')); - $locale = array_map('trim', $locale); + $localeArray = app('steam')->getLocaleArray($locale); - setlocale(LC_TIME, $locale); - $moneyResult = setlocale(LC_MONETARY, $locale); + setlocale(LC_TIME, $localeArray); + $moneyResult = setlocale(LC_MONETARY, $localeArray); // send error to view if could not set money format if (false === $moneyResult) { @@ -92,12 +91,12 @@ class Range } // save some formats: - $monthAndDayFormat = (string) trans('config.month_and_day'); - $dateTimeFormat = (string) trans('config.date_time'); + $monthAndDayFormat = (string) trans('config.month_and_day', [], $locale); + $dateTimeFormat = (string) trans('config.date_time', [], $locale); $defaultCurrency = app('amount')->getDefaultCurrency(); // also format for moment JS: - $madMomentJS = (string) trans('config.month_and_day_moment_js'); + $madMomentJS = (string) trans('config.month_and_day_moment_js', [], $locale); app('view')->share('madMomentJS', $madMomentJS); app('view')->share('monthAndDayFormat', $monthAndDayFormat); diff --git a/app/Models/AccountMeta.php b/app/Models/AccountMeta.php index 66b8fe7b7c..c1b661e5a2 100644 --- a/app/Models/AccountMeta.php +++ b/app/Models/AccountMeta.php @@ -83,7 +83,7 @@ class AccountMeta extends Model */ public function getDataAttribute($value) { - return json_decode($value); + return json_decode($value, true, 512, JSON_THROW_ON_ERROR); } /** diff --git a/app/Models/Tag.php b/app/Models/Tag.php index 45c56c3368..1a7834771e 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -78,13 +78,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property-read \Illuminate\Database\Eloquent\Collection|Location[] $locations * @property-read int|null $locations_count * @property-read int|null $transaction_journals_count - * @property \Illuminate\Support\Carbon|null $created_at - * @property \Illuminate\Support\Carbon|null $updated_at - * @property string $tagMode - * @property string|null $description - * @property float|null $latitude - * @property float|null $longitude - * @property int|null $zoomLevel */ class Tag extends Model { diff --git a/app/Support/Amount.php b/app/Support/Amount.php index c5b69fbdbf..729539a2f6 100644 --- a/app/Support/Amount.php +++ b/app/Support/Amount.php @@ -325,9 +325,11 @@ class Amount */ public function getLocaleInfo(): array { - $locale = explode(',', (string) trans('config.locale')); - $locale = array_map('trim', $locale); - setlocale(LC_MONETARY, $locale); + // get config from preference, not from translation: + $locale = app('steam')->getLocale(); + $array = app('steam')->getLocaleArray($locale); + + setlocale(LC_MONETARY, $array); $info = localeconv(); // correct variables $info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes'); diff --git a/app/Support/Http/Controllers/ChartGeneration.php b/app/Support/Http/Controllers/ChartGeneration.php index f19b9370fd..9f708d2052 100644 --- a/app/Support/Http/Controllers/ChartGeneration.php +++ b/app/Support/Http/Controllers/ChartGeneration.php @@ -61,6 +61,7 @@ trait ChartGeneration return $cache->get(); // @codeCoverageIgnore } Log::debug('Regenerate chart.account.account-balance-chart from scratch.'); + $locale = app('steam')->getLocale(); /** @var GeneratorInterface $generator */ $generator = app(GeneratorInterface::class); @@ -89,7 +90,7 @@ trait ChartGeneration $previous = array_values($range)[0]; while ($currentStart <= $end) { $format = $currentStart->format('Y-m-d'); - $label = $currentStart->formatLocalized((string)trans('config.month_and_day')); + $label = $currentStart->formatLocalized((string)trans('config.month_and_day', [], $locale)); $balance = isset($range[$format]) ? round($range[$format], 12) : $previous; $previous = $balance; $currentStart->addDay(); diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index 581e3a4663..3199d74e29 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -287,10 +287,11 @@ class Navigation */ public function listOfPeriods(Carbon $start, Carbon $end): array { + $locale = app('steam')->getLocale(); // define period to increment $increment = 'addDay'; $format = $this->preferredCarbonFormat($start, $end); - $displayFormat = (string)trans('config.month_and_day'); + $displayFormat = (string)trans('config.month_and_day', [], $locale); // increment by month (for year) if ($start->diffInMonths($end) > 1) { $increment = 'addMonth'; @@ -391,13 +392,14 @@ class Navigation */ public function preferredCarbonLocalizedFormat(Carbon $start, Carbon $end): string { - $format = (string)trans('config.month_and_day'); + $locale = app('steam')->getLocale(); + $format = (string)trans('config.month_and_day', [], $locale); if ($start->diffInMonths($end) > 1) { - $format = (string)trans('config.month'); + $format = (string)trans('config.month', [], $locale); } if ($start->diffInMonths($end) > 12) { - $format = (string)trans('config.year'); + $format = (string)trans('config.year', [], $locale); } return $format; diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 4c92d5be2c..8a7281bcf9 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -610,4 +610,17 @@ class Steam return $locale; } + /** + * @param string $locale + * + * @return array + */ + public function getLocaleArray(string $locale): array { + return [ + sprintf('%s', $locale), + sprintf('%s.utf8', $locale), + sprintf('%s.UTF-8', $locale), + ]; + } + } diff --git a/config/firefly.php b/config/firefly.php index 875656054c..c840e502f5 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -323,7 +323,8 @@ return [ */ 'languages' => [ // currently enabled languages - 'en_US' => ['name_locale' => 'English', 'name_english' => 'English'], + 'en_US' => ['name_locale' => 'English (US)', 'name_english' => 'English (US)'], + 'en_GB' => ['name_locale' => 'English (GB)', 'name_english' => 'English (GB)'], 'cs_CZ' => ['name_locale' => 'Czech', 'name_english' => 'Czech'], 'el_GR' => ['name_locale' => 'Ελληνικά', 'name_english' => 'Greek'], 'es_ES' => ['name_locale' => 'Español', 'name_english' => 'Spanish'], @@ -557,6 +558,7 @@ return [ ], 'default_currency' => 'EUR', 'default_language' => envNonEmpty('DEFAULT_LANGUAGE', 'en_US'), + 'default_locale' => envNonEmpty('DEFAULT_LOCALE', 'equal'), 'search_modifiers' => ['amount_is', 'amount', 'amount_max', 'amount_min', 'amount_less', 'amount_more', 'source', 'destination', 'category', 'budget', 'bill', 'type', 'date', 'date_before', 'date_after', 'on', 'before', 'after', 'from', 'to', 'tag', 'created_on', 'updated_on',],