diff --git a/config/config.sample.php b/config/config.sample.php index 14e093600b..5a79140dfb 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -157,7 +157,11 @@ $CONFIG = array( * language codes such as ``en`` for English, ``de`` for German, and ``fr`` for * French. It overrides automatic language detection on public pages like login * or shared items. User's language preferences configured under "personal -> - * language" override this setting after they have logged in. + * language" override this setting after they have logged in. Nextcloud has two + * distinguished language codes for German, 'de' and 'de_DE'. 'de' is used for + * informal German and 'de_DE' for formal German. By setting this value to 'de_DE' + * you can enforce the formal version of German unless the user has chosen + * something different explicitly. * * Defaults to ``en`` */ diff --git a/lib/private/L10N/Factory.php b/lib/private/L10N/Factory.php index 399bebb818..e277a00e65 100644 --- a/lib/private/L10N/Factory.php +++ b/lib/private/L10N/Factory.php @@ -260,7 +260,7 @@ class Factory implements IFactory { foreach ($available as $available_language) { if ($preferred_language === strtolower($available_language)) { - return $available_language; + return $this->respectDefaultLanguage($app, $available_language); } } @@ -276,6 +276,31 @@ class Factory implements IFactory { throw new LanguageNotFoundException(); } + /** + * if default language is set to de_DE (formal German) this should be + * preferred to 'de' (non-formal German) if possible + * + * @param string|null $app + * @param string $lang + * @return string + */ + protected function respectDefaultLanguage($app, $lang) { + $result = $lang; + $defaultLanguage = $this->config->getSystemValue('default_language', false); + + // use formal version of german ("Sie" instead of "Du") if the default + // language is set to 'de_DE' if possible + if (is_string($defaultLanguage) && + strtolower($lang) === 'de' && + strtolower($defaultLanguage) === 'de_de' && + $this->languageExists($app, 'de_DE') + ) { + $result = 'de_DE'; + } + + return $result; + } + /** * Checks if $sub is a subdirectory of $parent * diff --git a/tests/lib/L10N/FactoryTest.php b/tests/lib/L10N/FactoryTest.php index 171be67d33..602967b162 100644 --- a/tests/lib/L10N/FactoryTest.php +++ b/tests/lib/L10N/FactoryTest.php @@ -368,12 +368,17 @@ class FactoryTest extends TestCase { * @param string $expected */ public function testGetLanguageFromRequest($app, $header, array $availableLanguages, $expected) { - $factory = $this->getFactory(['findAvailableLanguages']); + $factory = $this->getFactory(['findAvailableLanguages', 'respectDefaultLanguage']); $factory->expects($this->once()) ->method('findAvailableLanguages') ->with($app) ->willReturn($availableLanguages); + $factory->expects($this->any()) + ->method('respectDefaultLanguage')->willReturnCallback(function($app, $lang) { + return $lang; + }); + $this->request->expects($this->once()) ->method('getHeader') ->with('ACCEPT_LANGUAGE') @@ -497,7 +502,7 @@ class FactoryTest extends TestCase { ->with($this->equalTo('ACCEPT_LANGUAGE')) ->willReturn($browserLang); - $factory = $this->getFactory(['languageExists', 'findAvailableLanguages']); + $factory = $this->getFactory(['languageExists', 'findAvailableLanguages', 'respectDefaultLanguage']); $factory->expects($this->any()) ->method('languageExists') ->will($this->returnCallback(function ($app, $lang) use ($availableLang) { @@ -508,9 +513,44 @@ class FactoryTest extends TestCase { ->will($this->returnCallback(function ($app) use ($availableLang) { return $availableLang; })); + $factory->expects($this->any()) + ->method('respectDefaultLanguage')->willReturnCallback(function($app, $lang) { + return $lang; + }); $lang = $factory->findLanguage(null); $this->assertSame($expected, $lang); } + + public function dataTestRespectDefaultLanguage() { + return [ + ['de', 'de_DE', true, 'de_DE'], + ['de', 'de', true, 'de'], + ['de', false, true, 'de'], + ['fr', 'de_DE', true, 'fr'], + ]; + } + + /** + * test if we respect default language if possible + * + * @dataProvider dataTestRespectDefaultLanguage + * + * @param string $lang + * @param string $defaultLanguage + * @param bool $langExists + * @param string $expected + */ + public function testRespectDefaultLanguage($lang, $defaultLanguage, $langExists, $expected) { + $factory = $this->getFactory(['languageExists']); + $factory->expects($this->any()) + ->method('languageExists')->willReturn($langExists); + $this->config->expects($this->any()) + ->method('getSystemValue')->with('default_language', false)->willReturn($defaultLanguage); + + $result = $this->invokePrivate($factory, 'respectDefaultLanguage', ['app', $lang]); + $this->assertSame($expected, $result); + } + }