summaryrefslogtreecommitdiffstats
path: root/wp-includes/l10n/class-wp-translations.php
blob: e177e1d8c536bb3bf4dff461dc6aa4d00f1d96a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<?php
/**
 * I18N: WP_Translations class.
 *
 * @package WordPress
 * @subpackage I18N
 * @since 6.5.0
 */

/**
 * Class WP_Translations.
 *
 * @since 6.5.0
 *
 * @property-read array<string, string> $headers
 * @property-read array<string, string[]> $entries
 */
class WP_Translations {
	/**
	 * Text domain.
	 *
	 * @since 6.5.0
	 * @var string
	 */
	protected $textdomain = 'default';

	/**
	 * Translation controller instance.
	 *
	 * @since 6.5.0
	 * @var WP_Translation_Controller
	 */
	protected $controller;

	/**
	 * Constructor.
	 *
	 * @since 6.5.0
	 *
	 * @param WP_Translation_Controller $controller I18N controller.
	 * @param string                    $textdomain Optional. Text domain. Default 'default'.
	 */
	public function __construct( WP_Translation_Controller $controller, string $textdomain = 'default' ) {
		$this->controller = $controller;
		$this->textdomain = $textdomain;
	}

	/**
	 * Magic getter for backward compatibility.
	 *
	 * @since 6.5.0
	 *
	 * @param string $name Property name.
	 * @return mixed
	 */
	public function __get( string $name ) {
		if ( 'entries' === $name ) {
			$entries = $this->controller->get_entries( $this->textdomain );

			$result = array();

			foreach ( $entries as $original => $translations ) {
				$result[] = $this->make_entry( $original, $translations );
			}

			return $result;
		}

		if ( 'headers' === $name ) {
			return $this->controller->get_headers( $this->textdomain );
		}

		return null;
	}

	/**
	 * Builds a Translation_Entry from original string and translation strings.
	 *
	 * @see MO::make_entry()
	 *
	 * @since 6.5.0
	 *
	 * @param string $original     Original string to translate from MO file. Might contain
	 *                             0x04 as context separator or 0x00 as singular/plural separator.
	 * @param string $translations Translation strings from MO file.
	 * @return Translation_Entry Entry instance.
	 */
	private function make_entry( $original, $translations ): Translation_Entry {
		$entry = new Translation_Entry();

		// Look for context, separated by \4.
		$parts = explode( "\4", $original );
		if ( isset( $parts[1] ) ) {
			$original       = $parts[1];
			$entry->context = $parts[0];
		}

		$entry->singular     = $original;
		$entry->translations = explode( "\0", $translations );
		$entry->is_plural    = count( $entry->translations ) > 1;

		return $entry;
	}

	/**
	 * Translates a plural string.
	 *
	 * @since 6.5.0
	 *
	 * @param string|null $singular Singular string.
	 * @param string|null $plural   Plural string.
	 * @param int|float   $count    Count. Should be an integer, but some plugins pass floats.
	 * @param string|null $context  Context.
	 * @return string|null Translation if it exists, or the unchanged singular string.
	 */
	public function translate_plural( $singular, $plural, $count = 1, $context = '' ) {
		if ( null === $singular || null === $plural ) {
			return $singular;
		}

		$translation = $this->controller->translate_plural( array( $singular, $plural ), (int) $count, (string) $context, $this->textdomain );
		if ( false !== $translation ) {
			return $translation;
		}

		// Fall back to the original with English grammar rules.
		return ( 1 === $count ? $singular : $plural );
	}

	/**
	 * Translates a singular string.
	 *
	 * @since 6.5.0
	 *
	 * @param string|null $singular Singular string.
	 * @param string|null $context  Context.
	 * @return string|null Translation if it exists, or the unchanged singular string
	 */
	public function translate( $singular, $context = '' ) {
		if ( null === $singular ) {
			return null;
		}

		$translation = $this->controller->translate( $singular, (string) $context, $this->textdomain );
		if ( false !== $translation ) {
			return $translation;
		}

		// Fall back to the original.
		return $singular;
	}
}