Plugin Directory

Changeset 3480268


Ignore:
Timestamp:
03/11/2026 02:34:06 PM (4 weeks ago)
Author:
vinsmach
Message:

Version 1.6.4 — fix language 2

Location:
mescio-for-agents/trunk/includes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • mescio-for-agents/trunk/includes/class-llms-endpoints.php

    r3480216 r3480268  
    1616    const QUERY_VAR = 'mescio_llms_txt';
    1717
     18    /**
     19     * Language code extracted from the request URL (e.g. "en", "it").
     20     * Set by early_intercept() and used by resolve_translated_post() so we
     21     * never rely on WPML/Polylang's "current language" context, which is not
     22     * set when serving our custom endpoints outside normal WP routing.
     23     *
     24     * @var string|null  null = not yet detected, '' = no prefix in URL (default lang)
     25     */
     26    private static ?string $request_lang = null;
     27
    1828    // ── Rewrite plumbing ──────────────────────────────────────────────────────
    1929
     
    3646    }
    3747
     48    /** Query var used to pass the detected language to build_index/build_full. */
     49    const LANG_VAR = 'mescio_llms_lang';
     50
    3851    /**
    3952     * Early intercept on `parse_request` for multilingual sites where
     
    4962        // Strip query string and surrounding slashes
    5063        $path = trim( strtok( $uri, '?' ), '/' );
    51         // Strip optional language prefix like "it", "en", "pt-br"
    52         $path = preg_replace( '#^[a-z]{2}(-[a-z]{2})?/#', '', $path );
     64
     65        // Extract optional language prefix like "it", "en", "pt-br" BEFORE stripping it.
     66        $lang = '';
     67        if ( preg_match( '#^([a-z]{2}(?:-[a-z]{2})?)/#i', $path, $m ) ) {
     68            $lang = strtolower( $m[1] );
     69        }
     70
     71        // Strip the language prefix to get the bare filename.
     72        $path = preg_replace( '#^[a-z]{2}(-[a-z]{2})?/#i', '', $path );
    5373
    5474        if ( $path === 'llms.txt' ) {
    5575            set_query_var( self::QUERY_VAR, '' );
     76            if ( $lang ) set_query_var( self::LANG_VAR, $lang );
    5677        } elseif ( $path === 'llms-full.txt' ) {
    5778            set_query_var( self::QUERY_VAR, '-full' );
     79            if ( $lang ) set_query_var( self::LANG_VAR, $lang );
    5880        }
    5981    }
     
    6486    public static function add_query_var( array $vars ): array {
    6587        $vars[] = self::QUERY_VAR;
     88        $vars[] = self::LANG_VAR;
    6689        return $vars;
    6790    }
     
    340363    /**
    341364     * Given a post in the default language, return its translated version
    342      * matching the current language context (WPML or Polylang).
    343      * Falls back to the original post if no translation exists.
     365     * matching the current language context.
     366     *
     367     * Priority:
     368     *   1. Language detected from the request URL (e.g. /en/llms.txt → "en"),
     369     *      stored in the mescio_llms_lang query var by early_intercept().
     370     *   2. WPML current language.
     371     *   3. Polylang current language.
     372     *
     373     * Falls back to the original post if no translation is found.
    344374     */
    345375    private static function resolve_translated_post( WP_Post $post ): WP_Post {
     376        // 1. Language from request URL (most reliable on llms.txt requests).
     377        $url_lang = sanitize_key( (string) get_query_var( self::LANG_VAR, '' ) );
     378
     379        // Helper: try WPML with a given lang code.
     380        $try_wpml = static function ( int $id, string $type, string $lang ): ?WP_Post {
     381            if ( ! function_exists( 'icl_object_id' ) ) return null;
     382            $tid = icl_object_id( $id, $type, false, $lang );
     383            if ( $tid && $tid !== $id ) {
     384                $p = get_post( $tid );
     385                if ( $p instanceof WP_Post ) return $p;
     386            }
     387            return null;
     388        };
     389
     390        // Helper: try Polylang with a given lang code.
     391        $try_pll = static function ( int $id, string $lang ): ?WP_Post {
     392            if ( ! function_exists( 'pll_get_post' ) ) return null;
     393            $tid = pll_get_post( $id, $lang );
     394            if ( $tid && $tid !== $id ) {
     395                $p = get_post( $tid );
     396                if ( $p instanceof WP_Post ) return $p;
     397            }
     398            return null;
     399        };
     400
     401        // Try URL-detected language first.
     402        if ( $url_lang ) {
     403            $p = $try_wpml( $post->ID, $post->post_type, $url_lang )
     404              ?? $try_pll( $post->ID, $url_lang );
     405            if ( $p ) return $p;
     406        }
     407
     408        // Fallback: ask the language plugin for its current language context.
    346409        // WPML
    347410        if ( function_exists( 'icl_object_id' ) ) {
    348411            $lang = apply_filters( 'wpml_current_language', null ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
    349412            if ( $lang ) {
    350                 $translated_id = icl_object_id( $post->ID, $post->post_type, false, $lang );
    351                 if ( $translated_id && $translated_id !== $post->ID ) {
    352                     $translated = get_post( $translated_id );
    353                     if ( $translated instanceof WP_Post ) return $translated;
    354                 }
     413                $p = $try_wpml( $post->ID, $post->post_type, $lang );
     414                if ( $p ) return $p;
    355415            }
    356416        }
    357417        // Polylang
    358         if ( function_exists( 'pll_current_language' ) && function_exists( 'pll_get_post' ) ) {
     418        if ( function_exists( 'pll_current_language' ) ) {
    359419            $lang = pll_current_language( 'slug' );
    360420            if ( $lang ) {
    361                 $translated_id = pll_get_post( $post->ID, $lang );
    362                 if ( $translated_id && $translated_id !== $post->ID ) {
    363                     $translated = get_post( $translated_id );
    364                     if ( $translated instanceof WP_Post ) return $translated;
    365                 }
    366             }
    367         }
     421                $p = $try_pll( $post->ID, $lang );
     422                if ( $p ) return $p;
     423            }
     424        }
     425
    368426        return $post;
    369427    }
  • mescio-for-agents/trunk/includes/class-markdown-generator.php

    r3480216 r3480268  
    378378     * If WPML or Polylang is active, return the translated version of $post
    379379     * matching the current language context. Falls back to $post unchanged.
     380     *
     381     * Reads the mescio_llms_lang query var (set by early_intercept from the
     382     * request URL) as the primary language source, so excerpts are correct
     383     * even before WPML/Polylang have set their own language context.
    380384     */
    381385    private static function maybe_get_translated_post( WP_Post $post ): WP_Post {
     386        // Primary: language detected from request URL (/en/llms.txt → "en").
     387        $url_lang = sanitize_key( (string) get_query_var( 'mescio_llms_lang', '' ) );
     388        $lang     = $url_lang;
     389
     390        // Fallback: ask WPML / Polylang for the current language.
     391        if ( ! $lang && function_exists( 'icl_object_id' ) ) {
     392            $lang = (string) apply_filters( 'wpml_current_language', '' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
     393        }
     394        if ( ! $lang && function_exists( 'pll_current_language' ) ) {
     395            $lang = (string) pll_current_language( 'slug' );
     396        }
     397
     398        if ( ! $lang ) return $post;
     399
    382400        // WPML
    383401        if ( function_exists( 'icl_object_id' ) ) {
    384             $lang        = apply_filters( 'wpml_current_language', null ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
    385             $translated  = $lang ? icl_object_id( $post->ID, $post->post_type, false, $lang ) : null;
    386             if ( $translated && $translated !== $post->ID ) {
    387                 $p = get_post( $translated );
     402            $tid = icl_object_id( $post->ID, $post->post_type, false, $lang );
     403            if ( $tid && $tid !== $post->ID ) {
     404                $p = get_post( $tid );
    388405                if ( $p instanceof WP_Post ) return $p;
    389406            }
    390407        }
    391408        // Polylang
    392         if ( function_exists( 'pll_current_language' ) && function_exists( 'pll_get_post' ) ) {
    393             $lang       = pll_current_language( 'slug' );
    394             $translated = $lang ? pll_get_post( $post->ID, $lang ) : null;
    395             if ( $translated && $translated !== $post->ID ) {
    396                 $p = get_post( $translated );
     409        if ( function_exists( 'pll_get_post' ) ) {
     410            $tid = pll_get_post( $post->ID, $lang );
     411            if ( $tid && $tid !== $post->ID ) {
     412                $p = get_post( $tid );
    397413                if ( $p instanceof WP_Post ) return $p;
    398414            }
    399415        }
     416
    400417        return $post;
    401418    }
Note: See TracChangeset for help on using the changeset viewer.