Localevalidator
**Site relevance:** Antichrist.net
**Memory type:** plugin source memory
**Source path:** Antichrist.net/wp-content/plugins/uaix-locale-router/src/LocaleValidator.php
**Size:** 4 KB
Summary
namespace UAIXLocaleRouter;
Source Preview
This source file is short enough to preview directly on its source-memory page.
<?php
namespace UAIXLocaleRouter;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
final class LocaleValidator {
/**
* Validate a BCP 47 style locale tag.
*
* @param string $tag Locale tag.
* @return bool
*/
public static function is_valid_locale_tag( $tag ) {
$tag = trim( (string) $tag );
return '' !== $tag
&& strlen( $tag ) <= 64
&& (bool) preg_match( '/^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{2,8})*$/', $tag );
}
/**
* Canonicalize a locale tag.
*
* @param string $tag Locale tag.
* @return string
*/
public static function canonicalize_tag( $tag ) {
$tag = str_replace( '_', '-', trim( (string) $tag ) );
if ( '' === $tag ) {
return '';
}
if ( strlen( $tag ) > 64 || ! preg_match( '/^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{2,8})*$/', $tag ) ) {
return '';
}
$parts = array_values( array_filter( explode( '-', $tag ), 'strlen' ) );
if ( empty( $parts ) ) {
return '';
}
$parts[0] = strtolower( $parts[0] );
for ( $index = 1; $index < count( $parts ); $index++ ) {
if ( 4 === strlen( $parts[ $index ] ) && ctype_alpha( $parts[ $index ] ) ) {
$parts[ $index ] = ucfirst( strtolower( $parts[ $index ] ) );
} elseif ( ( 2 === strlen( $parts[ $index ] ) && ctype_alpha( $parts[ $index ] ) ) || ( 3 === strlen( $parts[ $index ] ) && ctype_digit( $parts[ $index ] ) ) ) {
$parts[ $index ] = strtoupper( $parts[ $index ] );
} else {
$parts[ $index ] = strtolower( $parts[ $index ] );
}
}
return implode( '-', $parts );
}
/**
* Determine whether the locale is RTL.
*
* @param string $tag Locale tag.
* @return bool
*/
public static function is_rtl_locale( $tag ) {
$language = strtolower( strtok( self::canonicalize_tag( $tag ), '-' ) );
$rtl = array( 'ar', 'arc', 'fa', 'he', 'ps', 'ur', 'ckb', 'ug', 'yi' );
return in_array( $language, $rtl, true );
}
/**
* Normalize a supported locale record.
*
* @param array $record Locale record.
* @return array
*/
public static function normalize_supported_record( array $record ) {
$tag = isset( $record['tag'] ) ? self::canonicalize_tag( $record['tag'] ) : '';
return array(
'tag' => $tag,
'urlTag' => strtolower( str_replace( '_', '-', $tag ) ),
'language' => isset( $record['language'] ) ? (string) $record['language'] : $tag,
'nativeName' => isset( $record['nativeName'] ) ? (string) $record['nativeName'] : $tag,
'region' => isset( $record['region'] ) ? (string) $record['region'] : self::extract_region( $tag ),
'script' => isset( $record['script'] ) ? (string) $record['script'] : self::extract_script( $tag ),
'isRtl' => isset( $record['isRtl'] ) ? (bool) $record['isRtl'] : self::is_rtl_locale( $tag ),
'enabled' => ! empty( $record['enabled'] ),
'isDefault' => ! empty( $record['isDefault'] ),
'fallback' => isset( $record['fallback'] ) ? self::canonicalize_tag( $record['fallback'] ) : $tag,
'catalogHit' => isset( $record['catalogHit'] ) ? (bool) $record['catalogHit'] : false,
);
}
/**
* Extract a region subtag.
*
* @param string $tag Locale tag.
* @return string
*/
public static function extract_region( $tag ) {
$parts = explode( '-', self::canonicalize_tag( $tag ) );
foreach ( $parts as $index => $part ) {
if ( 0 === $index ) {
continue;
}
if ( ( 2 === strlen( $part ) && ctype_alpha( $part ) ) || ( 3 === strlen( $part ) && ctype_digit( $part ) ) ) {
return strtoupper( $part );
}
}
return '';
}
/**
* Extract a script subtag.
*
* @param string $tag Locale tag.
* @return string
*/
public static function extract_script( $tag ) {
$parts = explode( '-', self::canonicalize_tag( $tag ) );
foreach ( $parts as $index => $part ) {
if ( 0 === $index ) {
continue;
}
if ( 4 === strlen( $part ) && ctype_alpha( $part ) ) {
return ucfirst( strtolower( $part ) );
}
}
return '';
}
}