diff --git a/lib/private/l10n.php b/lib/private/l10n.php index 085914a68b..43e1121b98 100644 --- a/lib/private/l10n.php +++ b/lib/private/l10n.php @@ -88,44 +88,6 @@ class OC_L10N implements \OCP\IL10N { $this->lang = $lang; } - /** - * @return string - */ - public static function setLanguageFromRequest() { - if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $available = self::findAvailableLanguages(); - - // E.g. make sure that 'de' is before 'de_DE'. - sort($available); - - $preferences = preg_split('/,\s*/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); - foreach ($preferences as $preference) { - list($preferred_language) = explode(';', $preference); - $preferred_language = str_replace('-', '_', $preferred_language); - foreach ($available as $available_language) { - if ($preferred_language === strtolower($available_language)) { - if (!self::$language) { - self::$language = $available_language; - } - return $available_language; - } - } - foreach ($available as $available_language) { - if (substr($preferred_language, 0, 2) === $available_language) { - if (!self::$language) { - self::$language = $available_language; - } - return $available_language; - } - } - } - } - - self::$language = 'en'; - // Last try: English - return 'en'; - } - /** * @param $transFile * @param bool $mergeTranslations @@ -169,7 +131,7 @@ class OC_L10N implements \OCP\IL10N { if(array_key_exists($app.'::'.$lang, self::$cache)) { $this->translations = self::$cache[$app.'::'.$lang]['t']; } else{ - $i18nDir = self::findI18nDir($app); + $i18nDir = $this->findI18nDir($app); $transFile = strip_tags($i18nDir).strip_tags($lang).'.json'; // Texts are in $i18ndir // (Just no need to define date/time format etc. twice) @@ -391,49 +353,12 @@ class OC_L10N implements \OCP\IL10N { return $this->lang ? $this->lang : self::findLanguage(); } - /** - * find the best language - * @param string $app - * @return string language - * - * If nothing works it returns 'en' - */ - public static function findLanguage($app = null) { - if (self::$language != '' && self::languageExists($app, self::$language)) { - return self::$language; - } - - $config = \OC::$server->getConfig(); - $userId = \OC_User::getUser(); - - if($userId && $config->getUserValue($userId, 'core', 'lang')) { - $lang = $config->getUserValue($userId, 'core', 'lang'); - self::$language = $lang; - if(self::languageExists($app, $lang)) { - return $lang; - } - } - - $default_language = $config->getSystemValue('default_language', false); - - if($default_language !== false) { - return $default_language; - } - - $lang = self::setLanguageFromRequest(); - if($userId && !$config->getUserValue($userId, 'core', 'lang')) { - $config->setUserValue($userId, 'core', 'lang', $lang); - } - - return $lang; - } - /** * find the l10n directory * @param string $app App that needs to be translated * @return string directory */ - protected static function findI18nDir($app) { + protected function findI18nDir($app) { // find the i18n dir $i18nDir = OC::$SERVERROOT.'/core/l10n/'; if($app != '') { @@ -448,26 +373,6 @@ class OC_L10N implements \OCP\IL10N { return $i18nDir; } - /** - * find all available languages for an app - * @param string $app App that needs to be translated - * @return array an array of available languages - * @deprecated 9.0.0 Use \OC::$server->getL10NFactory()->findAvailableLanguages() instead - */ - public static function findAvailableLanguages($app=null) { - return \OC::$server->getL10NFactory()->findAvailableLanguages($app); - } - - /** - * @param string $app - * @param string $lang - * @return bool - * @deprecated 9.0.0 Use \OC::$server->getL10NFactory()->languageExists() instead - */ - public static function languageExists($app, $lang) { - return \OC::$server->getL10NFactory()->languageExists($app, $lang); - } - /** * @return string * @throws \Punic\Exception\ValueNotInList @@ -494,4 +399,44 @@ class OC_L10N implements \OCP\IL10N { return $locale; } + + /** + * find the best language + * @param string $app + * @return string language + * + * If nothing works it returns 'en' + * @deprecated 9.0.0 Use \OC::$server->getL10NFactory()->findLanguage() instead + */ + public static function findLanguage($app = null) { + return \OC::$server->getL10NFactory()->findLanguage($app); + } + + /** + * @return string + * @deprecated 9.0.0 Use \OC::$server->getL10NFactory()->setLanguageFromRequest() instead + */ + public static function setLanguageFromRequest() { + return \OC::$server->getL10NFactory()->setLanguageFromRequest(); + } + + /** + * find all available languages for an app + * @param string $app App that needs to be translated + * @return array an array of available languages + * @deprecated 9.0.0 Use \OC::$server->getL10NFactory()->findAvailableLanguages() instead + */ + public static function findAvailableLanguages($app=null) { + return \OC::$server->getL10NFactory()->findAvailableLanguages($app); + } + + /** + * @param string $app + * @param string $lang + * @return bool + * @deprecated 9.0.0 Use \OC::$server->getL10NFactory()->languageExists() instead + */ + public static function languageExists($app, $lang) { + return \OC::$server->getL10NFactory()->languageExists($app, $lang); + } } diff --git a/lib/private/l10n/factory.php b/lib/private/l10n/factory.php index b130472760..ecc2318893 100644 --- a/lib/private/l10n/factory.php +++ b/lib/private/l10n/factory.php @@ -25,12 +25,18 @@ namespace OC\L10N; +use OCP\IConfig; +use OCP\IRequest; use OCP\L10N\IFactory; /** * A factory that generates language instances */ class Factory implements IFactory { + + /** @var string */ + protected $requestLanguage = ''; + /** * cached instances * @var array Structure: Lang => App => \OCP\IL10N @@ -42,6 +48,21 @@ class Factory implements IFactory { */ protected $availableLanguages = []; + /** @var IConfig */ + protected $config; + + /** @var IRequest */ + protected $request; + + /** + * @param IConfig $config + * @param IRequest $request + */ + public function __construct(IConfig $config, IRequest $request) { + $this->config = $config; + $this->request = $request; + } + /** * Get a language instance * @@ -62,6 +83,41 @@ class Factory implements IFactory { return $this->instances[$key][$app]; } + /** + * Find the best language + * + * @param string|null $app App id or null for core + * @return string language If nothing works it returns 'en' + */ + public function findLanguage($app = null) { + if ($this->requestLanguage !== '' && $this->languageExists($app, $this->requestLanguage)) { + return $this->requestLanguage; + } + + $userId = \OC_User::getUser(); // FIXME not available in non-static? + + if ($userId && $this->config->getUserValue($userId, 'core', 'lang')) { + $lang = $this->config->getUserValue($userId, 'core', 'lang'); + $this->requestLanguage = $lang; + if ($this->languageExists($app, $lang)) { + return $lang; + } + } + + $defaultLanguage = $this->config->getSystemValue('default_language', false); + + if ($defaultLanguage !== false) { + return $defaultLanguage; + } + + $lang = $this->setLanguageFromRequest($app); + if ($userId && $app === null && !$this->config->getUserValue($userId, 'core', 'lang')) { + $this->config->setUserValue($userId, 'core', 'lang', $lang); + } + + return $lang; + } + /** * Find all available languages for an app * @@ -110,6 +166,50 @@ class Factory implements IFactory { return array_search($lang, $languages); } + /** + * @param string|null $app App id or null for core + * @return string + */ + public function setLanguageFromRequest($app = null) { + $header = $this->request->getHeader('ACCEPT_LANGUAGE'); + if ($header) { + $available = $this->findAvailableLanguages($app); + + // E.g. make sure that 'de' is before 'de_DE'. + sort($available); + + $preferences = preg_split('/,\s*/', strtolower($header)); + foreach ($preferences as $preference) { + list($preferred_language) = explode(';', $preference); + $preferred_language = str_replace('-', '_', $preferred_language); + + foreach ($available as $available_language) { + if ($preferred_language === strtolower($available_language)) { + if ($app === null && !$this->requestLanguage) { + $this->requestLanguage = $available_language; + } + return $available_language; + } + } + + // Fallback from de_De to de + foreach ($available as $available_language) { + if (substr($preferred_language, 0, 2) === $available_language) { + if ($app === null && !$this->requestLanguage) { + $this->requestLanguage = $available_language; + } + return $available_language; + } + } + } + } + + if (!$this->requestLanguage) { + $this->requestLanguage = 'en'; + } + return 'en'; // Last try: English + } + /** * find the l10n directory * diff --git a/lib/private/server.php b/lib/private/server.php index b8f4bdb53f..81929d0c7b 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -262,8 +262,11 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('AppConfig', function (Server $c) { return new \OC\AppConfig($c->getDatabaseConnection()); }); - $this->registerService('L10NFactory', function ($c) { - return new \OC\L10N\Factory(); + $this->registerService('L10NFactory', function (Server $c) { + return new \OC\L10N\Factory( + $c->getConfig(), + $c->getRequest() + ); }); $this->registerService('URLGenerator', function (Server $c) { $config = $c->getConfig(); diff --git a/lib/public/l10n/ifactory.php b/lib/public/l10n/ifactory.php index 09c75e9af7..2d6f8e873c 100644 --- a/lib/public/l10n/ifactory.php +++ b/lib/public/l10n/ifactory.php @@ -34,6 +34,15 @@ interface IFactory { */ public function get($app, $lang = null); + /** + * Find the best language + * + * @param string|null $app App id or null for core + * @return string language If nothing works it returns 'en' + * @since 9.0.0 + */ + public function findLanguage($app = null); + /** * Find all available languages for an app * @@ -50,4 +59,11 @@ interface IFactory { * @since 9.0.0 */ public function languageExists($app, $lang); + + /** + * @param string|null $app App id or null for core + * @return string + * @since 9.0.0 + */ + public function setLanguageFromRequest($app = null); } diff --git a/ocs/v1.php b/ocs/v1.php index 4371b0b604..39a8f4e468 100644 --- a/ocs/v1.php +++ b/ocs/v1.php @@ -46,7 +46,7 @@ try { OC_App::loadApps(); // force language as given in the http request - \OC_L10N::setLanguageFromRequest(); + \OC::$server->getL10NFactory()->setLanguageFromRequest(); OC::$server->getRouter()->match('/ocs'.\OC::$server->getRequest()->getRawPathInfo()); } catch (ResourceNotFoundException $e) { diff --git a/remote.php b/remote.php index a145fc4bd8..26203e2df8 100644 --- a/remote.php +++ b/remote.php @@ -109,7 +109,7 @@ try { } // force language as given in the http request - \OC_L10N::setLanguageFromRequest(); + \OC::$server->getL10NFactory()->setLanguageFromRequest(); $file=ltrim($file, '/'); diff --git a/tests/lib/l10n.php b/tests/lib/l10n.php index d77548c5bf..eb0d911751 100644 --- a/tests/lib/l10n.php +++ b/tests/lib/l10n.php @@ -157,7 +157,7 @@ class Test_L10n extends \Test\TestCase { } public function testFactoryGetLanguageCode() { - $factory = new \OC\L10N\Factory(); + $factory = new \OC\L10N\Factory($this->getMock('OCP\IConfig'), $this->getMock('OCP\IRequest')); $l = $factory->get('lib', 'de'); $this->assertEquals('de', $l->getLanguageCode()); }