diff --git a/app.php b/app.php index c61a562d..45ddce71 100644 --- a/app.php +++ b/app.php @@ -105,15 +105,7 @@ if (!empty(GROCY_BASE_PATH)) $app->setBasePath(GROCY_BASE_PATH); } -if (GROCY_MODE === 'production' || GROCY_MODE === 'dev') -{ - $app->add(new LocaleMiddleware($container, $app->getResponseFactory())); -} -else -{ - define('GROCY_LOCALE', GROCY_DEFAULT_LOCALE); -} - +$app->add(new LocaleMiddleware($container, $app->getResponseFactory())); $authMiddlewareClass = GROCY_AUTH_CLASS; $app->add(new $authMiddlewareClass($container, $app->getResponseFactory())); diff --git a/changelog/82_UNRELEASED_xxxx-xx-xx.md b/changelog/82_UNRELEASED_xxxx-xx-xx.md index ff3bf3be..131eea1c 100644 --- a/changelog/82_UNRELEASED_xxxx-xx-xx.md +++ b/changelog/82_UNRELEASED_xxxx-xx-xx.md @@ -55,6 +55,7 @@ - Fixed accent insensitive searching using the general table search field was broken - Fixed that it wasn't possible to log in using passwords containing special escape sequences (e.g. `<<`) +- Fixed that the initially created location and quantity units weren't localized (only applies to new installations) ### API diff --git a/config-dist.php b/config-dist.php index d63e6e93..f5b82e4a 100644 --- a/config-dist.php +++ b/config-dist.php @@ -21,6 +21,10 @@ Setting('MODE', 'production'); // The directory name of one of the available localization folders // in the "/localization" directory (e.g. "en" or "de") +// Grocy uses the first available locale / setting in this order +// 1. Browser prefered locale +// 2. The one set in user settings +// 3. The one defined here below Setting('DEFAULT_LOCALE', 'en'); // This is used to define the first day of a week for calendar views, diff --git a/localization/demo_data.pot b/localization/demo_data.pot index a43cf112..7800898f 100644 --- a/localization/demo_data.pot +++ b/localization/demo_data.pot @@ -27,19 +27,6 @@ msgstr "" msgid "Tinned food cupboard" msgstr "" -msgid "Fridge" -msgstr "" - -msgid "Piece" -msgid_plural "Pieces" -msgstr[0] "" -msgstr[1] "" - -msgid "Pack" -msgid_plural "Packs" -msgstr[0] "" -msgstr[1] "" - msgid "Glass" msgid_plural "Glasses" msgstr[0] "" diff --git a/localization/strings.pot b/localization/strings.pot index dc8d22d2..f11687be 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -2473,3 +2473,19 @@ msgstr "" msgid "After this product was once in stock and when the desired quantity unit cannot be selected here, first create a corresponding unit conversion" msgstr "" + +# Default / initially created location +msgid "Fridge" +msgstr "" + +# Default / initially created quantity unit +msgid "Piece" +msgid_plural "Pieces" +msgstr[0] "" +msgstr[1] "" + +# Default / initially created quantity unit +msgid "Pack" +msgid_plural "Packs" +msgstr[0] "" +msgstr[1] "" diff --git a/middleware/LocaleMiddleware.php b/middleware/LocaleMiddleware.php index 5f20c0e5..94271f54 100644 --- a/middleware/LocaleMiddleware.php +++ b/middleware/LocaleMiddleware.php @@ -11,16 +11,24 @@ class LocaleMiddleware extends BaseMiddleware { public function __invoke(Request $request, RequestHandler $handler): Response { - $locale = $this->getLocale($request); - define('GROCY_LOCALE', $locale); + define('GROCY_LOCALE', $this->GetLocale($request)); + return $handler->handle($request); } - protected function getLocale(Request $request) + private function GetLocale(Request $request) { + // demo and prerelease modes are fixed to the default locale + if (GROCY_MODE === 'demo' || GROCY_MODE === 'prerelease') + { + return GROCY_DEFAULT_LOCALE; + } + + // Prefer user setting if (defined('GROCY_AUTHENTICATED') && GROCY_AUTHENTICATED) { $locale = UsersService::GetInstance()->GetUserSetting(GROCY_USER_ID, 'locale'); + if (isset($locale) && !empty($locale)) { if (in_array($locale, scandir(__DIR__ . '/../localization'))) @@ -30,11 +38,9 @@ class LocaleMiddleware extends BaseMiddleware } } - $langs = implode(',', $request->getHeader('Accept-Language')); - - // Src: https://gist.github.com/spolischook/0cde9c6286415cddc088 - $prefLocales = array_reduce( - explode(',', $langs), + // Otherwise use Browser prefered locale + $browserPreferedLocales = array_reduce( + explode(',', implode(',', $request->getHeader('Accept-Language'))), function ($res, $el) { list($l, $q) = array_merge(explode(';q=', $el), [1]); @@ -43,10 +49,10 @@ class LocaleMiddleware extends BaseMiddleware }, [] ); - arsort($prefLocales); + arsort($browserPreferedLocales); $availableLocales = scandir(__DIR__ . '/../localization'); - foreach ($prefLocales as $locale => $q) + foreach ($browserPreferedLocales as $locale => $q) { if (in_array($locale, $availableLocales)) { @@ -66,6 +72,7 @@ class LocaleMiddleware extends BaseMiddleware } } + // Falback to default locale return GROCY_DEFAULT_LOCALE; } } diff --git a/services/DatabaseMigrationService.php b/services/DatabaseMigrationService.php index 0fd19eb5..86ffe164 100644 --- a/services/DatabaseMigrationService.php +++ b/services/DatabaseMigrationService.php @@ -12,8 +12,6 @@ class DatabaseMigrationService extends BaseService public function MigrateDatabase() { - define('GROCY_DATABASE_MIGRATIONS_RUNNING', true); - DatabaseService::GetInstance()->ExecuteDbStatement("CREATE TABLE IF NOT EXISTS migrations (migration INTEGER NOT NULL PRIMARY KEY UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')))"); $migrationFiles = []; diff --git a/services/LocalizationService.php b/services/LocalizationService.php index 22ac79a4..bd133a45 100644 --- a/services/LocalizationService.php +++ b/services/LocalizationService.php @@ -8,12 +8,12 @@ use Gettext\Translator; class LocalizationService extends BaseService { - public function __construct(string $culture) + public function __construct(string $locale) { parent::__construct(); - $this->Culture = $culture; - $this->LoadLocalizations($culture); + $this->Locale = $locale; + $this->LoadLocalizations($locale); } protected $Po; @@ -22,8 +22,8 @@ class LocalizationService extends BaseService protected $PotMain; protected $Translator; protected $TranslatorQu; - protected $Culture; - private static $instanceMap = []; + protected $Locale; + private static $InstanceMap = []; public function CheckAndAddMissingTranslationToPot($text) { @@ -112,31 +112,24 @@ class LocalizationService extends BaseService } } - public static function GetInstance(string $culture = '') + public static function GetInstance(string $locale = '') { - if (empty($culture)) + if (empty($locale)) { - if (defined('GROCY_LOCALE')) - { - $culture = GROCY_LOCALE; - } - else - { - $culture = GROCY_DEFAULT_LOCALE; - } + $locale = GROCY_LOCALE; } - if (!in_array($culture, self::$instanceMap)) + if (!in_array($locale, self::$InstanceMap)) { - self::$instanceMap[$culture] = new self($culture); + self::$InstanceMap[$locale] = new self($locale); } - return self::$instanceMap[$culture]; + return self::$InstanceMap[$locale]; } private function LoadLocalizations() { - $culture = $this->Culture; + $locale = $this->Locale; if (GROCY_MODE === 'dev') { @@ -153,47 +146,46 @@ class LocalizationService extends BaseService $this->Pot = $this->Pot->mergeWith(Translations::fromPoFile(__DIR__ . '/../localization/demo_data.pot')); } - $this->Po = Translations::fromPoFile(__DIR__ . "/../localization/$culture/strings.po"); + $this->Po = Translations::fromPoFile(__DIR__ . "/../localization/$locale/strings.po"); - if (file_exists(__DIR__ . "/../localization/$culture/chore_assignment_types.po")) + if (file_exists(__DIR__ . "/../localization/$locale/chore_assignment_types.po")) { - $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/chore_assignment_types.po")); + $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$locale/chore_assignment_types.po")); } - if (file_exists(__DIR__ . "/../localization/$culture/component_translations.po")) + if (file_exists(__DIR__ . "/../localization/$locale/component_translations.po")) { - $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/component_translations.po")); + $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$locale/component_translations.po")); } - if (file_exists(__DIR__ . "/../localization/$culture/stock_transaction_types.po")) + if (file_exists(__DIR__ . "/../localization/$locale/stock_transaction_types.po")) { - $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/stock_transaction_types.po")); + $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$locale/stock_transaction_types.po")); } - if (file_exists(__DIR__ . "/../localization/$culture/chore_period_types.po")) + if (file_exists(__DIR__ . "/../localization/$locale/chore_period_types.po")) { - $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/chore_period_types.po")); + $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$locale/chore_period_types.po")); } - if (file_exists(__DIR__ . "/../localization/$culture/userfield_types.po")) + if (file_exists(__DIR__ . "/../localization/$locale/userfield_types.po")) { - $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/userfield_types.po")); + $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$locale/userfield_types.po")); } - if (file_exists(__DIR__ . "/../localization/$culture/permissions.po")) + if (file_exists(__DIR__ . "/../localization/$locale/permissions.po")) { - $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/permissions.po")); + $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$locale/permissions.po")); } - if (file_exists(__DIR__ . "/../localization/$culture/locales.po")) + if (file_exists(__DIR__ . "/../localization/$locale/locales.po")) { - $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/locales.po")); + $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$locale/locales.po")); } - // Load demo data localizations also during database migrations since e.g. default quantity units are created localized by that - if ((GROCY_MODE !== 'production' || defined('GROCY_DATABASE_MIGRATIONS_RUNNING')) && file_exists(__DIR__ . "/../localization/$culture/demo_data.po")) + if (GROCY_MODE !== 'production' && file_exists(__DIR__ . "/../localization/$locale/demo_data.po")) { - $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/demo_data.po")); + $this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$locale/demo_data.po")); } $this->Translator = new Translator();