Passed
Push — master ( 024fc2...78c149 )
by Morris
12:42 queued 10s
created
lib/private/L10N/LazyL10N.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -28,43 +28,43 @@
 block discarded – undo
28 28
 
29 29
 class LazyL10N implements IL10N {
30 30
 
31
-	/** @var IL10N */
32
-	private $l;
31
+    /** @var IL10N */
32
+    private $l;
33 33
 
34
-	/** @var \Closure */
35
-	private $factory;
34
+    /** @var \Closure */
35
+    private $factory;
36 36
 
37 37
 
38
-	public function __construct(\Closure $factory) {
39
-		$this->factory = $factory;
40
-	}
38
+    public function __construct(\Closure $factory) {
39
+        $this->factory = $factory;
40
+    }
41 41
 
42
-	private function getL(): IL10N {
43
-		if ($this->l === null) {
44
-			$this->l = ($this->factory)();
45
-		}
42
+    private function getL(): IL10N {
43
+        if ($this->l === null) {
44
+            $this->l = ($this->factory)();
45
+        }
46 46
 
47
-		return $this->l;
48
-	}
47
+        return $this->l;
48
+    }
49 49
 
50
-	public function t(string $text, $parameters = []): string {
51
-		return $this->getL()->t($text, $parameters);
52
-	}
50
+    public function t(string $text, $parameters = []): string {
51
+        return $this->getL()->t($text, $parameters);
52
+    }
53 53
 
54
-	public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string {
55
-		return $this->getL()->n($text_singular, $text_plural, $count, $parameters);
56
-	}
54
+    public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string {
55
+        return $this->getL()->n($text_singular, $text_plural, $count, $parameters);
56
+    }
57 57
 
58
-	public function l(string $type, $data, array $options = []) {
59
-		return $this->getL()->l($type, $data, $options);
60
-	}
58
+    public function l(string $type, $data, array $options = []) {
59
+        return $this->getL()->l($type, $data, $options);
60
+    }
61 61
 
62
-	public function getLanguageCode(): string {
63
-		return $this->getL()->getLanguageCode();
64
-	}
62
+    public function getLanguageCode(): string {
63
+        return $this->getL()->getLanguageCode();
64
+    }
65 65
 
66
-	public function getLocaleCode(): string {
67
-		return $this->getL()->getLocaleCode();
68
-	}
66
+    public function getLocaleCode(): string {
67
+        return $this->getL()->getLocaleCode();
68
+    }
69 69
 
70 70
 }
Please login to merge, or discard this patch.
lib/private/L10N/Factory.php 2 patches
Indentation   +598 added lines, -598 removed lines patch added patch discarded remove patch
@@ -42,603 +42,603 @@
 block discarded – undo
42 42
  */
