*/ public const LOCALES = array( 'de' => 'de_DE', 'es' => 'es_ES', ); /** * Text domains and their languages folders. * * @var array */ private static array $domains = array(); /** * Whether the hooks are in place. * * @var bool */ private static bool $hooked = false; /** * Registers a text domain whose translations live in the given folder. * * @param string $domain Text domain. * @param string $path Absolute path of the languages folder. */ public static function add( string $domain, string $path ): void { self::$domains[ $domain ] = untrailingslashit( $path ); if ( ! self::$hooked ) { self::$hooked = true; add_filter( 'plugin_locale', array( self::class, 'filter_locale' ), 10, 2 ); add_filter( 'load_script_translation_file', array( self::class, 'filter_script_file' ), 10, 3 ); add_action( 'init', array( self::class, 'load' ), 0 ); } if ( did_action( 'init' ) ) { self::load_domain( $domain ); } } /** * Maps a WordPress locale to one of the shipped languages, or returns it unchanged. * * @param string $locale Locale such as de_DE_formal or es_MX. */ public static function map( string $locale ): string { $language = strtolower( substr( $locale, 0, 2 ) ); return self::LOCALES[ $language ] ?? $locale; } /** * Uses the shipped language for our own text domains. * * @param string $locale Locale WordPress picked. * @param string $domain Text domain being loaded. */ public static function filter_locale( $locale, $domain ): string { $locale = (string) $locale; return isset( self::$domains[ (string) $domain ] ) ? self::map( $locale ) : $locale; } /** * Points script translations of our domains at the shipped language file. * * @param string|false $file Translation file WordPress looks for. * @param string $handle Script handle. * @param string $domain Text domain. * @return string|false */ public static function filter_script_file( $file, $handle, $domain ) { if ( ! is_string( $file ) || ! isset( self::$domains[ (string) $domain ] ) ) { return $file; } $locale = determine_locale(); $mapped = self::map( $locale ); if ( $mapped === $locale ) { return $file; } return str_replace( '-' . $locale . '-', '-' . $mapped . '-', $file ); } /** * Loads all registered text domains. Hooked to init, priority 0. */ public static function load(): void { foreach ( array_keys( self::$domains ) as $domain ) { self::load_domain( $domain ); } } /** * Loads one text domain from its languages folder. * * @param string $domain Text domain. */ private static function load_domain( string $domain ): void { $locale = self::map( determine_locale() ); if ( ! in_array( $locale, self::LOCALES, true ) ) { return; } $file = self::$domains[ $domain ] . '/' . $domain . '-' . $locale . '.mo'; if ( is_readable( $file ) ) { load_textdomain( $domain, $file, $locale ); } } /** * Path of the folder that holds a domain's script translations. * * @param string $domain Text domain. */ public static function path( string $domain ): string { return self::$domains[ $domain ] ?? ''; } }