PluginProbe
ActivityPub / 9.2.1
ActivityPub v9.2.1
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
activitypub / includes / rest / trait-language-map.php

trait-language-map.php in ActivityPub 9.2.1, at includes/rest/trait-language-map.php

185 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Language_Map Trait file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Rest;
9
10 /**
11 * Language_Map Trait.
12 *
13 * Provides methods for resolving ActivityStreams natural language values.
14 *
15 * Properties like `summary`, `content`, and `name` should be plain strings.
16 * Language maps should use the `*Map` variant (`summaryMap`, `contentMap`,
17 * `nameMap`).
18 *
19 * @since 8.0.0
20 *
21 * @see https://www.w3.org/TR/activitystreams-core/#naturalLanguageValues
22 * @see https://www.w3.org/wiki/Activity_Streams/Primer/Language_mapping
23 */
24 trait Language_Map {
25
26 /**
27 * Default fallback language code.
28 *
29 * @since 8.0.0
30 *
31 * @var string
32 */
33 protected $fallback_language = 'en';
34
35 /**
36 * Localize language map properties in an activity object array.
37 *
38 * Normalizes `summary`, `content`, and `name` (and their `*Map` variants)
39 * to plain strings. Also recurses into nested `object` properties.
40 *
41 * Can be used as a sanitize_callback for REST API args.
42 *
43 * @since 8.0.0
44 *
45 * @param mixed $data The activity object data (array or string URI).
46 *
47 * @return mixed The data with language maps resolved, or unchanged if not an array.
48 */
49 public function localize_language_maps( $data ) {
50 if ( ! \is_array( $data ) ) {
51 return $data;
52 }
53
54 $properties = array( 'summary', 'content', 'name' );
55
56 foreach ( $properties as $key ) {
57 if ( isset( $data[ $key ] ) || isset( $data[ $key . 'Map' ] ) ) {
58 $data[ $key ] = $this->get_localized_value(
59 isset( $data[ $key ] ) ? $data[ $key ] : null,
60 isset( $data[ $key . 'Map' ] ) ? $data[ $key . 'Map' ] : null,
61 isset( $data['language'] ) ? $data['language'] : null
62 );
63 }
64 }
65
66 /* Also normalize within the nested object if it is an array. */
67 if ( isset( $data['object'] ) && \is_array( $data['object'] ) ) {
68 $data['object'] = $this->localize_language_maps( $data['object'] );
69 }
70
71 return $data;
72 }
73
74 /**
75 * Resolve a natural language value to a plain string.
76 *
77 * Resolution priority:
78 * 1. The base property when the object's language matches the site locale.
79 * 2. Site locale or English match in the `*Map` variant.
80 * 3. The base property as a plain string (the default).
81 * 4. First `*Map` entry if no base string and no preferred language match.
82 *
83 * Non-string base values (e.g. arrays) are ignored.
84 *
85 * @since 8.0.0
86 *
87 * @param mixed $value The base property value (only strings are used).
88 * @param array|null $map The `*Map` variant (e.g. `summaryMap`).
89 * @param string|null $object_lang The object's language property.
90 *
91 * @return string|null The resolved string, or null if empty.
92 */
93 public function get_localized_value( $value, $map, $object_lang ) {
94 $site_lang = \strtolower( \strtok( \get_locale(), '_-' ) );
95
96 /*
97 * If the object's language matches the site locale,
98 * the base property is already in the right language.
99 */
100 if ( $object_lang && \is_string( $object_lang ) && \is_string( $value ) ) {
101 if ( \strtolower( \strtok( $object_lang, '_-' ) ) === $site_lang ) {
102 return $value;
103 }
104 }
105
106 $languages = $this->get_preferred_languages( $site_lang );
107
108 /* Check the *Map variant for a locale match. */
109 if ( \is_array( $map ) ) {
110 $resolved = $this->resolve_language_map( $map, $languages );
111 if ( $resolved ) {
112 return $resolved;
113 }
114 }
115
116 if ( \is_string( $value ) ) {
117 return $value;
118 }
119
120 /* No base value and no language match: use first map entry. */
121 if ( \is_array( $map ) && ! empty( $map ) ) {
122 return \current( $map );
123 }
124
125 return null;
126 }
127
128 /**
129 * Get the preferred language codes in priority order.
130 *
131 * Returns the site locale as primary, with English as fallback
132 * (unless the site is already English). Additional languages can
133 * be added via the `activitypub_preferred_languages` filter.
134 *
135 * @since 8.0.0
136 *
137 * @param string $site_lang The site's primary language code (e.g. 'de').
138 *
139 * @return string[] Language codes in priority order.
140 */
141 public function get_preferred_languages( $site_lang ) {
142 $languages = array( $site_lang );
143
144 if ( $this->fallback_language !== $site_lang ) {
145 $languages[] = $this->fallback_language;
146 }
147
148 /**
149 * Filters the preferred language codes for language map resolution.
150 *
151 * @since 8.0.0
152 *
153 * @param string[] $languages Preferred language codes in priority order.
154 * @param string $site_lang The site's primary language code.
155 */
156 return \apply_filters( 'activitypub_preferred_languages', $languages, $site_lang );
157 }
158
159 /**
160 * Resolve a language map to a single string.
161 *
162 * Tries each preferred language in order (site locale, then English).
163 *
164 * @since 8.0.0
165 *
166 * @param array $map The language map (e.g. `{"en": "Hello", "de": "Hallo"}`).
167 * @param string[] $languages Preferred language codes in priority order (e.g. `['de', 'en']`).
168 *
169 * @return string|null The matched string, or null if no match found.
170 */
171 private function resolve_language_map( $map, $languages ) {
172 if ( empty( $map ) ) {
173 return null;
174 }
175
176 foreach ( $languages as $lang ) {
177 if ( isset( $map[ $lang ] ) ) {
178 return $map[ $lang ];
179 }
180 }
181
182 return null;
183 }
184 }
185