first commit

This commit is contained in:
2023-09-12 21:41:04 +02:00
commit 3361a7f053
13284 changed files with 2116755 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
<?php
interface IWPML_ST_Translations_File {
/**
* @return WPML_ST_Translations_File_Translation[]
*/
public function get_translations();
}

View File

@@ -0,0 +1,78 @@
<?php
class WPML_ST_Translations_File_JED implements IWPML_ST_Translations_File {
const EMPTY_PROPERTY_NAME = '_empty_';
const DECODED_EOT_CHAR = '"\u0004"';
const PLURAL_SUFFIX_PATTERN = ' [plural %d]';
/** @var string $filepath */
private $filepath;
/** @var string $decoded_eot_char */
private $decoded_eot_char;
public function __construct( $filepath ) {
$this->filepath = $filepath;
$this->decoded_eot_char = json_decode( self::DECODED_EOT_CHAR );
}
/**
* @return WPML_ST_Translations_File_Translation[]
*/
public function get_translations() {
$translations = array();
$data = json_decode( file_get_contents( $this->filepath ) );
if ( isset( $data->locale_data->messages ) ) {
$entries = (array) $data->locale_data->messages;
unset( $entries[ self::EMPTY_PROPERTY_NAME ] );
foreach ( $entries as $str => $str_data ) {
$str_data = (array) $str_data;
if ( ! isset( $str_data[0] ) ) {
continue;
}
list( $str, $context ) = $this->get_string_and_context( $str );
$count_translations = count( $str_data );
$translations[] = new WPML_ST_Translations_File_Translation( $str, $str_data[0], $context );
if ( $count_translations > 1 ) {
/**
* The strings coming after the first element are the plural translations.
* As we don't have the information about the original plural in the JED file,
* we will add a suffix to the original singular string.
*/
for ( $i = 1; $i < $count_translations; $i++ ) {
$plural_str = $str . sprintf( self::PLURAL_SUFFIX_PATTERN, $i );
$translations[] = new WPML_ST_Translations_File_Translation( $plural_str, $str_data[ $i ], $context );
}
}
}
}
return $translations;
}
/**
* The context is the first part of the string separated with the EOT char (\u0004)
*
* @param string $string
*
* @return array
*/
private function get_string_and_context( $string ) {
$context = '';
$parts = explode( $this->decoded_eot_char, $string );
if ( count( $parts ) > 1 ) {
$context = $parts[0];
$string = $parts[1];
}
return array( $string, $context );
}
}

View File

@@ -0,0 +1,146 @@
<?php
class WPML_ST_Translations_File_Locale {
const PATTERN_SEARCH_LANG_JSON = '#DOMAIN_PLACEHOLDER(LOCALES_PLACEHOLDER)-[-_a-z0-9]+\.json$#i';
/** @var \SitePress */
private $sitepress;
/** @var \WPML_Locale */
private $locale;
/**
* @param SitePress $sitepress
* @param WPML_Locale $locale
*/
public function __construct( SitePress $sitepress, WPML_Locale $locale ) {
$this->sitepress = $sitepress;
$this->locale = $locale;
}
/**
* It extracts language code from mo file path, examples
* '/wp-content/languages/admin-pl_PL.mo' => 'pl'
* '/wp-content/plugins/sitepress/sitepress-hr.mo' => 'hr'
* '/wp-content/languages/fr_FR-4gh5e6d3g5s33d6gg51zas2.json' => 'fr_FR'
* '/wp-content/plugins/my-plugin/languages/-my-plugin-fr_FR-my-handler.json' => 'fr_FR'
*
* @param string $filepath
* @param string $domain
*
* @return string
*/
public function get( $filepath, $domain ) {
switch ( $this->get_extension( $filepath ) ) {
case 'mo':
return $this->get_from_mo_file( $filepath );
case 'json':
return $this->get_from_json_file( $filepath, $domain );
default:
return '';
}
}
/**
* @param string $filepath
*
* @return string|null
*/
private function get_extension( $filepath ) {
return wpml_collect( pathinfo( $filepath ) )->get( 'extension', null );
}
/**
* @param string $filepath
*
* @return string
*/
private function get_from_mo_file( $filepath ) {
return $this->get_locales()
->first(
function ( $locale ) use ( $filepath ) {
return strpos( $filepath, $locale . '.mo' );
},
''
);
}
/**
* @param string $filepath
* @param string $domain
*
* @return string
*/
private function get_from_json_file( $filepath, $domain ) {
$original_domain = $this->get_original_domain_for_json( $filepath, $domain );
$domain_replace = 'default' === $original_domain ? '' : $original_domain . '-';
$locales = $this->get_locales()->implode( '|' );
$searches['native-file'] = '#' . $domain_replace . '(' . $locales . ')-[-_a-z0-9]+\.json$#i';
$searches['wpml-file'] = '#' . $domain . '-(' . $locales . ').json#i';
foreach ( $searches as $search ) {
if ( preg_match( $search, $filepath, $matches ) && isset( $matches[1] ) ) {
return $matches[1];
}
}
return '';
}
/**
* We need the original domain name to refine the regex pattern.
* Unfortunately, the domain is concatenated with the script handler
* in the import queue table. That's why we need to retrieve the original
* domain from the registration domain and the filepath.
*
* @param string $filepath
* @param string $domain
*
* @return string
*/
private function get_original_domain_for_json( $filepath, $domain ) {
$filename = basename( $filepath );
/**
* Case of WP JED files:
* - filename: de_DE-73f9977556584a369800e775b48f3dbe.json
* - domain: default-some-script
* => original_domain: default
*/
if ( 0 === strpos( $domain, 'default' ) && 0 !== strpos( $filename, 'default' ) ) {
return 'default';
}
/**
* Case of 3rd part JED files:
* - filename: plugin-domain-de_DE-script-handler.json
* - domain: plugin-domain-script-handler
* => original_domain: plugin-domain
*/
$filename_parts = explode( '-', $filename );
$domain_parts = explode( '-', $domain );
$original_domain_parts = array();
foreach ( $domain_parts as $i => $part ) {
if ( $filename_parts[ $i ] !== $part ) {
break;
}
$original_domain_parts[] = $part;
}
return implode( '-', $original_domain_parts );
}
/**
* @return \WPML\Collect\Support\Collection
*/
private function get_locales() {
return \wpml_collect( $this->sitepress->get_active_languages() )
->keys()
->map( [ $this->locale, 'get_locale' ] );
}
}

View File

@@ -0,0 +1,38 @@
<?php
class WPML_ST_Translations_File_MO implements IWPML_ST_Translations_File {
/** @var string $filepath */
private $filepath;
/**
* @param string $filepath
*/
public function __construct( $filepath ) {
$this->filepath = $filepath;
}
/**
* @return WPML_ST_Translations_File_Translation[]
*/
public function get_translations() {
$translations = array();
$mo = new MO();
$pomo_reader = new POMO_CachedFileReader( $this->filepath );
$mo->import_from_reader( $pomo_reader );
foreach ( $mo->entries as $str => $v ) {
$str = str_replace( "\n", '\n', $v->singular );
$translations[] = new WPML_ST_Translations_File_Translation( $str, $v->translations[0], $v->context );
if ( $v->is_plural ) {
$str = str_replace( "\n", '\n', $v->plural );
$translation = ! empty( $v->translations[1] ) ? $v->translations[1] : $v->translations[0];
$translations[] = new WPML_ST_Translations_File_Translation( $str, $translation, $v->context );
}
}
return $translations;
}
}