translated words. */ public static function labels(): array { return array( 'ready' => __( 'Optimized files ready', 'affstackdev-image-manager' ), 'no_saving' => __( 'No useful saving', 'affstackdev-image-manager' ), 'held' => __( 'Retained by policy', 'affstackdev-image-manager' ), 'unsupported' => __( 'Unsupported format or integration', 'affstackdev-image-manager' ), 'excluded' => __( 'Excluded by you', 'affstackdev-image-manager' ), 'waiting' => __( 'Waiting or in progress', 'affstackdev-image-manager' ), 'failed' => __( 'Needs attention', 'affstackdev-image-manager' ), ); } /** * The source counts by state, gathered into the result groups. * * @param array $counts Counts by state. * @return array Counts by group. */ public static function buckets( array $counts ): array { return array( 'ready' => (int) ( $counts['ready'] ?? 0 ), 'no_saving' => (int) ( $counts['no_saving'] ?? 0 ), 'held' => (int) ( $counts['held'] ?? 0 ), 'unsupported' => (int) ( $counts['unsupported'] ?? 0 ) + (int) ( $counts['unmapped'] ?? 0 ), 'excluded' => (int) ( $counts['excluded'] ?? 0 ), 'waiting' => (int) ( $counts['queued'] ?? 0 ) + (int) ( $counts['discovered'] ?? 0 ), 'failed' => (int) ( $counts['failed'] ?? 0 ), ); } /** * The words for a reason code (an unknown code gets general words). * * @param string $reason The reason code. * @return string The translated words. */ public static function reason( string $reason ): string { $map = array( 'editor_access_denied' => __( 'You do not have permission to edit this image.', 'affstackdev-image-manager' ), 'editor_invalid_request' => __( 'Choose a supported image and valid edit settings.', 'affstackdev-image-manager' ), 'editor_confirmation_required' => __( 'Confirm that you want to prepare this edit. The source will remain unchanged.', 'affstackdev-image-manager' ), 'editor_save_confirmation_required' => __( 'Confirm that you want to save this prepared edit as a new Media Library image.', 'affstackdev-image-manager' ), 'editor_no_changes' => __( 'Choose at least one crop, rotate, flip or resize change.', 'affstackdev-image-manager' ), 'editor_invalid_crop' => __( 'The custom crop rectangle must stay inside the current image.', 'affstackdev-image-manager' ), 'editor_size_too_large' => __( 'That enlargement is larger than the editor makes (16,384 pixels a side and 24 megapixels, so the server does not run out of memory). Choose a smaller width or height.', 'affstackdev-image-manager' ), 'editor_backend_unavailable' => __( 'WordPress does not have a working image editor for this file on this host.', 'affstackdev-image-manager' ), 'editor_operation_failed' => __( 'The image editor could not complete that operation. The source is unchanged.', 'affstackdev-image-manager' ), 'editor_save_failed' => __( 'The edited preview could not be validated or saved. The source is unchanged.', 'affstackdev-image-manager' ), 'editor_draft_missing' => __( 'This edit draft is no longer available. Prepare a fresh preview.', 'affstackdev-image-manager' ), 'editor_source_changed' => __( 'The source image changed after this preview was prepared. Discard it and prepare a fresh edit.', 'affstackdev-image-manager' ), 'editor_storage_unavailable' => __( 'Private temporary edit storage is unavailable on this host. The source is unchanged.', 'affstackdev-image-manager' ), 'editor_upload_unavailable' => __( 'WordPress upload storage is unavailable for the edited copy. The source is unchanged.', 'affstackdev-image-manager' ), 'editor_attachment_failed' => __( 'WordPress could not create the edited Media Library item. The source is unchanged.', 'affstackdev-image-manager' ), 'editor_source_invalid' => __( 'This image cannot be safely opened by the editor.', 'affstackdev-image-manager' ), 'editor_source_too_large' => __( 'This source exceeds the editor safety limit. The source is unchanged.', 'affstackdev-image-manager' ), 'batch_access_changed' => __( 'Skipped: your permission to manage this image is no longer available.', 'affstackdev-image-manager' ), 'batch_invalid_action' => __( 'Choose a supported bulk action.', 'affstackdev-image-manager' ), 'batch_invalid_selection' => __( 'Choose checked images, this page, or all matching results.', 'affstackdev-image-manager' ), 'batch_invalid_sizing' => __( 'Choose existing sizes, useful missing display sizes or sizes measured on your pages.', 'affstackdev-image-manager' ), 'fit_invalid_result' => __( 'The measurement of this page could not be read. Measure it again.', 'affstackdev-image-manager' ), 'fit_page_not_public' => __( 'That page is not one of the public pages Image Manager works on, so it was not measured.', 'affstackdev-image-manager' ), 'fit_page_limit' => __( 'Image Manager keeps measurements of up to 100 pages. Forget the measurements to start again.', 'affstackdev-image-manager' ), 'fit_nothing_measured' => __( 'No measured picture of the Media Library or the theme was found. Measure pages first.', 'affstackdev-image-manager' ), 'fit_no_need' => __( 'This picture has no measured widths yet, so no display size was planned for it. Existing sizes stay.', 'affstackdev-image-manager' ), 'batch_confirmation_required' => __( 'Confirm the action and selection scope before starting.', 'affstackdev-image-manager' ), 'batch_resize_confirmation' => __( 'Confirm that this run may create resized display copies. Originals stay unchanged.', 'affstackdev-image-manager' ), 'batch_selection_limit' => __( 'Use All matching results for selections larger than 1,000 images.', 'affstackdev-image-manager' ), 'resize_backend_unavailable' => __( 'Additional widths need the supported GD resampling functions. Existing-size compression remains available.', 'affstackdev-image-manager' ), 'resize_format_held' => __( 'Additional widths are not enabled for this format choice; existing-size compression still runs.', 'affstackdev-image-manager' ), 'resize_metadata_or_alpha_held' => __( 'Color, metadata or transparency needs a supported resizing path. Existing sizes are retained.', 'affstackdev-image-manager' ), 'resize_no_complete_family' => __( 'No worthwhile additional width could be offered with a complete supported image family. Existing files stay in use.', 'affstackdev-image-manager' ), 'resize_no_saving' => __( 'The extra width did not reduce the existing parent file enough; no additional file was kept.', 'affstackdev-image-manager' ), 'resize_failed' => __( 'This display size could not be validated. Native dimensions and files are unchanged.', 'affstackdev-image-manager' ), 'delivery_no_page' => __( 'No known public page is available for this image. Run Scan only to refresh discovery.', 'affstackdev-image-manager' ), 'delivery_invalid_result' => __( 'The browser-check result was invalid; no delivery claim was recorded.', 'affstackdev-image-manager' ), 'delivery_check_stale' => __( 'These files or delivery choices changed. Reopen the browser check for a fresh result.', 'affstackdev-image-manager' ), 'invalid_compression_policy' => __( 'Choose valid compression settings.', 'affstackdev-image-manager' ), 'lossless_avif_not_supported' => __( 'AVIF is available only for photographic lossy modes. Choose Lossless with Auto, Native or WebP.', 'affstackdev-image-manager' ), 'compression_confirmation_required' => __( 'Confirm that photographic compression may change pixels before selecting a lossy policy.', 'affstackdev-image-manager' ), 'image_access_denied' => __( 'You do not have permission to manage this image.', 'affstackdev-image-manager' ), 'preview_public_required' => __( 'A supported public image and public-image approval are required. Private or excluded media stays unchanged.', 'affstackdev-image-manager' ), 'preview_work_pending' => __( 'This image already has work queued. Wait for it to finish, or discard the existing comparison first.', 'affstackdev-image-manager' ), 'preview_expired' => __( 'This comparison has changed or expired. Reopen it from Images.', 'affstackdev-image-manager' ), 'preview_approval_required' => __( 'Review the comparison and select the approval checkbox before applying these copies.', 'affstackdev-image-manager' ), 'preview_not_ready' => __( 'The comparison is not ready or has no qualifying smaller copy. Existing published files are retained.', 'affstackdev-image-manager' ), 'preview_source_changed' => __( 'The source or its prepared files changed. Discard this comparison and prepare a fresh one.', 'affstackdev-image-manager' ), 'preview_history_limit' => __( 'Too many retained comparison files. Disable delivery and retire cached copies through the existing cleanup workflow before continuing.', 'affstackdev-image-manager' ), 'requested_encoder_unavailable' => __( 'No verified encoder can produce this policy on this host. Review Tools or select another format.', 'affstackdev-image-manager' ), 'metadata_preserved_native_only' => __( 'This metadata requires a native-format optimizer or a tested profile-preserving path. Other formats were not used.', 'affstackdev-image-manager' ), 'metadata_roundtrip_failed' => __( 'Metadata did not round-trip unchanged. The candidate was rejected.', 'affstackdev-image-manager' ), 'metadata_needs_review' => __( 'The metadata structure could not be safely interpreted. The original is retained.', 'affstackdev-image-manager' ), 'gps_xmp_requires_review' => __( 'This image has text/XMP metadata that requires review before GPS removal. No ambiguous privacy claim is made.', 'affstackdev-image-manager' ), 'quality_gate_failed' => __( 'The candidate failed the sampled quality threshold. Select a higher-fidelity policy or keep the original.', 'affstackdev-image-manager' ), 'alpha_changed' => __( 'The candidate did not preserve the required transparency.', 'affstackdev-image-manager' ), 'unsupported_lossless_target' => __( 'This encoder cannot guarantee lossless output in the selected format.', 'affstackdev-image-manager' ), 'unsupported_png_chunk' => __( 'This PNG contains unsupported structural data and was not changed.', 'affstackdev-image-manager' ), 'jpeg_verifier_unavailable' => __( 'Native JPEG optimization needs both a safe jpegtran installation and a decoded-pixel verifier.', 'affstackdev-image-manager' ), 'encoder_timeout' => __( 'The native compression process reached its time limit. No partial output was used.', 'affstackdev-image-manager' ), 'encoder_output_limit' => __( 'The native compression process exceeded its output limit. No partial output was used.', 'affstackdev-image-manager' ), 'exact_png_scanlines' => __( 'Lossless PNG: decompressed native image data matched exactly.', 'affstackdev-image-manager' ), 'exact_decoded_pixels' => __( 'Lossless: every decoded pixel matched in this encoder path.', 'affstackdev-image-manager' ), 'coefficient_preserving_exact_pixels' => __( 'Native JPEG: coefficient-preserving transform with an exact decoded-pixel check.', 'affstackdev-image-manager' ), 'sampled_ssim_color_gate' => __( 'Photographic output passed sampled SSIM and color-error checks. Inspect fine detail before approving.', 'affstackdev-image-manager' ), 'pixel_limit' => __( 'This size is larger than the Largest picture to make lighter setting allows. Its original is retained.', 'affstackdev-image-manager' ), 'source_byte_limit' => __( 'This file is larger than the Largest picture to make lighter setting allows. Its original is retained.', 'affstackdev-image-manager' ), 'memory_limit' => __( 'There is not enough safe processing memory for this size.', 'affstackdev-image-manager' ), 'existing_webp_kept' => __( 'Already WebP. This release leaves the existing file unchanged.', 'affstackdev-image-manager' ), 'unsupported_format' => __( 'This format is not supported by the current compression pipeline.', 'affstackdev-image-manager' ), 'lossless_encoder_unavailable' => __( 'No verified lossless encoder is available on this server.', 'affstackdev-image-manager' ), 'alpha_requires_exact_imagick' => __( 'This transparency needs an exact-alpha-capable encoder. The original is retained.', 'affstackdev-image-manager' ), 'profile_or_color_metadata_held' => __( 'This image needs color-profile handling outside the current verified pipeline.', 'affstackdev-image-manager' ), 'jpeg_profile_or_orientation_held' => __( 'Color or orientation information requires the original to be kept.', 'affstackdev-image-manager' ), 'orientation_held' => __( 'The original orientation is being preserved.', 'affstackdev-image-manager' ), 'animated_image_held' => __( 'Animation is not supported by this pipeline. All original frames are preserved.', 'affstackdev-image-manager' ), 'animated_loop_held' => __( 'This animated GIF plays a set number of times. Animated copies are made only of animations that repeat without end, so the GIF is kept as it is.', 'affstackdev-image-manager' ), 'animated_timing_held' => __( 'An image in this animated GIF is shown for 10 milliseconds or less, which browsers stretch to 100 milliseconds. The GIF is kept as it is.', 'affstackdev-image-manager' ), 'animated_frames_limit' => __( 'This animated GIF has more images or pixels than Image Manager converts at the current large pictures setting. The GIF is kept as it is.', 'affstackdev-image-manager' ), 'watermark_picture_unavailable' => __( 'The watermark picture is missing or not a still PNG or WebP of at most 2,048 pixels. Choose it again in Settings > Watermark.', 'affstackdev-image-manager' ), 'watermark_native_unavailable' => __( 'No watermarked copy in the picture’s own format could be made on this server, so its ordinary copies stay in use.', 'affstackdev-image-manager' ), 'svg_role_unknown' => __( 'One of those roles does not exist on this site or may not upload files.', 'affstackdev-image-manager' ), 'svg_roles_required' => __( 'SVG uploads need at least one role that may upload SVG files.', 'affstackdev-image-manager' ), 'svg_unavailable' => __( 'SVG uploads cannot be switched on: this server’s PHP lacks the DOM or XMLReader extension that cleaning SVG files needs.', 'affstackdev-image-manager' ), 'unsupported_color_or_frames' => __( 'The color model or frame structure is not supported.', 'affstackdev-image-manager' ), 'unsupported_precision' => __( 'This image precision is not supported by the current encoder.', 'affstackdev-image-manager' ), 'unsupported_precision_or_cmyk' => __( 'This JPEG precision or color model is not supported.', 'affstackdev-image-manager' ), 'source_metadata_dimensions_mismatch' => __( 'The file and saved dimensions disagree. Review the source before retrying.', 'affstackdev-image-manager' ), 'pixel_or_source_mismatch' => __( 'Exact-image verification did not pass. The candidate was not used.', 'affstackdev-image-manager' ), 'not_verified_lossless_webp' => __( 'The candidate did not pass the required lossless-format validation.', 'affstackdev-image-manager' ), 'candidate_dimensions_or_mime' => __( 'The candidate has unexpected dimensions or file type and was not used.', 'affstackdev-image-manager' ), 'invalid_image' => __( 'The source could not be validated as an image.', 'affstackdev-image-manager' ), 'invalid_png' => __( 'The PNG source could not be validated.', 'affstackdev-image-manager' ), 'truncated_png' => __( 'The PNG source is incomplete.', 'affstackdev-image-manager' ), 'invalid_png_crc' => __( 'The PNG source failed its integrity check.', 'affstackdev-image-manager' ), 'invalid_gif' => __( 'The GIF source could not be validated.', 'affstackdev-image-manager' ), 'truncated_gif' => __( 'The GIF source is incomplete.', 'affstackdev-image-manager' ), 'truncated_jpeg' => __( 'The JPEG source is incomplete.', 'affstackdev-image-manager' ), 'codec_warning' => __( 'The image library reported a problem. The original is retained.', 'affstackdev-image-manager' ), 'http_status_404' => __( 'This page was not found (404). Its images were not scanned.', 'affstackdev-image-manager' ), 'http_status_503' => __( 'This page is temporarily unavailable (503).', 'affstackdev-image-manager' ), 'http_status_429' => __( 'The site limited these scan requests (429).', 'affstackdev-image-manager' ), 'http_request_blocked' => __( 'The anonymous page request could not complete.', 'affstackdev-image-manager' ), 'dns_unavailable' => __( 'The public hostname could not be resolved for scanning.', 'affstackdev-image-manager' ), 'metadata_wait' => __( 'The source file or complete saved metadata is not available yet.', 'affstackdev-image-manager' ), 'worker_interrupted' => __( 'The last worker was interrupted. Its saved work will be retried safely.', 'affstackdev-image-manager' ), 'temporary_failure' => __( 'A temporary processing problem occurred.', 'affstackdev-image-manager' ), 'retry_limit' => __( 'Three attempts could not finish this task. Review the reason and use Retry when the cause is fixed.', 'affstackdev-image-manager' ), 'public_policy_required' => __( 'Public-image approval is required before a copy can be made.', 'affstackdev-image-manager' ), 'public_association_required' => __( 'No supported public association is confirmed. No new public copy is generated.', 'affstackdev-image-manager' ), 'storage_unavailable' => __( 'Processing storage is unavailable. Originals are unchanged.', 'affstackdev-image-manager' ), 'space_low' => __( 'There is not enough verified free disk space for safe processing.', 'affstackdev-image-manager' ), 'legacy_review' => __( 'An earlier theme-image record needs a new scan before optimization. Existing copies are retained.', 'affstackdev-image-manager' ), 'cancelled' => __( 'This run was stopped. Existing files were not deleted.', 'affstackdev-image-manager' ), ); if ( isset( $map[ $reason ] ) ) { return $map[ $reason ]; } // Sentences the engine stores in image records (in English, also by earlier releases) are shown translated. $stored = array( 'Smaller validated copies are ready.' => __( 'Smaller validated copies are ready.', 'affstackdev-image-manager' ), 'No eligible smaller copy. Native image delivery is retained.' => __( 'No eligible smaller copy. Native image delivery is retained.', 'affstackdev-image-manager' ), 'Less than 5% or 1 KiB saved; current file retained.' => __( 'Less than 5% or 1 KiB saved; current file retained.', 'affstackdev-image-manager' ), 'Preparing image sizes.' => __( 'Preparing image sizes.', 'affstackdev-image-manager' ), 'Existing prepared copies retained; preview is ready for review.' => __( 'Existing prepared copies retained; preview is ready for review.', 'affstackdev-image-manager' ), 'Preview ready for review. No website image was changed.' => __( 'Preview ready for review. No website image was changed.', 'affstackdev-image-manager' ), 'Derivative removal needs attention; purge host/CDN caches for the removed content.' => __( 'Derivative removal needs attention; purge host/CDN caches for the removed content.', 'affstackdev-image-manager' ), 'Source removed; managed copies retired.' => __( 'Source removed; managed copies retired.', 'affstackdev-image-manager' ), 'Source or public ownership changed; native delivery restored.' => __( 'Source or public ownership changed; native delivery restored.', 'affstackdev-image-manager' ), 'Approved compression copies prepared. Delivery controls are unchanged.' => __( 'Approved compression copies prepared. Delivery controls are unchanged.', 'affstackdev-image-manager' ), 'Comparison discarded. Existing delivery retained.' => __( 'Comparison discarded. Existing delivery retained.', 'affstackdev-image-manager' ), 'Managed copies removed or recorded for cleanup review. Original unchanged.' => __( 'Managed copies removed or recorded for cleanup review. Original unchanged.', 'affstackdev-image-manager' ), 'New upload: awaiting a supported published post/product or approved comment association.' => __( 'New upload: awaiting a supported published post/product or approved comment association.', 'affstackdev-image-manager' ), 'No qualifying alternative.' => __( 'No qualifying alternative.', 'affstackdev-image-manager' ), 'Identical decompressed PNG scanlines; all other chunks preserved except explicitly removed EXIF GPS.' => __( 'Identical decompressed PNG scanlines; all other chunks preserved except explicitly removed EXIF GPS.', 'affstackdev-image-manager' ), 'Exact decoded RGBA verified.' => __( 'Exact decoded RGBA verified.', 'affstackdev-image-manager' ), 'Sampled luma SSIM and color-error checks passed; review the visual preview.' => __( 'Sampled luma SSIM and color-error checks passed; review the visual preview.', 'affstackdev-image-manager' ), 'JPEG coefficient optimization; exact decoded raster and preserved metadata verified.' => __( 'JPEG coefficient optimization; exact decoded raster and preserved metadata verified.', 'affstackdev-image-manager' ), 'exact decoded RGBA at native dimensions; VP8L verified' => __( 'exact decoded RGBA at native dimensions; VP8L verified', 'affstackdev-image-manager' ), 'Display resize, no crop; compression validated against the same-size reference.' => __( 'Display resize, no crop; compression validated against the same-size reference.', 'affstackdev-image-manager' ), ); if ( isset( $stored[ $reason ] ) ) { return $stored[ $reason ]; } if ( preg_match( '/^Added (\d+) × (\d+) display size\. Originals unchanged\.$/uD', $reason, $added ) ) { /* translators: 1: width in pixels; 2: height in pixels of a display size Image Manager added. */ return sprintf( __( 'Added %1$d × %2$d display size. Originals unchanged.', 'affstackdev-image-manager' ), (int) $added[1], (int) $added[2] ); } if ( '' === $reason ) { return __( 'No processing result yet.', 'affstackdev-image-manager' ); } // Existing releases stored administrator-facing sentences. Never display a raw machine code as prose. if ( preg_match( '/^[a-z0-9_]+$/D', $reason ) ) { return __( 'The current pipeline could not process this image. Its original is retained.', 'affstackdev-image-manager' ); } return $reason; } /** * What the Images list shows for one source: its group, the reason, the copies prepared and whether they are * delivered. * * @param array $r The decoded source row. * @return array Label, reason, copy count, delivery and verification words. */ public static function row( array $r ): array { $key = match ( $r['state'] ) { 'queued', 'discovered' => 'waiting', 'unmapped', 'grouped' => 'unsupported', default => $r['state'] }; $label = self::labels()[ $key ] ?? __( 'Original retained', 'affstackdev-image-manager' ); $reason = self::reason( (string) $r['reason'] ); if ( 'unmapped' === $r['state'] ) { $reason = __( 'This URL has no supported local image mapping. No copy was generated.', 'affstackdev-image-manager' ); } elseif ( 'held' === $r['state'] && ! $r['reason'] ) { $reason = __( 'A public-ownership or preservation check is holding this image.', 'affstackdev-image-manager' ); } elseif ( 'discovered' === $r['state'] ) { $reason = __( 'Found on the website; not processed yet.', 'affstackdev-image-manager' ); } elseif ( 'queued' === $r['state'] && (int) $r['available_at'] > time() ) { /* translators: 1: time of day in UTC (hours:minutes:seconds); 2: attempts used so far. */ $reason .= ' ' . sprintf( __( 'Next attempt no earlier than %1$s UTC (%2$d of 3 attempts used).', 'affstackdev-image-manager' ), gmdate( 'H:i:s', (int) $r['available_at'] ), (int) $r['attempts'] ); } $files = $r['manifest']['results'] ?? array(); $unsupported = count( array_filter( $files, static fn( $v ) => 'unsupported' === ( $v['state'] ?? '' ) ) ); if ( 'no_saving' === $r['state'] ) { $reason = $unsupported ? __( 'Tested sizes gave no useful saving; other sizes require unsupported handling. See size results.', 'affstackdev-image-manager' ) : __( 'The tested copies were not at least 5% and 1,024 bytes smaller. Original files stay in use.', 'affstackdev-image-manager' ); } if ( 'ready' === $r['state'] ) { $reason = $unsupported ? __( 'Optimized files exist for supported sizes. Some sizes remain original; check delivery for this page.', 'affstackdev-image-manager' ) : __( 'Optimized files are ready. Use Check public page or Check in browser to inspect delivery.', 'affstackdev-image-manager' ); } if ( 'failed' === $r['state'] ) { $reason = self::reason( (string) $r['reason'] ) . ' ' . __( 'Review the cause, then retry. No original was replaced.', 'affstackdev-image-manager' ); } $prepared = Repository::manifest_totals( $r['manifest'] )['copy_count']; $enabled = $prepared > 0 && Settings::get()['delivery'] && Settings::get()['public_policy'] && $r['delivery'] && ! $r['excluded']; return array( 'label' => $label, 'reason' => $reason, 'prepared' => $prepared, 'delivery' => $enabled ? __( 'Delivery enabled for supported output', 'affstackdev-image-manager' ) : __( 'Original delivery / alternatives not enabled', 'affstackdev-image-manager' ), 'verification' => __( 'Browser delivery not checked', 'affstackdev-image-manager' ), ); } }