PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/AI/Assistant/LanguageResolver.php +152 -152 4.3.9.14.4.8 View file →
@@ -1,152 +1,152 @@
1 -<?php
2 -
3 -namespace LearnPress\AI\Assistant;
4 -
5 -/**
6 - * LanguageResolver — detects learner language and generates instruction for the model.
7 - *
8 - * Completely stateless utility; can be reused across Agent and QuickQuizEngine.
9 - *
10 - * @package LearnPress\AI\Assistant
11 - * @since 4.3.5
12 - */
13 -class LanguageResolver {
14 -
15 - /**
16 - * Build strict language guidance so the model replies in the learner's language.
17 - *
18 - * @param string $user_message Current learner input.
19 - * @param array $history Conversation history.
20 - * @param int $user_id Current user ID.
21 - *
22 - * @return string
23 - */
24 - public function build_instruction( string $user_message, array $history, int $user_id ): string {
25 -
26 - $sample = $this->resolve_language_sample( $user_message, $history );
27 - $locale_hint = $this->resolve_locale_hint( $user_id );
28 -
29 - if ( $sample !== '' ) {
30 - return sprintf(
31 - /* translators: 1: learner message sample, 2: locale hint. */
32 - __( 'Language policy: reply strictly in the same language as the learner. Do not default to English. Learner sample: "%1$s". Locale fallback: %2$s.', 'learnpress' ),
33 - $sample,
34 - $locale_hint !== '' ? $locale_hint : 'n/a'
35 - );
36 - }
37 -
38 - return sprintf(
39 - /* translators: %s: locale hint. */
40 - __( 'Language policy: reply strictly in the learner language and do not default to English. If the latest learner message is language-neutral, use locale fallback: %s.', 'learnpress' ),
41 - $locale_hint !== '' ? $locale_hint : 'n/a'
42 - );
43 - }
44 -
45 - // ----------------------------------------------------------------
46 - // Private helpers
47 - // ----------------------------------------------------------------
48 -
49 - /**
50 - * Pick the best text sample to infer learner language.
51 - *
52 - * Prefers the current message; falls back to previous user turns.
53 - *
54 - * @param string $user_message Current learner input.
55 - * @param array $history Conversation history.
56 - *
57 - * @return string
58 - */
59 - private function resolve_language_sample( string $user_message, array $history ): string {
60 -
61 - $current = $this->trim_text_for_prompt( $user_message );
62 - if ( $this->has_letters( $current ) && ! $this->is_language_neutral_command( $current ) ) {
63 - return $current;
64 - }
65 -
66 - for ( $index = count( $history ) - 1; $index >= 0; $index-- ) {
67 - $item = $history[ $index ] ?? array();
68 - if ( ( $item['role'] ?? '' ) !== 'user' || ! isset( $item['content'] ) ) {
69 - continue;
70 - }
71 -
72 - $content = $this->trim_text_for_prompt( (string) $item['content'] );
73 - if ( ! $this->has_letters( $content ) || $this->is_language_neutral_command( $content ) ) {
74 - continue;
75 - }
76 -
77 - return $content;
78 - }
79 -
80 - return '';
81 - }
82 -
83 - /**
84 - * Resolve locale hint from WordPress user/site settings.
85 - *
86 - * @param int $user_id Current user ID.
87 - *
88 - * @return string
89 - */
90 - private function resolve_locale_hint( int $user_id ): string {
91 - $locale = (string) get_user_locale( $user_id );
92 - if ( $locale !== '' ) {
93 - return $locale;
94 - }
95 -
96 - $locale = (string) determine_locale();
97 - if ( $locale !== '' ) {
98 - return $locale;
99 - }
100 -
101 - return (string) get_locale();
102 - }
103 -
104 - /**
105 - * Determine if input is a language-neutral command (e.g. /quick-quiz, "1", "A", ...).
106 - *
107 - * @param string $text Input text.
108 - *
109 - * @return bool
110 - */
111 - private function is_language_neutral_command( string $text ): bool {
112 -
113 - $normalized = trim( $text );
114 - if ( $normalized === '' ) {
115 - return true;
116 - }
117 -
118 - if ( str_starts_with( $normalized, '/' ) ) {
119 - return true;
120 - }
121 -
122 - return preg_match( '/^[\d\W_]+$/u', $normalized ) === 1;
123 - }
124 -
125 - /**
126 - * Check whether input contains at least one letter character.
127 - *
128 - * @param string $text Input text.
129 - *
130 - * @return bool
131 - */
132 - private function has_letters( string $text ): bool {
133 - return preg_match( '/\p{L}/u', $text ) === 1;
134 - }
135 -
136 - /**
137 - * Trim and cap text length for safe system prompt injection.
138 - *
139 - * @param string $text Input text.
140 - *
141 - * @return string
142 - */
143 - private function trim_text_for_prompt( string $text ): string {
144 -
145 - $clean = trim( preg_replace( '/\s+/', ' ', $text ) ?? '' );
146 - if ( $clean === '' ) {
147 - return '';
148 - }
149 -
150 - return mb_substr( $clean, 0, 220, 'UTF-8' );
151 - }
152 -}
1 +<?php
2 +
3 +namespace LearnPress\AI\Assistant;
4 +
5 +/**
6 + * LanguageResolver — detects learner language and generates instruction for the model.
7 + *
8 + * Completely stateless utility; can be reused across Agent and QuickQuizEngine.
9 + *
10 + * @package LearnPress\AI\Assistant
11 + * @since 4.3.5
12 + */
13 +class LanguageResolver {
14 +
15 + /**
16 + * Build strict language guidance so the model replies in the learner's language.
17 + *
18 + * @param string $user_message Current learner input.
19 + * @param array $history Conversation history.
20 + * @param int $user_id Current user ID.
21 + *
22 + * @return string
23 + */
24 + public function build_instruction( string $user_message, array $history, int $user_id ): string {
25 +
26 + $sample = $this->resolve_language_sample( $user_message, $history );
27 + $locale_hint = $this->resolve_locale_hint( $user_id );
28 +
29 + if ( $sample !== '' ) {
30 + return sprintf(
31 + /* translators: 1: learner message sample, 2: locale hint. */
32 + __( 'Language policy: reply strictly in the same language as the learner. Do not default to English. Learner sample: "%1$s". Locale fallback: %2$s.', 'learnpress' ),
33 + $sample,
34 + $locale_hint !== '' ? $locale_hint : 'n/a'
35 + );
36 + }
37 +
38 + return sprintf(
39 + /* translators: %s: locale hint. */
40 + __( 'Language policy: reply strictly in the learner language and do not default to English. If the latest learner message is language-neutral, use locale fallback: %s.', 'learnpress' ),
41 + $locale_hint !== '' ? $locale_hint : 'n/a'
42 + );
43 + }
44 +
45 + // ----------------------------------------------------------------
46 + // Private helpers
47 + // ----------------------------------------------------------------
48 +
49 + /**
50 + * Pick the best text sample to infer learner language.
51 + *
52 + * Prefers the current message; falls back to previous user turns.
53 + *
54 + * @param string $user_message Current learner input.
55 + * @param array $history Conversation history.
56 + *
57 + * @return string
58 + */
59 + private function resolve_language_sample( string $user_message, array $history ): string {
60 +
61 + $current = $this->trim_text_for_prompt( $user_message );
62 + if ( $this->has_letters( $current ) && ! $this->is_language_neutral_command( $current ) ) {
63 + return $current;
64 + }
65 +
66 + for ( $index = count( $history ) - 1; $index >= 0; $index-- ) {
67 + $item = $history[ $index ] ?? array();
68 + if ( ( $item['role'] ?? '' ) !== 'user' || ! isset( $item['content'] ) ) {
69 + continue;
70 + }
71 +
72 + $content = $this->trim_text_for_prompt( (string) $item['content'] );
73 + if ( ! $this->has_letters( $content ) || $this->is_language_neutral_command( $content ) ) {
74 + continue;
75 + }
76 +
77 + return $content;
78 + }
79 +
80 + return '';
81 + }
82 +
83 + /**
84 + * Resolve locale hint from WordPress user/site settings.
85 + *
86 + * @param int $user_id Current user ID.
87 + *
88 + * @return string
89 + */
90 + private function resolve_locale_hint( int $user_id ): string {
91 + $locale = (string) get_user_locale( $user_id );
92 + if ( $locale !== '' ) {
93 + return $locale;
94 + }
95 +
96 + $locale = (string) determine_locale();
97 + if ( $locale !== '' ) {
98 + return $locale;
99 + }
100 +
101 + return (string) get_locale();
102 + }
103 +
104 + /**
105 + * Determine if input is a language-neutral command (e.g. /quick-quiz, "1", "A", ...).
106 + *
107 + * @param string $text Input text.
108 + *
109 + * @return bool
110 + */
111 + private function is_language_neutral_command( string $text ): bool {
112 +
113 + $normalized = trim( $text );
114 + if ( $normalized === '' ) {
115 + return true;
116 + }
117 +
118 + if ( str_starts_with( $normalized, '/' ) ) {
119 + return true;
120 + }
121 +
122 + return preg_match( '/^[\d\W_]+$/u', $normalized ) === 1;
123 + }
124 +
125 + /**
126 + * Check whether input contains at least one letter character.
127 + *
128 + * @param string $text Input text.
129 + *
130 + * @return bool
131 + */
132 + private function has_letters( string $text ): bool {
133 + return preg_match( '/\p{L}/u', $text ) === 1;
134 + }
135 +
136 + /**
137 + * Trim and cap text length for safe system prompt injection.
138 + *
139 + * @param string $text Input text.
140 + *
141 + * @return string
142 + */
143 + private function trim_text_for_prompt( string $text ): string {
144 +
145 + $clean = trim( preg_replace( '/\s+/', ' ', $text ) ?? '' );
146 + if ( $clean === '' ) {
147 + return '';
148 + }
149 +
150 + return mb_substr( $clean, 0, 220, 'UTF-8' );
151 + }
152 +}