>|null */ private static ?array $catalogs = null; /** @var array>|null */ private static ?array $audit_pass = null; /** * Return a localized merchant-facing string. * * Unknown languages deterministically fall back to Bosnian. Unknown keys are * deliberately visible so incomplete editorial wiring cannot pass unnoticed. * * @param string $language Selected language. * @param string $key Catalog key. * @param array $values Sprintf replacement values. */ public static function text( string $language, string $key, array $values = array() ): string { $catalogs = self::catalogs(); $language = isset( $catalogs[ $language ] ) ? $language : LanguageCatalog::BOSNIAN; $text = $catalogs[ $language ][ $key ] ?? $catalogs[ LanguageCatalog::BOSNIAN ][ $key ] ?? '[' . $key . ']'; return empty( $values ) ? $text : vsprintf( $text, $values ); } /** @return array */ public static function all( string $language ): array { $catalogs = self::catalogs(); return $catalogs[ $language ] ?? $catalogs[ LanguageCatalog::BOSNIAN ]; } /** * Return the locked factual PASS message for one of the 24 audit checks. */ public static function audit_pass( string $language, string $code ): string { $messages = self::audit_pass_messages(); $language = in_array( $language, LanguageCatalog::supported_codes(), true ) ? $language : LanguageCatalog::BOSNIAN; return $messages[ $code ][ $language ] ?? self::text( $language, 'finding_pass' ); } /** @return array> */ private static function catalogs(): array { if ( null !== self::$catalogs ) { return self::$catalogs; } $key_first = array_replace( self::read_json( self::COPY_FILE ), self::read_json( self::BEHAVIOR_FILE ) ); $catalogs = array_fill_keys( LanguageCatalog::supported_codes(), array() ); foreach ( $key_first as $key => $translations ) { if ( ! is_array( $translations ) ) { continue; } foreach ( LanguageCatalog::supported_codes() as $language ) { if ( isset( $translations[ $language ] ) && is_string( $translations[ $language ] ) ) { $catalogs[ $language ][ (string) $key ] = $translations[ $language ]; } } } self::$catalogs = $catalogs; return self::$catalogs; } /** @return array> */ private static function audit_pass_messages(): array { if ( null === self::$audit_pass ) { self::$audit_pass = self::read_json( self::AUDIT_PASS_FILE ); } return self::$audit_pass; } /** @return array */ private static function read_json( string $relative_path ): array { $path = dirname( __DIR__, 3 ) . '/' . $relative_path; // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Read-only bundled plugin data. $json = file_get_contents( $path ); if ( false === $json ) { throw new RuntimeException( 'The bundled editorial catalog could not be read.' ); } $data = json_decode( $json, true, 512, JSON_THROW_ON_ERROR ); if ( ! is_array( $data ) ) { throw new RuntimeException( 'The bundled editorial catalog is invalid.' ); } return $data; } private function __construct() {} }