php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
gettext.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Alex Plotnick <alex@wgate.com> |
14 +----------------------------------------------------------------------+
15 */
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "php.h"
22
23#ifdef HAVE_LIBINTL
24
25#include <stdio.h>
26#include <locale.h>
27#include "ext/standard/info.h"
28#include "php_gettext.h"
29#include "gettext_arginfo.h"
30
31#include <libintl.h>
32
33zend_module_entry php_gettext_module_entry = {
35 "gettext",
36 ext_functions,
37 NULL,
38 NULL,
39 NULL,
40 NULL,
41 PHP_MINFO(php_gettext),
42 PHP_GETTEXT_VERSION,
44};
45
46#ifdef COMPILE_DL_GETTEXT
47ZEND_GET_MODULE(php_gettext)
48#endif
49
50#define PHP_GETTEXT_MAX_DOMAIN_LENGTH 1024
51#define PHP_GETTEXT_MAX_MSGID_LENGTH 4096
52
53#define PHP_GETTEXT_DOMAIN_LENGTH_CHECK(_arg_num, domain_len) \
54 if (UNEXPECTED(domain_len > PHP_GETTEXT_MAX_DOMAIN_LENGTH)) { \
55 zend_argument_value_error(_arg_num, "is too long"); \
56 RETURN_THROWS(); \
57 } else if (domain_len == 0) { \
58 zend_argument_must_not_be_empty_error(_arg_num); \
59 RETURN_THROWS(); \
60 }
61
62#define PHP_GETTEXT_LENGTH_CHECK(_arg_num, check_len) \
63 if (UNEXPECTED(check_len > PHP_GETTEXT_MAX_MSGID_LENGTH)) { \
64 zend_argument_value_error(_arg_num, "is too long"); \
65 RETURN_THROWS(); \
66 }
67
68#define PHP_DCGETTEXT_CATEGORY_CHECK(_arg_num, category) \
69 if (category == LC_ALL) { \
70 zend_argument_value_error(_arg_num, "cannot be LC_ALL"); \
71 RETURN_THROWS(); \
72 }
73
74PHP_MINFO_FUNCTION(php_gettext)
75{
77 php_info_print_table_row(2, "GetText Support", "enabled");
79}
80
81/* {{{ Set the textdomain to "domain". Returns the current domain */
83{
84 char *domain_name = NULL, *retval = NULL;
85 zend_string *domain = NULL;
86
91
92 if (domain != NULL) {
93 PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
94 if (zend_string_equals_literal(domain, "0")) {
95 zend_argument_value_error(1, "cannot be zero");
97 }
98 domain_name = ZSTR_VAL(domain);
99 }
100
101 retval = textdomain(domain_name);
102
104}
105/* }}} */
106
107/* {{{ Return the translation of msgid for the current domain, or msgid unaltered if a translation does not exist */
109{
110 char *msgstr = NULL;
111 zend_string *msgid;
112
114 Z_PARAM_STR(msgid)
116
117 PHP_GETTEXT_LENGTH_CHECK(1, ZSTR_LEN(msgid))
118 msgstr = gettext(ZSTR_VAL(msgid));
119
120 if (msgstr != ZSTR_VAL(msgid)) {
121 RETURN_STRING(msgstr);
122 } else {
123 RETURN_STR_COPY(msgid);
124 }
125}
126/* }}} */
127
128/* {{{ Return the translation of msgid for domain_name, or msgid unaltered if a translation does not exist */
130{
131 char *msgstr = NULL;
132 zend_string *domain, *msgid;
133
135 Z_PARAM_STR(domain)
136 Z_PARAM_STR(msgid)
138
139 PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
140 PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid))
141
142 msgstr = dgettext(ZSTR_VAL(domain), ZSTR_VAL(msgid));
143
144 if (msgstr != ZSTR_VAL(msgid)) {
145 RETURN_STRING(msgstr);
146 } else {
147 RETURN_STR_COPY(msgid);
148 }
149}
150/* }}} */
151
152/* {{{ Return the translation of msgid for domain_name and category, or msgid unaltered if a translation does not exist */
154{
155 char *msgstr = NULL;
156 zend_string *domain, *msgid;
157 zend_long category;
158
160 Z_PARAM_STR(domain)
161 Z_PARAM_STR(msgid)
162 Z_PARAM_LONG(category)
164
165 PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
166 PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid))
167 PHP_DCGETTEXT_CATEGORY_CHECK(3, category)
168
169 msgstr = dcgettext(ZSTR_VAL(domain), ZSTR_VAL(msgid), category);
170
171 if (msgstr != ZSTR_VAL(msgid)) {
172 RETURN_STRING(msgstr);
173 } else {
174 RETURN_STR_COPY(msgid);
175 }
176}
177/* }}} */
178
179/* {{{ Bind to the text domain domain_name, looking for translations in dir. Returns the current domain */
181{
182 zend_string *domain, *dir = NULL;
183 char *retval, dir_name[MAXPATHLEN], *btd_result;
184
186 Z_PARAM_PATH_STR(domain)
190
191 PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
192
193 if (dir == NULL) {
194 btd_result = bindtextdomain(ZSTR_VAL(domain), NULL);
195 if (btd_result == NULL) {
196 /* POSIX-compliant implementations can return
197 * NULL if an error occured. On musl you will
198 * also get NULL if the domain is not yet
199 * bound, because musl has no default directory
200 * to return in that case. */
202 }
203 RETURN_STRING(btd_result);
204 }
205
206 if (ZSTR_LEN(dir) != 0 && !zend_string_equals_literal(dir, "0")) {
207 if (!VCWD_REALPATH(ZSTR_VAL(dir), dir_name)) {
209 }
210 } else if (!VCWD_GETCWD(dir_name, MAXPATHLEN)) {
212 }
213
214 retval = bindtextdomain(ZSTR_VAL(domain), dir_name);
215
217}
218/* }}} */
219
220#ifdef HAVE_NGETTEXT
221/* {{{ Plural version of gettext() */
223{
224 char *msgstr = NULL;
225 zend_string *msgid1, *msgid2;
227
229 Z_PARAM_STR(msgid1)
230 Z_PARAM_STR(msgid2)
233
234 PHP_GETTEXT_LENGTH_CHECK(1, ZSTR_LEN(msgid1))
235 PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid2))
236
237 msgstr = ngettext(ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count);
238
239 ZEND_ASSERT(msgstr);
240 RETURN_STRING(msgstr);
241}
242/* }}} */
243#endif
244
245#ifdef HAVE_DNGETTEXT
246/* {{{ Plural version of dgettext() */
248{
249 char *msgstr = NULL;
250 zend_string *domain, *msgid1, *msgid2;
252
254 Z_PARAM_STR(domain)
255 Z_PARAM_STR(msgid1)
256 Z_PARAM_STR(msgid2)
259
260 PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
261 PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid1))
262 PHP_GETTEXT_LENGTH_CHECK(3, ZSTR_LEN(msgid2))
263
264 msgstr = dngettext(ZSTR_VAL(domain), ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count);
265
266 ZEND_ASSERT(msgstr);
267 RETURN_STRING(msgstr);
268}
269/* }}} */
270#endif
271
272#ifdef HAVE_DCNGETTEXT
273/* {{{ Plural version of dcgettext() */
275{
276 char *msgstr = NULL;
277 zend_string *domain, *msgid1, *msgid2;
278 zend_long count, category;
279
281
283 Z_PARAM_STR(domain)
284 Z_PARAM_STR(msgid1)
285 Z_PARAM_STR(msgid2)
287 Z_PARAM_LONG(category)
289
290 PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
291 PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid1))
292 PHP_GETTEXT_LENGTH_CHECK(3, ZSTR_LEN(msgid2))
293 PHP_DCGETTEXT_CATEGORY_CHECK(5, category)
294
295 msgstr = dcngettext(ZSTR_VAL(domain), ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count, category);
296
297 ZEND_ASSERT(msgstr);
298 RETURN_STRING(msgstr);
299}
300/* }}} */
301#endif
302
303#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
304
305/* {{{ Specify the character encoding in which the messages from the DOMAIN message catalog will be returned. */
307{
308 char *retval = NULL;
309 zend_string *domain, *codeset = NULL;
310
312 Z_PARAM_STR(domain)
316
317 PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
318
320
321 if (!retval) {
323 }
325}
326/* }}} */
327#endif
328
329
330#endif /* HAVE_LIBINTL */
dir(string $directory, $context=null)
count(Countable|array $value, int $mode=COUNT_NORMAL)
#define NULL
Definition gdcache.h:45
gettext(string $message)
textdomain(?string $domain=null)
bind_textdomain_codeset(string $domain, ?string $codeset=null)
dcngettext(string $domain, string $singular, string $plural, int $count, int $category)
bindtextdomain(string $domain, ?string $directory=null)
dcgettext(string $domain, string $message, int $category)
dgettext(string $domain, string $message)
dngettext(string $domain, string $singular, string $plural, int $count)
ngettext(string $singular, string $plural, int $count)
foreach($dp as $el) foreach( $dp as $el) if( $pass2< 2) echo ""
const char * codeset
Definition html_tables.h:37
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MINFO
Definition php.h:396
#define PHP_MINFO_FUNCTION
Definition php.h:404
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
#define Z_PARAM_PATH_STR(dest)
Definition zend_API.h:2041
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define Z_PARAM_STR_OR_NULL(dest)
Definition zend_API.h:2089
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define Z_PARAM_STR(dest)
Definition zend_API.h:2086
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETVAL_FALSE
Definition zend_API.h:1032
#define Z_PARAM_PATH_STR_OR_NULL(dest)
Definition zend_API.h:2044
#define RETURN_STR_COPY(s)
Definition zend_API.h:1042
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
#define STANDARD_MODULE_HEADER
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES
#define ZEND_ASSERT(c)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define zend_string_equals_literal(str, literal)
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define VCWD_GETCWD(buff, size)
#define MAXPATHLEN
#define VCWD_REALPATH(path, real_path)
zval retval