Dictionariespage - Source Excerpt 02
Summary
This source excerpt preserves a bounded section of Antichrist.net/wp-content/plugins/uaix-locale-router/src/Admin/DictionariesPage.php so readers can inspect the evidence without opening the full source file.
**Source path:** Antichrist.net/wp-content/plugins/uaix-locale-router/src/Admin/DictionariesPage.php
$contents = file_get_contents( $tmp_name );
if ( false === $contents ) {
Plugin::set_flash_notice( 'The uploaded file could not be read.', 'error' );
wp_safe_redirect( AdminPages::page_url( 'uaixlr-dictionaries' ) );
exit;
}
$result = DictionaryValidator::validate_json_string( $contents, $file_name );
if ( self::has_error_issues( $result ) || empty( $result['localeTag'] ) ) {
Plugin::set_flash_notice(
sprintf( 'Dictionary upload failed. %d issue(s) were found.', isset( $result['issueCount'] ) ? $result['issueCount'] : 0 ),
'error',
self::upload_failure_notice_data( $result, $file_name )
);
wp_safe_redirect( AdminPages::page_url( 'uaixlr-dictionaries' ) );
exit;
}
Plugin::ensure_upload_directories();
$locale_tag = LocaleValidator::canonicalize_tag( $result['localeTag'] );
$file_path = DictionaryRepository::dictionary_path( $locale_tag );
$written = Json::write_file( $file_path, $result['normalized_dictionary'] );
if ( ! $written ) {
Plugin::set_flash_notice( 'The validated dictionary could not be written to the uploads directory.', 'error' );
wp_safe_redirect( AdminPages::page_url( 'uaixlr-dictionaries' ) );
exit;
}
$file_hash = hash( 'sha256', Json::encode( $result['normalized_dictionary'] ) );
$manifest = DictionaryRepository::dictionary_manifest();
$manifest[ $locale_tag ] = array(
'localeTag' => $locale_tag,
'fileName' => $file_name,
'fileHash' => $file_hash,
'templateVersion' => isset( $result['templateVersion'] ) ? absint( $result['templateVersion'] ) : 1,
'qualityStatus' => isset( $result['qualityStatus'] ) ? (string) $result['qualityStatus'] : 'draft',
'lastValidationStatus' => isset( $result['status'] ) ? (string) $result['status'] : 'draft',
'issueCount' => isset( $result['issueCount'] ) ? absint( $result['issueCount'] ) : 0,
'lastIssues' => isset( $result['issues'] ) ? $result['issues'] : array(),
'uploadedAt' => gmdate( DATE_ATOM ),
'uploadedByUserId' => get_current_user_id(),
);
DictionaryRepository::save_dictionary_manifest( $manifest );
DictionaryRepository::clear_cache( $locale_tag );
DictionaryValidator::record_validation_result( $result, get_current_user_id(), $file_hash );
Plugin::set_flash_notice(
sprintf(
'%s uploaded successfully with %d warning(s).',
$locale_tag,
self::warning_count( $result )
),
self::warning_count( $result ) > 0 ? 'warning' : 'success'
);
wp_safe_redirect( AdminPages::page_url( 'uaixlr-dictionaries' ) );
exit;
}
/**
* Download the bundled template dictionary.
*
* @return void
*/
public static function handle_download_template() {
self::assert_permissions( 'uaixlr_download_template' );
self::stream_dictionary_download( 'template' );
}
/**
* Download a locale dictionary export.
*
* @return void
*/
public static function handle_download_dictionary() {
self::assert_permissions( 'uaixlr_download_dictionary' );
$locale_tag = isset( $_POST['locale_tag'] ) ? LocaleValidator::canonicalize_tag( wp_unslash( $_POST['locale_tag'] ) ) : '';
if ( '' === $locale_tag ) {
Plugin::set_flash_notice( 'Choose a locale to download.', 'error' );
wp_safe_redirect( AdminPages::page_url( 'uaixlr-dictionaries' ) );
exit;
}
self::stream_dictionary_download( $locale_tag );
}
/**
* Determine whether a validation result has blocking errors.
*
* @param array $result Validation result.
* @return bool
*/
private static function has_error_issues( array $result ) {
if ( empty( $result['issues'] ) || ! is_array( $result['issues'] ) ) {
return false;
}
foreach ( $result['issues'] as $issue ) {
if ( isset( $issue['severity'] ) && 'error' === $issue['severity'] ) {
return true;
}
}
return false;
}
/**
* Count warning issues.
*
* @param array $result Validation result.
* @return int
*/
private static function warning_count( array $result ) {
$count = 0;
if ( empty( $result['issues'] ) || ! is_array( $result['issues'] ) ) {
return 0;
}
foreach ( $result['issues'] as $issue ) {
if ( isset( $issue['severity'] ) && 'warning' === $issue['severity'] ) {
++$count;
}
}
return $count;
}
/**
* Build detailed admin-notice data for a failed upload.
*
* @param array $result Validation result.
* @param string $file_name Uploaded file name.
* @return array
*/
private static function upload_failure_notice_data( array $result, $file_name ) {
$locale_tag = isset( $result['localeTag'] ) ? LocaleValidator::canonicalize_tag( (string) $result['localeTag'] ) : '';
$key_mode = isset( $result['dictionaryKeyMode'] ) ? (string) $result['dictionaryKeyMode'] : '';
$errors = self::issue_count_by_severity( $result, 'error' );
$warnings = self::issue_count_by_severity( $result, 'warning' );
$details = array(
'File' => (string) $file_name,
'Detected locale' => '' !== $locale_tag ? $locale_tag : 'Missing or invalid',
'Detected key mode' => self::describe_key_mode( $key_mode ),
'Validation status' => isset( $result['status'] ) ? (string) $result['status'] : 'rejected',
'Issue summary' => sprintf( '%d error(s), %d warning(s)', $errors, $warnings ),
);
return array(
'summary' => 'The uploaded dictionary did not pass validation and was not saved.',
'details' => $details,
'issues' => isset( $result['issues'] ) && is_array( $result['issues'] ) ? $result['issues'] : array(),
'guidance' => self::upload_failure_guidance( $result ),
);
}
/**
* Count issues by severity.
*
* @param array $result Validation result.
* @param string $severity Severity label.
* @return int
*/
private static function issue_count_by_severity( array $result, $severity ) {
$count = 0;
if ( empty( $result['issues'] ) || ! is_array( $result['issues'] ) ) {
return 0;
}
foreach ( $result['issues'] as $issue ) {
if ( isset( $issue['severity'] ) && $severity === $issue['severity'] ) {
++$count;
}
}
return $count;
}
/**
* Describe a detected dictionary key mode for admins.
*
* @param string $key_mode Detected key mode.
* @return string
*/
private static function describe_key_mode( $key_mode ) {
if ( 'runtime-key' === $key_mode ) {
return 'Legacy internal runtime keys';
}
if ( 'source-text' === $key_mode ) {
return 'English source-text keys';
}
return 'Unknown';
}
/**
* Suggest likely fixes for the current upload failure.
*
* @param array $result Validation result.
* @return array
*/
private static function upload_failure_guidance( array $result ) {
$guidance = array();
$codes = array();
if ( ! empty( $result['issues'] ) && is_array( $result['issues'] ) ) {
foreach ( $result['issues'] as $issue ) {
if ( ! empty( $issue['code'] ) && is_string( $issue['code'] ) ) {
$codes[ $issue['code'] ] = true;
}
}
}
if ( isset( $codes['missing_key'] ) ) {
$guidance[] = 'Start from Download Template JSON or a full locale export so every expected source string is present before upload.';
}
if ( isset( $codes['filename_locale_mismatch'] ) ) {
$guidance[] = 'Rename the file to match meta.locale, or update meta.locale so it matches the filename you are uploading.';
}
if ( isset( $codes['missing_locale'] ) || isset( $codes['invalid_locale_tag'] ) ) {
$guidance[] = 'Set meta.locale to a valid locale tag such as zh-SG, en-US, fr-FR, or spiral.';
}
if ( isset( $codes['invalid_json'] ) ) {
$guidance[] = 'Make sure the file is valid JSON with double-quoted keys and values before uploading it again.';
}
if ( isset( $result['dictionaryKeyMode'] ) && 'runtime-key' === $result['dictionaryKeyMode'] ) {
$guidance[] = 'Legacy runtime-key dictionaries are still accepted, but new template and locale exports now use English source text as the key.';
}
if ( empty( $guidance ) ) {
$guidance[] = 'Use the template or locale download on this page as your starting point, then re-upload the completed JSON file unchanged except for the translation values.';
}
return array_values( array_unique( $guidance ) );
}
/**
* Capability and nonce guard.
*
* @param string $action Nonce action.
* @return void
*/
private static function assert_permissions( $action ) {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You are not allowed to manage dictionaries.', 'uaix-locale-router' ) );
}
check_admin_referer( $action );
}
/**
* Build the list of locale exports available from the dictionaries screen.
*
* @return array
*/