43 43
 class Factory implements IFactory {
44 44
 
45
-	/** @var string */
46
-	protected $requestLanguage = '';
47
-
48
-	/**
49
-	 * cached instances
50
-	 * @var array Structure: Lang => App => \OCP\IL10N
51
-	 */
52
-	protected $instances = [];
53
-
54
-	/**
55
-	 * @var array Structure: App => string[]
56
-	 */
57
-	protected $availableLanguages = [];
58
-
59
-	/**
60
-	 * @var array
61
-	 */
62
-	protected $availableLocales = [];
63
-
64
-	/**
65
-	 * @var array Structure: string => callable
66
-	 */
67
-	protected $pluralFunctions = [];
68
-
69
-	const COMMON_LANGUAGE_CODES = [
70
-		'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
71
-		'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
72
-	];
73
-
74
-	/** @var IConfig */
75
-	protected $config;
76
-
77
-	/** @var IRequest */
78
-	protected $request;
79
-
80
-	/** @var IUserSession */
81
-	protected $userSession;
82
-
83
-	/** @var string */
84
-	protected $serverRoot;
85
-
86
-	/**
87
-	 * @param IConfig $config
88
-	 * @param IRequest $request
89
-	 * @param IUserSession $userSession
90
-	 * @param string $serverRoot
91
-	 */
92
-	public function __construct(IConfig $config,
93
-								IRequest $request,
94
-								IUserSession $userSession,
95
-								$serverRoot) {
96
-		$this->config = $config;
97
-		$this->request = $request;
98
-		$this->userSession = $userSession;
99
-		$this->serverRoot = $serverRoot;
100
-	}
101
-
102
-	/**
103
-	 * Get a language instance
104
-	 *
105
-	 * @param string $app
106
-	 * @param string|null $lang
107
-	 * @param string|null $locale
108
-	 * @return \OCP\IL10N
109
-	 */
110
-	public function get($app, $lang = null, $locale = null) {
111
-		return new LazyL10N(function() use ($app, $lang, $locale) {
112
-
113
-			$app = \OC_App::cleanAppId($app);
114
-			if ($lang !== null) {
115
-				$lang = str_replace(array('\0', '/', '\\', '..'), '', (string)$lang);
116
-			}
117
-
118
-			$forceLang = $this->config->getSystemValue('force_language', false);
119
-			if (is_string($forceLang)) {
120
-				$lang = $forceLang;
121
-			}
122
-
123
-			$forceLocale = $this->config->getSystemValue('force_locale', false);
124
-			if (is_string($forceLocale)) {
125
-				$locale = $forceLocale;
126
-			}
127
-
128
-			if ($lang === null || !$this->languageExists($app, $lang)) {
129
-				$lang = $this->findLanguage($app);
130
-			}
131
-
132
-			if ($locale === null || !$this->localeExists($locale)) {
133
-				$locale = $this->findLocale($lang);
134
-			}
135
-
136
-			if (!isset($this->instances[$lang][$app])) {
137
-				$this->instances[$lang][$app] = new L10N(
138
-					$this, $app, $lang, $locale,
139
-					$this->getL10nFilesForApp($app, $lang)
140
-				);
141
-			}
142
-
143
-			return $this->instances[$lang][$app];
144
-		});
145
-	}
146
-
147
-	/**
148
-	 * Find the best language
149
-	 *
150
-	 * @param string|null $app App id or null for core
151
-	 * @return string language If nothing works it returns 'en'
152
-	 */
153
-	public function findLanguage($app = null) {
154
-		$forceLang = $this->config->getSystemValue('force_language', false);
155
-		if (is_string($forceLang)) {
156
-			$this->requestLanguage = $forceLang;
157
-		}
158
-
159
-		if ($this->requestLanguage !== '' && $this->languageExists($app, $this->requestLanguage)) {
160
-			return $this->requestLanguage;
161
-		}
162
-
163
-		/**
164
-		 * At this point Nextcloud might not yet be installed and thus the lookup
165
-		 * in the preferences table might fail. For this reason we need to check
166
-		 * whether the instance has already been installed
167
-		 *
168
-		 * @link https://github.com/owncloud/core/issues/21955
169
-		 */
170
-		if ($this->config->getSystemValue('installed', false)) {
171
-			$userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() :  null;
172
-			if (!is_null($userId)) {
173
-				$userLang = $this->config->getUserValue($userId, 'core', 'lang', null);
174
-			} else {
175
-				$userLang = null;
176
-			}
177
-		} else {
178
-			$userId = null;
179
-			$userLang = null;
180
-		}
181
-
182
-		if ($userLang) {
183
-			$this->requestLanguage = $userLang;
184
-			if ($this->languageExists($app, $userLang)) {
185
-				return $userLang;
186
-			}
187
-		}
188
-
189
-		try {
190
-			// Try to get the language from the Request
191
-			$lang = $this->getLanguageFromRequest($app);
192
-			if ($userId !== null && $app === null && !$userLang) {
193
-				$this->config->setUserValue($userId, 'core', 'lang', $lang);
194
-			}
195
-			return $lang;
196
-		} catch (LanguageNotFoundException $e) {
197
-			// Finding language from request failed fall back to default language
198
-			$defaultLanguage = $this->config->getSystemValue('default_language', false);
199
-			if ($defaultLanguage !== false && $this->languageExists($app, $defaultLanguage)) {
200
-				return $defaultLanguage;
201
-			}
202
-		}
203
-
204
-		// We could not find any language so fall back to english
205
-		return 'en';
206
-	}
207
-
208
-	/**
209
-	 * find the best locale
210
-	 *
211
-	 * @param string $lang
212
-	 * @return null|string
213
-	 */
214
-	public function findLocale($lang = null) {
215
-		$forceLocale = $this->config->getSystemValue('force_locale', false);
216
-		if (is_string($forceLocale) && $this->localeExists($forceLocale)) {
217
-			return $forceLocale;
218
-		}
219
-
220
-		if ($this->config->getSystemValue('installed', false)) {
221
-			$userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() :  null;
222
-			$userLocale = null;
223
-			if (null !== $userId) {
224
-				$userLocale = $this->config->getUserValue($userId, 'core', 'locale', null);
225
-			}
226
-		} else {
227
-			$userId = null;
228
-			$userLocale = null;
229
-		}
230
-
231
-		if ($userLocale && $this->localeExists($userLocale)) {
232
-			return $userLocale;
233
-		}
234
-
235
-		// Default : use system default locale
236
-		$defaultLocale = $this->config->getSystemValue('default_locale', false);
237
-		if ($defaultLocale !== false && $this->localeExists($defaultLocale)) {
238
-			return $defaultLocale;
239
-		}
240
-
241
-		// If no user locale set, use lang as locale
242
-		if (null !== $lang && $this->localeExists($lang)) {
243
-			return $lang;
244
-		}
245
-
246
-		// At last, return USA
247
-		return 'en_US';
248
-	}
249
-
250
-	/**
251
-	 * find the matching lang from the locale
252
-	 *
253
-	 * @param string $app
254
-	 * @param string $locale
255
-	 * @return null|string
256
-	 */
257
-	public function findLanguageFromLocale(string $app = 'core', string $locale = null) {
258
-		if ($this->languageExists($app, $locale)) {
259
-			return $locale;
260
-		}
45
+    /** @var string */
46
+    protected $requestLanguage = '';
47
+
48
+    /**
49
+     * cached instances
50
+     * @var array Structure: Lang => App => \OCP\IL10N
51
+     */
52
+    protected $instances = [];
53
+
54
+    /**
55
+     * @var array Structure: App => string[]
56
+     */
57
+    protected $availableLanguages = [];
58
+
59
+    /**
60
+     * @var array
61
+     */
62
+    protected $availableLocales = [];
63
+
64
+    /**
65
+     * @var array Structure: string => callable
66
+     */
67
+    protected $pluralFunctions = [];
68
+
69
+    const COMMON_LANGUAGE_CODES = [
70
+        'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
71
+        'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
72
+    ];
73
+
74
+    /** @var IConfig */
75
+    protected $config;
76
+
77
+    /** @var IRequest */
78
+    protected $request;
79
+
80
+    /** @var IUserSession */
81
+    protected $userSession;
82
+
83
+    /** @var string */
84
+    protected $serverRoot;
85
+
86
+    /**
87
+     * @param IConfig $config
88
+     * @param IRequest $request
89
+     * @param IUserSession $userSession
90
+     * @param string $serverRoot
91
+     */
92
+    public function __construct(IConfig $config,
93
+                                IRequest $request,
94
+                                IUserSession $userSession,
95
+                                $serverRoot) {
96
+        $this->config = $config;
97
+        $this->request = $request;
98
+        $this->userSession = $userSession;
99
+        $this->serverRoot = $serverRoot;
100
+    }
101
+
102
+    /**
103
+     * Get a language instance
104
+     *
105
+     * @param string $app
106
+     * @param string|null $lang
107
+     * @param string|null $locale
108
+     * @return \OCP\IL10N
109
+     */
110
+    public function get($app, $lang = null, $locale = null) {
111
+        return new LazyL10N(function() use ($app, $lang, $locale) {
112
+
113
+            $app = \OC_App::cleanAppId($app);
114
+            if ($lang !== null) {
115
+                $lang = str_replace(array('\0', '/', '\\', '..'), '', (string)$lang);
116
+            }
117
+
118
+            $forceLang = $this->config->getSystemValue('force_language', false);
119
+            if (is_string($forceLang)) {
120
+                $lang = $forceLang;
121
+            }
122
+
123
+            $forceLocale = $this->config->getSystemValue('force_locale', false);
124
+            if (is_string($forceLocale)) {
125
+                $locale = $forceLocale;
126
+            }
127
+
128
+            if ($lang === null || !$this->languageExists($app, $lang)) {
129
+                $lang = $this->findLanguage($app);
130
+            }
131
+
132
+            if ($locale === null || !$this->localeExists($locale)) {
133
+                $locale = $this->findLocale($lang);
134
+            }
135
+
136
+            if (!isset($this->instances[$lang][$app])) {
137
+                $this->instances[$lang][$app] = new L10N(
138
+                    $this, $app, $lang, $locale,
139
+                    $this->getL10nFilesForApp($app, $lang)
140
+                );
141
+            }
142
+
143
+            return $this->instances[$lang][$app];
144
+        });
145
+    }
146
+
147
+    /**
148
+     * Find the best language
149
+     *
150
+     * @param string|null $app App id or null for core
151
+     * @return string language If nothing works it returns 'en'
152
+     */
153
+    public function findLanguage($app = null) {
154
+        $forceLang = $this->config->getSystemValue('force_language', false);
155
+        if (is_string($forceLang)) {
156
+            $this->requestLanguage = $forceLang;
157
+        }
158
+
159
+        if ($this->requestLanguage !== '' && $this->languageExists($app, $this->requestLanguage)) {
160
+            return $this->requestLanguage;
161
+        }
162
+
163
+        /**
164
+         * At this point Nextcloud might not yet be installed and thus the lookup
165
+         * in the preferences table might fail. For this reason we need to check
166
+         * whether the instance has already been installed
167
+         *
168
+         * @link https://github.com/owncloud/core/issues/21955
169
+         */
170
+        if ($this->config->getSystemValue('installed', false)) {
171
+            $userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() :  null;
172
+            if (!is_null($userId)) {
173
+                $userLang = $this->config->getUserValue($userId, 'core', 'lang', null);
174
+            } else {
175
+                $userLang = null;
176
+            }
177
+        } else {
178
+            $userId = null;
179
+            $userLang = null;
180
+        }
181
+
182
+        if ($userLang) {
183
+            $this->requestLanguage = $userLang;
184
+            if ($this->languageExists($app, $userLang)) {
185
+                return $userLang;
186
+            }
187
+        }
188
+
189
+        try {
190
+            // Try to get the language from the Request
191
+            $lang = $this->getLanguageFromRequest($app);
192
+            if ($userId !== null && $app === null && !$userLang) {
193
+                $this->config->setUserValue($userId, 'core', 'lang', $lang);
194
+            }
195
+            return $lang;
196
+        } catch (LanguageNotFoundException $e) {
197
+            // Finding language from request failed fall back to default language
198
+            $defaultLanguage = $this->config->getSystemValue('default_language', false);
199
+            if ($defaultLanguage !== false && $this->languageExists($app, $defaultLanguage)) {
200
+                return $defaultLanguage;
201
+            }
202
+        }
203
+
204
+        // We could not find any language so fall back to english
205
+        return 'en';
206
+    }
207
+
208
+    /**
209
+     * find the best locale
210
+     *
211
+     * @param string $lang
212
+     * @return null|string
213
+     */
214
+    public function findLocale($lang = null) {
215
+        $forceLocale = $this->config->getSystemValue('force_locale', false);
216
+        if (is_string($forceLocale) && $this->localeExists($forceLocale)) {
217
+            return $forceLocale;
218
+        }
219
+
220
+        if ($this->config->getSystemValue('installed', false)) {
221
+            $userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() :  null;
222
+            $userLocale = null;
223
+            if (null !== $userId) {
224
+                $userLocale = $this->config->getUserValue($userId, 'core', 'locale', null);
225
+            }
226
+        } else {
227
+            $userId = null;
228
+            $userLocale = null;
229
+        }
230
+
231
+        if ($userLocale && $this->localeExists($userLocale)) {
232
+            return $userLocale;
233
+        }
234
+
235
+        // Default : use system default locale
236
+        $defaultLocale = $this->config->getSystemValue('default_locale', false);
237
+        if ($defaultLocale !== false && $this->localeExists($defaultLocale)) {
238
+            return $defaultLocale;
239
+        }
240
+
241
+        // If no user locale set, use lang as locale
242
+        if (null !== $lang && $this->localeExists($lang)) {
243
+            return $lang;
244
+        }
245
+
246
+        // At last, return USA
247
+        return 'en_US';
248
+    }
249
+
250
+    /**
251
+     * find the matching lang from the locale
252
+     *
253
+     * @param string $app
254
+     * @param string $locale
255
+     * @return null|string
256
+     */
257
+    public function findLanguageFromLocale(string $app = 'core', string $locale = null) {
258
+        if ($this->languageExists($app, $locale)) {
259
+            return $locale;
260
+        }
261 261
 		
262
-		// Try to split e.g: fr_FR => fr
263
-		$locale = explode('_', $locale)[0];
264
-		if ($this->languageExists($app, $locale)) {
265
-			return $locale;
266
-		}
267
-	}
268
-
269
-	/**
270
-	 * Find all available languages for an app
271
-	 *
272
-	 * @param string|null $app App id or null for core
273
-	 * @return array an array of available languages
274
-	 */
275
-	public function findAvailableLanguages($app = null) {
276
-		$key = $app;
277
-		if ($key === null) {
278
-			$key = 'null';
279
-		}
280
-
281
-		// also works with null as key
282
-		if (!empty($this->availableLanguages[$key])) {
283
-			return $this->availableLanguages[$key];
284
-		}
285
-
286
-		$available = ['en']; //english is always available
287
-		$dir = $this->findL10nDir($app);
288
-		if (is_dir($dir)) {
289
-			$files = scandir($dir);
290
-			if ($files !== false) {
291
-				foreach ($files as $file) {
292
-					if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
293
-						$available[] = substr($file, 0, -5);
294
-					}
295
-				}
296
-			}
297
-		}
298
-
299
-		// merge with translations from theme
300
-		$theme = $this->config->getSystemValue('theme');
301
-		if (!empty($theme)) {
302
-			$themeDir = $this->serverRoot . '/themes/' . $theme . substr($dir, strlen($this->serverRoot));
303
-
304
-			if (is_dir($themeDir)) {
305
-				$files = scandir($themeDir);
306
-				if ($files !== false) {
307
-					foreach ($files as $file) {
308
-						if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
309
-							$available[] = substr($file, 0, -5);
310
-						}
311
-					}
312
-				}
313
-			}
314
-		}
315
-
316
-		$this->availableLanguages[$key] = $available;
317
-		return $available;
318
-	}
319
-
320
-	/**
321
-	 * @return array|mixed
322
-	 */
323
-	public function findAvailableLocales() {
324
-		if (!empty($this->availableLocales)) {
325
-			return $this->availableLocales;
326
-		}
327
-
328
-		$localeData = file_get_contents(\OC::$SERVERROOT . '/resources/locales.json');
329
-		$this->availableLocales = \json_decode($localeData, true);
330
-
331
-		return $this->availableLocales;
332
-	}
333
-
334
-	/**
335
-	 * @param string|null $app App id or null for core
336
-	 * @param string $lang
337
-	 * @return bool
338
-	 */
339
-	public function languageExists($app, $lang) {
340
-		if ($lang === 'en') {//english is always available
341
-			return true;
342
-		}
343
-
344
-		$languages = $this->findAvailableLanguages($app);
345
-		return array_search($lang, $languages) !== false;
346
-	}
347
-
348
-	public function getLanguageIterator(IUser $user = null): ILanguageIterator {
349
-		$user = $user ?? $this->userSession->getUser();
350
-		if($user === null) {
351
-			throw new \RuntimeException('Failed to get an IUser instance');
352
-		}
353
-		return new LanguageIterator($user, $this->config);
354
-	}
355
-
356
-	/**
357
-	 * @param string $locale
358
-	 * @return bool
359
-	 */
360
-	public function localeExists($locale) {
361
-		if ($locale === 'en') { //english is always available
362
-			return true;
363
-		}
364
-
365
-		$locales = $this->findAvailableLocales();
366
-		$userLocale = array_filter($locales, function($value) use ($locale) {
367
-			return $locale === $value['code'];
368
-		});
369
-
370
-		return !empty($userLocale);
371
-	}
372
-
373
-	/**
374
-	 * @param string|null $app
375
-	 * @return string
376
-	 * @throws LanguageNotFoundException
377
-	 */
378
-	private function getLanguageFromRequest($app) {
379
-		$header = $this->request->getHeader('ACCEPT_LANGUAGE');
380
-		if ($header !== '') {
381
-			$available = $this->findAvailableLanguages($app);
382
-
383
-			// E.g. make sure that 'de' is before 'de_DE'.
384
-			sort($available);
385
-
386
-			$preferences = preg_split('/,\s*/', strtolower($header));
387
-			foreach ($preferences as $preference) {
388
-				list($preferred_language) = explode(';', $preference);
389
-				$preferred_language = str_replace('-', '_', $preferred_language);
390
-
391
-				foreach ($available as $available_language) {
392
-					if ($preferred_language === strtolower($available_language)) {
393
-						return $this->respectDefaultLanguage($app, $available_language);
394
-					}
395
-				}
396
-
397
-				// Fallback from de_De to de
398
-				foreach ($available as $available_language) {
399
-					if (substr($preferred_language, 0, 2) === $available_language) {
400
-						return $available_language;
401
-					}
402
-				}
403
-			}
404
-		}
405
-
406
-		throw new LanguageNotFoundException();
407
-	}
408
-
409
-	/**
410
-	 * if default language is set to de_DE (formal German) this should be
411
-	 * preferred to 'de' (non-formal German) if possible
412
-	 *
413
-	 * @param string|null $app
414
-	 * @param string $lang
415
-	 * @return string
416
-	 */
417
-	protected function respectDefaultLanguage($app, $lang) {
418
-		$result = $lang;
419
-		$defaultLanguage = $this->config->getSystemValue('default_language', false);
420
-
421
-		// use formal version of german ("Sie" instead of "Du") if the default
422
-		// language is set to 'de_DE' if possible
423
-		if (is_string($defaultLanguage) &&
424
-			strtolower($lang) === 'de' &&
425
-			strtolower($defaultLanguage) === 'de_de' &&
426
-			$this->languageExists($app, 'de_DE')
427
-		) {
428
-			$result = 'de_DE';
429
-		}
430
-
431
-		return $result;
432
-	}
433
-
434
-	/**
435
-	 * Checks if $sub is a subdirectory of $parent
436
-	 *
437
-	 * @param string $sub
438
-	 * @param string $parent
439
-	 * @return bool
440
-	 */
441
-	private function isSubDirectory($sub, $parent) {
442
-		// Check whether $sub contains no ".."
443
-		if (strpos($sub, '..') !== false) {
444
-			return false;
445
-		}
446
-
447
-		// Check whether $sub is a subdirectory of $parent
448
-		if (strpos($sub, $parent) === 0) {
449
-			return true;
450
-		}
451
-
452
-		return false;
453
-	}
454
-
455
-	/**
456
-	 * Get a list of language files that should be loaded
457
-	 *
458
-	 * @param string $app
459
-	 * @param string $lang
460
-	 * @return string[]
461
-	 */
462
-	// FIXME This method is only public, until OC_L10N does not need it anymore,
463
-	// FIXME This is also the reason, why it is not in the public interface
464
-	public function getL10nFilesForApp($app, $lang) {
465
-		$languageFiles = [];
466
-
467
-		$i18nDir = $this->findL10nDir($app);
468
-		$transFile = strip_tags($i18nDir) . strip_tags($lang) . '.json';
469
-
470
-		if (($this->isSubDirectory($transFile, $this->serverRoot . '/core/l10n/')
471
-				|| $this->isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/')
472
-				|| $this->isSubDirectory($transFile, $this->serverRoot . '/settings/l10n/')
473
-				|| $this->isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/')
474
-			)
475
-			&& file_exists($transFile)) {
476
-			// load the translations file
477
-			$languageFiles[] = $transFile;
478
-		}
479
-
480
-		// merge with translations from theme
481
-		$theme = $this->config->getSystemValue('theme');
482
-		if (!empty($theme)) {
483
-			$transFile = $this->serverRoot . '/themes/' . $theme . substr($transFile, strlen($this->serverRoot));
484
-			if (file_exists($transFile)) {
485
-				$languageFiles[] = $transFile;
486
-			}
487
-		}
488
-
489
-		return $languageFiles;
490
-	}
491
-
492
-	/**
493
-	 * find the l10n directory
494
-	 *
495
-	 * @param string $app App id or empty string for core
496
-	 * @return string directory
497
-	 */
498
-	protected function findL10nDir($app = null) {
499
-		if (in_array($app, ['core', 'lib', 'settings'])) {
500
-			if (file_exists($this->serverRoot . '/' . $app . '/l10n/')) {
501
-				return $this->serverRoot . '/' . $app . '/l10n/';
502
-			}
503
-		} else if ($app && \OC_App::getAppPath($app) !== false) {
504
-			// Check if the app is in the app folder
505
-			return \OC_App::getAppPath($app) . '/l10n/';
506
-		}
507
-		return $this->serverRoot . '/core/l10n/';
508
-	}
509
-
510
-
511
-	/**
512
-	 * Creates a function from the plural string
513
-	 *
514
-	 * Parts of the code is copied from Habari:
515
-	 * https://github.com/habari/system/blob/master/classes/locale.php
516
-	 * @param string $string
517
-	 * @return string
518
-	 */
519
-	public function createPluralFunction($string) {
520
-		if (isset($this->pluralFunctions[$string])) {
521
-			return $this->pluralFunctions[$string];
522
-		}
523
-
524
-		if (preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s*plural=(.*)$/u', $string, $matches)) {
525
-			// sanitize
526
-			$nplurals = preg_replace( '/[^0-9]/', '', $matches[1] );
527
-			$plural = preg_replace( '#[^n0-9:\(\)\?\|\&=!<>+*/\%-]#', '', $matches[2] );
528
-
529
-			$body = str_replace(
530
-				array( 'plural', 'n', '$n$plurals', ),
531
-				array( '$plural', '$n', '$nplurals', ),
532
-				'nplurals='. $nplurals . '; plural=' . $plural
533
-			);
534
-
535
-			// add parents
536
-			// important since PHP's ternary evaluates from left to right
537
-			$body .= ';';
538
-			$res = '';
539
-			$p = 0;
540
-			$length = strlen($body);
541
-			for($i = 0; $i < $length; $i++) {
542
-				$ch = $body[$i];
543
-				switch ( $ch ) {
544
-					case '?':
545
-						$res .= ' ? (';
546
-						$p++;
547
-						break;
548
-					case ':':
549
-						$res .= ') : (';
550
-						break;
551
-					case ';':
552
-						$res .= str_repeat( ')', $p ) . ';';
553
-						$p = 0;
554
-						break;
555
-					default:
556
-						$res .= $ch;
557
-				}
558
-			}
559
-
560
-			$body = $res . 'return ($plural>=$nplurals?$nplurals-1:$plural);';
561
-			$function = create_function('$n', $body);
562
-			$this->pluralFunctions[$string] = $function;
563
-			return $function;
564
-		} else {
565
-			// default: one plural form for all cases but n==1 (english)
566
-			$function = create_function(
567
-				'$n',
568
-				'$nplurals=2;$plural=($n==1?0:1);return ($plural>=$nplurals?$nplurals-1:$plural);'
569
-			);
570
-			$this->pluralFunctions[$string] = $function;
571
-			return $function;
572
-		}
573
-	}
574
-
575
-	/**
576
-	 * returns the common language and other languages in an
577
-	 * associative array
578
-	 *
579
-	 * @return array
580
-	 */
581
-	public function getLanguages() {
582
-		$forceLanguage = $this->config->getSystemValue('force_language', false);
583
-		if ($forceLanguage !== false) {
584
-			return [];
585
-		}
586
-
587
-		$languageCodes = $this->findAvailableLanguages();
588
-
589
-		$commonLanguages = [];
590
-		$languages = [];
591
-
592
-		foreach($languageCodes as $lang) {
593
-			$l = $this->get('lib', $lang);
594
-			// TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
595
-			$potentialName = (string) $l->t('__language_name__');
596
-			if ($l->getLanguageCode() === $lang && $potentialName[0] !== '_') {//first check if the language name is in the translation file
597
-				$ln = array(
598
-					'code' => $lang,
599
-					'name' => $potentialName
600
-				);
601
-			} else if ($lang === 'en') {
602
-				$ln = array(
603
-					'code' => $lang,
604
-					'name' => 'English (US)'
605
-				);
606
-			} else {//fallback to language code
607
-				$ln = array(
608
-					'code' => $lang,
609
-					'name' => $lang
610
-				);
611
-			}
612
-
613
-			// put appropriate languages into appropriate arrays, to print them sorted
614
-			// common languages -> divider -> other languages
615
-			if (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
616
-				$commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)] = $ln;
617
-			} else {
618
-				$languages[] = $ln;
619
-			}
620
-		}
621
-
622
-		ksort($commonLanguages);
623
-
624
-		// sort now by displayed language not the iso-code
625
-		usort( $languages, function ($a, $b) {
626
-			if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
627
-				// If a doesn't have a name, but b does, list b before a
628
-				return 1;
629
-			}
630
-			if ($a['code'] !== $a['name'] && $b['code'] === $b['name']) {
631
-				// If a does have a name, but b doesn't, list a before b
632
-				return -1;
633
-			}
634
-			// Otherwise compare the names
635
-			return strcmp($a['name'], $b['name']);
636
-		});
637
-
638
-		return [
639
-			// reset indexes
640
-			'commonlanguages' => array_values($commonLanguages),
641
-			'languages' => $languages
642
-		];
643
-	}
262
+        // Try to split e.g: fr_FR => fr
263
+        $locale = explode('_', $locale)[0];
264
+        if ($this->languageExists($app, $locale)) {
265
+            return $locale;
266
+        }
267
+    }
268
+
269
+    /**
270
+     * Find all available languages for an app
271
+     *
272
+     * @param string|null $app App id or null for core
273
+     * @return array an array of available languages
274
+     */
275
+    public function findAvailableLanguages($app = null) {
276
+        $key = $app;
277
+        if ($key === null) {
278
+            $key = 'null';
279
+        }
280
+
281
+        // also works with null as key
282
+        if (!empty($this->availableLanguages[$key])) {
283
+            return $this->availableLanguages[$key];
284
+        }
285
+
286
+        $available = ['en']; //english is always available
287
+        $dir = $this->findL10nDir($app);
288
+        if (is_dir($dir)) {
289
+            $files = scandir($dir);
290
+            if ($files !== false) {
291
+                foreach ($files as $file) {
292
+                    if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
293
+                        $available[] = substr($file, 0, -5);
294
+                    }
295
+                }
296
+            }
297
+        }
298
+
299
+        // merge with translations from theme
300
+        $theme = $this->config->getSystemValue('theme');
301
+        if (!empty($theme)) {
302
+            $themeDir = $this->serverRoot . '/themes/' . $theme . substr($dir, strlen($this->serverRoot));
303
+
304
+            if (is_dir($themeDir)) {
305
+                $files = scandir($themeDir);
306
+                if ($files !== false) {
307
+                    foreach ($files as $file) {
308
+                        if (substr($file, -5) === '.json' && substr($file, 0, 4) !== 'l10n') {
309
+                            $available[] = substr($file, 0, -5);
310
+                        }
311
+                    }
312
+                }
313
+            }
314
+        }
315
+
316
+        $this->availableLanguages[$key] = $available;
317
+        return $available;
318
+    }
319
+
320
+    /**
321
+     * @return array|mixed
322
+     */
323
+    public function findAvailableLocales() {
324
+        if (!empty($this->availableLocales)) {
325
+            return $this->availableLocales;
326
+        }
327
+
328
+        $localeData = file_get_contents(\OC::$SERVERROOT . '/resources/locales.json');
329
+        $this->availableLocales = \json_decode($localeData, true);
330
+
331
+        return $this->availableLocales;
332
+    }
333
+
334
+    /**
335
+     * @param string|null $app App id or null for core
336
+     * @param string $lang
337
+     * @return bool
338
+     */
339
+    public function languageExists($app, $lang) {
340
+        if ($lang === 'en') {//english is always available
341
+            return true;
342
+        }
343
+
344
+        $languages = $this->findAvailableLanguages($app);
345
+        return array_search($lang, $languages) !== false;
346
+    }
347
+
348
+    public function getLanguageIterator(IUser $user = null): ILanguageIterator {
349
+        $user = $user ?? $this->userSession->getUser();
350
+        if($user === null) {
351
+            throw new \RuntimeException('Failed to get an IUser instance');
352
+        }
353
+        return new LanguageIterator($user, $this->config);
354
+    }
355
+
356
+    /**
357
+     * @param string $locale
358
+     * @return bool
359
+     */
360
+    public function localeExists($locale) {
361
+        if ($locale === 'en') { //english is always available
362
+            return true;
363
+        }
364
+
365
+        $locales = $this->findAvailableLocales();
366
+        $userLocale = array_filter($locales, function($value) use ($locale) {
367
+            return $locale === $value['code'];
368
+        });
369
+
370
+        return !empty($userLocale);
371
+    }
372
+
373
+    /**
374
+     * @param string|null $app
375
+     * @return string
376
+     * @throws LanguageNotFoundException
377
+     */
378
+    private function getLanguageFromRequest($app) {
379
+        $header = $this->request->getHeader('ACCEPT_LANGUAGE');
380
+        if ($header !== '') {
381
+            $available = $this->findAvailableLanguages($app);
382
+
383
+            // E.g. make sure that 'de' is before 'de_DE'.
384
+            sort($available);
385
+
386
+            $preferences = preg_split('/,\s*/', strtolower($header));
387
+            foreach ($preferences as $preference) {
388
+                list($preferred_language) = explode(';', $preference);
389
+                $preferred_language = str_replace('-', '_', $preferred_language);
390
+
391
+                foreach ($available as $available_language) {
392
+                    if ($preferred_language === strtolower($available_language)) {
393
+                        return $this->respectDefaultLanguage($app, $available_language);
394
+                    }
395
+                }
396
+
397
+                // Fallback from de_De to de
398
+                foreach ($available as $available_language) {
399
+                    if (substr($preferred_language, 0, 2) === $available_language) {
400
+                        return $available_language;
401
+                    }
402
+                }
403
+            }
404
+        }
405
+
406
+        throw new LanguageNotFoundException();
407
+    }
408
+
409
+    /**
410
+     * if default language is set to de_DE (formal German) this should be
411
+     * preferred to 'de' (non-formal German) if possible
412
+     *
413
+     * @param string|null $app
414
+     * @param string $lang
415
+     * @return string
416
+     */
417
+    protected function respectDefaultLanguage($app, $lang) {
418
+        $result = $lang;
419
+        $defaultLanguage = $this->config->getSystemValue('default_language', false);
420
+
421
+        // use formal version of german ("Sie" instead of "Du") if the default
422
+        // language is set to 'de_DE' if possible
423
+        if (is_string($defaultLanguage) &&
424
+            strtolower($lang) === 'de' &&
425
+            strtolower($defaultLanguage) === 'de_de' &&
426
+            $this->languageExists($app, 'de_DE')
427
+        ) {
428
+            $result = 'de_DE';
429
+        }
430
+
431
+        return $result;
432
+    }
433
+
434
+    /**
435
+     * Checks if $sub is a subdirectory of $parent
436
+     *
437
+     * @param string $sub
438
+     * @param string $parent
439
+     * @return bool
440
+     */
441
+    private function isSubDirectory($sub, $parent) {
442
+        // Check whether $sub contains no ".."
443
+        if (strpos($sub, '..') !== false) {
444
+            return false;
445
+        }
446
+
447
+        // Check whether $sub is a subdirectory of $parent
448
+        if (strpos($sub, $parent) === 0) {
449
+            return true;
450
+        }
451
+
452
+        return false;
453
+    }
454
+
455
+    /**
456
+     * Get a list of language files that should be loaded
457
+     *
458
+     * @param string $app
459
+     * @param string $lang
460
+     * @return string[]
461
+     */
462
+    // FIXME This method is only public, until OC_L10N does not need it anymore,
463
+    // FIXME This is also the reason, why it is not in the public interface
464
+    public function getL10nFilesForApp($app, $lang) {
465
+        $languageFiles = [];
466
+
467
+        $i18nDir = $this->findL10nDir($app);
468
+        $transFile = strip_tags($i18nDir) . strip_tags($lang) . '.json';
469
+
470
+        if (($this->isSubDirectory($transFile, $this->serverRoot . '/core/l10n/')
471
+                || $this->isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/')
472
+                || $this->isSubDirectory($transFile, $this->serverRoot . '/settings/l10n/')
473
+                || $this->isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/')
474
+            )
475
+            && file_exists($transFile)) {
476
+            // load the translations file
477
+            $languageFiles[] = $transFile;
478
+        }
479
+
480
+        // merge with translations from theme
481
+        $theme = $this->config->getSystemValue('theme');
482
+        if (!empty($theme)) {
483
+            $transFile = $this->serverRoot . '/themes/' . $theme . substr($transFile, strlen($this->serverRoot));
484
+            if (file_exists($transFile)) {
485
+                $languageFiles[] = $transFile;
486
+            }
487
+        }
488
+
489
+        return $languageFiles;
490
+    }
491
+
492
+    /**
493
+     * find the l10n directory
494
+     *
495
+     * @param string $app App id or empty string for core
496
+     * @return string directory
497
+     */
498
+    protected function findL10nDir($app = null) {
499
+        if (in_array($app, ['core', 'lib', 'settings'])) {
500
+            if (file_exists($this->serverRoot . '/' . $app . '/l10n/')) {
501
+                return $this->serverRoot . '/' . $app . '/l10n/';
502
+            }
503
+        } else if ($app && \OC_App::getAppPath($app) !== false) {
504
+            // Check if the app is in the app folder
505
+            return \OC_App::getAppPath($app) . '/l10n/';
506
+        }
507
+        return $this->serverRoot . '/core/l10n/';
508
+    }
509
+
510
+
511
+    /**
512
+     * Creates a function from the plural string
513
+     *
514
+     * Parts of the code is copied from Habari:
515
+     * https://github.com/habari/system/blob/master/classes/locale.php
516
+     * @param string $string
517
+     * @return string
518
+     */
519
+    public function createPluralFunction($string) {
520
+        if (isset($this->pluralFunctions[$string])) {
521
+            return $this->pluralFunctions[$string];
522
+        }
523
+
524
+        if (preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s*plural=(.*)$/u', $string, $matches)) {
525
+            // sanitize
526
+            $nplurals = preg_replace( '/[^0-9]/', '', $matches[1] );
527
+            $plural = preg_replace( '#[^n0-9:\(\)\?\|\&=!<>+*/\%-]#', '', $matches[2] );
528
+
529
+            $body = str_replace(
530
+                array( 'plural', 'n', '$n$plurals', ),
531
+                array( '$plural', '$n', '$nplurals', ),
532
+                'nplurals='. $nplurals . '; plural=' . $plural
533
+            );
534
+
535
+            // add parents
536
+            // important since PHP's ternary evaluates from left to right
537
+            $body .= ';';
538
+            $res = '';
539
+            $p = 0;
540
+            $length = strlen($body);
541
+            for($i = 0; $i < $length; $i++) {
542
+                $ch = $body[$i];
543
+                switch ( $ch ) {
544
+                    case '?':
545
+                        $res .= ' ? (';
546
+                        $p++;
547
+                        break;
548
+                    case ':':
549
+                        $res .= ') : (';
550
+                        break;
551
+                    case ';':
552
+                        $res .= str_repeat( ')', $p ) . ';';
553
+                        $p = 0;
554
+                        break;
555
+                    default:
556
+                        $res .= $ch;
557
+                }
558
+            }
559
+
560
+            $body = $res . 'return ($plural>=$nplurals?$nplurals-1:$plural);';
561
+            $function = create_function('$n', $body);
562
+            $this->pluralFunctions[$string] = $function;
563
+            return $function;
564
+        } else {
565
+            // default: one plural form for all cases but n==1 (english)
566
+            $function = create_function(
567
+                '$n',
568
+                '$nplurals=2;$plural=($n==1?0:1);return ($plural>=$nplurals?$nplurals-1:$plural);'
569
+            );
570
+            $this->pluralFunctions[$string] = $function;
571
+            return $function;
572
+        }
573
+    }
574
+
575
+    /**
576
+     * returns the common language and other languages in an
577
+     * associative array
578
+     *
579
+     * @return array
580
+     */
581
+    public function getLanguages() {
582
+        $forceLanguage = $this->config->getSystemValue('force_language', false);
583
+        if ($forceLanguage !== false) {
584
+            return [];
585
+        }
586
+
587
+        $languageCodes = $this->findAvailableLanguages();
588
+
589
+        $commonLanguages = [];
590
+        $languages = [];
591
+
592
+        foreach($languageCodes as $lang) {
593
+            $l = $this->get('lib', $lang);
594
+            // TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
595
+            $potentialName = (string) $l->t('__language_name__');
596
+            if ($l->getLanguageCode() === $lang && $potentialName[0] !== '_') {//first check if the language name is in the translation file
597
+                $ln = array(
598
+                    'code' => $lang,
599
+                    'name' => $potentialName
600
+                );
601
+            } else if ($lang === 'en') {
602
+                $ln = array(
603
+                    'code' => $lang,
604
+                    'name' => 'English (US)'
605
+                );
606
+            } else {//fallback to language code
607
+                $ln = array(
608
+                    'code' => $lang,
609
+                    'name' => $lang
610
+                );
611
+            }
612
+
613
+            // put appropriate languages into appropriate arrays, to print them sorted
614
+            // common languages -> divider -> other languages
615
+            if (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
616
+                $commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)] = $ln;
617
+            } else {
618
+                $languages[] = $ln;
619
+            }
620
+        }
621
+
622
+        ksort($commonLanguages);
623
+
624
+        // sort now by displayed language not the iso-code
625
+        usort( $languages, function ($a, $b) {
626
+            if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
627
+                // If a doesn't have a name, but b does, list b before a
628
+                return 1;
629
+            }
630
+            if ($a['code'] !== $a['name'] && $b['code'] === $b['name']) {
631
+                // If a does have a name, but b doesn't, list a before b
632
+                return -1;
633
+            }
634
+            // Otherwise compare the names
635
+            return strcmp($a['name'], $b['name']);
636
+        });
637
+
638
+        return [
639
+            // reset indexes
640
+            'commonlanguages' => array_values($commonLanguages),
641
+            'languages' => $languages
642
+        ];
643
+    }
644 644
 }
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -112,7 +112,7 @@  discard block
 block discarded – undo
