[ Index ] |
PHP Cross Reference of GlotPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Routes: GP_Route_Translation class 4 * 5 * @package GlotPress 6 * @subpackage Routes 7 * @since 1.0.0 8 */ 9 10 /** 11 * Core class used to implement the translation route. 12 * 13 * @since 1.0.0 14 */ 15 class GP_Route_Translation extends GP_Route_Main { 16 17 public function import_translations_get( $project_path, $locale_slug, $translation_set_slug ) { 18 $project = GP::$project->by_path( $project_path ); 19 $locale = GP_Locales::by_slug( $locale_slug ); 20 21 if ( ! $project || ! $locale ) { 22 return $this->die_with_404(); 23 } 24 25 $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug ); 26 27 if ( ! $translation_set ) { 28 return $this->die_with_404(); 29 } 30 31 $can_import_current = $this->can( 'approve', 'translation-set', $translation_set->id ); 32 $can_import_waiting = $can_import_current || $this->can( 'import-waiting', 'translation-set', $translation_set->id ); 33 34 if ( ! $can_import_current && ! $can_import_waiting ) { 35 $this->redirect_with_error( __( 'You are not allowed to do that!', 'glotpress' ) ); 36 return; 37 } 38 39 $kind = 'translations'; 40 $this->tmpl( 'project-import', get_defined_vars() ); 41 } 42 43 public function import_translations_post( $project_path, $locale_slug, $translation_set_slug ) { 44 $project = GP::$project->by_path( $project_path ); 45 $locale = GP_Locales::by_slug( $locale_slug ); 46 47 if ( ! $project || ! $locale ) { 48 return $this->die_with_404(); 49 } 50 51 if ( $this->invalid_nonce_and_redirect( 'import-translations_' . $project->id ) ) { 52 return; 53 } 54 55 $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug ); 56 57 if ( ! $translation_set ) { 58 return $this->die_with_404(); 59 } 60 61 $can_import_current = $this->can( 'approve', 'translation-set', $translation_set->id ); 62 $can_import_waiting = $can_import_current || $this->can( 'import-waiting', 'translation-set', $translation_set->id ); 63 64 if ( ! $can_import_current && ! $can_import_waiting ) { 65 $this->redirect_with_error( __( 'You are not allowed to do that!', 'glotpress' ) ); 66 return; 67 } 68 69 $import_status = gp_post( 'status', 'waiting' ); 70 71 $allowed_import_status = array(); 72 if ( $can_import_current ) { 73 $allowed_import_status[] = 'current'; 74 } 75 if ( $can_import_waiting ) { 76 $allowed_import_status[] = 'waiting'; 77 } 78 79 if ( ! in_array( $import_status, $allowed_import_status, true ) ) { 80 $this->redirect_with_error( __( 'Invalid translation status.', 'glotpress' ) ); 81 return; 82 } 83 84 if ( ! is_uploaded_file( $_FILES['import-file']['tmp_name'] ) ) { 85 $this->redirect_with_error( __( 'Error uploading the file.', 'glotpress' ) ); 86 return; 87 } 88 89 $format = gp_get_import_file_format( gp_post( 'format', 'po' ), $_FILES['import-file']['name'] ); 90 91 if ( ! $format ) { 92 $this->redirect_with_error( __( 'No such format.', 'glotpress' ) ); 93 return; 94 } 95 96 $translations = $format->read_translations_from_file( $_FILES['import-file']['tmp_name'], $project ); 97 if ( ! $translations ) { 98 $this->redirect_with_error( __( 'Couldn’t load translations from file!', 'glotpress' ) ); 99 return; 100 } 101 102 $translations_added = $translation_set->import( $translations, $import_status ); 103 $this->notices[] = sprintf( 104 /* translators: %s: Translations count. */ 105 _n( '%s translation was added', '%s translations were added', $translations_added, 'glotpress' ), 106 $translations_added 107 ); 108 109 $this->redirect( gp_url_project( $project, gp_url_join( $locale->slug, $translation_set->slug ) ) ); 110 } 111 112 public function export_translations_get( $project_path, $locale_slug, $translation_set_slug ) { 113 $project = GP::$project->by_path( $project_path ); 114 $locale = GP_Locales::by_slug( $locale_slug ); 115 116 if ( ! $project || ! $locale ) { 117 return $this->die_with_404(); 118 } 119 120 $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug ); 121 122 if ( ! $translation_set ) { 123 return $this->die_with_404(); 124 } 125 126 $get_format = gp_get( 'format', 'po' ); 127 128 // If for some reason we were passed in an array or object from the get parameters, don't use it. 129 if ( ! is_string( $get_format ) ) { 130 $get_format = 'po'; 131 } 132 133 /** @var GP_Format|null $format */ 134 $format = gp_array_get( GP::$formats, $get_format, null ); 135 136 if ( ! $format ) { 137 return $this->die_with_404(); 138 } 139 140 /** 141 * Filter the locale in the file name of the translation set export. 142 * 143 * @since 1.0.0 144 * 145 * @param string $slug Slug of the locale. 146 * @param GP_Locale $locale The current locale. 147 */ 148 $export_locale = apply_filters( 'gp_export_locale', $locale->slug, $locale ); 149 $filename = sprintf( $format->filename_pattern . '.' . $format->extension, str_replace( '/', '-', $project->path ), $export_locale ); 150 151 /** 152 * Filter the filename of the translation set export. 153 * 154 * @since 1.0.0 155 * 156 * @param string $filename Filename of the exported translation set. 157 * @param GP_Format $format Format of the export. 158 * @param GP_Locale $locale Locale of the export. 159 * @param GP_Project $project Project the translation set belongs to. 160 * @param GP_Translation_Set $translation_set The translation set to be exported. 161 */ 162 $filename = apply_filters( 'gp_export_translations_filename', $filename, $format, $locale, $project, $translation_set ); 163 164 $entries = GP::$translation->for_export( $project, $translation_set, gp_get( 'filters' ) ); 165 166 if ( gp_has_translation_been_updated( $translation_set ) ) { 167 $last_modified = gmdate( 'D, d M Y H:i:s', gp_gmt_strtotime( GP::$translation->last_modified( $translation_set ) ) ) . ' GMT'; 168 $this->headers_for_download( $filename, $last_modified ); 169 170 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 171 echo $format->print_exported_file( $project, $locale, $translation_set, $entries ); 172 } else { 173 // As has_translation_been_updated() compared against HTTP_IF_MODIFIED_SINCE here, send an appropriate header. 174 $this->status_header( 304 ); 175 } 176 } 177 178 public function translations_get( $project_path, $locale_slug, $translation_set_slug ) { 179 $project = GP::$project->by_path( $project_path ); 180 $locale = GP_Locales::by_slug( $locale_slug ); 181 182 if ( ! $project || ! $locale ) { 183 return $this->die_with_404(); 184 } 185 186 $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug ); 187 188 if ( ! $translation_set ) { 189 return $this->die_with_404(); 190 } 191 192 $glossary = $this->get_extended_glossary( $translation_set, $project ); 193 194 $page = gp_get( 'page', 1 ); 195 $filters = gp_get( 'filters', array() ); 196 $sort = gp_get( 'sort', array() ); 197 198 if ( is_array( $sort ) && 'random' === gp_array_get( $sort, 'by' ) ) { 199 add_filter( 'gp_pagination', '__return_null' ); 200 } 201 202 $per_page = (int) get_user_option( 'gp_per_page' ); 203 if ( 0 === $per_page ) { 204 $per_page = GP::$translation->per_page; 205 } else { 206 GP::$translation->per_page = $per_page; 207 } 208 209 if ( ! is_array( $filters ) ) { 210 $filters = array(); 211 } 212 213 if ( ! is_array( $sort ) ) { 214 $sort = array(); 215 } 216 217 $translations = GP::$translation->for_translation( $project, $translation_set, $page, $filters, $sort ); 218 $total_translations_count = GP::$translation->found_rows; 219 220 $can_edit = $this->can( 'edit', 'translation-set', $translation_set->id ); 221 $can_write = $this->can( 'write', 'project', $project->id ); 222 $can_approve = $this->can( 'approve', 'translation-set', $translation_set->id ); 223 $can_import_current = $can_approve; 224 $can_import_waiting = $can_approve || $this->can( 'import-waiting', 'translation-set', $translation_set->id ); 225 $url = gp_url_project( $project, gp_url_join( $locale->slug, $translation_set->slug ) ); 226 $set_priority_url = gp_url( '/originals/%original-id%/set_priority' ); 227 $discard_warning_url = gp_url_project( $project, gp_url_join( $locale->slug, $translation_set->slug, '-discard-warning' ) ); 228 $set_status_url = gp_url_project( $project, gp_url_join( $locale->slug, $translation_set->slug, '-set-status' ) ); 229 $bulk_action = gp_url_join( $url, '-bulk' ); 230 231 // Add action to use different font for translations 232 add_action( 233 'gp_head', 234 function() use ( $locale ) { 235 return gp_preferred_sans_serif_style_tag( $locale ); 236 } 237 ); 238 239 $this->tmpl( 'translations', get_defined_vars() ); 240 } 241 242 public function translations_post( $project_path, $locale_slug, $translation_set_slug ) { 243 $project = GP::$project->by_path( $project_path ); 244 $locale = GP_Locales::by_slug( $locale_slug ); 245 246 if ( ! $project || ! $locale ) { 247 return $this->die_with_404(); 248 } 249 250 $original_id = gp_post( 'original_id' ); 251 252 if ( ! $this->verify_nonce( 'add-translation_' . $original_id ) ) { 253 return $this->die_with_error( __( 'An error has occurred. Please try again.', 'glotpress' ), 403 ); 254 } 255 256 $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug ); 257 258 $this->can_or_forbidden( 'edit', 'translation-set', $translation_set->id ); 259 260 if ( ! $translation_set ) { 261 return $this->die_with_404(); 262 } 263 264 $glossary = $this->get_extended_glossary( $translation_set, $project ); 265 266 $output = array(); 267 foreach ( gp_post( 'translation', array() ) as $original_id => $translations ) { 268 $data = compact( 'original_id' ); 269 $data['user_id'] = get_current_user_id(); 270 $data['translation_set_id'] = $translation_set->id; 271 272 // Reduce range by one since we're starting at 0, see GH#516. 273 foreach ( range( 0, GP::$translation->get_static( 'number_of_plural_translations' ) - 1 ) as $i ) { 274 if ( isset( $translations[ $i ] ) ) { 275 $data[ "translation_$i" ] = $translations[ $i ]; 276 } 277 } 278 279 if ( isset( $data['status'] ) ) { 280 $set_status = $data['status']; 281 } else { 282 $set_status = 'waiting'; 283 } 284 285 $data['status'] = 'waiting'; 286 287 if ( $this->can( 'approve', 'translation-set', $translation_set->id ) || $this->can( 'write', 'project', $project->id ) ) { 288 $set_status = 'current'; 289 } else { 290 $set_status = 'waiting'; 291 } 292 293 $original = GP::$original->get( $original_id ); 294 $data['warnings'] = GP::$translation_warnings->check( $original->singular, $original->plural, $translations, $locale ); 295 296 $existing_translations = GP::$translation->for_translation( 297 $project, 298 $translation_set, 299 'no-limit', 300 array( 301 'original_id' => $original_id, 302 'status' => 'current_or_waiting', 303 ), 304 array() 305 ); 306 foreach ( $existing_translations as $e ) { 307 if ( array_pad( $translations, $locale->nplurals, null ) == $e->translations ) { 308 return $this->die_with_error( __( 'Identical current or waiting translation already exists.', 'glotpress' ), 200 ); 309 } 310 } 311 312 $translation = GP::$translation->create( $data ); 313 314 if ( ! $translation ) { 315 return $this->die_with_error( __( 'Error in saving the translation!', 'glotpress' ) ); 316 } 317 318 if ( ! $translation->validate() ) { 319 $error_output = '<ul>'; 320 foreach ( $translation->errors as $error ) { 321 $error_output .= '<li>' . $error . '</li>'; 322 } 323 $error_output .= '</ul>'; 324 $translation->delete(); 325 326 return $this->die_with_error( $error_output, 200 ); 327 } else { 328 if ( 'current' === $set_status ) { 329 $translation->set_status( 'current' ); 330 } 331 332 $translations = GP::$translation->for_translation( $project, $translation_set, 'no-limit', array( 'translation_id' => $translation->id ), array() ); 333 334 if ( ! empty( $translations ) ) { 335 $translation = $translations[0]; 336 337 $can_edit = $this->can( 'edit', 'translation-set', $translation_set->id ); 338 $can_write = $this->can( 'write', 'project', $project->id ); 339 $can_approve = $this->can( 'approve', 'translation-set', $translation_set->id ); 340 $can_approve_translation = $this->can( 'approve', 'translation', $translation->id, array( 'translation' => $translation ) ); 341 342 $output[ $original_id ] = gp_tmpl_get_output( 'translation-row', get_defined_vars() ); 343 } else { 344 $output[ $original_id ] = false; 345 } 346 } 347 } 348 echo wp_json_encode( $output ); 349 } 350 351 public function bulk_post( $project_path, $locale_slug, $translation_set_slug ) { 352 $project = GP::$project->by_path( $project_path ); 353 $locale = GP_Locales::by_slug( $locale_slug ); 354 355 if ( ! $project || ! $locale ) { 356 return $this->die_with_404(); 357 } 358 359 $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug ); 360 361 if ( ! $translation_set ) { 362 return $this->die_with_404(); 363 } 364 365 if ( $this->invalid_nonce_and_redirect( 'bulk-actions' ) ) { 366 return; 367 } 368 369 if ( $this->cannot_and_redirect( 'approve', 'translation-set', $translation_set->id ) ) { 370 return; 371 } 372 373 $bulk = gp_post( 'bulk' ); 374 $bulk['row-ids'] = array_filter( explode( ',', $bulk['row-ids'] ) ); 375 if ( ! empty( $bulk['row-ids'] ) ) { 376 switch ( $bulk['action'] ) { 377 case 'approve': 378 case 'reject': 379 $this->_bulk_approve( $bulk ); 380 break; 381 case 'fuzzy': 382 $this->_bulk_fuzzy( $bulk ); 383 break; 384 case 'set-priority': 385 $this->_bulk_set_priority( $project, $bulk ); 386 } 387 388 /** 389 * Bulk action for translation set allows handling of custom actions. 390 * 391 * @since 1.0.0 392 * 393 * @param GP_Project $project The current project. 394 * @param GP_Locale $locale The current locale. 395 * @param GP_Translation_Set $translation_set The current translation set. 396 * @param array $bulk { 397 * The bulk action data, read from the POST. 398 * 399 * @type string $action Action value chosen from the drop down menu. 400 * @type string $priority The selected value from the priority drop down menu. 401 * @type string $redirect_to The URL that after the bulk actions are executed the 402 * browser is redirected to. 403 * @type array $row-ids An array of strings of row IDs. 404 * } 405 */ 406 do_action( 'gp_translation_set_bulk_action_post', $project, $locale, $translation_set, $bulk ); 407 } else { 408 $this->errors[] = 'No translations were supplied.'; 409 } 410 411 $bulk['redirect_to'] = esc_url_raw( $bulk['redirect_to'] ); 412 $this->redirect( $bulk['redirect_to'] ); 413 } 414 415 private function _bulk_approve( $bulk ) { 416 417 $action = $bulk['action']; 418 419 $ok = $error = 0; 420 $new_status = 'approve' == $action ? 'current' : 'rejected'; 421 foreach ( $bulk['row-ids'] as $row_id ) { 422 $translation_id = gp_array_get( explode( '-', $row_id ), 1 ); 423 $translation = GP::$translation->get( $translation_id ); 424 if ( ! $translation ) { 425 continue; 426 } 427 if ( $translation->set_status( $new_status ) ) { 428 $ok++; 429 } else { 430 $error++; 431 } 432 } 433 434 if ( 0 === $error ) { 435 $this->notices[] = 'approve' == $action ? 436 sprintf( 437 /* translators: %d: Translations count. */ 438 _n( '%d translation was approved.', '%d translations were approved.', $ok, 'glotpress' ), 439 $ok 440 ) : 441 sprintf( 442 /* translators: %d: Translations count. */ 443 _n( '%d translation was rejected.', '%d translations were rejected.', $ok, 'glotpress' ), 444 $ok 445 ); 446 } else { 447 if ( $ok > 0 ) { 448 $message = 'approve' == $action ? 449 sprintf( 450 /* translators: %s: Translations count. */ 451 _n( 'Error with approving %s translation.', 'Error with approving %s translations.', $error, 'glotpress' ), 452 $error 453 ) : 454 sprintf( 455 /* translators: %s: Translations count. */ 456 _n( 'Error with rejecting %s translation.', 'Error with rejecting %s translations.', $error, 'glotpress' ), 457 $error 458 ); 459 $message .= ' '; 460 $message .= 'approve' == $action ? 461 sprintf( 462 /* translators: %s: Translations count. */ 463 _n( 'The remaining %s translation was approved successfully.', 'The remaining %s translations were approved successfully.', $ok, 'glotpress' ), 464 $ok 465 ) : 466 sprintf( 467 /* translators: %s: Translations count. */ 468 _n( 'The remaining %s translation was rejected successfully.', 'The remaining %s translations were rejected successfully.', $ok, 'glotpress' ), 469 $ok 470 ); 471 $this->errors[] = $message; 472 } else { 473 $this->errors[] = 'approve' == $action ? 474 sprintf( 475 /* translators: %s: Translations count. */ 476 _n( 'Error with approving %s translation.', 'Error with approving all %s translations.', $error, 'glotpress' ), 477 $error 478 ) : 479 sprintf( 480 /* translators: %s: Translations count. */ 481 _n( 'Error with rejecting %s translation.', 'Error with rejecting all %s translations.', $error, 'glotpress' ), 482 $error 483 ); 484 } 485 } 486 } 487 488 /** 489 * Processes the bulk action to set translations to fuzzy. 490 * 491 * @since 2.3.0 492 * 493 * @param array $bulk The bulk data to process. 494 */ 495 private function _bulk_fuzzy( $bulk ) { 496 $ok = $error = 0; 497 498 foreach ( $bulk['row-ids'] as $row_id ) { 499 $translation_id = gp_array_get( explode( '-', $row_id ), 1 ); 500 $translation = GP::$translation->get( $translation_id ); 501 502 if ( ! $translation ) { 503 continue; 504 } 505 506 if ( $translation->set_status( 'fuzzy' ) ) { 507 $ok++; 508 } else { 509 $error++; 510 } 511 } 512 513 if ( 0 === $error ) { 514 $this->notices[] = sprintf( 515 /* translators: %d: Translations count. */ 516 _n( '%d translation was marked as fuzzy.', '%d translations were marked as fuzzy.', $ok, 'glotpress' ), 517 $ok 518 ); 519 } else { 520 if ( $ok > 0 ) { 521 $message = sprintf( 522 /* translators: %d: Translations count. */ 523 _n( 'Error with marking %d translation as fuzzy.', 'Error with marking %d translations as fuzzy.', $error, 'glotpress' ), 524 $error 525 ); 526 $message .= ' '; 527 $message .= sprintf( 528 /* translators: %d: Translations count. */ 529 _n( 'The remaining %d translation was marked as fuzzy successfully.', 'The remaining %d translations were marked as fuzzy successfully.', $ok, 'glotpress' ), 530 $ok 531 ); 532 533 $this->errors[] = $message; 534 } else { 535 $this->errors[] = sprintf( 536 /* translators: %d: Translations count. */ 537 _n( 'Error with marking %d translation as fuzzy.', 'Error with marking all %d translation as fuzzy.', $error, 'glotpress' ), 538 $error 539 ); 540 } 541 } 542 } 543 544 private function _bulk_set_priority( $project, $bulk ) { 545 546 if ( $this->cannot_and_redirect( 'write', 'project', $project->id ) ) { 547 return; 548 } 549 550 $ok = $error = 0; 551 foreach ( $bulk['row-ids'] as $row_id ) { 552 $original_id = gp_array_get( explode( '-', $row_id ), 0 ); 553 $original = GP::$original->get( $original_id ); 554 555 if ( ! $original ) { 556 continue; 557 } 558 559 $original->priority = $bulk['priority']; 560 561 if ( ! $original->validate() ) { 562 return $this->die_with_error( 'Invalid priority value!' ); 563 } 564 565 if ( ! $original->save() ) { 566 $error++; 567 } else { 568 $ok ++; 569 } 570 } 571 572 if ( 0 === $error ) { 573 $this->notices[] = sprintf( 574 /* translators: %d: Originals count. */ 575 _n( 'Priority of %d original was modified.', 'Priority of %d originals were modified.', $ok, 'glotpress' ), 576 $ok 577 ); 578 } else { 579 if ( $ok > 0 ) { 580 $message = sprintf( 581 /* translators: %d: Originals count. */ 582 _n( 'Error modifying priority of %d original.', 'Error modifying priority of %d originals.', $error, 'glotpress' ), 583 $error 584 ); 585 $message .= sprintf( 586 /* translators: %d: Originals count. */ 587 _n( 'The remaining %d original was modified successfully.', 'The remaining %d originals were modified successfully.', $ok, 'glotpress' ), 588 $ok 589 ); 590 591 $this->errors[] = $message; 592 } else { 593 $this->errors[] = sprintf( 594 /* translators: %d: Originals count. */ 595 _n( 'Error modifying priority of %d original.', 'Error modifying priority of all %d originals.', $error, 'glotpress' ), 596 $error 597 ); 598 } 599 } 600 601 } 602 603 public function discard_warning( $project_path, $locale_slug, $translation_set_slug ) { 604 $index = gp_post( 'index' ); 605 $key = gp_post( 'key' ); 606 607 if ( ! $this->verify_nonce( 'discard-warning_' . $index . $key ) ) { 608 return $this->die_with_error( __( 'An error has occurred. Please try again.', 'glotpress' ), 403 ); 609 } 610 611 return $this->edit_single_translation( $project_path, $locale_slug, $translation_set_slug, array( $this, 'discard_warning_edit_function' ) ); 612 } 613 614 public function set_status( $project_path, $locale_slug, $translation_set_slug ) { 615 $status = gp_post( 'status' ); 616 $translation_id = gp_post( 'translation_id' ); 617 618 if ( ! $this->verify_nonce( 'update-translation-status-' . $status . '_' . $translation_id ) ) { 619 return $this->die_with_error( __( 'An error has occurred. Please try again.', 'glotpress' ), 403 ); 620 } 621 622 return $this->edit_single_translation( $project_path, $locale_slug, $translation_set_slug, array( $this, 'set_status_edit_function' ) ); 623 } 624 625 /** 626 * Edits a single translation. 627 * 628 * @since 1.0.0 629 * 630 * @param string $project_path The path of the project. 631 * @param string $locale_slug The locale slug. 632 * @param string $translation_set_slug The slug of the translation set. 633 * @param callable $edit_function The edit function to call on the translation. 634 */ 635 private function edit_single_translation( $project_path, $locale_slug, $translation_set_slug, $edit_function ) { 636 $project = GP::$project->by_path( $project_path ); 637 $locale = GP_Locales::by_slug( $locale_slug ); 638 639 if ( ! $project || ! $locale ) { 640 return $this->die_with_404(); 641 } 642 643 $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug ); 644 645 if ( ! $translation_set ) { 646 return $this->die_with_404(); 647 } 648 649 $glossary = $this->get_extended_glossary( $translation_set, $project ); 650 651 $translation = GP::$translation->get( gp_post( 'translation_id' ) ); 652 653 if ( ! $translation ) { 654 return $this->die_with_error( 'Translation doesn’t exist!' ); 655 } 656 657 $this->can_approve_translation_or_forbidden( $translation ); 658 659 $edit_function( $project, $locale, $translation_set, $translation ); 660 661 $translations = GP::$translation->for_translation( 662 $project, 663 $translation_set, 664 'no-limit', 665 array( 666 'translation_id' => $translation->id, 667 'status' => 'either', 668 ), 669 array() 670 ); 671 if ( ! empty( $translations ) ) { 672 $translation = $translations[0]; 673 674 $can_edit = $this->can( 'edit', 'translation-set', $translation_set->id ); 675 $can_write = $this->can( 'write', 'project', $project->id ); 676 $can_approve = $this->can( 'approve', 'translation-set', $translation_set->id ); 677 $can_approve_translation = $this->can( 'approve', 'translation', $translation->id, array( 'translation' => $translation ) ); 678 679 $this->tmpl( 'translation-row', get_defined_vars() ); 680 } else { 681 return $this->die_with_error( 'Error in retrieving translation!' ); 682 } 683 } 684 685 /** 686 * Discard a warning. 687 * 688 * @since 1.0.0 689 * 690 * @param GP_Project $project The project. 691 * @param GP_Locale $locale The GlotPress locale. 692 * @param GP_Translation_Set $translation_set The translation set. 693 * @param GP_Translation $translation The translation object. 694 */ 695 private function discard_warning_edit_function( $project, $locale, $translation_set, $translation ) { 696 if ( ! isset( $translation->warnings[ gp_post( 'index' ) ][ gp_post( 'key' ) ] ) ) { 697 return $this->die_with_error( 'The warning doesn’exist!' ); 698 } 699 700 $warning = array( 701 'project_id' => $project->id, 702 'translation_set' => $translation_set->id, 703 'translation' => $translation->id, 704 'warning' => gp_post( 'key' ), 705 'user' => get_current_user_id(), 706 ); 707 708 /** 709 * Fires before a warning gets discarded. 710 * 711 * @since 1.0.0 712 * 713 * @param array $warning { 714 * @type string $project_id ID of the project. 715 * @type string $translation_set ID of the translation set. 716 * @type string $translation ID of the translation. 717 * @type string $warning The warning key. 718 * @type int $user Current user's ID. 719 * } 720 */ 721 do_action_ref_array( 'gp_warning_discarded', $warning ); 722 723 unset( $translation->warnings[ gp_post( 'index' ) ][ gp_post( 'key' ) ] ); 724 if ( empty( $translation->warnings[ gp_post( 'index' ) ] ) ) { 725 unset( $translation->warnings[ gp_post( 'index' ) ] ); 726 } 727 728 $res = $translation->save(); 729 730 if ( false === $res || null === $res ) { 731 return $this->die_with_error( 'Error in saving the translation!' ); 732 } 733 } 734 735 private function set_status_edit_function( $project, $locale, $translation_set, $translation ) { 736 $res = $translation->set_status( gp_post( 'status' ) ); 737 738 if ( ! $res ) { 739 return $this->die_with_error( 'Error in saving the translation status!' ); 740 } 741 } 742 743 private function can_approve_translation_or_forbidden( $translation ) { 744 $can_reject_self = ( get_current_user_id() == $translation->user_id && 'waiting' == $translation->status ); 745 if ( $can_reject_self ) { 746 return; 747 } 748 $this->can_or_forbidden( 'approve', 'translation', $translation->id, null, array( 'translation' => $translation ) ); 749 } 750 751 /** 752 * Get the glossary for the translation set. 753 * 754 * This also fetches contents from a potential locale glossary, as well as from a parent project. 755 * 756 * @since 2.3.0 757 * 758 * @param GP_Translation_Set $translation_set Translation set for which to retrieve the glossary. 759 * @param GP_Project $project Project for finding potential parent projects. 760 * @return GP_Glossary Extended glossary. 761 */ 762 protected function get_extended_glossary( $translation_set, $project ) { 763 $glossary = GP::$glossary->by_set_or_parent_project( $translation_set, $project ); 764 765 $locale_glossary_project_id = 0; 766 $locale_glossary_translation_set = GP::$translation_set->by_project_id_slug_and_locale( $locale_glossary_project_id, $translation_set->slug, $translation_set->locale ); 767 768 if ( ! $locale_glossary_translation_set ) { 769 return $glossary; 770 } 771 772 $locale_glossary = GP::$glossary->by_set_id( $locale_glossary_translation_set->id ); 773 774 // Return locale glossary if a project has no glossary. 775 if ( false === $glossary && $locale_glossary instanceof GP_Glossary ) { 776 return $locale_glossary; 777 } 778 779 if ( $glossary instanceof GP_Glossary && $locale_glossary instanceof GP_Glossary && $locale_glossary->id !== $glossary->id ) { 780 $glossary->merge_with_glossary( $locale_glossary ); 781 } 782 783 return $glossary; 784 } 785 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Dec 3 01:01:05 2024 | Cross-referenced by PHPXref 0.7.1 |