Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /**
|
Chris@0
|
4 * @file
|
Chris@0
|
5 * Install, update, and uninstall functions for the Locale module.
|
Chris@0
|
6 */
|
Chris@0
|
7
|
Chris@18
|
8 use Drupal\Core\File\Exception\FileException;
|
Chris@18
|
9 use Drupal\Core\File\FileSystemInterface;
|
Chris@0
|
10 use Drupal\Core\Url;
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * Implements hook_install().
|
Chris@0
|
14 */
|
Chris@0
|
15 function locale_install() {
|
Chris@0
|
16 // Create the interface translations directory and ensure it's writable.
|
Chris@0
|
17 if (!$directory = \Drupal::config('locale.settings')->get('translation.path')) {
|
Chris@0
|
18 $site_path = \Drupal::service('site.path');
|
Chris@0
|
19 $directory = $site_path . '/files/translations';
|
Chris@0
|
20 \Drupal::configFactory()->getEditable('locale.settings')->set('translation.path', $directory)->save();
|
Chris@0
|
21 }
|
Chris@18
|
22 \Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
|
Chris@0
|
23 }
|
Chris@0
|
24
|
Chris@0
|
25 /**
|
Chris@0
|
26 * Implements hook_uninstall().
|
Chris@0
|
27 */
|
Chris@0
|
28 function locale_uninstall() {
|
Chris@0
|
29 $config = \Drupal::config('locale.settings');
|
Chris@0
|
30 // Delete all JavaScript translation files.
|
Chris@0
|
31 $locale_js_directory = 'public://' . $config->get('javascript.directory');
|
Chris@0
|
32
|
Chris@0
|
33 if (is_dir($locale_js_directory)) {
|
Chris@0
|
34 $locale_javascripts = \Drupal::state()->get('locale.translation.javascript') ?: [];
|
Chris@0
|
35 foreach ($locale_javascripts as $langcode => $file_suffix) {
|
Chris@0
|
36 if (!empty($file_suffix)) {
|
Chris@18
|
37 try {
|
Chris@18
|
38 \Drupal::service('file_system')->delete($locale_js_directory . '/' . $langcode . '_' . $file_suffix . '.js');
|
Chris@18
|
39 }
|
Chris@18
|
40 catch (FileException $e) {
|
Chris@18
|
41 // Ignore and continue.
|
Chris@18
|
42 }
|
Chris@0
|
43 }
|
Chris@0
|
44 }
|
Chris@0
|
45 // Delete the JavaScript translations directory if empty.
|
Chris@0
|
46 if (!file_scan_directory($locale_js_directory, '/.*/')) {
|
Chris@18
|
47 \Drupal::service('file_system')->rmdir($locale_js_directory);
|
Chris@0
|
48 }
|
Chris@0
|
49 }
|
Chris@0
|
50
|
Chris@0
|
51 // Clear variables.
|
Chris@0
|
52 \Drupal::state()->delete('system.javascript_parsed');
|
Chris@0
|
53 \Drupal::state()->delete('locale.translation.plurals');
|
Chris@0
|
54 \Drupal::state()->delete('locale.translation.javascript');
|
Chris@0
|
55 }
|
Chris@0
|
56
|
Chris@0
|
57 /**
|
Chris@0
|
58 * Implements hook_schema().
|
Chris@0
|
59 */
|
Chris@0
|
60 function locale_schema() {
|
Chris@0
|
61 $schema['locales_source'] = [
|
Chris@0
|
62 'description' => 'List of English source strings.',
|
Chris@0
|
63 'fields' => [
|
Chris@0
|
64 'lid' => [
|
Chris@0
|
65 'type' => 'serial',
|
Chris@0
|
66 'not null' => TRUE,
|
Chris@0
|
67 'description' => 'Unique identifier of this string.',
|
Chris@0
|
68 ],
|
Chris@0
|
69 'source' => [
|
Chris@0
|
70 'type' => 'text',
|
Chris@0
|
71 'mysql_type' => 'blob',
|
Chris@0
|
72 'not null' => TRUE,
|
Chris@0
|
73 'description' => 'The original string in English.',
|
Chris@0
|
74 ],
|
Chris@0
|
75 'context' => [
|
Chris@0
|
76 'type' => 'varchar_ascii',
|
Chris@0
|
77 'length' => 255,
|
Chris@0
|
78 'not null' => TRUE,
|
Chris@0
|
79 'default' => '',
|
Chris@0
|
80 'description' => 'The context this string applies to.',
|
Chris@0
|
81 ],
|
Chris@0
|
82 'version' => [
|
Chris@0
|
83 'type' => 'varchar_ascii',
|
Chris@0
|
84 'length' => 20,
|
Chris@0
|
85 'not null' => TRUE,
|
Chris@0
|
86 'default' => 'none',
|
Chris@0
|
87 'description' => 'Version of Drupal where the string was last used (for locales optimization).',
|
Chris@0
|
88 ],
|
Chris@0
|
89 ],
|
Chris@0
|
90 'primary key' => ['lid'],
|
Chris@0
|
91 'indexes' => [
|
Chris@0
|
92 'source_context' => [['source', 30], 'context'],
|
Chris@0
|
93 ],
|
Chris@0
|
94 ];
|
Chris@0
|
95
|
Chris@0
|
96 $schema['locales_target'] = [
|
Chris@0
|
97 'description' => 'Stores translated versions of strings.',
|
Chris@0
|
98 'fields' => [
|
Chris@0
|
99 'lid' => [
|
Chris@0
|
100 'type' => 'int',
|
Chris@0
|
101 'not null' => TRUE,
|
Chris@0
|
102 'default' => 0,
|
Chris@0
|
103 'description' => 'Source string ID. References {locales_source}.lid.',
|
Chris@0
|
104 ],
|
Chris@0
|
105 'translation' => [
|
Chris@0
|
106 'type' => 'text',
|
Chris@0
|
107 'mysql_type' => 'blob',
|
Chris@0
|
108 'not null' => TRUE,
|
Chris@0
|
109 'description' => 'Translation string value in this language.',
|
Chris@0
|
110 ],
|
Chris@0
|
111 'language' => [
|
Chris@0
|
112 'type' => 'varchar_ascii',
|
Chris@0
|
113 'length' => 12,
|
Chris@0
|
114 'not null' => TRUE,
|
Chris@0
|
115 'default' => '',
|
Chris@0
|
116 'description' => 'Language code. References {language}.langcode.',
|
Chris@0
|
117 ],
|
Chris@0
|
118 'customized' => [
|
Chris@0
|
119 'type' => 'int',
|
Chris@0
|
120 'not null' => TRUE,
|
Chris@0
|
121 // LOCALE_NOT_CUSTOMIZED
|
Chris@0
|
122 'default' => 0,
|
Chris@0
|
123 'description' => 'Boolean indicating whether the translation is custom to this site.',
|
Chris@0
|
124 ],
|
Chris@0
|
125 ],
|
Chris@0
|
126 'primary key' => ['language', 'lid'],
|
Chris@0
|
127 'foreign keys' => [
|
Chris@0
|
128 'locales_source' => [
|
Chris@0
|
129 'table' => 'locales_source',
|
Chris@0
|
130 'columns' => ['lid' => 'lid'],
|
Chris@0
|
131 ],
|
Chris@0
|
132 ],
|
Chris@0
|
133 'indexes' => [
|
Chris@0
|
134 'lid' => ['lid'],
|
Chris@0
|
135 ],
|
Chris@0
|
136 ];
|
Chris@0
|
137
|
Chris@0
|
138 $schema['locales_location'] = [
|
Chris@0
|
139 'description' => 'Location information for source strings.',
|
Chris@0
|
140 'fields' => [
|
Chris@0
|
141 'lid' => [
|
Chris@0
|
142 'type' => 'serial',
|
Chris@0
|
143 'not null' => TRUE,
|
Chris@0
|
144 'description' => 'Unique identifier of this location.',
|
Chris@0
|
145 ],
|
Chris@0
|
146 'sid' => [
|
Chris@0
|
147 'type' => 'int',
|
Chris@0
|
148 'not null' => TRUE,
|
Chris@0
|
149 'description' => 'Unique identifier of this string.',
|
Chris@0
|
150 ],
|
Chris@0
|
151 'type' => [
|
Chris@0
|
152 'type' => 'varchar_ascii',
|
Chris@0
|
153 'length' => 50,
|
Chris@0
|
154 'not null' => TRUE,
|
Chris@0
|
155 'default' => '',
|
Chris@0
|
156 'description' => 'The location type (file, config, path, etc).',
|
Chris@0
|
157 ],
|
Chris@0
|
158 'name' => [
|
Chris@0
|
159 'type' => 'varchar',
|
Chris@0
|
160 'length' => 255,
|
Chris@0
|
161 'not null' => TRUE,
|
Chris@0
|
162 'default' => '',
|
Chris@0
|
163 'description' => 'Type dependent location information (file name, path, etc).',
|
Chris@0
|
164 ],
|
Chris@0
|
165 'version' => [
|
Chris@0
|
166 'type' => 'varchar_ascii',
|
Chris@0
|
167 'length' => 20,
|
Chris@0
|
168 'not null' => TRUE,
|
Chris@0
|
169 'default' => 'none',
|
Chris@0
|
170 'description' => 'Version of Drupal where the location was found.',
|
Chris@0
|
171 ],
|
Chris@0
|
172 ],
|
Chris@0
|
173 'primary key' => ['lid'],
|
Chris@0
|
174 'foreign keys' => [
|
Chris@0
|
175 'locales_source' => [
|
Chris@0
|
176 'table' => 'locales_source',
|
Chris@0
|
177 'columns' => ['sid' => 'lid'],
|
Chris@0
|
178 ],
|
Chris@0
|
179 ],
|
Chris@0
|
180 'indexes' => [
|
Chris@0
|
181 'string_id' => ['sid'],
|
Chris@0
|
182 'string_type' => ['sid', 'type'],
|
Chris@0
|
183 ],
|
Chris@0
|
184 ];
|
Chris@0
|
185
|
Chris@0
|
186 $schema['locale_file'] = [
|
Chris@0
|
187 'description' => 'File import status information for interface translation files.',
|
Chris@0
|
188 'fields' => [
|
Chris@0
|
189 'project' => [
|
Chris@0
|
190 'type' => 'varchar_ascii',
|
Chris@0
|
191 'length' => '255',
|
Chris@0
|
192 'not null' => TRUE,
|
Chris@0
|
193 'default' => '',
|
Chris@0
|
194 'description' => 'A unique short name to identify the project the file belongs to.',
|
Chris@0
|
195 ],
|
Chris@0
|
196 'langcode' => [
|
Chris@0
|
197 'type' => 'varchar_ascii',
|
Chris@0
|
198 'length' => '12',
|
Chris@0
|
199 'not null' => TRUE,
|
Chris@0
|
200 'default' => '',
|
Chris@0
|
201 'description' => 'Language code of this translation. References {language}.langcode.',
|
Chris@0
|
202 ],
|
Chris@0
|
203 'filename' => [
|
Chris@0
|
204 'type' => 'varchar',
|
Chris@0
|
205 'length' => 255,
|
Chris@0
|
206 'not null' => TRUE,
|
Chris@0
|
207 'default' => '',
|
Chris@0
|
208 'description' => 'Filename of the imported file.',
|
Chris@0
|
209 ],
|
Chris@0
|
210 'version' => [
|
Chris@0
|
211 'type' => 'varchar',
|
Chris@0
|
212 'length' => '128',
|
Chris@0
|
213 'not null' => TRUE,
|
Chris@0
|
214 'default' => '',
|
Chris@0
|
215 'description' => 'Version tag of the imported file.',
|
Chris@0
|
216 ],
|
Chris@0
|
217 'uri' => [
|
Chris@0
|
218 'type' => 'varchar',
|
Chris@0
|
219 'length' => 255,
|
Chris@0
|
220 'not null' => TRUE,
|
Chris@0
|
221 'default' => '',
|
Chris@0
|
222 'description' => 'URI of the remote file, the resulting local file or the locally imported file.',
|
Chris@0
|
223 ],
|
Chris@0
|
224 'timestamp' => [
|
Chris@0
|
225 'type' => 'int',
|
Chris@0
|
226 'not null' => FALSE,
|
Chris@0
|
227 'default' => 0,
|
Chris@0
|
228 'description' => 'Unix timestamp of the imported file.',
|
Chris@0
|
229 ],
|
Chris@0
|
230 'last_checked' => [
|
Chris@0
|
231 'type' => 'int',
|
Chris@0
|
232 'not null' => FALSE,
|
Chris@0
|
233 'default' => 0,
|
Chris@0
|
234 'description' => 'Unix timestamp of the last time this translation was confirmed to be the most recent release available.',
|
Chris@0
|
235 ],
|
Chris@0
|
236 ],
|
Chris@0
|
237 'primary key' => ['project', 'langcode'],
|
Chris@0
|
238 ];
|
Chris@0
|
239 return $schema;
|
Chris@0
|
240 }
|
Chris@0
|
241
|
Chris@0
|
242 /**
|
Chris@0
|
243 * Implements hook_requirements().
|
Chris@0
|
244 */
|
Chris@0
|
245 function locale_requirements($phase) {
|
Chris@0
|
246 $requirements = [];
|
Chris@0
|
247 if ($phase == 'runtime') {
|
Chris@0
|
248 $available_updates = [];
|
Chris@0
|
249 $untranslated = [];
|
Chris@0
|
250 $languages = locale_translatable_language_list();
|
Chris@0
|
251
|
Chris@0
|
252 if ($languages) {
|
Chris@0
|
253 // Determine the status of the translation updates per language.
|
Chris@0
|
254 $status = locale_translation_get_status();
|
Chris@0
|
255 if ($status) {
|
Chris@0
|
256 foreach ($status as $project) {
|
Chris@0
|
257 foreach ($project as $langcode => $project_info) {
|
Chris@0
|
258 if (empty($project_info->type)) {
|
Chris@0
|
259 $untranslated[$langcode] = $languages[$langcode]->getName();
|
Chris@0
|
260 }
|
Chris@0
|
261 elseif ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE) {
|
Chris@0
|
262 $available_updates[$langcode] = $languages[$langcode]->getName();
|
Chris@0
|
263 }
|
Chris@0
|
264 }
|
Chris@0
|
265 }
|
Chris@0
|
266
|
Chris@0
|
267 if ($available_updates || $untranslated) {
|
Chris@0
|
268 if ($available_updates) {
|
Chris@0
|
269 $requirements['locale_translation'] = [
|
Chris@14
|
270 'title' => t('Translation update status'),
|
Chris@0
|
271 'value' => \Drupal::l(t('Updates available'), new Url('locale.translate_status')),
|
Chris@0
|
272 'severity' => REQUIREMENT_WARNING,
|
Chris@18
|
273 'description' => t('Updates available for: @languages. See the <a href=":updates">Available translation updates</a> page for more information.', ['@languages' => implode(', ', $available_updates), ':updates' => Url::fromRoute('locale.translate_status')->toString()]),
|
Chris@0
|
274 ];
|
Chris@0
|
275 }
|
Chris@0
|
276 else {
|
Chris@0
|
277 $requirements['locale_translation'] = [
|
Chris@14
|
278 'title' => t('Translation update status'),
|
Chris@0
|
279 'value' => t('Missing translations'),
|
Chris@0
|
280 'severity' => REQUIREMENT_INFO,
|
Chris@18
|
281 'description' => t('Missing translations for: @languages. See the <a href=":updates">Available translation updates</a> page for more information.', ['@languages' => implode(', ', $untranslated), ':updates' => Url::fromRoute('locale.translate_status')->toString()]),
|
Chris@0
|
282 ];
|
Chris@0
|
283 }
|
Chris@0
|
284 }
|
Chris@0
|
285 else {
|
Chris@0
|
286 $requirements['locale_translation'] = [
|
Chris@14
|
287 'title' => t('Translation update status'),
|
Chris@0
|
288 'value' => t('Up to date'),
|
Chris@0
|
289 'severity' => REQUIREMENT_OK,
|
Chris@0
|
290 ];
|
Chris@0
|
291 }
|
Chris@0
|
292 }
|
Chris@0
|
293 else {
|
Chris@0
|
294 $requirements['locale_translation'] = [
|
Chris@14
|
295 'title' => t('Translation update status'),
|
Chris@0
|
296 'value' => \Drupal::l(t('Can not determine status'), new Url('locale.translate_status')),
|
Chris@0
|
297 'severity' => REQUIREMENT_WARNING,
|
Chris@18
|
298 'description' => t('No translation status is available. See the <a href=":updates">Available translation updates</a> page for more information.', [':updates' => Url::fromRoute('locale.translate_status')->toString()]),
|
Chris@0
|
299 ];
|
Chris@0
|
300 }
|
Chris@0
|
301 }
|
Chris@0
|
302 }
|
Chris@0
|
303 return $requirements;
|
Chris@0
|
304 }
|
Chris@0
|
305
|
Chris@0
|
306 /**
|
Chris@0
|
307 * Delete translation status data in state.
|
Chris@0
|
308 */
|
Chris@0
|
309 function locale_update_8300() {
|
Chris@0
|
310 // Delete the old translation status data, it will be rebuilt and stored in
|
Chris@0
|
311 // the new key value collection.
|
Chris@0
|
312 \Drupal::state()->delete('locale.translation_status');
|
Chris@0
|
313 }
|
Chris@14
|
314
|
Chris@14
|
315 /**
|
Chris@14
|
316 * Update default server pattern value to use https.
|
Chris@14
|
317 */
|
Chris@14
|
318 function locale_update_8500() {
|
Chris@14
|
319 $update_url = \Drupal::config('locale.settings')->get('translation.default_server_pattern');
|
Chris@14
|
320 if ($update_url == 'http://ftp.drupal.org/files/translations/%core/%project/%project-%version.%language.po') {
|
Chris@14
|
321 \Drupal::configFactory()->getEditable('locale.settings')
|
Chris@14
|
322 ->set('translation.default_server_pattern', 'https://ftp.drupal.org/files/translations/%core/%project/%project-%version.%language.po')
|
Chris@14
|
323 ->save();
|
Chris@14
|
324 }
|
Chris@14
|
325 }
|