]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - application/Languages.php
Shaarli's translation
[github/shaarli/Shaarli.git] / application / Languages.php
CommitLineData
edf3ff5a
A
1<?php
2
12266213
A
3namespace Shaarli;
4
5use Gettext\GettextTranslator;
6use Gettext\Merge;
7use Gettext\Translations;
8use Gettext\Translator;
9use Gettext\TranslatorInterface;
10use Shaarli\Config\ConfigManager;
11
edf3ff5a 12/**
12266213
A
13 * Class Languages
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().
edf3ff5a 18 *
12266213
A
19 * Translation files PO/MO files follow gettext standard and must be placed under:
20 * <translation path>/<language>/LC_MESSAGES/<domain>.[po|mo]
edf3ff5a 21 *
12266213
A
22 * Pros/cons:
23 * - gettext extension is faster
24 * - gettext is very system dependent (PHP extension, the locale must be installed, and web server reloaded)
edf3ff5a 25 *
12266213
A
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
edf3ff5a 39 */
12266213
A
40class Languages
41{
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 override.
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 if ($confLanguage === 'auto' || ! $this->isValidLanguage($confLanguage)) {
73 $this->language = substr($language, 0, 5);
74 } else {
75 $this->language = $confLanguage;
76 }
77
78 if (! extension_loaded('gettext')
79 || in_array($this->conf->get('translation.mode', 'auto'), ['auto', 'php'])
80 ) {
81 $this->initPhpTranslator();
82 } else {
83 $this->initGettextTranslator();
84 }
85
86 // Register default functions (e.g. '__()') to use our Translator
87 $this->translator->register();
88 }
89
90 /**
91 * Initialize the translator using php gettext extension (gettext dependency act as a wrapper).
92 */
93 protected function initGettextTranslator ()
94 {
95 $this->translator = new GettextTranslator();
96 $this->translator->setLanguage($this->language);
97 $this->translator->loadDomain(self::DEFAULT_DOMAIN, 'inc/languages');
98
99 foreach ($this->conf->get('translation.extensions', []) as $domain => $translationPath) {
100 if ($domain !== self::DEFAULT_DOMAIN) {
101 $this->translator->loadDomain($domain, $translationPath, false);
102 }
103 }
104 }
105
106 /**
107 * Initialize the translator using a PHP implementation of gettext.
108 *
109 * Note that if language po file doesn't exist, errors are ignored (e.g. not installed language).
110 */
111 protected function initPhpTranslator()
112 {
113 $this->translator = new Translator();
114 $translations = new Translations();
115 // Core translations
116 try {
117 /** @var Translations $translations */
118 $translations = $translations->addFromPoFile('inc/languages/'. $this->language .'/LC_MESSAGES/shaarli.po');
119 $translations->setDomain('shaarli');
120 $this->translator->loadTranslations($translations);
121 } catch (\InvalidArgumentException $e) {}
122
123
124 // Extension translations (plugins, themes, etc.).
125 foreach ($this->conf->get('translation.extensions', []) as $domain => $translationPath) {
126 if ($domain === self::DEFAULT_DOMAIN) {
127 continue;
128 }
129
130 try {
131 /** @var Translations $extension */
132 $extension = Translations::fromPoFile($translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po');
133 $extension->setDomain($domain);
134 $this->translator->loadTranslations($extension);
135 } catch (\InvalidArgumentException $e) {}
136 }
137 }
138
139 /**
140 * Checks if a language string is valid.
141 *
142 * @param string $language e.g. 'fr' or 'en_US'
143 *
144 * @return bool true if valid, false otherwise
145 */
146 protected function isValidLanguage($language)
147 {
148 return preg_match('/^[a-z]{2}(_[A-Z]{2})?/', $language) === 1;
edf3ff5a 149 }
edf3ff5a 150}