112 112
 
113 113
 			$app = \OC_App::cleanAppId($app);
114 114
 			if ($lang !== null) {
115
-				$lang = str_replace(array('\0', '/', '\\', '..'), '', (string)$lang);
115
+				$lang = str_replace(array('\0', '/', '\\', '..'), '', (string) $lang);
116 116
 			}
117 117
 
118 118
 			$forceLang = $this->config->getSystemValue('force_language', false);
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
 		 * @link https://github.com/owncloud/core/issues/21955
169 169
 		 */
170 170
 		if ($this->config->getSystemValue('installed', false)) {
171
-			$userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() :  null;
171
+			$userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() : null;
172 172
 			if (!is_null($userId)) {
173 173
 				$userLang = $this->config->getUserValue($userId, 'core', 'lang', null);
174 174
 			} else {
@@ -218,7 +218,7 @@  discard block
 block discarded – undo
218 218
 		}
219 219
 
220 220
 		if ($this->config->getSystemValue('installed', false)) {
221
-			$userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() :  null;
221
+			$userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() : null;
222 222
 			$userLocale = null;
223 223
 			if (null !== $userId) {
224 224
 				$userLocale = $this->config->getUserValue($userId, 'core', 'locale', null);
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
 		// merge with translations from theme
300 300
 		$theme = $this->config->getSystemValue('theme');
301 301
 		if (!empty($theme)) {
302
-			$themeDir = $this->serverRoot . '/themes/' . $theme . substr($dir, strlen($this->serverRoot));
302
+			$themeDir = $this->serverRoot.'/themes/'.$theme.substr($dir, strlen($this->serverRoot));
303 303
 
304 304
 			if (is_dir($themeDir)) {
305 305
 				$files = scandir($themeDir);
@@ -325,7 +325,7 @@  discard block
 block discarded – undo
325 325
 			return $this->availableLocales;
326 326
 		}
327 327
 
328
-		$localeData = file_get_contents(\OC::$SERVERROOT . '/resources/locales.json');
328
+		$localeData = file_get_contents(\OC::$SERVERROOT.'/resources/locales.json');
329 329
 		$this->availableLocales = \json_decode($localeData, true);
330 330
 
331 331
 		return $this->availableLocales;
@@ -347,7 +347,7 @@  discard block
 block discarded – undo
347 347
 
348 348
 	public function getLanguageIterator(IUser $user = null): ILanguageIterator {
349 349
 		$user = $user ?? $this->userSession->getUser();
350
-		if($user === null) {
350
+		if ($user === null) {
351 351
 			throw new \RuntimeException('Failed to get an IUser instance');
352 352
 		}
353 353
 		return new LanguageIterator($user, $this->config);
@@ -465,12 +465,12 @@  discard block
 block discarded – undo
465 465
 		$languageFiles = [];
466 466
 
467 467
 		$i18nDir = $this->findL10nDir($app);
468
-		$transFile = strip_tags($i18nDir) . strip_tags($lang) . '.json';
468
+		$transFile = strip_tags($i18nDir).strip_tags($lang).'.json';
469 469
 
470
-		if (($this->isSubDirectory($transFile, $this->serverRoot . '/core/l10n/')
471
-				|| $this->isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/')
472
-				|| $this->isSubDirectory($transFile, $this->serverRoot . '/settings/l10n/')
473
-				|| $this->isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/')
470
+		if (($this->isSubDirectory($transFile, $this->serverRoot.'/core/l10n/')
471
+				|| $this->isSubDirectory($transFile, $this->serverRoot.'/lib/l10n/')
472
+				|| $this->isSubDirectory($transFile, $this->serverRoot.'/settings/l10n/')
473
+				|| $this->isSubDirectory($transFile, \OC_App::getAppPath($app).'/l10n/')
474 474
 			)
475 475
 			&& file_exists($transFile)) {
476 476
 			// load the translations file
@@ -480,7 +480,7 @@  discard block
 block discarded – undo
480 480
 		// merge with translations from theme
481 481
 		$theme = $this->config->getSystemValue('theme');
482 482
 		if (!empty($theme)) {
483
-			$transFile = $this->serverRoot . '/themes/' . $theme . substr($transFile, strlen($this->serverRoot));
483
+			$transFile = $this->serverRoot.'/themes/'.$theme.substr($transFile, strlen($this->serverRoot));
484 484
 			if (file_exists($transFile)) {
485 485
 				$languageFiles[] = $transFile;
486 486
 			}
@@ -497,14 +497,14 @@  discard block
 block discarded – undo
497 497
 	 */
498 498
 	protected function findL10nDir($app = null) {
499 499
 		if (in_array($app, ['core', 'lib', 'settings'])) {
500
-			if (file_exists($this->serverRoot . '/' . $app . '/l10n/')) {
501
-				return $this->serverRoot . '/' . $app . '/l10n/';
500
+			if (file_exists($this->serverRoot.'/'.$app.'/l10n/')) {
501
+				return $this->serverRoot.'/'.$app.'/l10n/';
502 502
 			}
503 503
 		} else if ($app && \OC_App::getAppPath($app) !== false) {
504 504
 			// Check if the app is in the app folder
505
-			return \OC_App::getAppPath($app) . '/l10n/';
505
+			return \OC_App::getAppPath($app).'/l10n/';
506 506
 		}
507
-		return $this->serverRoot . '/core/l10n/';
507
+		return $this->serverRoot.'/core/l10n/';
508 508
 	}
509 509
 
510 510
 
@@ -521,15 +521,15 @@  discard block
 block discarded – undo
521 521
 			return $this->pluralFunctions[$string];
522 522
 		}
523 523
 
524
-		if (preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s*plural=(.*)$/u', $string, $matches)) {
524
+		if (preg_match('/^\s*nplurals\s*=\s*(\d+)\s*;\s*plural=(.*)$/u', $string, $matches)) {
525 525
 			// sanitize
526
-			$nplurals = preg_replace( '/[^0-9]/', '', $matches[1] );
527
-			$plural = preg_replace( '#[^n0-9:\(\)\?\|\&=!<>+*/\%-]#', '', $matches[2] );
526
+			$nplurals = preg_replace('/[^0-9]/', '', $matches[1]);
527
+			$plural = preg_replace('#[^n0-9:\(\)\?\|\&=!<>+*/\%-]#', '', $matches[2]);
528 528
 
529 529
 			$body = str_replace(
530
-				array( 'plural', 'n', '$n$plurals', ),
531
-				array( '$plural', '$n', '$nplurals', ),
532
-				'nplurals='. $nplurals . '; plural=' . $plural
530
+				array('plural', 'n', '$n$plurals',),
531
+				array('$plural', '$n', '$nplurals',),
532
+				'nplurals='.$nplurals.'; plural='.$plural
533 533
 			);
534 534
 
535 535
 			// add parents
@@ -538,9 +538,9 @@  discard block
 block discarded – undo
538 538
 			$res = '';
539 539
 			$p = 0;
540 540
 			$length = strlen($body);
541
-			for($i = 0; $i < $length; $i++) {
541
+			for ($i = 0; $i < $length; $i++) {
542 542
 				$ch = $body[$i];
543
-				switch ( $ch ) {
543
+				switch ($ch) {
544 544
 					case '?':
545 545
 						$res .= ' ? (';
546 546
 						$p++;
@@ -549,7 +549,7 @@  discard block
 block discarded – undo
549 549
 						$res .= ') : (';
550 550
 						break;
551 551
 					case ';':
552
-						$res .= str_repeat( ')', $p ) . ';';
552
+						$res .= str_repeat(')', $p).';';
553 553
 						$p = 0;
554 554
 						break;
555 555
 					default:
@@ -557,7 +557,7 @@  discard block
 block discarded – undo
557 557
 				}
558 558
 			}
559 559
 
560
-			$body = $res . 'return ($plural>=$nplurals?$nplurals-1:$plural);';
560
+			$body = $res.'return ($plural>=$nplurals?$nplurals-1:$plural);';
561 561
 			$function = create_function('$n', $body);
562 562
 			$this->pluralFunctions[$string] = $function;
563 563
 			return $function;
@@ -589,7 +589,7 @@  discard block
 block discarded – undo
589 589
 		$commonLanguages = [];
590 590
 		$languages = [];
591 591
 
592
-		foreach($languageCodes as $lang) {
592
+		foreach ($languageCodes as $lang) {
593 593
 			$l = $this->get('lib', $lang);
594 594
 			// TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
595 595
 			$potentialName = (string) $l->t('__language_name__');
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
 		ksort($commonLanguages);
623 623
 
624 624
 		// sort now by displayed language not the iso-code
625
-		usort( $languages, function ($a, $b) {
625
+		usort($languages, function($a, $b) {
626 626
 			if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
627 627
 				// If a doesn't have a name, but b does, list b before a
628 628
 				return 1;
Please login to merge, or discard this patch.