PluginProbe
Bogo / 3.9.3
Bogo v3.9.3
3.9.3 trunk 1.0 1.1 2.0 2.0.1 2.1 2.1.1 2.1.2 2.1.3 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5 2.6 2.6.1 2.7 2.8 2.8.1 2.9 3.0 3.0.1 All 52 releases
bogo / includes / language-functions.php

language-functions.php in Bogo 3.9.3, at includes/language-functions.php

958 lines 23.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Retrieves installable languages.
5 *
6 * @link http://api.wordpress.org/translations/core/1.0/
7 */
8 function bogo_languages() {
9 static $languages = array();
10 static $textdomain_loaded = false;
11
12 if ( $languages and $textdomain_loaded and ! is_locale_switched() ) {
13 return apply_filters( 'bogo_languages', $languages );
14 }
15
16 $languages = array(
17 'af' => __( 'Afrikaans', 'bogo' ),
18 'am' => __( 'Amharic', 'bogo' ),
19 'ar' => __( 'Arabic', 'bogo' ),
20 'arg' => __( 'Aragonese', 'bogo' ),
21 'ary' => __( 'Moroccan Arabic', 'bogo' ),
22 'as' => __( 'Assamese', 'bogo' ),
23 'az' => __( 'Azerbaijani', 'bogo' ),
24 'azb' => __( 'South Azerbaijani', 'bogo' ),
25 'bel' => __( 'Belarusian', 'bogo' ),
26 'bg_BG' => __( 'Bulgarian', 'bogo' ),
27 'bn_BD' => __( 'Bengali (Bangladesh)', 'bogo' ),
28 'bo' => __( 'Tibetan', 'bogo' ),
29 'bs_BA' => __( 'Bosnian', 'bogo' ),
30 'ca' => __( 'Catalan', 'bogo' ),
31 'ceb' => __( 'Cebuano', 'bogo' ),
32 'ckb' => __( 'Kurdish (Sorani)', 'bogo' ),
33 'cs_CZ' => __( 'Czech', 'bogo' ),
34 'cy' => __( 'Welsh', 'bogo' ),
35 'da_DK' => __( 'Danish', 'bogo' ),
36 'de_AT' => __( 'German (Austria)', 'bogo' ),
37 'de_CH' => __( 'German (Switzerland)', 'bogo' ),
38 'de_CH_informal' => __( 'German (Switzerland, Informal)', 'bogo' ),
39 'de_DE' => __( 'German', 'bogo' ),
40 'de_DE_formal' => __( 'German (Formal)', 'bogo' ),
41 'dsb' => __( 'Lower Sorbian', 'bogo' ),
42 'dzo' => __( 'Dzongkha', 'bogo' ),
43 'el' => __( 'Greek', 'bogo' ),
44 'en_AU' => __( 'English (Australia)', 'bogo' ),
45 'en_CA' => __( 'English (Canada)', 'bogo' ),
46 'en_GB' => __( 'English (UK)', 'bogo' ),
47 'en_NZ' => __( 'English (New Zealand)', 'bogo' ),
48 'en_US' => __( 'English (United States)', 'bogo' ),
49 'en_ZA' => __( 'English (South Africa)', 'bogo' ),
50 'eo' => __( 'Esperanto', 'bogo' ),
51 'es_AR' => __( 'Spanish (Argentina)', 'bogo' ),
52 'es_CL' => __( 'Spanish (Chile)', 'bogo' ),
53 'es_CO' => __( 'Spanish (Colombia)', 'bogo' ),
54 'es_CR' => __( 'Spanish (Costa Rica)', 'bogo' ),
55 'es_DO' => __( 'Spanish (Dominican Republic)', 'bogo' ),
56 'es_EC' => __( 'Spanish (Ecuador)', 'bogo' ),
57 'es_ES' => __( 'Spanish (Spain)', 'bogo' ),
58 'es_GT' => __( 'Spanish (Guatemala)', 'bogo' ),
59 'es_MX' => __( 'Spanish (Mexico)', 'bogo' ),
60 'es_PE' => __( 'Spanish (Peru)', 'bogo' ),
61 'es_PR' => __( 'Spanish (Puerto Rico)', 'bogo' ),
62 'es_UY' => __( 'Spanish (Uruguay)', 'bogo' ),
63 'es_VE' => __( 'Spanish (Venezuela)', 'bogo' ),
64 'et' => __( 'Estonian', 'bogo' ),
65 'eu' => __( 'Basque', 'bogo' ),
66 'fa_AF' => __( 'Persian (Afghanistan)', 'bogo' ),
67 'fa_IR' => __( 'Persian', 'bogo' ),
68 'fi' => __( 'Finnish', 'bogo' ),
69 'fr_BE' => __( 'French (Belgium)', 'bogo' ),
70 'fr_CA' => __( 'French (Canada)', 'bogo' ),
71 'fr_FR' => __( 'French (France)', 'bogo' ),
72 'fur' => __( 'Friulian', 'bogo' ),
73 'fy' => __( 'Frisian', 'bogo' ),
74 'gd' => __( 'Scottish Gaelic', 'bogo' ),
75 'gl_ES' => __( 'Galician', 'bogo' ),
76 'gu' => __( 'Gujarati', 'bogo' ),
77 'haz' => __( 'Hazaragi', 'bogo' ),
78 'he_IL' => __( 'Hebrew', 'bogo' ),
79 'hi_IN' => __( 'Hindi', 'bogo' ),
80 'hr' => __( 'Croatian', 'bogo' ),
81 'hsb' => __( 'Upper Sorbian', 'bogo' ),
82 'hu_HU' => __( 'Hungarian', 'bogo' ),
83 'hy' => __( 'Armenian', 'bogo' ),
84 'id_ID' => __( 'Indonesian', 'bogo' ),
85 'is_IS' => __( 'Icelandic', 'bogo' ),
86 'it_IT' => __( 'Italian', 'bogo' ),
87 'ja' => __( 'Japanese', 'bogo' ),
88 'jv_ID' => __( 'Javanese', 'bogo' ),
89 'ka_GE' => __( 'Georgian', 'bogo' ),
90 'kab' => __( 'Kabyle', 'bogo' ),
91 'kk' => __( 'Kazakh', 'bogo' ),
92 'km' => __( 'Khmer', 'bogo' ),
93 'kn' => __( 'Kannada', 'bogo' ),
94 'ko_KR' => __( 'Korean', 'bogo' ),
95 'lo' => __( 'Lao', 'bogo' ),
96 'lt_LT' => __( 'Lithuanian', 'bogo' ),
97 'lv' => __( 'Latvian', 'bogo' ),
98 'mk_MK' => __( 'Macedonian', 'bogo' ),
99 'ml_IN' => __( 'Malayalam', 'bogo' ),
100 'mn' => __( 'Mongolian', 'bogo' ),
101 'mr' => __( 'Marathi', 'bogo' ),
102 'ms_MY' => __( 'Malay', 'bogo' ),
103 'my_MM' => __( 'Myanmar (Burmese)', 'bogo' ),
104 'nb_NO' => __( 'Norwegian (Bokmål)', 'bogo' ),
105 'ne_NP' => __( 'Nepali', 'bogo' ),
106 'nl_BE' => __( 'Dutch (Belgium)', 'bogo' ),
107 'nl_NL' => __( 'Dutch', 'bogo' ),
108 'nl_NL_formal' => __( 'Dutch (Formal)', 'bogo' ),
109 'nn_NO' => __( 'Norwegian (Nynorsk)', 'bogo' ),
110 'oci' => __( 'Occitan', 'bogo' ),
111 'pa_IN' => __( 'Panjabi (India)', 'bogo' ),
112 'pl_PL' => __( 'Polish', 'bogo' ),
113 'ps' => __( 'Pashto', 'bogo' ),
114 'pt_AO' => __( 'Portuguese (Angola)', 'bogo' ),
115 'pt_BR' => __( 'Portuguese (Brazil)', 'bogo' ),
116 'pt_PT' => __( 'Portuguese (Portugal)', 'bogo' ),
117 'pt_PT_ao90' => __( 'Portuguese (Portugal, AO90)', 'bogo' ),
118 'rhg' => __( 'Rohingya', 'bogo' ),
119 'ro_RO' => __( 'Romanian', 'bogo' ),
120 'ru_RU' => __( 'Russian', 'bogo' ),
121 'sah' => __( 'Sakha', 'bogo' ),
122 'si_LK' => __( 'Sinhala', 'bogo' ),
123 'sk_SK' => __( 'Slovak', 'bogo' ),
124 'skr' => __( 'Saraiki', 'bogo' ),
125 'sl_SI' => __( 'Slovenian', 'bogo' ),
126 'snd' => __( 'Sindhi', 'bogo' ),
127 'sq' => __( 'Albanian', 'bogo' ),
128 'sr_RS' => __( 'Serbian', 'bogo' ),
129 'sv_SE' => __( 'Swedish', 'bogo' ),
130 'sw' => __( 'Swahili', 'bogo' ),
131 'szl' => __( 'Silesian', 'bogo' ),
132 'ta_IN' => __( 'Tamil', 'bogo' ),
133 'ta_LK' => __( 'Tamil (Sri Lanka)', 'bogo' ),
134 'tah' => __( 'Tahitian', 'bogo' ),
135 'te' => __( 'Telugu', 'bogo' ),
136 'th' => __( 'Thai', 'bogo' ),
137 'tl' => __( 'Tagalog', 'bogo' ),
138 'tr_TR' => __( 'Turkish', 'bogo' ),
139 'tt_RU' => __( 'Tatar', 'bogo' ),
140 'ug_CN' => __( 'Uighur', 'bogo' ),
141 'uk' => __( 'Ukrainian', 'bogo' ),
142 'ur' => __( 'Urdu', 'bogo' ),
143 'uz_UZ' => __( 'Uzbek', 'bogo' ),
144 'vi' => __( 'Vietnamese', 'bogo' ),
145 'zh_CN' => __( 'Chinese (China)', 'bogo' ),
146 'zh_HK' => __( 'Chinese (Hong Kong)', 'bogo' ),
147 'zh_TW' => __( 'Chinese (Taiwan)', 'bogo' ),
148 );
149
150 $textdomain_loaded = is_textdomain_loaded( 'bogo' ) && ! is_locale_switched();
151
152 asort( $languages, SORT_STRING );
153
154 return apply_filters( 'bogo_languages', $languages );
155 }
156
157
158 /**
159 * Returns the language name corresponding to the specified locale code.
160 *
161 * @param string $locale Locale code.
162 */
163 function bogo_get_language( $locale ) {
164 $languages = bogo_languages();
165
166 if ( isset( $languages[$locale] ) ) {
167 $language = $languages[$locale];
168 } else {
169 $language = false;
170 }
171
172 return apply_filters( 'bogo_get_language', $language, $locale );
173 }
174
175
176 /**
177 * Returns the language native name corresponding to the specified locale code.
178 *
179 * @link http://api.wordpress.org/translations/core/1.0/
180 *
181 * @param string $locale Locale code.
182 */
183 function bogo_get_language_native_name( $locale ) {
184 $native_names = array(
185 'af' => 'Afrikaans',
186 'am' => 'አማርኛ',
187 'ar' => 'العربية',
188 'arg' => 'Aragonés',
189 'ary' => 'العربية ال�
190 غربية',
191 'as' => '�
192 সমীয়া',
193 'az' => 'Azərbaycan dili',
194 'azb' => 'گؤنئی آذربایجان',
195 'bel' => 'Беларуская мова',
196 'bg_BG' => 'Български',
197 'bn_BD' => 'বাংলা',
198 'bo' => 'བོད་ཡིག',
199 'bs_BA' => 'Bosanski',
200 'ca' => 'Català',
201 'ceb' => 'Cebuano',
202 'ckb' => 'كوردی‎',
203 'cs_CZ' => 'Čeština',
204 'cy' => 'Cymraeg',
205 'da_DK' => 'Dansk',
206 'de_AT' => 'Deutsch (Österreich)',
207 'de_CH' => 'Deutsch (Schweiz)',
208 'de_CH_informal' => 'Deutsch (Schweiz, Du)',
209 'de_DE' => 'Deutsch',
210 'de_DE_formal' => 'Deutsch (Sie)',
211 'dsb' => 'Dolnoserbšćina',
212 'dzo' => 'རྫོང་ཁ',
213 'el' => 'Ελληνικά',
214 'en_AU' => 'English (Australia)',
215 'en_CA' => 'English (Canada)',
216 'en_GB' => 'English (UK)',
217 'en_NZ' => 'English (New Zealand)',
218 'en_US' => 'English (United States)',
219 'en_ZA' => 'English (South Africa)',
220 'eo' => 'Esperanto',
221 'es_AR' => 'Español de Argentina',
222 'es_CL' => 'Español de Chile',
223 'es_CO' => 'Español de Colombia',
224 'es_CR' => 'Español de Costa Rica',
225 'es_DO' => 'Español de República Dominicana',
226 'es_EC' => 'Español de Ecuador',
227 'es_ES' => 'Español',
228 'es_GT' => 'Español de Guatemala',
229 'es_MX' => 'Español de México',
230 'es_PE' => 'Español de Perú',
231 'es_PR' => 'Español de Puerto Rico',
232 'es_UY' => 'Español de Uruguay',
233 'es_VE' => 'Español de Venezuela',
234 'et' => 'Eesti',
235 'eu' => 'Euskara',
236 'fa_AF' => '(فارسی (افغانستان',
237 'fa_IR' => 'فارسی',
238 'fi' => 'Suomi',
239 'fr_BE' => 'Français de Belgique',
240 'fr_CA' => 'Français du Canada',
241 'fr_FR' => 'Français',
242 'fur' => 'Friulian',
243 'fy' => 'Frysk',
244 'gd' => 'Gàidhlig',
245 'gl_ES' => 'Galego',
246 'gu' => 'ગુજરાતી',
247 'haz' => 'هزاره گی',
248 'he_IL' => 'עִבְרִית',
249 'hi_IN' => 'हिन्दी',
250 'hr' => 'Hrvatski',
251 'hsb' => 'Hornjoserbšćina',
252 'hu_HU' => 'Magyar',
253 'hy' => 'Հայերեն',
254 'id_ID' => 'Bahasa Indonesia',
255 'is_IS' => 'Íslenska',
256 'it_IT' => 'Italiano',
257 'ja' => '日本語',
258 'jv_ID' => 'Basa Jawa',
259 'ka_GE' => 'ქართული',
260 'kab' => 'Taqbaylit',
261 'kk' => 'Қазақ тілі',
262 'km' => 'ភាសាខ្មែរ',
263 'kn' => 'ಕನ್ನಡ',
264 'ko_KR' => '한국어',
265 'lo' => 'ພາສາລາວ',
266 'lt_LT' => 'Lietuvių kalba',
267 'lv' => 'Latviešu valoda',
268 'mk_MK' => 'Македонски јазик',
269 'ml_IN' => 'മലയാളം',
270 'mn' => 'Монгол',
271 'mr' => 'मराठी',
272 'ms_MY' => 'Bahasa Melayu',
273 'my_MM' => 'ဗမာ�
274 ',
275 'nb_NO' => 'Norsk bokmål',
276 'ne_NP' => 'नेपाली',
277 'nl_BE' => 'Nederlands (België)',
278 'nl_NL' => 'Nederlands',
279 'nl_NL_formal' => 'Nederlands (Formeel)',
280 'nn_NO' => 'Norsk nynorsk',
281 'oci' => 'Occitan',
282 'pa_IN' => 'ਪੰਜਾਬੀ',
283 'pl_PL' => 'Polski',
284 'ps' => 'پښتو',
285 'pt_AO' => 'Português de Angola',
286 'pt_BR' => 'Português do Brasil',
287 'pt_PT' => 'Português',
288 'pt_PT_ao90' => 'Português (AO90)',
289 'rhg' => 'Ruáinga',
290 'ro_RO' => 'Română',
291 'ru_RU' => 'Русский',
292 'sah' => 'Са�
293 алыы',
294 'si_LK' => 'සිංහල',
295 'sk_SK' => 'Slovenčina',
296 'skr' => 'سرائیکی',
297 'sl_SI' => 'Slovenščina',
298 'snd' => 'سنڌي',
299 'sq' => 'Shqip',
300 'sr_RS' => 'Српски језик',
301 'sv_SE' => 'Svenska',
302 'sw' => 'Kiswahili',
303 'szl' => 'Ślōnskŏ gŏdka',
304 'ta_IN' => 'தமிழ்',
305 'ta_LK' => 'தமிழ்',
306 'tah' => 'Reo Tahiti',
307 'te' => 'తెలుగు',
308 'th' => 'ไทย',
309 'tl' => 'Tagalog',
310 'tr_TR' => 'Türkçe',
311 'tt_RU' => 'Татар теле',
312 'ug_CN' => 'ئۇيغۇرچە',
313 'uk' => 'Українська',
314 'ur' => 'اردو',
315 'uz_UZ' => 'O‘zbekcha',
316 'vi' => 'Tiếng Việt',
317 'zh_CN' => '简体中文',
318 'zh_HK' => '香港中文',
319 'zh_TW' => '繁體中文',
320 );
321
322 if ( isset( $native_names[$locale] ) ) {
323 $native_name = $native_names[$locale];
324 } else {
325 $native_name = false;
326 }
327
328 return apply_filters( 'bogo_get_language_native_name',
329 $native_name, $locale
330 );
331 }
332
333
334 /**
335 * Returns the ISO 3166-1 alpha-2 country code corresponding to
336 * the specified locale code.
337 *
338 * @link https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
339 *
340 * @param string $locale Locale code.
341 */
342 function bogo_get_country_code( $locale ) {
343 $special_cases = array(
344 'am' => 'ET', // Amharic => Ethiopia
345 'ary' => 'MA', // Moroccan Arabic => Morocco
346 'az' => 'AZ', // Azerbaijani => Azerbaijan
347 'bel' => 'BY', // Belarusian => Belarus
348 'dzo' => 'BT', // Dzongkha => Bhutan
349 'el' => 'GR', // Greek => Greece
350 'et' => 'EE', // Estonian => Estonia
351 'fi' => 'FI', // Finnish => Finland
352 'hr' => 'HR', // Croatian => Croatia
353 'hy' => 'AM', // Armenian => Armenia
354 'ja' => 'JP', // Japanese => Japan
355 'kk' => 'KZ', // Kazakh => Kazakhstan
356 'km' => 'KH', // Khmer => Cambodia
357 'lo' => 'LA', // Lao => Laos
358 'lv' => 'LV', // Latvian => Latvia
359 'mn' => 'MN', // Mongolian => Mongolia
360 'ps' => 'AF', // Pashto => Afghanistan
361 'sq' => 'AL', // Albanian => Albania
362 'th' => 'TH', // Thai => Thailand
363 'tl' => 'PH', // Tagalog => Philippines
364 'uk' => 'UA', // Ukrainian => Ukraine
365 'ur' => 'PK', // Urdu => Pakistan
366 'vi' => 'VN', // Vietnamese => Vietnam
367 );
368
369 if ( preg_match( '/^[a-z]+_([A-Z]{2})/', $locale, $matches ) ) {
370 $country_code = $matches[1];
371 } elseif ( isset( $special_cases[$locale] ) ) {
372 $country_code = $special_cases[$locale];
373 } else {
374 $country_code = false;
375 }
376
377 return apply_filters( 'bogo_get_country_code', $country_code, $locale );
378 }
379
380
381 /**
382 * Retrieves the default locale for the site.
383 */
384 function bogo_get_default_locale() {
385 static $locale = '';
386
387 if ( ! empty( $locale ) ) {
388 return $locale;
389 }
390
391 if ( defined( 'WPLANG' ) ) {
392 $locale = WPLANG;
393 }
394
395 if ( is_multisite() ) {
396 if ( wp_installing() or false === $ms_locale = get_option( 'WPLANG' ) ) {
397 $ms_locale = get_site_option( 'WPLANG' );
398 }
399
400 if ( $ms_locale !== false ) {
401 $locale = $ms_locale;
402 }
403 } else {
404 $db_locale = get_option( 'WPLANG' );
405
406 if ( $db_locale !== false ) {
407 $locale = $db_locale;
408 }
409 }
410
411 if ( ! empty( $locale ) ) {
412 return $locale;
413 }
414
415 return 'en_US';
416 }
417
418
419 /**
420 * Returns true if the specified locale is the default locale.
421 *
422 * @param string $locale Locale code.
423 */
424 function bogo_is_default_locale( $locale ) {
425 $default_locale = bogo_get_default_locale();
426
427 return ! empty( $locale ) && $locale === bogo_get_default_locale();
428 }
429
430
431 /**
432 * Returns true if the en_US locale is deactivated on this site.
433 */
434 function bogo_is_enus_deactivated() {
435 if ( bogo_is_default_locale( 'en_US' ) ) {
436 return false;
437 }
438
439 return (bool) bogo_get_prop( 'enus_deactivated' );
440 }
441
442
443 /**
444 * Retrieves locale codes active on this site.
445 */
446 function bogo_available_locales( $args = '' ) {
447 $defaults = array(
448 'exclude' => array(),
449 'exclude_enus_if_inactive' => true,
450 'current_user_can_access' => false,
451 );
452
453 $args = wp_parse_args( $args, $defaults );
454
455 static $installed_locales = array();
456
457 if ( empty( $installed_locales ) ) {
458 $installed_locales = get_available_languages();
459 $installed_locales[] = bogo_get_default_locale();
460 $installed_locales[] = 'en_US';
461 }
462
463 $available_locales = $installed_locales;
464
465 if (
466 $args['current_user_can_access'] and
467 ! current_user_can( 'bogo_access_all_locales' )
468 ) {
469 $user_accessible_locales = bogo_get_user_accessible_locales(
470 get_current_user_id()
471 );
472
473 $available_locales = array_intersect(
474 $available_locales,
475 $user_accessible_locales
476 );
477 }
478
479 if ( ! empty( $args['exclude'] ) ) {
480 $available_locales = array_diff(
481 $available_locales,
482 (array) $args['exclude']
483 );
484 }
485
486 if ( $args['exclude_enus_if_inactive'] and bogo_is_enus_deactivated() ) {
487 $available_locales = array_diff(
488 $available_locales,
489 array( 'en_US' )
490 );
491 }
492
493 return array_unique( array_filter( $available_locales ) );
494 }
495
496
497 /**
498 * Retrieves languages active on this site.
499 */
500 function bogo_available_languages( $args = '' ) {
501 $defaults = array(
502 'exclude' => array(),
503 'orderby' => 'key',
504 'order' => 'ASC',
505 'exclude_enus_if_inactive' => true,
506 'current_user_can_access' => false,
507 'short_name' => true,
508 );
509
510 $args = wp_parse_args( $args, $defaults );
511
512 $langs = array();
513
514 $available_locales = bogo_available_locales( $args );
515
516 foreach ( $available_locales as $locale ) {
517 $lang = (string) bogo_get_language( $locale );
518
519 if ( $args['short_name'] and bogo_locale_is_alone( $locale ) ) {
520 $lang = bogo_get_short_name( $lang );
521 }
522
523 $lang = trim( $lang );
524 $langs[$locale] = empty( $lang ) ? "[$locale]" : $lang;
525 }
526
527 if ( 'value' === $args['orderby'] ) {
528 natcasesort( $langs );
529
530 if ( 'DESC' === $args['order'] ) {
531 $langs = array_reverse( $langs );
532 }
533 } else {
534 if ( 'DESC' === $args['order'] ) {
535 krsort( $langs );
536 } else {
537 ksort( $langs );
538 }
539 }
540
541 $langs = apply_filters( 'bogo_available_languages', $langs, $args );
542
543 return $langs;
544 }
545
546
547 /**
548 * Returns true if the specified locale is active on this site.
549 *
550 * @param string $locale Locale code.
551 */
552 function bogo_is_available_locale( $locale ) {
553 if ( empty( $locale ) ) {
554 return false;
555 }
556
557 static $available_locales = array();
558
559 if ( empty( $available_locales ) ) {
560 $available_locales = bogo_available_locales();
561 }
562
563 return in_array( $locale, $available_locales );
564 }
565
566
567 /**
568 * Filters locales list.
569 */
570 function bogo_filter_locales( $locales, $filter = 'available' ) {
571 return array_intersect( (array) $locales, bogo_available_locales() );
572 }
573
574
575 /**
576 * Retrieves the language tag for the specified locale.
577 *
578 * @link https://www.ietf.org/rfc/bcp/bcp47.txt
579 *
580 * @param string $locale Locale code.
581 */
582 function bogo_language_tag( $locale ) {
583 $tag = preg_replace( '/[^0-9a-zA-Z]+/', '-', $locale );
584 $tag = trim( $tag, '-' );
585
586 $tag = explode( '-', $tag );
587 $tag = array_slice( $tag, 0, 2 ); // de-DE-formal => de-DE
588 $tag = implode( '-', $tag );
589
590 return apply_filters( 'bogo_language_tag', $tag, $locale );
591 }
592
593
594 /**
595 * Retrieves the language slug for the specified locale.
596 *
597 * @param string $locale Locale code.
598 */
599 function bogo_lang_slug( $locale ) {
600 $tag = bogo_language_tag( $locale );
601 $slug = $tag;
602
603 if ( false !== $pos = strpos( $tag, '-' ) ) {
604 $slug = substr( $tag, 0, $pos );
605 }
606
607 $variations = preg_grep( '/^' . $slug . '/',
608 bogo_available_locales()
609 );
610
611 if ( 1 < count( $variations ) ) {
612 $slug = $tag;
613 }
614
615 return apply_filters( 'bogo_lang_slug', $slug, $locale );
616 }
617
618
619 /**
620 * Returns true if the specified locale has no sibling active on this site.
621 *
622 * @param string $locale Locale code.
623 */
624 function bogo_locale_is_alone( $locale ) {
625 $tag = bogo_language_tag( $locale );
626
627 if ( false === strpos( $tag, '-' ) ) {
628 return true;
629 }
630
631 $slug = bogo_lang_slug( $locale );
632
633 return strlen( $slug ) < strlen( $tag );
634 }
635
636
637 /**
638 * Retrieves the short version of the specified language name.
639 */
640 function bogo_get_short_name( $orig_name ) {
641 $short_name = $orig_name = (string) $orig_name;
642
643 $langs_with_variants = array(
644 '中文',
645 'Français',
646 'Português',
647 'Español',
648 );
649
650 foreach ( $langs_with_variants as $lang ) {
651 if ( false !== strpos( $orig_name, $lang ) ) {
652 $short_name = $lang;
653 break;
654 }
655 }
656
657 if ( preg_match( '/^([^()]+)/', $short_name, $matches ) ) {
658 $short_name = $matches[1];
659 }
660
661 $short_name = apply_filters( 'bogo_get_short_name', $short_name, $orig_name );
662
663 return trim( $short_name );
664 }
665
666
667 /**
668 * Retrieves the regular expression pattern that matches
669 * all available language slugs on this site.
670 */
671 function bogo_get_lang_regex() {
672 $langs = array_map( 'bogo_lang_slug', bogo_available_locales() );
673 $langs = array_filter( $langs );
674
675 if ( empty( $langs ) ) {
676 return '';
677 }
678
679 return '(' . implode( '|', $langs ) . ')';
680 }
681
682
683 /**
684 * Retrieves the locale that is active on this site and
685 * closest to the specified locale.
686 *
687 * @param string $locale_orig Locale code.
688 * @return string|bool Locale code. False if there is no close locale.
689 */
690 function bogo_get_closest_locale( $locale_orig ) {
691 $locale_orig = strtolower( $locale_orig );
692 $locale_pattern = '/^([a-z]{2,3})(?:[_-]([a-z]{2})(?:[_-]([a-z0-9]+))?)?$/';
693
694 if ( ! preg_match( $locale_pattern, $locale_orig, $matches ) ) {
695 return false;
696 }
697
698 $language_code = $matches[1];
699 $region_code = isset( $matches[2] ) ? $matches[2] : '';
700 $variant_code = isset( $matches[3] ) ? $matches[3] : '';
701
702 $locales = bogo_available_locales();
703
704 if ( $variant_code and $region_code ) {
705 $locale = $language_code
706 . '_' . strtoupper( $region_code )
707 . '_' . $variant_code;
708
709 if ( false !== array_search( $locale, $locales ) ) {
710 return $locale;
711 }
712 }
713
714 if ( $region_code ) {
715 $locale = $language_code
716 . '_' . strtoupper( $region_code );
717
718 if ( false !== array_search( $locale, $locales ) ) {
719 return $locale;
720 }
721 }
722
723 $locale = $language_code;
724
725 if ( false !== array_search( $locale, $locales ) ) {
726 return $locale;
727 }
728
729 if ( $matches = preg_grep( "/^{$locale}_/", $locales ) ) {
730 return array_shift( $matches );
731 }
732
733 return false;
734 }
735
736
737 /**
738 * Returns an ordered list of language tags based on the client
739 * language preference.
740 *
741 * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
742 *
743 * @return array Locale codes of languages the browser accepts.
744 */
745 function bogo_http_accept_languages() {
746 $languages = array();
747
748 if ( ! isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) {
749 return $languages;
750 }
751
752 foreach ( explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) as $lang ) {
753 $lang = trim( strtolower( $lang ) );
754
755 if ( preg_match( '/^([a-z-]+)(?:;q=([0-9.]+))?$/', $lang, $matches ) ) {
756 $language_tag = $matches[1];
757 $qvalue = isset( $matches[2] ) ? 0 + $matches[2] : 1;
758
759 if (
760 preg_match( '/^([a-z]{2})(?:-([a-z]{2}))?$/', $language_tag, $matches )
761 ) {
762 $language_tag = $matches[1];
763
764 if ( isset( $matches[2] ) ) {
765 $language_tag .= '_' . strtoupper( $matches[2] );
766 }
767
768 $languages[$language_tag] = $qvalue;
769 }
770 }
771 }
772
773 natsort( $languages );
774
775 return array_reverse( array_keys( $languages ) );
776 }
777
778
779 /**
780 * A wrapper function of bogo_get_url_with_lang().
781 */
782 function bogo_url( $url = '', $locale = '' ) {
783 if ( ! $locale ) {
784 $locale = determine_locale();
785 }
786
787 $args = array(
788 'using_permalinks' => (bool) get_option( 'permalink_structure' ),
789 );
790
791 return bogo_get_url_with_lang( $url, $locale, $args );
792 }
793
794
795 /**
796 * Returns a URL that is a different language version of the original URL.
797 *
798 * @param string $url The original URL.
799 * @param string $locale Locale code.
800 * @param string|array $args Options.
801 * @return string The result URL.
802 */
803 function bogo_get_url_with_lang( $url = '', $locale = '', $args = '' ) {
804 global $wp_rewrite;
805
806 $defaults = array(
807 'using_permalinks' => true,
808 );
809
810 $args = wp_parse_args( $args, $defaults );
811
812 if ( ! $url ) {
813 if ( ! $url = redirect_canonical( $url, false ) ) {
814 $url = is_ssl() ? 'https://' : 'http://';
815 $url .= $_SERVER['HTTP_HOST'];
816 $url .= $_SERVER['REQUEST_URI'];
817 }
818
819 if ( $frag = strstr( $url, '#' ) ) {
820 $url = substr( $url, 0, - strlen( $frag ) );
821 }
822
823 if ( $query = wp_parse_url( $url, PHP_URL_QUERY ) ) {
824 parse_str( $query, $query_vars );
825
826 foreach ( array_keys( $query_vars ) as $qv ) {
827 if ( ! get_query_var( $qv ) ) {
828 $url = remove_query_arg( $qv, $url );
829 }
830 }
831 }
832 }
833
834 $default_locale = bogo_get_default_locale();
835
836 if ( ! $locale ) {
837 $locale = $default_locale;
838 }
839
840 $use_implicit_lang = apply_filters( 'bogo_use_implicit_lang', true );
841
842 $lang_slug = ( $use_implicit_lang && $locale === $default_locale )
843 ? ''
844 : bogo_lang_slug( $locale );
845
846 $url = remove_query_arg( 'lang', $url );
847
848 if ( ! $args['using_permalinks'] ) {
849 if ( $lang_slug ) {
850 $url = add_query_arg( array( 'lang' => $lang_slug ), $url );
851 }
852
853 return $url;
854 }
855
856 $tail_slashed = str_ends_with( $url, '/' );
857
858 $home = set_url_scheme( get_option( 'home' ) );
859 $home = untrailingslashit( $home );
860
861 if ( $wp_rewrite->using_index_permalinks() ) {
862 $pattern = '#^'
863 . preg_quote( $home )
864 . '(?:/' . preg_quote( $wp_rewrite->index ) . ')?'
865 . '(?:/' . bogo_get_lang_regex() . '(?![0-9A-Za-z%_-]))?'
866 . '#';
867
868 $replacement = $home . '/' . $wp_rewrite->index;
869
870 if ( $lang_slug ) {
871 $replacement .= '/' . $lang_slug;
872 }
873
874 $url = preg_replace(
875 $pattern,
876 $replacement,
877 $url
878 );
879
880 $url = preg_replace(
881 '#' . preg_quote( $wp_rewrite->index ) . '/?$#',
882 '',
883 $url
884 );
885
886 } else {
887 $pattern = '#^'
888 . preg_quote( $home )
889 . '(?:/' . bogo_get_lang_regex() . '(?![0-9A-Za-z%_-]))?'
890 . '#';
891
892 $replacement = $home;
893
894 if ( $lang_slug ) {
895 $replacement .= '/' . $lang_slug;
896 }
897
898 $url = preg_replace(
899 $pattern,
900 $replacement,
901 $url
902 );
903 }
904
905 if ( ! $tail_slashed ) {
906 $url = untrailingslashit( $url );
907 }
908
909 return $url;
910 }
911
912
913 /**
914 * Determines the language from the specified URL.
915 *
916 * @param string $url URL.
917 */
918 function bogo_get_lang_from_url( $url = '' ) {
919 if ( ! $url ) {
920 $url = is_ssl() ? 'https://' : 'http://';
921 $url .= $_SERVER['HTTP_HOST'];
922 $url .= $_SERVER['REQUEST_URI'];
923 }
924
925 if ( $frag = strstr( $url, '#' ) ) {
926 $url = substr( $url, 0, - strlen( $frag ) );
927 }
928
929 $home = set_url_scheme( get_option( 'home' ) );
930 $home = trailingslashit( $home );
931
932 $available_languages = array_map( 'bogo_lang_slug',
933 bogo_available_locales()
934 );
935
936 $regex = '#^'
937 . preg_quote( $home )
938 . '(' . implode( '|', $available_languages ) . ')'
939 . '/#';
940
941 if ( preg_match( $regex, trailingslashit( $url ), $matches ) ) {
942 return $matches[1];
943 }
944
945 if ( $query = wp_parse_url( $url, PHP_URL_QUERY ) ) {
946 parse_str( $query, $query_vars );
947
948 if (
949 isset( $query_vars['lang'] ) and
950 in_array( $query_vars['lang'], $available_languages, true )
951 ) {
952 return $query_vars['lang'];
953 }
954 }
955
956 return false;
957 }
958