Skip to content
wiki.fftac.org

Translationcatalog - Source Excerpt 02

Back to Translationcatalog

Summary

This source excerpt preserves a bounded section of Antichrist.net/wp-content/plugins/uaix-locale-router/src/TranslationCatalog.php so readers can inspect the evidence without opening the full source file.

**Source path:** Antichrist.net/wp-content/plugins/uaix-locale-router/src/TranslationCatalog.php

return array(
			'detectedKeyMode'     => $key_mode,
			'translatorDictionary' => array(
				'meta'    => $translator_meta,
				'strings' => $translator,
			),
			'runtimeDictionary'  => array(
				'meta'    => $runtime_meta,
				'strings' => $runtime,
			),
		);
	}

	/**
	 * Determine whether a dictionary uses runtime keys or source-text keys.
	 *
	 * @param array $strings Raw dictionary strings.
	 * @return string
	 */
	public static function detect_dictionary_key_mode( array $strings ) {
		$runtime_matches = 0;
		$source_matches  = 0;
		$runtime_keys    = array_flip( array_keys( self::runtime_strings() ) );
		$source_keys     = array_flip( array_keys( self::source_to_runtime_keys() ) );

		foreach ( array_keys( $strings ) as $key ) {
			if ( ! is_string( $key ) ) {
				continue;
			}

			if ( isset( $runtime_keys[ $key ] ) ) {
				++$runtime_matches;
			}

			if ( isset( $source_keys[ $key ] ) ) {
				++$source_matches;
			}
		}

		if ( $runtime_matches > $source_matches ) {
			return 'runtime-key';
		}

		return 'source-text';
	}

	/**
	 * Return the PHP files that participate in the shared translation surface.
	 *
	 * @return array
	 */
	private static function catalog_php_files() {
		$files        = array();
		$max_files    = function_exists( 'apply_filters' ) ? (int) apply_filters( 'uaixlr_translation_scan_max_files', 500 ) : 500;
		$max_bytes    = function_exists( 'apply_filters' ) ? (int) apply_filters( 'uaixlr_translation_scan_max_file_bytes', 262144 ) : 262144;
		$max_files    = $max_files > 0 ? $max_files : 500;
		$max_bytes    = $max_bytes > 0 ? $max_bytes : 262144;

		foreach ( self::scan_roots() as $root ) {
			try {
				$iterator = new RegexIterator(
					new RecursiveIteratorIterator(
						new RecursiveDirectoryIterator(
							$root,
							FilesystemIterator::SKIP_DOTS
						)
					),
					'/^.+\.php$/i'
				);
			} catch ( \UnexpectedValueException $exception ) {
				continue;
			}

			foreach ( $iterator as $file_info ) {
				$path = (string) $file_info->getPathname();

				if ( '' !== $path && is_readable( $path ) && ! self::should_skip_catalog_path( $path ) && $file_info->getSize() <= $max_bytes ) {
					$files[ $path ] = $path;
				}

				if ( count( $files ) >= $max_files ) {
					break 2;
				}
			}
		}

		return array_values( $files );
	}

	/**
	 * Resolve the directories that should be scanned for locale-router-managed strings.
	 *
	 * @return array
	 */
	private static function scan_roots() {
		$roots = array();

		foreach ( self::active_theme_roots() as $root ) {
			$roots[] = $root;
		}

		foreach ( self::active_plugin_roots() as $root ) {
			$roots[] = $root;
		}

		if ( defined( 'UAIXLR_PLUGIN_PATH' ) && is_dir( UAIXLR_PLUGIN_PATH ) ) {
			$roots[] = UAIXLR_PLUGIN_PATH;
		}

		$roots = apply_filters( 'uaixlr_translation_scan_roots', $roots );
		$roots = apply_filters( 'ns12lr_translation_scan_roots', $roots );

		if ( ! is_array( $roots ) ) {
			return array();
		}

		$unique = array();

		foreach ( $roots as $root ) {
			$root = is_string( $root ) ? trim( $root ) : '';

			if ( '' === $root ) {
				continue;
			}

			$real_root = realpath( $root );

			if ( false === $real_root || ! is_dir( $real_root ) ) {
				continue;
			}

			$unique[ $real_root ] = $real_root;
		}

		return array_values( $unique );
	}

	/**
	 * Resolve active theme roots for catalog scanning.
	 *
	 * @return array
	 */
	private static function active_theme_roots() {
		$roots          = array();
		$stylesheet_dir = function_exists( 'get_stylesheet_directory' ) ? get_stylesheet_directory() : '';
		$template_dir   = function_exists( 'get_template_directory' ) ? get_template_directory() : '';

		if ( is_string( $stylesheet_dir ) && '' !== trim( $stylesheet_dir ) && is_dir( $stylesheet_dir ) ) {
			$roots[] = $stylesheet_dir;
		}

		if ( is_string( $template_dir ) && '' !== trim( $template_dir ) && $template_dir !== $stylesheet_dir && is_dir( $template_dir ) ) {
			$roots[] = $template_dir;
		}

		if ( ! empty( $roots ) ) {
			return $roots;
		}

		if ( defined( 'ABSPATH' ) ) {
			$themes_root = rtrim( ABSPATH, '/\\' ) . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR . 'themes';

			if ( is_dir( $themes_root ) ) {
				$roots[] = $themes_root;
			}
		}

		return $roots;
	}

	/**
	 * Resolve active plugin roots for catalog scanning.
	 *
	 * @return array
	 */
	private static function active_plugin_roots() {
		$roots = array();

		if ( function_exists( 'wp_get_active_and_valid_plugins' ) ) {
			foreach ( wp_get_active_and_valid_plugins() as $plugin_file ) {
				if ( is_string( $plugin_file ) && '' !== trim( $plugin_file ) ) {
					$roots[] = dirname( $plugin_file );
				}
			}
		} else {
			foreach ( self::active_plugin_paths_from_options() as $plugin_file ) {
				$roots[] = dirname( $plugin_file );
			}
		}

		if ( ! empty( $roots ) ) {
			return $roots;
		}

		if ( defined( 'ABSPATH' ) ) {
			$plugins_root = rtrim( ABSPATH, '/\\' ) . DIRECTORY_SEPARATOR . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins';

			if ( is_dir( $plugins_root ) ) {
				$roots[] = $plugins_root;
			}
		}

		return $roots;
	}

	/**
	 * Resolve plugin file paths from the active plugin option payload.
	 *
	 * @return array
	 */
	private static function active_plugin_paths_from_options() {
		$plugin_paths = array();
		$plugin_dir   = defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : '';
		$active       = function_exists( 'get_option' ) ? get_option( 'active_plugins', array() ) : array();

		if ( is_array( $active ) ) {
			foreach ( $active as $plugin_rel_path ) {
				if ( ! is_string( $plugin_rel_path ) || '' === trim( $plugin_rel_path ) || '' === $plugin_dir ) {
					continue;
				}

				$plugin_paths[] = trailingslashit( $plugin_dir ) . ltrim( $plugin_rel_path, '/\\' );
			}
		}

		if ( function_exists( 'get_site_option' ) ) {
			$network_active = get_site_option( 'active_sitewide_plugins', array() );

			if ( is_array( $network_active ) ) {
				foreach ( array_keys( $network_active ) as $plugin_rel_path ) {
					if ( ! is_string( $plugin_rel_path ) || '' === trim( $plugin_rel_path ) || '' === $plugin_dir ) {
						continue;
					}

					$plugin_paths[] = trailingslashit( $plugin_dir ) . ltrim( $plugin_rel_path, '/\\' );
				}
			}
		}

		return array_values( array_unique( $plugin_paths ) );
	}

	/**
	 * Determine whether a file path should be skipped during catalog scanning.
	 *
	 * @param string $path Absolute file path.
	 * @return bool
	 */
	private static function should_skip_catalog_path( $path ) {
		$normalized = str_replace( '\\', '/', (string) $path );
		$fragments  = array(
			'/vendor/',
			'/node_modules/',
			'/tests/',
			'/languages/',
			'/exports/static-book/',
			'/exports/static-book--zip/',
			'/wp-includes/sodium_compat/',
		);

		foreach ( $fragments as $fragment ) {
			if ( false !== strpos( $normalized, $fragment ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Merge the active English runtime dictionary into the source catalog.
	 *
	 * Some site integrations generate their runtime dictionaries from large
	 * source arrays or wrappers that are intentionally outside the scanner's
	 * request-time limits. The English dictionary is the canonical runtime
	 * source text, so it keeps translator exports complete.
	 *
	 * @param array $strings Runtime string map.
	 * @return void
	 */
	private static function merge_en_us_dictionary_source_strings( array &$strings ) {
		foreach ( self::en_us_dictionary_paths() as $file_path ) {
			$data = self::read_dictionary_file( $file_path );

			if ( ! is_array( $data ) || ! isset( $data['strings'] ) || ! is_array( $data['strings'] ) ) {
				continue;
			}

			foreach ( $data['strings'] as $runtime_key => $source_text ) {
				if ( ! is_string( $runtime_key ) || ! is_string( $source_text ) ) {
					continue;
				}

				self::register_runtime_string( $strings, $runtime_key, $source_text );
			}
		}
	}

	/**
	 * Return readable English dictionary files from uploads and bundled data.
	 *
	 * @return array
	 */
	private static function en_us_dictionary_paths() {
		$candidates = array();

		if ( function_exists( 'wp_upload_dir' ) ) {
			$upload_dir = wp_upload_dir();
			$base_dir   = isset( $upload_dir['basedir'] ) && is_string( $upload_dir['basedir'] ) ? $upload_dir['basedir'] : '';

			if ( '' !== $base_dir ) {
				$candidates[] = rtrim( $base_dir, '/\\' ) . DIRECTORY_SEPARATOR . 'uaix-locale-router' . DIRECTORY_SEPARATOR . 'dictionaries' . DIRECTORY_SEPARATOR . 'en-US.json';
			}
		}

		if ( defined( 'UAIXLR_PLUGIN_PATH' ) ) {
			$candidates[] = rtrim( UAIXLR_PLUGIN_PATH, '/\\' ) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'dictionaries' . DIRECTORY_SEPARATOR . 'en-US.json';
		}

		$paths = array();