Skip to content
wiki.fftac.org

Translationcatalog - Source Excerpt 01

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

<?php

namespace UAIXLocaleRouter;

use FilesystemIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RegexIterator;


if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class TranslationCatalog {
	/**
	 * Cached runtime string inventory.
	 *
	 * @var array|null
	 */
	private static $runtime_strings = null;

	/**
	 * Cached source-to-runtime map.
	 *
	 * @var array|null
	 */
	private static $source_map = null;

	/**
	 * Return the current catalog version.
	 *
	 * @return int
	 */
	public static function template_version() {
		return 1;
	}

	/**
	 * Build the runtime template dictionary keyed by internal runtime IDs.
	 *
	 * @return array
	 */
	public static function build_runtime_dictionary() {
		return array(
			'meta'    => array(
				'locale'       => 'en-US',
				'sourceLocale' => 'en-US',
				'version'      => self::template_version(),
				'generatedFrom' => 'uaix-locale-router-source-catalog',
				'keyMode'      => 'runtime-key',
			),
			'strings' => self::runtime_strings(),
		);
	}

	/**
	 * Reset the in-memory catalog cache.
	 *
	 * @return void
	 */
	public static function reset_cache() {
		self::$runtime_strings = null;
		self::$source_map      = null;

		if ( function_exists( 'delete_transient' ) ) {
			delete_transient( 'uaixlr_translation_runtime_strings' );
		}
	}

	/**
	 * Return the runtime string inventory keyed by stable internal IDs.
	 *
	 * @return array
	 */
	public static function runtime_strings() {
		if ( null !== self::$runtime_strings ) {
			return self::$runtime_strings;
		}

		if ( function_exists( 'get_transient' ) ) {
			$cached = get_transient( 'uaixlr_translation_runtime_strings' );

			if ( is_array( $cached ) && ! empty( $cached ) ) {
				self::$runtime_strings = $cached;

				return self::$runtime_strings;
			}
		}

		$strings = array();

		// This scan can touch theme/plugin files, so it is capped and cached to avoid request-time churn.
		foreach ( self::catalog_php_files() as $file_path ) {
			$contents = file_get_contents( $file_path );

			if ( ! is_string( $contents ) || '' === $contents ) {
				continue;
			}

			self::extract_helper_call_strings( $contents, $strings );
			self::extract_array_pair_strings( $contents, 'label', $strings );
			self::extract_array_pair_strings( $contents, 'title', $strings );
			self::extract_array_pair_strings( $contents, 'copy', $strings );
		}

		self::merge_en_us_dictionary_source_strings( $strings );

		uksort( $strings, 'strnatcasecmp' );
		self::$runtime_strings = $strings;

		if ( function_exists( 'set_transient' ) ) {
			set_transient( 'uaixlr_translation_runtime_strings', self::$runtime_strings, 12 * HOUR_IN_SECONDS );
		}

		return self::$runtime_strings;
	}

	/**
	 * Return the source-text map used for translator-facing files.
	 *
	 * @return array
	 */
	public static function source_to_runtime_keys() {
		if ( null !== self::$source_map ) {
			return self::$source_map;
		}

		$map = array();

		foreach ( self::runtime_strings() as $runtime_key => $source_text ) {
			if ( '' === $runtime_key || '' === $source_text ) {
				continue;
			}

			if ( ! isset( $map[ $source_text ] ) ) {
				$map[ $source_text ] = array();
			}

			$map[ $source_text ][] = $runtime_key;
		}

		uksort( $map, 'strnatcasecmp' );
		self::$source_map = $map;

		return self::$source_map;
	}

	/**
	 * Build a translator-facing export for a locale.
	 *
	 * @param string $locale_tag Locale tag or "template".
	 * @return array
	 */
	public static function build_translator_dictionary( $locale_tag ) {
		$locale_tag = self::normalize_export_locale( $locale_tag );
		$strings    = array();
		$runtime    = array();

		if ( 'template' !== $locale_tag && 'en-US' !== $locale_tag ) {
			$runtime = DictionaryRepository::load_locale_dictionary( $locale_tag );
			$runtime = isset( $runtime['strings'] ) && is_array( $runtime['strings'] ) ? $runtime['strings'] : array();
		}

		foreach ( self::source_to_runtime_keys() as $source_text => $runtime_keys ) {
			$value = '';

			if ( 'en-US' === $locale_tag ) {
				$value = $source_text;
			} elseif ( 'template' !== $locale_tag ) {
				foreach ( $runtime_keys as $runtime_key ) {
					if ( isset( $runtime[ $runtime_key ] ) && is_string( $runtime[ $runtime_key ] ) && '' !== trim( $runtime[ $runtime_key ] ) ) {
						$value = $runtime[ $runtime_key ];
						break;
					}
				}
			}

			$strings[ $source_text ] = $value;
		}

		return array(
			'meta'    => array(
				'locale'       => $locale_tag,
				'sourceLocale' => 'en-US',
				'version'      => self::template_version(),
				'generatedFrom' => 'uaix-locale-router-source-catalog',
				'keyMode'      => 'source-text',
			),
			'strings' => $strings,
		);
	}

	/**
	 * Normalize a translator-facing or legacy runtime-key dictionary.
	 *
	 * @param array $data Raw dictionary payload.
	 * @return array
	 */
	public static function normalize_dictionary_payload( array $data ) {
		$meta         = isset( $data['meta'] ) && is_array( $data['meta'] ) ? $data['meta'] : array();
		$locale_tag   = isset( $meta['locale'] ) ? self::normalize_export_locale( $meta['locale'] ) : '';
		$raw_strings  = isset( $data['strings'] ) && is_array( $data['strings'] ) ? $data['strings'] : array();
		$key_mode     = self::detect_dictionary_key_mode( $raw_strings );
		$source_keys  = self::source_to_runtime_keys();
		$translator   = array();
		$runtime      = array();

		foreach ( $source_keys as $source_text => $runtime_keys ) {
			$value = '';

			if ( 'source-text' === $key_mode ) {
				if ( array_key_exists( $source_text, $raw_strings ) && is_string( $raw_strings[ $source_text ] ) ) {
					$value = $raw_strings[ $source_text ];
				}
			} else {
				foreach ( $runtime_keys as $runtime_key ) {
					if ( array_key_exists( $runtime_key, $raw_strings ) && is_string( $raw_strings[ $runtime_key ] ) && '' !== trim( $raw_strings[ $runtime_key ] ) ) {
						$value = $raw_strings[ $runtime_key ];
						break;
					}
				}
			}

			if ( 'en-US' === $locale_tag ) {
				$value = $source_text;
			}

			$translator[ $source_text ] = $value;

			foreach ( $runtime_keys as $runtime_key ) {
				$runtime[ $runtime_key ] = $value;
			}
		}

		$runtime_meta = array_merge(
			array(
				'locale'       => $locale_tag,
				'sourceLocale' => 'en-US',
				'version'      => isset( $meta['version'] ) ? absint( $meta['version'] ) : self::template_version(),
				'generatedFrom' => isset( $meta['generatedFrom'] ) ? (string) $meta['generatedFrom'] : 'uaix-locale-router-source-catalog',
				'keyMode'      => 'runtime-key',
			),
			$meta
		);
		$runtime_meta['locale']  = $locale_tag;
		$runtime_meta['keyMode'] = 'runtime-key';

		$translator_meta = array_merge(
			array(
				'locale'       => $locale_tag,
				'sourceLocale' => 'en-US',
				'version'      => isset( $meta['version'] ) ? absint( $meta['version'] ) : self::template_version(),
				'generatedFrom' => isset( $meta['generatedFrom'] ) ? (string) $meta['generatedFrom'] : 'uaix-locale-router-source-catalog',
				'keyMode'      => 'source-text',
			),
			$meta
		);
		$translator_meta['locale']  = $locale_tag;
		$translator_meta['keyMode'] = 'source-text';

		foreach ( $raw_strings as $raw_key => $raw_value ) {
			if ( ! is_string( $raw_key ) || ! is_string( $raw_value ) || isset( $runtime[ $raw_key ] ) ) {
				continue;
			}

			if ( preg_match( '/^[A-Za-z0-9._:-]{1,190}$/', $raw_key ) ) {
				$runtime[ $raw_key ] = $raw_value;
			}
		}