diff options
author | ArthurHoaro <arthur@hoa.ro> | 2018-07-28 11:07:55 +0200 |
---|---|---|
committer | ArthurHoaro <arthur@hoa.ro> | 2018-07-28 11:07:55 +0200 |
commit | 83faedadff76c5bdca036f39f13943f63b27e164 (patch) | |
tree | 6f44cede16ec6a60f10b9699e211e0818f06d2c8 /application/Languages.php | |
parent | 1d9eb22a3df85b67fe6652c0876cd7382c2fb525 (diff) | |
parent | 658988f3aeba7a5a938783249ccf2765251e5597 (diff) | |
download | Shaarli-83faedadff76c5bdca036f39f13943f63b27e164.tar.gz Shaarli-83faedadff76c5bdca036f39f13943f63b27e164.tar.zst Shaarli-83faedadff76c5bdca036f39f13943f63b27e164.zip |
Merge tag 'v0.9.7' into stable
Release v0.9.7
Diffstat (limited to 'application/Languages.php')
-rw-r--r-- | application/Languages.php | 169 |
1 files changed, 157 insertions, 12 deletions
diff --git a/application/Languages.php b/application/Languages.php index c8b0a25a..3eb3388f 100644 --- a/application/Languages.php +++ b/application/Languages.php | |||
@@ -1,21 +1,166 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Shaarli; | ||
4 | |||
5 | use Gettext\GettextTranslator; | ||
6 | use Gettext\Merge; | ||
7 | use Gettext\Translations; | ||
8 | use Gettext\Translator; | ||
9 | use Gettext\TranslatorInterface; | ||
10 | use Shaarli\Config\ConfigManager; | ||
11 | |||
3 | /** | 12 | /** |
4 | * Wrapper function for translation which match the API | 13 | * Class Languages |
5 | * of gettext()/_() and ngettext(). | 14 | * |
15 | * Load Shaarli translations using 'gettext/gettext'. | ||
16 | * This class allows to either use PHP gettext extension, or a PHP implementation of gettext, | ||
17 | * with a fixed language, or dynamically using autoLocale(). | ||
6 | * | 18 | * |
7 | * Not doing translation for now. | 19 | * Translation files PO/MO files follow gettext standard and must be placed under: |
20 | * <translation path>/<language>/LC_MESSAGES/<domain>.[po|mo] | ||
8 | * | 21 | * |
9 | * @param string $text Text to translate. | 22 | * Pros/cons: |
10 | * @param string $nText The plural message ID. | 23 | * - gettext extension is faster |
11 | * @param int $nb The number of items for plural forms. | 24 | * - gettext is very system dependent (PHP extension, the locale must be installed, and web server reloaded) |
12 | * | 25 | * |
13 | * @return String Text translated. | 26 | * Settings: |
27 | * - translation.mode: | ||
28 | * - auto: use default setting (PHP implementation) | ||
29 | * - php: use PHP implementation | ||
30 | * - gettext: use gettext wrapper | ||
31 | * - translation.language: | ||
32 | * - auto: use autoLocale() and the language change according to user HTTP headers | ||
33 | * - fixed language: e.g. 'fr' | ||
34 | * - translation.extensions: | ||
35 | * - domain => translation_path: allow plugins and themes to extend the defaut extension | ||
36 | * The domain must be unique, and translation path must be relative, and contains the tree mentioned above. | ||
37 | * | ||
38 | * @package Shaarli | ||
14 | */ | 39 | */ |
15 | function t($text, $nText = '', $nb = 0) { | 40 | class Languages |
16 | if (empty($nText)) { | 41 | { |
17 | return $text; | 42 | /** |
43 | * Core translations domain | ||
44 | */ | ||
45 | const DEFAULT_DOMAIN = 'shaarli'; | ||
46 | |||
47 | /** | ||
48 | * @var TranslatorInterface | ||
49 | */ | ||
50 | protected $translator; | ||
51 | |||
52 | /** | ||
53 | * @var string | ||
54 | */ | ||
55 | protected $language; | ||
56 | |||
57 | /** | ||
58 | * @var ConfigManager | ||
59 | */ | ||
60 | protected $conf; | ||
61 | |||
62 | /** | ||
63 | * Languages constructor. | ||
64 | * | ||
65 | * @param string $language lang determined by autoLocale(), can be overridden. | ||
66 | * @param ConfigManager $conf instance. | ||
67 | */ | ||
68 | public function __construct($language, $conf) | ||
69 | { | ||
70 | $this->conf = $conf; | ||
71 | $confLanguage = $this->conf->get('translation.language', 'auto'); | ||
72 | // Auto mode or invalid parameter, use the detected language. | ||
73 | // If the detected language is invalid, it doesn't matter, it will use English. | ||
74 | if ($confLanguage === 'auto' || ! $this->isValidLanguage($confLanguage)) { | ||
75 | $this->language = substr($language, 0, 5); | ||
76 | } else { | ||
77 | $this->language = $confLanguage; | ||
78 | } | ||
79 | |||
80 | if (! extension_loaded('gettext') | ||
81 | || in_array($this->conf->get('translation.mode', 'auto'), ['auto', 'php']) | ||
82 | ) { | ||
83 | $this->initPhpTranslator(); | ||
84 | } else { | ||
85 | $this->initGettextTranslator(); | ||
86 | } | ||
87 | |||
88 | // Register default functions (e.g. '__()') to use our Translator | ||
89 | $this->translator->register(); | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * Initialize the translator using php gettext extension (gettext dependency act as a wrapper). | ||
94 | */ | ||
95 | protected function initGettextTranslator () | ||
96 | { | ||
97 | $this->translator = new GettextTranslator(); | ||
98 | $this->translator->setLanguage($this->language); | ||
99 | $this->translator->loadDomain(self::DEFAULT_DOMAIN, 'inc/languages'); | ||
100 | |||
101 | foreach ($this->conf->get('translation.extensions', []) as $domain => $translationPath) { | ||
102 | if ($domain !== self::DEFAULT_DOMAIN) { | ||
103 | $this->translator->loadDomain($domain, $translationPath, false); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * Initialize the translator using a PHP implementation of gettext. | ||
110 | * | ||
111 | * Note that if language po file doesn't exist, errors are ignored (e.g. not installed language). | ||
112 | */ | ||
113 | protected function initPhpTranslator() | ||
114 | { | ||
115 | $this->translator = new Translator(); | ||
116 | $translations = new Translations(); | ||
117 | // Core translations | ||
118 | try { | ||
119 | /** @var Translations $translations */ | ||
120 | $translations = $translations->addFromPoFile('inc/languages/'. $this->language .'/LC_MESSAGES/shaarli.po'); | ||
121 | $translations->setDomain('shaarli'); | ||
122 | $this->translator->loadTranslations($translations); | ||
123 | } catch (\InvalidArgumentException $e) {} | ||
124 | |||
125 | |||
126 | // Extension translations (plugins, themes, etc.). | ||
127 | foreach ($this->conf->get('translation.extensions', []) as $domain => $translationPath) { | ||
128 | if ($domain === self::DEFAULT_DOMAIN) { | ||
129 | continue; | ||
130 | } | ||
131 | |||
132 | try { | ||
133 | /** @var Translations $extension */ | ||
134 | $extension = Translations::fromPoFile($translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po'); | ||
135 | $extension->setDomain($domain); | ||
136 | $this->translator->loadTranslations($extension); | ||
137 | } catch (\InvalidArgumentException $e) {} | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * Checks if a language string is valid. | ||
143 | * | ||
144 | * @param string $language e.g. 'fr' or 'en_US' | ||
145 | * | ||
146 | * @return bool true if valid, false otherwise | ||
147 | */ | ||
148 | protected function isValidLanguage($language) | ||
149 | { | ||
150 | return preg_match('/^[a-z]{2}(_[A-Z]{2})?/', $language) === 1; | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Get the list of available languages for Shaarli. | ||
155 | * | ||
156 | * @return array List of available languages, with their label. | ||
157 | */ | ||
158 | public static function getAvailableLanguages() | ||
159 | { | ||
160 | return [ | ||
161 | 'auto' => t('Automatic'), | ||
162 | 'en' => t('English'), | ||
163 | 'fr' => t('French'), | ||
164 | ]; | ||
18 | } | 165 | } |
19 | $actualForm = $nb > 1 ? $nText : $text; | ||
20 | return sprintf($actualForm, $nb); | ||
21 | } | 166 | } |