xref: /webtrees/app/Http/Middleware/UseLanguage.php (revision b6017f990d38d8c56e04c0096ce9a7e8745ad4ba)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2021 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Http\Middleware;
21
22use Fisharebest\Localization\Locale;
23use Fisharebest\Localization\Locale\LocaleInterface;
24use Fisharebest\Webtrees\I18N;
25use Fisharebest\Webtrees\Module\LanguageEnglishUnitedStates;
26use Fisharebest\Webtrees\Module\ModuleLanguageInterface;
27use Fisharebest\Webtrees\Services\ModuleService;
28use Fisharebest\Webtrees\Session;
29use Fisharebest\Webtrees\Site;
30use Generator;
31use Psr\Http\Message\ResponseInterface;
32use Psr\Http\Message\ServerRequestInterface;
33use Psr\Http\Server\MiddlewareInterface;
34use Psr\Http\Server\RequestHandlerInterface;
35
36/**
37 * Middleware to select a language.
38 */
39class UseLanguage implements MiddlewareInterface
40{
41    /** @var ModuleService */
42    private $module_service;
43
44    /**
45     * UseTheme constructor.
46     *
47     * @param ModuleService $module_service
48     */
49    public function __construct(ModuleService $module_service)
50    {
51        $this->module_service = $module_service;
52    }
53
54    /**
55     * @param ServerRequestInterface  $request
56     * @param RequestHandlerInterface $handler
57     *
58     * @return ResponseInterface
59     */
60    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
61    {
62        foreach ($this->languages($request) as $language) {
63            if ($language instanceof ModuleLanguageInterface) {
64                I18N::init($language->locale()->languageTag());
65                Session::put('language', $language->locale()->languageTag());
66                break;
67            }
68        }
69
70        return $handler->handle($request);
71    }
72
73    /**
74     * The language can be chosen in various ways.
75     * Language module names have the form "language-<code>>".
76     *
77     * @param ServerRequestInterface $request
78     *
79     * @return Generator<ModuleLanguageInterface|null>
80     */
81    private function languages(ServerRequestInterface $request): Generator
82    {
83        $languages = $this->module_service->findByInterface(ModuleLanguageInterface::class, true);
84
85        // Last language used
86        yield $languages->get('language-' . Session::get('language', ''));
87
88        // Browser negotiation
89        $locales = $this->module_service->findByInterface(ModuleLanguageInterface::class, true)
90            ->map(static function (ModuleLanguageInterface $module): LocaleInterface {
91                return $module->locale();
92            });
93
94        $default = Locale::create(Site::getPreference('LANGUAGE', 'en-US'));
95        $locale  = Locale::httpAcceptLanguage($request->getServerParams(), $locales->all(), $default);
96
97        yield $languages->get('language-' . $locale->languageTag());
98
99        // No languages enabled?  Use en-US
100        yield new LanguageEnglishUnitedStates();
101    }
102}
103