PageRenderTime 73ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/wpml-string-translation/inc/functions.php

https://bitbucket.org/acipriani/madeinapulia.com
PHP | 2963 lines | 2343 code | 469 blank | 151 comment | 546 complexity | c25a6991b5a201f95a94d3a846626dd6 MD5 | raw file
Possible License(s): GPL-3.0, MIT, BSD-3-Clause, LGPL-2.1, GPL-2.0, Apache-2.0
  1. <?php
  2. $icl_st_string_translation_statuses = array(
  3. ICL_STRING_TRANSLATION_COMPLETE => __('Translation complete','wpml-string-translation'),
  4. ICL_STRING_TRANSLATION_PARTIAL => __('Partial translation','wpml-string-translation'),
  5. ICL_STRING_TRANSLATION_NEEDS_UPDATE => __('Translation needs update','wpml-string-translation'),
  6. ICL_STRING_TRANSLATION_NOT_TRANSLATED => __('Not translated','wpml-string-translation'),
  7. ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR => __('Waiting for translator','wpml-string-translation')
  8. );
  9. add_action('plugins_loaded', 'icl_st_init');
  10. if(!defined('XMLRPC')){
  11. // called separately for XMLRPC post saves
  12. add_action('save_post', 'icl_st_fix_links_in_strings', 19);
  13. }
  14. //add_filter('xmlrpc_methods','icl_add_custom_xmlrpc_methods');
  15. function icl_st_init(){
  16. global $sitepress_settings, $sitepress, $wpdb, $icl_st_err_str;
  17. if ( $GLOBALS['pagenow'] == 'site-new.php' && isset($_REQUEST['action']) && 'add-site' == $_REQUEST['action'] ) return;
  18. add_action('icl_update_active_languages', 'icl_update_string_status_all');
  19. add_action('update_option_blogname', 'icl_st_update_blogname_actions',5,2);
  20. add_action('update_option_blogdescription', 'icl_st_update_blogdescription_actions',5,2);
  21. if(isset($_GET['icl_action']) && $_GET['icl_action'] == 'view_string_in_page'){
  22. icl_st_string_in_page($_GET['string_id']);
  23. exit;
  24. }
  25. if(isset($_GET['icl_action']) && $_GET['icl_action'] == 'view_string_in_source'){
  26. icl_st_string_in_source($_GET['string_id']);
  27. exit;
  28. }
  29. if ( get_magic_quotes_gpc() && isset($_GET['page']) && $_GET['page'] == WPML_ST_FOLDER . '/menu/string-translation.php'){
  30. $_POST = stripslashes_deep( $_POST );
  31. }
  32. if(!isset($sitepress_settings['existing_content_language_verified']) || !$sitepress_settings['existing_content_language_verified']){
  33. return;
  34. }
  35. if(!isset($sitepress_settings['st']['sw'])){
  36. $sitepress_settings['st']['sw'] = array(); //no settings for now
  37. $sitepress->save_settings($sitepress_settings);
  38. $init_all = true;
  39. }
  40. if(!isset($sitepress_settings['st']['strings_per_page'])){
  41. $sitepress_settings['st']['strings_per_page'] = 10;
  42. $sitepress->save_settings($sitepress_settings);
  43. }elseif(isset($_GET['strings_per_page']) && $_GET['strings_per_page'] > 0){
  44. $sitepress_settings['st']['strings_per_page'] = $_GET['strings_per_page'];
  45. $sitepress->save_settings($sitepress_settings);
  46. }
  47. if(!isset($sitepress_settings['st']['icl_st_auto_reg'])){
  48. $sitepress_settings['st']['icl_st_auto_reg'] = 'disable';
  49. $sitepress->save_settings($sitepress_settings);
  50. }
  51. if(empty($sitepress_settings['st']['strings_language'])){
  52. $iclsettings['st']['strings_language'] = $sitepress_settings['st']['strings_language'] = 'en';
  53. $sitepress->save_settings($iclsettings);
  54. }
  55. if(!isset($sitepress_settings['st']['translated-users'])) $sitepress_settings['st']['translated-users'] = array();
  56. if((isset($_POST['iclt_st_sw_save']) && wp_verify_nonce($_POST['_wpnonce'], 'icl_sw_form')) || isset($init_all)){
  57. if(isset($init_all)){
  58. icl_register_string('WP',__('Blog Title','wpml-string-translation'), get_option('blogname'));
  59. icl_register_string('WP',__('Tagline', 'wpml-string-translation'), get_option('blogdescription'));
  60. __icl_st_init_register_widget_titles();
  61. // create a list of active widgets
  62. $active_text_widgets = array();
  63. $widgets = (array)get_option('sidebars_widgets');
  64. foreach($widgets as $k=>$w){
  65. if('wp_inactive_widgets' != $k && $k != 'array_version'){
  66. if(is_array($widgets[$k])){
  67. foreach($widgets[$k] as $v){
  68. if(preg_match('#text-([0-9]+)#i',$v, $matches)){
  69. $active_text_widgets[] = $matches[1];
  70. }
  71. }
  72. }
  73. }
  74. }
  75. $widget_text = get_option('widget_text');
  76. if(is_array($widget_text)){
  77. foreach($widget_text as $k=>$w){
  78. if(!empty($w) && isset($w['title']) && in_array($k, $active_text_widgets)){
  79. icl_register_string('Widgets', 'widget body - ' . md5($w['text']), $w['text']);
  80. }
  81. }
  82. }
  83. }
  84. if(isset($_POST['iclt_st_sw_save'])){
  85. $updat_string_statuses = false;
  86. $sitepress_settings['st']['sw'] = $_POST['icl_st_sw'];
  87. if($sitepress_settings['st']['strings_language'] != $_POST['icl_st_sw']['strings_language']){
  88. $updat_string_statuses = true;
  89. }
  90. $sitepress_settings['st']['strings_language'] = $_POST['icl_st_sw']['strings_language'];
  91. $sitepress->save_settings($sitepress_settings);
  92. $wpdb->query($wpdb->prepare("UPDATE {$wpdb->prefix}icl_strings SET language=%s WHERE language <> %s",
  93. $sitepress_settings['st']['strings_language'], $sitepress_settings['st']['strings_language']));
  94. if($updat_string_statuses){
  95. icl_update_string_status_all();
  96. }
  97. //register author strings
  98. if(!empty($sitepress_settings['st']['translated-users'])){
  99. icl_st_register_user_strings_all();
  100. }
  101. wp_redirect(admin_url('admin.php?page='. WPML_ST_FOLDER .'/menu/string-translation.php&updated=true'));
  102. }
  103. }
  104. // handle po file upload
  105. if ( isset( $_POST[ 'icl_po_upload' ] ) && wp_verify_nonce( $_POST[ '_wpnonce' ], 'icl_po_form' ) ) {
  106. global $icl_st_po_strings;
  107. if ( $_FILES[ 'icl_po_file' ][ 'size' ] == 0 ) {
  108. $icl_st_err_str = __( 'File upload error', 'wpml-string-translation' );
  109. } else {
  110. $lines = file( $_FILES[ 'icl_po_file' ][ 'tmp_name' ] );
  111. $icl_st_po_strings = array();
  112. $fuzzy = 0;
  113. for ( $k = 0; $k < count( $lines ); $k ++ ) {
  114. $date_time_flag = false;
  115. if ( 0 === strpos( $lines[ $k ], '#, fuzzy' ) ) {
  116. $fuzzy = 1;
  117. $k ++;
  118. }
  119. $name = false;
  120. if ( 0 === strpos( $lines[ $k ], '# wpml-name: ' ) ) {
  121. $name = preg_replace( "/^# wpml-name: /i", '', trim( $lines[ $k ] ) );
  122. $k ++;
  123. }
  124. if ( preg_match( '/msgctxt/', $lines[ $k ] ) ) { //we look for the line that poedit needs for unique identification of the string
  125. if ( preg_match( '/wpmldatei18/', $lines[ $k ] ) ) { //if it contains the date_time setting we add the flag to escape the control structures in the date time placeholder string
  126. $date_time_flag = true;
  127. }
  128. $k ++;
  129. }
  130. $int = preg_match( '#msgid "(.+)"#im', trim( $lines[ $k ] ), $matches );
  131. if ( $int ) {
  132. $string = str_replace( '\"', '"', $matches[ 1 ] );
  133. $int = preg_match( '#msgstr "(.+)"#im', trim( $lines[ $k + 1 ] ), $matches );
  134. if ( $int ) {
  135. $translation = str_replace( '\"', '"', $matches[ 1 ] );
  136. } else {
  137. $translation = "";
  138. }
  139. if ( $name === false ) {
  140. $name = md5( $string );
  141. }
  142. $string_exists = $wpdb->get_var( "
  143. SELECT id FROM {$wpdb->prefix}icl_strings
  144. WHERE context='" . esc_sql( $_POST[ 'icl_st_i_context_new' ] ? $_POST[ 'icl_st_i_context_new' ] : $_POST[ 'icl_st_i_context' ] ) . "'
  145. AND name='" . $name . "'" );
  146. if ( $date_time_flag ) {
  147. $string = str_replace( "\\\\", "\\", $string );
  148. $translation = str_replace( "\\\\", "\\", $translation );
  149. $name = str_replace( "\\\\", "\\", $name );
  150. }
  151. $icl_st_po_strings[ ] = array(
  152. 'string' => $string,
  153. 'translation' => $translation,
  154. 'name' => $name,
  155. 'fuzzy' => $fuzzy,
  156. 'exists' => $string_exists
  157. );
  158. $k ++;
  159. }
  160. if ( ! trim( $lines[ $k ] ) ) {
  161. $fuzzy = 0;
  162. }
  163. }
  164. if ( empty( $icl_st_po_strings ) ) {
  165. $icl_st_err_str = __( 'No string found', 'wpml-string-translation' );
  166. }
  167. }
  168. } elseif ( isset( $_POST[ 'action' ] ) && 'icl_st_save_strings' == $_POST[ 'action' ] ) {
  169. $arr = array_intersect_key( $_POST[ 'icl_strings' ], array_flip( $_POST[ 'icl_strings_selected' ] ) );
  170. //$arr = array_map('html_entity_decode', $arr);
  171. if ( isset( $_POST[ 'icl_st_po_language' ] ) ) {
  172. $arr_t = array_intersect_key( $_POST[ 'icl_translations' ], array_flip( $_POST[ 'icl_strings_selected' ] ) );
  173. $arr_f = array_intersect_key( $_POST[ 'icl_fuzzy' ], array_flip( $_POST[ 'icl_strings_selected' ] ) );
  174. //$arr_t = array_map('html_entity_decode', $arr_t);
  175. }
  176. foreach ( $arr as $k => $string ) {
  177. $name = isset( $_POST[ 'icl_name' ][ $k ] ) && $_POST[ 'icl_name' ][ $k ] ? $_POST[ 'icl_name' ][ $k ] : md5( $string );
  178. $string_id = icl_register_string( $_POST[ 'icl_st_domain_name' ], $name, $string );
  179. if ( $string_id && isset( $_POST[ 'icl_st_po_language' ] ) ) {
  180. if ( $arr_t[ $k ] != "" ) {
  181. if ( $arr_f[ $k ] ) {
  182. $_status = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  183. } else {
  184. $_status = ICL_STRING_TRANSLATION_COMPLETE;
  185. }
  186. icl_add_string_translation( $string_id, $_POST[ 'icl_st_po_language' ], $arr_t[ $k ], $_status );
  187. icl_update_string_status( $string_id );
  188. }
  189. }
  190. }
  191. }
  192. //handle po export
  193. if(isset($_POST['icl_st_pie_e']) && wp_verify_nonce($_POST['_wpnonce'], 'icl_po_export')){
  194. //force some filters
  195. if(isset($_GET['status'])) unset($_GET['status']);
  196. $_GET['show_results']='all';
  197. if($_POST['icl_st_e_context']){
  198. $_GET['context'] = $_POST['icl_st_e_context'];
  199. }
  200. $_GET['translation_language'] = $_POST['icl_st_e_language'];
  201. $strings = icl_get_string_translations();
  202. if(!empty($strings)){
  203. $po = icl_st_generate_po_file($strings, !isset($_POST['icl_st_pe_translations']));
  204. }else{
  205. $po = "";
  206. }
  207. if(!isset($_POST['icl_st_pe_translations'])){
  208. $popot = 'pot';
  209. $poname = $_POST['icl_st_e_context'] ? urlencode($_POST['icl_st_e_context']) : 'all_context';
  210. }else{
  211. $popot = 'po';
  212. $poname = $_GET['translation_language'];
  213. }
  214. header("Content-Type: application/force-download");
  215. header("Content-Type: application/octet-stream");
  216. header("Content-Type: application/download");
  217. header("Content-Disposition: attachment; filename=".$poname.'.'.$popot.";");
  218. header("Content-Length: ". strlen($po));
  219. echo $po;
  220. exit(0);
  221. }
  222. // handle string translation request
  223. elseif(isset($_POST['icl_st_action']) && $_POST['icl_st_action'] == 'send_strings'){
  224. if($_POST['iclnonce'] == wp_create_nonce('icl-string-translation')){
  225. $_POST = stripslashes_deep($_POST);
  226. $services = $_POST['service'];
  227. $string_ids = explode(',', $_POST['strings']);
  228. $translate_to = array();
  229. foreach($_POST['translate_to'] as $lang_to=>$one){
  230. if(isset($services[$lang_to])){
  231. $translate_to[$lang_to] = $services[$lang_to];
  232. }
  233. }
  234. if(!empty($translate_to)){
  235. icl_translation_send_strings($string_ids, $translate_to);
  236. }
  237. }
  238. }
  239. // hook into blog title and tag line
  240. add_filter('option_blogname', 'icl_sw_filters_blogname');
  241. add_filter('option_blogdescription', 'icl_sw_filters_blogdescription');
  242. add_filter('widget_title', 'icl_sw_filters_widget_title', 0); //highest priority
  243. add_filter('widget_text', 'icl_sw_filters_widget_text', 0); //highest priority
  244. if(isset($sitepress_settings['theme_localization_type']) && $sitepress_settings['theme_localization_type']==1){
  245. add_filter('gettext', 'icl_sw_filters_gettext', 9, 3);
  246. add_filter('gettext_with_context', 'icl_sw_filters_gettext_with_context', 1, 4);
  247. add_filter('ngettext', 'icl_sw_filters_ngettext', 9, 5);
  248. add_filter('ngettext_with_context', 'icl_sw_filters_nxgettext', 9, 6);
  249. }
  250. $widget_groups = $wpdb->get_results("SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE 'widget\\_%'");
  251. foreach($widget_groups as $w){
  252. add_action('update_option_' . $w->option_name, 'icl_st_update_widget_title_actions', 5, 2);
  253. }
  254. add_action('update_option_widget_text', 'icl_st_update_text_widgets_actions', 5, 2);
  255. add_action('update_option_sidebars_widgets', '__icl_st_init_register_widget_titles');
  256. if($icl_st_err_str){
  257. add_action('admin_notices', 'icl_st_admin_notices');
  258. }
  259. if (isset($_REQUEST['string-translated']) && $_REQUEST['string-translated'] == true) {
  260. add_action('admin_notices', 'icl_st_admin_notices_string_updated');
  261. }
  262. add_filter('get_the_author_first_name', 'icl_st_author_first_name_filter', 10, 2);
  263. add_filter('get_the_author_last_name', 'icl_st_author_last_name_filter', 10, 2);
  264. add_filter('get_the_author_nickname', 'icl_st_author_nickname_filter', 10, 2);
  265. add_filter('get_the_author_description', 'icl_st_author_description_filter', 10, 2);
  266. add_filter('the_author', 'icl_st_author_displayname_filter', 10);
  267. }
  268. add_action('profile_update', 'icl_st_register_user_strings');
  269. add_action('user_register', 'icl_st_register_user_strings');
  270. function __icl_st_init_register_widget_titles(){
  271. global $wpdb;
  272. // create a list of active widgets
  273. $active_widgets = array();
  274. $widgets = (array)get_option('sidebars_widgets');
  275. foreach($widgets as $k=>$w){
  276. if('wp_inactive_widgets' != $k && $k != 'array_version'){
  277. if(is_array($widgets[$k]))
  278. foreach($widgets[$k] as $v){
  279. $active_widgets[] = $v;
  280. }
  281. }
  282. }
  283. foreach($active_widgets as $aw){
  284. $int = preg_match('#-([0-9]+)$#i',$aw, $matches);
  285. if($int){
  286. $suffix = $matches[1];
  287. }else{
  288. $suffix = 1;
  289. }
  290. $name = preg_replace('#-[0-9]+#','',$aw);
  291. //if($name == 'rss-links') $name = 'rss';
  292. //$w = $wpdb->get_row("SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name = 'widget_{$name}'");
  293. //$value = unserialize($w->option_value);
  294. $value = get_option("widget_".$name);
  295. if(isset($value[$suffix]['title']) && $value[$suffix]['title']){
  296. $w_title = $value[$suffix]['title'];
  297. }else{
  298. $w_title = __icl_get_default_widget_title($aw);
  299. $value[$suffix]['title'] = $w_title;
  300. update_option("widget_".$name, $value);
  301. }
  302. if($w_title){
  303. icl_register_string('Widgets', 'widget title - ' . md5($w_title), $w_title);
  304. }
  305. }
  306. }
  307. function __icl_get_default_widget_title($id){
  308. if(preg_match('#archives(-[0-9]+)?$#i',$id)){
  309. $w_title = 'Archives';
  310. }elseif(preg_match('#categories(-[0-9]+)?$#i',$id)){
  311. $w_title = 'Categories';
  312. }elseif(preg_match('#calendar(-[0-9]+)?$#i',$id)){
  313. $w_title = 'Calendar';
  314. }elseif(preg_match('#links(-[0-9]+)?$#i',$id)){
  315. $w_title = 'Links';
  316. }elseif(preg_match('#meta(-[0-9]+)?$#i',$id)){
  317. $w_title = 'Meta';
  318. }elseif(preg_match('#pages(-[0-9]+)?$#i',$id)){
  319. $w_title = 'Pages';
  320. }elseif(preg_match('#recent-posts(-[0-9]+)?$#i',$id)){
  321. $w_title = 'Recent Posts';
  322. }elseif(preg_match('#recent-comments(-[0-9]+)?$#i',$id)){
  323. $w_title = 'Recent Comments';
  324. }elseif(preg_match('#rss-links(-[0-9]+)?$#i',$id)){
  325. $w_title = 'RSS';
  326. }elseif(preg_match('#search(-[0-9]+)?$#i',$id)){
  327. $w_title = 'Search';
  328. }elseif(preg_match('#tag-cloud(-[0-9]+)?$#i',$id)){
  329. $w_title = 'Tag Cloud';
  330. }else{
  331. $w_title = false;
  332. }
  333. return $w_title;
  334. }
  335. function icl_register_string($context, $name, $value, $allow_empty_value = false){
  336. global $wpdb, $sitepress_settings;
  337. /* cpt slugs - do not register them when scanning themes and plugins
  338. * if name starting from 'URL slug: '
  339. * and context is different from 'WordPress'
  340. */
  341. if (substr($name, 0, 10) === 'URL slug: ' && 'WordPress' !== $context) {
  342. return false;
  343. }
  344. // if the default language is not set up return without doing anything
  345. if(
  346. !isset($sitepress_settings['existing_content_language_verified']) ||
  347. !$sitepress_settings['existing_content_language_verified']
  348. ){
  349. return false;
  350. }
  351. // Check if cached (so exists)
  352. $cached = icl_t_cache_lookup($context, $name);
  353. if ($cached && isset($cached['original']) && $cached['original'] == $value) {
  354. return false;
  355. }
  356. $language = isset($sitepress_settings['st']['strings_language']) ? $sitepress_settings['st']['strings_language'] : 'en';
  357. $res = $wpdb->get_row("SELECT id, value, status, language FROM {$wpdb->prefix}icl_strings WHERE context='".esc_sql($context)."' AND name='".esc_sql($name)."'");
  358. if($res){
  359. $string_id = $res->id;
  360. $update_string = array();
  361. /*
  362. * If Sticky Links plugin is active and set to change links in Strings,
  363. * we need to process $value and change links into sticky before comparing
  364. * with saved in DB $res->value.
  365. * Otherwise after every String Translation screen refresh status of this string
  366. * will be changed into 'needs update'
  367. */
  368. $alp_settings = get_option('alp_settings');
  369. if (!empty($alp_settings['sticky_links_strings']) // do we have setting about sticky links in strings?
  370. && $alp_settings['sticky_links_strings'] // is this set to TRUE?
  371. && defined('WPML_STICKY_LINKS_VERSION')) { // sticky links plugin is active?
  372. require_once ICL_PLUGIN_PATH . '/inc/absolute-links/absolute-links.class.php';
  373. $absolute_links_object = new AbsoluteLinks;
  374. $alp_broken_links = array();
  375. $value = $absolute_links_object->_process_generic_text($value, $alp_broken_links);
  376. }
  377. if($value != $res->value){
  378. $update_string['value'] = $value;
  379. }
  380. if($language != $res->language){
  381. $update_string['language'] = $language;
  382. }
  383. if(!empty($update_string)){
  384. $wpdb->update($wpdb->prefix.'icl_strings', $update_string, array('id'=>$string_id));
  385. $wpdb->update($wpdb->prefix.'icl_string_translations', array('status'=>ICL_STRING_TRANSLATION_NEEDS_UPDATE), array('string_id'=>$string_id));
  386. icl_update_string_status($string_id);
  387. }
  388. }else{
  389. if(!empty($value) && is_scalar($value) && trim($value) || $allow_empty_value){
  390. $string = array(
  391. 'language' => $language,
  392. 'context' => $context,
  393. 'name' => $name,
  394. 'value' => $value,
  395. 'status' => ICL_STRING_TRANSLATION_NOT_TRANSLATED,
  396. );
  397. $wpdb->insert($wpdb->prefix.'icl_strings', $string);
  398. $string_id = $wpdb->insert_id;
  399. }else{
  400. $string_id = 0;
  401. }
  402. }
  403. global $WPML_Sticky_Links;
  404. if(!empty($WPML_Sticky_Links) && $WPML_Sticky_Links->settings['sticky_links_strings']){
  405. require_once ICL_PLUGIN_PATH . '/inc/translation-management/pro-translation.class.php';
  406. ICL_Pro_Translation::_content_make_links_sticky($string_id, 'string', false);
  407. }
  408. return $string_id;
  409. }
  410. add_filter('register_string_for_translation', 'icl_register_string', 10, 4);
  411. function icl_translate($context, $name, $original_value = false, $allow_empty_value = false, &$has_translation = null) {
  412. global $sitepress;
  413. $current_language = $sitepress->get_current_language();
  414. static $cache = null;
  415. if (isset($cache[$context][$name][$current_language])) {
  416. if ( $cache[$context][$name][$current_language] != $original_value ) {
  417. $has_translation = true;
  418. } else {
  419. $has_translation = false;
  420. }
  421. return $cache[$context][$name][$current_language];
  422. }
  423. icl_register_string($context, $name, $original_value, $allow_empty_value);
  424. $cache[$context][$name][$current_language] = icl_t($context, $name, $original_value, $has_translation);
  425. return $cache[$context][$name][$current_language];
  426. }
  427. function icl_st_is_registered_string($context, $name){
  428. global $wpdb;
  429. static $cache = array();
  430. if(isset($cache[$context][$name])){
  431. $string_id = $cache[$context][$name];
  432. }else{
  433. $string_id = $wpdb->get_var("
  434. SELECT id
  435. FROM {$wpdb->prefix}icl_strings WHERE context='".esc_sql($context)."' AND name='".esc_sql($name)."'");
  436. $cache[$context][$name] = $string_id;
  437. }
  438. return $string_id;
  439. }
  440. function icl_st_string_has_translations($context, $name){
  441. global $wpdb;
  442. $sql = "
  443. SELECT COUNT(st.id)
  444. FROM {$wpdb->prefix}icl_string_translations st
  445. JOIN {$wpdb->prefix}icl_strings s ON s.id=st.string_id
  446. WHERE s.name='".esc_sql($name)."' AND s.context='".esc_sql($context)."'
  447. ";
  448. return $wpdb->get_var($sql);
  449. }
  450. function icl_rename_string($context, $old_name, $new_name){
  451. global $wpdb;
  452. $wpdb->update($wpdb->prefix.'icl_strings', array('name'=>$new_name), array('context'=>$context, 'name'=>$old_name));
  453. }
  454. function icl_update_string_status($string_id){
  455. global $wpdb, $sitepress, $sitepress_settings;
  456. $st = $wpdb->get_results($wpdb->prepare("SELECT language, status FROM {$wpdb->prefix}icl_string_translations WHERE string_id=%d", $string_id));
  457. if($st){
  458. if (isset($sitepress_settings['st']['strings_language'])) {
  459. $strings_language = $sitepress_settings['st']['strings_language'];
  460. } else {
  461. $strings_language = false;
  462. }
  463. foreach($st as $t){
  464. if( $strings_language != $t->language){
  465. $translations[$t->language] = $t->status;
  466. }
  467. }
  468. $active_languages = $sitepress->get_active_languages();
  469. if(empty($translations) || max($translations) == ICL_STRING_TRANSLATION_NOT_TRANSLATED){
  470. $status = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  471. }elseif( in_array(ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR,$translations) ){
  472. $status = ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR;
  473. }elseif(count($translations) < count($active_languages) - intval(in_array($strings_language, array_keys($active_languages)))){
  474. if(in_array(ICL_STRING_TRANSLATION_NEEDS_UPDATE,$translations)){
  475. $status = ICL_STRING_TRANSLATION_NEEDS_UPDATE;
  476. }elseif(in_array(ICL_STRING_TRANSLATION_COMPLETE,$translations)){
  477. $status = ICL_STRING_TRANSLATION_PARTIAL;
  478. }else{
  479. $status = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  480. }
  481. }elseif(ICL_STRING_TRANSLATION_NEEDS_UPDATE == array_unique($translations)){
  482. $status = ICL_STRING_TRANSLATION_NEEDS_UPDATE;
  483. }else{
  484. if(in_array(ICL_STRING_TRANSLATION_NEEDS_UPDATE,$translations)){
  485. $status = ICL_STRING_TRANSLATION_NEEDS_UPDATE;
  486. }elseif(in_array(ICL_STRING_TRANSLATION_NOT_TRANSLATED,$translations)){
  487. $status = ICL_STRING_TRANSLATION_PARTIAL;
  488. }else{
  489. $status = ICL_STRING_TRANSLATION_COMPLETE;
  490. }
  491. }
  492. }else{
  493. $status = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  494. }
  495. $wpdb->update($wpdb->prefix.'icl_strings', array('status'=>$status), array('id'=>$string_id));
  496. return $status;
  497. }
  498. function icl_update_string_status_all(){
  499. global $wpdb;
  500. $res = $wpdb->get_col("SELECT id FROM {$wpdb->prefix}icl_strings");
  501. foreach($res as $id){
  502. icl_update_string_status($id);
  503. }
  504. }
  505. function icl_unregister_string($context, $name){
  506. global $wpdb;
  507. $string_id = $wpdb->get_var("SELECT id FROM {$wpdb->prefix}icl_strings WHERE context='".esc_sql($context)."' AND name='".esc_sql($name)."'");
  508. if($string_id){
  509. $wpdb->query( $wpdb->prepare("DELETE FROM {$wpdb->prefix}icl_strings WHERE id=%d", $string_id));
  510. $wpdb->query( $wpdb->prepare("DELETE FROM {$wpdb->prefix}icl_string_translations WHERE string_id=%d", $string_id));
  511. $wpdb->query( $wpdb->prepare("DELETE FROM {$wpdb->prefix}icl_string_positions WHERE string_id=%d", $string_id));
  512. }
  513. do_action('icl_st_unregister_string', $string_id);
  514. }
  515. function __icl_unregister_string_multi($arr){
  516. global $wpdb;
  517. $str = join(',', array_map('intval', $arr));
  518. $wpdb->query("
  519. DELETE s.*, t.* FROM {$wpdb->prefix}icl_strings s LEFT JOIN {$wpdb->prefix}icl_string_translations t ON s.id = t.string_id
  520. WHERE s.id IN ({$str})");
  521. $wpdb->query("DELETE FROM {$wpdb->prefix}icl_string_positions WHERE string_id IN ({$str})");
  522. do_action('icl_st_unregister_string_multi', $arr);
  523. }
  524. function icl_t($context, $name, $original_value=false, &$has_translation=null, $dont_auto_register = false){
  525. global $sitepress, $sitepress_settings;
  526. // we need this to devide static $results cache by blogs in multiblog
  527. $blog_id = 0;
  528. if (isset($GLOBALS['blog_id'])) {
  529. $blog_id = $GLOBALS['blog_id'];
  530. }
  531. // if the default language is not set up return
  532. if(!isset($sitepress_settings['existing_content_language_verified'])){
  533. if(isset($has_translation)) $has_translation = false;
  534. return $original_value !== false ? $original_value : $name;
  535. }
  536. $current_language = get_current_string_language( $name );
  537. $default_language = !empty($sitepress_settings['st']['strings_language']) ? $sitepress_settings['st']['strings_language'] : $sitepress->get_default_language();
  538. $cache_key_args = array($blog_id, $current_language, $default_language, $context, $name, $original_value);
  539. $cache_key = md5( json_encode( $cache_key_args ) );
  540. $cache_group = '_icl_t';
  541. $found = false;
  542. $to_return = wp_cache_get($cache_key, $cache_group, false, $found);
  543. if ($found) {
  544. if ($to_return == $original_value) {
  545. $has_translation = false;
  546. } else {
  547. $has_translation = true;
  548. }
  549. return $to_return;
  550. }
  551. if($current_language == $default_language && $original_value){
  552. $ret_val = $original_value;
  553. if(isset($has_translation)) $has_translation = false;
  554. }else{
  555. $result = icl_t_cache_lookup($context, $name);
  556. $is_string_change = _icl_is_string_change($result, $original_value);
  557. if (($result === false || $is_string_change) && !is_admin() && !$dont_auto_register && $context != 'Widgets') {
  558. static $string_registrations_per_request = 0;
  559. if($string_registrations_per_request < ICL_STRING_TRANSLATION_AUTO_REGISTER_THRESHOLD){
  560. // See if we should auto register the strings.
  561. if (isset($sitepress_settings['st']['icl_st_auto_reg'])) {
  562. $auto_reg = $sitepress_settings['st']['icl_st_auto_reg'];
  563. } else {
  564. $auto_reg = 'disable';
  565. }
  566. if($auto_reg == 'auto-always' || ($auto_reg == 'auto-admin' && current_user_can('manage_options'))){
  567. icl_register_string($context, $name, $original_value);
  568. $string_registrations_per_request++;
  569. }
  570. }
  571. }
  572. if($result === false || ( is_array($result) && ( !isset($result['value']) || ( isset($result['translated']) && !$result['translated'] && $original_value ) ) ) ){
  573. $ret_val = $original_value;
  574. if(isset($has_translation)) $has_translation = false;
  575. }else{
  576. $ret_val = $result['value'];
  577. if(isset($has_translation)) $has_translation = true;
  578. }
  579. }
  580. wp_cache_set($cache_key, $ret_val, $cache_group);
  581. return $ret_val;
  582. }
  583. /**
  584. * @param $name
  585. *
  586. * Checks whether a given string is to be translated in the Admin back-end.
  587. * Currently only tagline and title of a site are to be translated.
  588. * All other admin strings are to always be displayed in the user admin language.
  589. *
  590. * @return bool
  591. */
  592. function is_translated_admin_string( $name ) {
  593. $translated = false;
  594. $exclusions = array( 'Tagline', 'Blog Title' );
  595. if ( in_array( $name, $exclusions ) ) {
  596. $translated = true;
  597. }
  598. return $translated;
  599. }
  600. /**
  601. * @param $name
  602. * Returns the language the current string is to be translated into.
  603. *
  604. * @return string
  605. */
  606. function get_current_string_language( $name ) {
  607. global $sitepress;
  608. if ( defined( 'DOING_AJAX' ) ) {
  609. $current_language = $sitepress->get_language_cookie();
  610. } else {
  611. $current_language = $sitepress->get_current_language();
  612. }
  613. /*
  614. * The logic for this is a little different in the admin backend. Here we always use the user admin language if the admin backend is accessed.
  615. * We have to take care of two exceptions though.
  616. * 1. Plugins doing admin ajax calls in the frontend.
  617. * 2. Certain strings are to always be translated in the admin backend.
  618. * 3. We have to handle special exception when check_if_admin_action_from_referrer is not available yet (during upgrade)
  619. */
  620. if (version_compare(ICL_SITEPRESS_VERSION, '3.1.7.2', '>')) {
  621. if (defined('WP_ADMIN') && ( $sitepress->check_if_admin_action_from_referer() || !defined('DOING_AJAX') ) && !is_translated_admin_string($name)) {
  622. $current_user = $sitepress->get_current_user();
  623. if (isset($current_user->ID)) {
  624. $current_language = $sitepress->get_user_admin_language($current_user->ID);
  625. }
  626. }
  627. }
  628. return $current_language;
  629. }
  630. /**
  631. * Helper function for icl_t()
  632. * @param array $result
  633. * @param string $original_value
  634. * @return boolean
  635. */
  636. function _icl_is_string_change($result, $original_value) {
  637. if ($result == false) {
  638. return false;
  639. }
  640. if (!isset($result['value'])) {
  641. return false;
  642. }
  643. return (
  644. $result['translated'] && $result['original'] != $original_value ||
  645. !$result['translated'] && $result['value'] != $original_value
  646. );
  647. }
  648. add_filter('translate_string', 'icl_t', 10, 5);
  649. function icl_add_string_translation($string_id, $language, $value = null, $status = false, $translator_id = null){
  650. global $wpdb, $sitepress;
  651. $current_user = $sitepress->get_current_user();
  652. $res = $wpdb->get_row("SELECT id, value, status FROM {$wpdb->prefix}icl_string_translations WHERE string_id='".esc_sql($string_id)."' AND language='".esc_sql($language)."'");
  653. // the same string should not be sent two times to translation
  654. if(isset($res->status) && $res->status == ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR && is_null($value)){
  655. return false;
  656. }
  657. if($res){
  658. $st_id = $res->id;
  659. $st_update = array();
  660. if(!is_null($value) && $value != $res->value){ // null $value is for sending to translation. don't override existing.
  661. $st_update['value'] = $value;
  662. }
  663. if($status){
  664. $st_update['status'] = $status;
  665. }elseif($status === ICL_STRING_TRANSLATION_NOT_TRANSLATED){
  666. $st_update['status'] = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  667. }
  668. if(!empty($st_update)){
  669. if(!is_null($translator_id)){
  670. $st_update['translator_id'] = $current_user->ID;
  671. }
  672. $st_update['translation_date'] = current_time("mysql");
  673. $wpdb->update($wpdb->prefix.'icl_string_translations', $st_update, array('id'=>$st_id));
  674. }
  675. }else{
  676. if(!$status){
  677. $status = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  678. }
  679. $st = array(
  680. 'string_id' => $string_id,
  681. 'language' => $language,
  682. 'status' => $status
  683. );
  684. if(!is_null($value)){
  685. $st['value'] = $value;
  686. }
  687. if(!is_null($translator_id)){
  688. $st_update['translator_id'] = $current_user->ID;
  689. }
  690. $wpdb->insert($wpdb->prefix.'icl_string_translations', $st);
  691. $st_id = $wpdb->insert_id;
  692. }
  693. if(isset($GLOBALS['ICL_Pro_Translation'])){
  694. $GLOBALS['ICL_Pro_Translation']->_content_fix_links_to_translated_content($st_id, $language, 'string');
  695. }
  696. icl_update_string_status($string_id);
  697. do_action('icl_st_add_string_translation', $st_id);
  698. return $st_id;
  699. }
  700. /**
  701. *
  702. * @global WPDB $wpdb
  703. * @global array $sitepress_settings
  704. * @param string $option_name
  705. * @param string $language
  706. * @param string $new_value
  707. * @param int|bool $status
  708. * @param int $translator_id
  709. * @param int $rec_level
  710. * @return boolean|mixed
  711. */
  712. function icl_update_string_translation($option_name, $language, $new_value = null, $status = false, $translator_id = null, $rec_level = 0) {
  713. global $wpdb, $sitepress_settings;
  714. if (!is_array($new_value)) {
  715. $new_value = (array) $new_value;
  716. }
  717. $updated = array();
  718. foreach ($new_value as $index => $value) {
  719. if (is_array($value)) {
  720. $name = "[". $option_name ."][" . $index . "]";
  721. $result = icl_update_string_translation($name, $language, $value, $status, $translator_id, $rec_level + 1);
  722. $updated[] = array_sum( explode(",", $result) );
  723. } else {
  724. if (is_string($index)) {
  725. if ($rec_level == 0) {
  726. $name = "[". $option_name ."]" . $index;
  727. } else {
  728. $name = $option_name . $index;
  729. }
  730. } else {
  731. $name = $option_name;
  732. }
  733. $select_original_string = "SELECT * FROM {$wpdb->prefix}icl_strings WHERE name = %s AND language = %s";
  734. $original_string = $wpdb->get_row($wpdb->prepare($select_original_string, $name, $sitepress_settings['st']['strings_language']));
  735. if (!$original_string || !isset($original_string->id) || !is_numeric($original_string->id)) {
  736. continue;
  737. }
  738. $updated[] = icl_add_string_translation($original_string->id, $language, $value, $status, $translator_id);
  739. }
  740. }
  741. if (array_sum($updated) > 0) {
  742. return join(",", $updated);
  743. } else {
  744. return false;
  745. }
  746. }
  747. function icl_get_string_id($string, $context){
  748. global $wpdb;
  749. $id = (int) $wpdb->get_var($wpdb->prepare("SELECT id FROM {$wpdb->prefix}icl_strings WHERE value=%s AND context=%s", $string, $context));
  750. return $id;
  751. }
  752. function icl_get_string_translations($offset=0){
  753. global $wpdb, $sitepress, $sitepress_settings, $wp_query, $icl_st_string_translation_statuses;
  754. $string_translations = array();
  755. $current_user = $sitepress->get_current_user();
  756. $extra_cond = "";
  757. if(icl_st_is_translator() && isset($_GET['status']) && preg_match("#".ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR."-(.+)#", $_GET['status'], $matches)){
  758. $status_filter = ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR;
  759. $status_filter_lang = $matches[1];
  760. $lcode_alias = str_replace('-', '', $status_filter_lang);
  761. $extra_cond .= " AND str_{$lcode_alias}.language = '{$status_filter_lang}' ";
  762. }else{
  763. $status_filter = isset($_GET['status']) ? intval($_GET['status']) : false;
  764. }
  765. $search_filter = isset($_GET['search']) ? $_GET['search'] : false;
  766. $exact_match = isset($_GET['em']) ? $_GET['em'] == 1 : false;
  767. if($status_filter !== false){
  768. if($status_filter == ICL_STRING_TRANSLATION_COMPLETE){
  769. $extra_cond .= " AND s.status = " . ICL_STRING_TRANSLATION_COMPLETE;
  770. }elseif($status_filter == ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR){
  771. ; // do nothing
  772. }else{
  773. $extra_cond .= " AND status IN (" . ICL_STRING_TRANSLATION_PARTIAL . "," . ICL_STRING_TRANSLATION_NEEDS_UPDATE . "," . ICL_STRING_TRANSLATION_NOT_TRANSLATED . "," . ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR . ")";
  774. }
  775. }
  776. if($search_filter != false){
  777. if($exact_match){
  778. $extra_cond .= " AND s.value = '". esc_sql($search_filter)."' ";
  779. }else{
  780. $extra_cond .= " AND s.value LIKE '%". esc_sql($search_filter)."%' ";
  781. }
  782. }
  783. $context_filter = isset($_GET['context']) ? $_GET['context'] : false;
  784. if($context_filter !== false){
  785. $extra_cond .= " AND s.context = '" . esc_sql($context_filter) . "'";
  786. }
  787. if(isset($_GET['show_results']) && $_GET['show_results']=='all'){
  788. $limit = 9999;
  789. $offset = 0;
  790. }else{
  791. $limit = $sitepress_settings['st']['strings_per_page'];
  792. if(!isset($_GET['paged'])) $_GET['paged'] = 1;
  793. $offset = ($_GET['paged']-1)*$limit;
  794. }
  795. /* TRANSLATOR - START */
  796. if(icl_st_is_translator()){
  797. $user_lang_pairs = get_user_meta($current_user->ID, $wpdb->prefix.'language_pairs', true);
  798. if(!empty($status_filter_lang)){
  799. $_joins = $_sels = $_where = array();
  800. foreach($sitepress->get_active_languages() as $l){
  801. if($l['code'] == $sitepress_settings['st']['strings_language']) continue;
  802. $lcode_alias = str_replace('-', '', $l['code']);
  803. $_sels[] = "str_{$lcode_alias}.id AS id_{$lcode_alias},
  804. str_{$lcode_alias}.status AS status_{$lcode_alias},
  805. str_{$lcode_alias}.value AS value_{$lcode_alias},
  806. str_{$lcode_alias}.translator_id AS translator_{$lcode_alias},
  807. str_{$lcode_alias}.translation_date AS date_{$lcode_alias}
  808. ";
  809. $_joins[] = " LEFT JOIN {$wpdb->prefix}icl_string_translations str_{$lcode_alias} ON str_{$lcode_alias}.string_id = s.id AND str_{$lcode_alias}.language = '{$l['code']}'";
  810. }
  811. $sql = "
  812. SELECT SQL_CALC_FOUND_ROWS s.id AS string_id, s.language AS string_language, s.context, s.name, s.value, s.status,
  813. " . join(", ", $_sels) . "
  814. FROM {$wpdb->prefix}icl_strings s
  815. " . join("\n", $_joins) . "
  816. WHERE
  817. str_{$status_filter_lang}.status = %d AND
  818. (str_{$status_filter_lang}.translator_id IS NULL OR str_{$status_filter_lang}.translator_id = %d)
  819. {$extra_cond}
  820. ORDER BY string_id DESC
  821. LIMIT {$offset},{$limit}
  822. ";
  823. $sql_prepared = $wpdb->prepare($sql, array(ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR, $current_user->ID));
  824. $res = $wpdb->get_results($sql_prepared, ARRAY_A);
  825. }else{
  826. $_joins = $_sels = $_where = array();
  827. foreach($sitepress->get_active_languages() as $l){
  828. if($l['code'] == $sitepress_settings['st']['strings_language']
  829. || empty($user_lang_pairs[$sitepress_settings['st']['strings_language']][$l['code']])) continue;
  830. $lcode_alias = str_replace('-', '', $l['code']);
  831. $lcode_alias = str_replace('-', '', $l['code']);
  832. $_sels[] = "str_{$lcode_alias}.id AS id_{$lcode_alias},
  833. str_{$lcode_alias}.status AS status_{$lcode_alias},
  834. str_{$lcode_alias}.value AS value_{$lcode_alias},
  835. str_{$lcode_alias}.translator_id AS translator_{$lcode_alias},
  836. str_{$lcode_alias}.translation_date AS date_{$lcode_alias}
  837. ";
  838. $_joins[] = "LEFT JOIN {$wpdb->prefix}icl_string_translations str_{$lcode_alias} ON str_{$lcode_alias}.string_id = s.id AND str_{$lcode_alias}.language='{$l['code']}'";
  839. if($status_filter == ICL_STRING_TRANSLATION_COMPLETE){
  840. $_where[] .= " AND str_{$lcode_alias}.status = " . ICL_STRING_TRANSLATION_COMPLETE;
  841. }else{
  842. if(empty($_lwhere)){
  843. $_lwhere = ' AND (';
  844. foreach($sitepress->get_active_languages() as $l2){
  845. if($l2['code'] == $sitepress_settings['st']['strings_language'] || empty($user_lang_pairs[$sitepress_settings['st']['strings_language']][$l2['code']])) continue;
  846. $l2code_alias = str_replace('-', '', $l2['code']);
  847. $_lwheres[] = " str_{$l2code_alias}.status = " . ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR . " OR
  848. str_{$l2code_alias}.translator_id = " . $current_user->ID ;
  849. }
  850. $_lwhere .= join(' OR ', $_lwheres ) . ')';
  851. $_where[] = $_lwhere;
  852. }
  853. }
  854. }
  855. $sql = "
  856. SELECT SQL_CALC_FOUND_ROWS s.id AS string_id, s.language AS string_language, s.context, s.name, s.value, s.status, ".
  857. join(', ', $_sels) . "
  858. FROM {$wpdb->prefix}icl_strings s " . join("\n", $_joins) . "
  859. WHERE s.language = '{$sitepress_settings['st']['strings_language']}' ".join(' ', $_where) . "
  860. {$extra_cond}
  861. ORDER BY s.id DESC
  862. LIMIT {$offset},{$limit}
  863. ";
  864. $res = $wpdb->get_results($sql, ARRAY_A);
  865. }
  866. $wp_query->found_posts = $wpdb->get_var("SELECT FOUND_ROWS()");
  867. $wp_query->query_vars['posts_per_page'] = $limit;
  868. $wp_query->max_num_pages = ceil($wp_query->found_posts/$limit);
  869. if($res){
  870. if(!empty($status_filter_lang)){
  871. foreach($res as $row){
  872. $_translations = array();
  873. foreach($sitepress->get_active_languages() as $l){
  874. if($l['code'] == $sitepress_settings['st']['strings_language']) continue;
  875. $lcode_alias = str_replace('-', '', $l['code']);
  876. if($row['id_'. $lcode_alias]){
  877. $_translations[$l['code']] = array(
  878. 'id' => $row['id_'. $lcode_alias],
  879. 'status' => $row['status_'. $lcode_alias],
  880. 'language' => $l['code'],
  881. 'value' => $row['value_'. $lcode_alias],
  882. 'translator_id' => $row['translator_'. $lcode_alias],
  883. 'translation_date' => $row['date_'. $lcode_alias]
  884. );
  885. }
  886. }
  887. $string_translations[$row['string_id']] = array(
  888. 'string_id' => $row['string_id'],
  889. 'string_language' => $row['string_language'],
  890. 'context' => $row['context'],
  891. 'name' => $row['name'],
  892. 'value' => $row['value'],
  893. 'status' => ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR,
  894. 'translations' => $_translations
  895. );
  896. }
  897. }else{
  898. foreach($res as $row){
  899. $_translations = array();
  900. $_status = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  901. $_statuses = array();
  902. foreach($sitepress->get_active_languages() as $l){
  903. if($l['code'] == $sitepress_settings['st']['strings_language'] || empty($user_lang_pairs[$sitepress_settings['st']['strings_language']][$l['code']])) continue;
  904. $lcode_alias = str_replace('-', '', $l['code']);
  905. if($row['id_'. $lcode_alias]){
  906. $_translations[$l['code']] = array(
  907. 'id' => $row['id_'. $lcode_alias],
  908. 'status' => $row['status_'. $lcode_alias],
  909. 'language' => $l['code'],
  910. 'value' => $row['value_'. $lcode_alias],
  911. 'translator_id' => $row['translator_'. $lcode_alias],
  912. 'translation_date' => $row['date_'. $lcode_alias]
  913. );
  914. }
  915. $_statuses[$l['code']] = @intval($row['status_'. $lcode_alias]);
  916. if($row['status_'. $lcode_alias] == ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR){
  917. $_status == ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR;
  918. }
  919. }
  920. $_statuses = array_values($_statuses);
  921. $_statuses = array_unique($_statuses);
  922. if($_statuses == array(ICL_STRING_TRANSLATION_NOT_TRANSLATED)){
  923. $_status = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  924. }elseif($_statuses == array(ICL_STRING_TRANSLATION_COMPLETE, ICL_STRING_TRANSLATION_NOT_TRANSLATED)){
  925. $_status = ICL_STRING_TRANSLATION_PARTIAL;
  926. }elseif($_statuses == array(ICL_STRING_TRANSLATION_COMPLETE)){
  927. $_status = ICL_STRING_TRANSLATION_COMPLETE;
  928. }elseif(in_array(ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR, $_statuses) || in_array(ICL_STRING_TRANSLATION_NEEDS_UPDATE, $_statuses)){
  929. $_status = ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR;
  930. }
  931. $string_translations[$row['string_id']] = array(
  932. 'string_id' => $row['string_id'],
  933. 'string_language' => $row['string_language'],
  934. 'context' => $row['context'],
  935. 'name' => $row['name'],
  936. 'value' => $row['value'],
  937. 'status' => $_status,
  938. 'translations' => $_translations
  939. );
  940. }
  941. }
  942. }
  943. /* TRANSLATOR - END */
  944. }else{
  945. // removed check for language = default lang
  946. if($status_filter != ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR){
  947. $res = $wpdb->get_results("
  948. SELECT SQL_CALC_FOUND_ROWS id AS string_id, language AS string_language, context, name, value, status
  949. FROM {$wpdb->prefix}icl_strings s
  950. WHERE
  951. 1
  952. {$extra_cond}
  953. ORDER BY string_id DESC
  954. LIMIT {$offset},{$limit}
  955. ", ARRAY_A);
  956. }else{
  957. $res = $wpdb->get_results("
  958. SELECT SQL_CALC_FOUND_ROWS s.id AS string_id, s.language AS string_language, s.context, s.name, s.value, " . ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR . " AS status
  959. FROM {$wpdb->prefix}icl_strings s
  960. JOIN {$wpdb->prefix}icl_string_translations str ON str.string_id = s.id
  961. WHERE
  962. str.status = " . ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR . "
  963. {$extra_cond}
  964. ORDER BY string_id DESC
  965. LIMIT {$offset},{$limit}
  966. ", ARRAY_A);
  967. }
  968. if(!is_null($wp_query)){
  969. $wp_query->found_posts = $wpdb->get_var("SELECT FOUND_ROWS()");
  970. $wp_query->query_vars['posts_per_page'] = $limit;
  971. $wp_query->max_num_pages = ceil($wp_query->found_posts/$limit);
  972. }
  973. if($res){
  974. $extra_cond = '';
  975. if(isset($_GET['translation_language'])){
  976. $extra_cond .= " AND language='".esc_sql($_GET['translation_language'])."'";
  977. }
  978. foreach($res as $row){
  979. $string_translations[$row['string_id']] = $row;
  980. $tr = $wpdb->get_results( $wpdb->prepare("
  981. SELECT id, language, status, value, translator_id, translation_date
  982. FROM {$wpdb->prefix}icl_string_translations
  983. WHERE string_id=%d {$extra_cond}
  984. ", $row['string_id']), ARRAY_A);
  985. if($tr){
  986. foreach($tr as $t){
  987. $string_translations[$row['string_id']]['translations'][$t['language']] = $t;
  988. }
  989. }
  990. }
  991. }
  992. }
  993. return $string_translations;
  994. }
  995. /**
  996. * Returns indexed array with language code and value of string
  997. *
  998. * @param int $string_id ID of string in icl_strings DB table
  999. * @param bool|string $language_code false, or language code
  1000. *
  1001. * @return string
  1002. */
  1003. function icl_get_string_by_id( $string_id, $language_code = false ) {
  1004. global $wpdb, $sitepress_settings;
  1005. if ( !$language_code ) {
  1006. $language_code = $sitepress_settings[ 'st' ][ 'strings_language' ];
  1007. }
  1008. if ( $language_code == $sitepress_settings[ 'st' ][ 'strings_language' ] ) {
  1009. $result_prepared = $wpdb->prepare( "SELECT language, value FROM {$wpdb->prefix}icl_strings WHERE id=%d", $string_id );
  1010. $result = $wpdb->get_row( $result_prepared );
  1011. if ( $result ) {
  1012. return $result->value;
  1013. }
  1014. } else {
  1015. $translations = icl_get_string_translations_by_id( $string_id );
  1016. if ( isset( $translations[ $language_code ] ) ) {
  1017. return $translations[ $language_code ]['value'];
  1018. }
  1019. }
  1020. return false;
  1021. }
  1022. function icl_get_string_translations_by_id($string_id){
  1023. global $wpdb;
  1024. $translations = array();
  1025. $results = $wpdb->get_results($wpdb->prepare("SELECT language, value, status FROM {$wpdb->prefix}icl_string_translations WHERE string_id=%d", $string_id));
  1026. foreach($results as $row){
  1027. $translations[$row->language] = array('value' => $row->value, 'status' => $row->status);
  1028. }
  1029. return $translations;
  1030. }
  1031. function icl_get_relative_translation_status($string_id, $translator_id){
  1032. global $wpdb, $sitepress, $sitepress_settings;
  1033. $current_user = $sitepress->get_current_user();
  1034. $user_lang_pairs = get_user_meta($current_user->ID, $wpdb->prefix.'language_pairs', true);
  1035. $src_langs = array_intersect(array_keys($sitepress->get_active_languages()), array_keys($user_lang_pairs[$sitepress_settings['st']['strings_language']]));
  1036. if(empty($src_langs)) return ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  1037. $sql = "SELECT st.status
  1038. FROM {$wpdb->prefix}icl_strings s
  1039. JOIN {$wpdb->prefix}icl_string_translations st ON s.id = st.string_id
  1040. WHERE st.language IN ('" . join("','", $src_langs) . "') AND s.id = %d
  1041. ";
  1042. $statuses = $wpdb->get_col($wpdb->prepare($sql, $string_id));
  1043. $status = ICL_STRING_TRANSLATION_NOT_TRANSLATED;
  1044. $one_incomplete = false;
  1045. foreach($statuses as $s){
  1046. if($s == ICL_STRING_TRANSLATION_COMPLETE){
  1047. $status = ICL_STRING_TRANSLATION_COMPLETE;
  1048. }elseif($s == ICL_STRING_TRANSLATION_NOT_TRANSLATED){
  1049. $one_incomplete = true;
  1050. }
  1051. }
  1052. if($status == ICL_STRING_TRANSLATION_COMPLETE && $one_incomplete){
  1053. $status = ICL_STRING_TRANSLATION_PARTIAL;
  1054. }
  1055. return $status;
  1056. }
  1057. function icl_get_strings_tracked_in_pages($string_translations){
  1058. global $wpdb;
  1059. // get string position in page - if found
  1060. $found_strings = $strings_in_page = array();
  1061. foreach(array_keys((array)$string_translations) as $string_id){
  1062. $found_strings[] = $string_id;
  1063. }
  1064. if($found_strings){
  1065. $res = $wpdb->get_results("
  1066. SELECT kind, string_id FROM {$wpdb->prefix}icl_string_positions
  1067. WHERE string_id IN (".implode(',', $found_strings).")");
  1068. foreach($res as $row){
  1069. $strings_in_page[$row->kind][$row->string_id] = true;
  1070. }
  1071. }
  1072. return $strings_in_page;
  1073. }
  1074. function icl_sw_filters_blogname($val){
  1075. $val = icl_t('WP', 'Blog Title', $val);
  1076. return $val;
  1077. }
  1078. function icl_sw_filters_blogdescription($val){
  1079. $val = icl_t('WP', 'Tagline', $val);
  1080. return $val;
  1081. }
  1082. function icl_sw_filters_widget_title($val){
  1083. $val = icl_t('Widgets', 'widget title - ' . md5($val) , $val);
  1084. return $val;
  1085. }
  1086. function icl_sw_filters_widget_text($val){
  1087. $val = icl_t('Widgets', 'widget body - ' . md5($val) , $val);
  1088. return $val;
  1089. }
  1090. /**
  1091. * @param $translation
  1092. * @param $text
  1093. * @param $domain
  1094. * @param bool $name
  1095. *
  1096. * @return bool|mixed|string
  1097. */
  1098. function icl_sw_filters_gettext( $translation, $text, $domain, $name = false )
  1099. {
  1100. global $sitepress_settings, $sitepress;
  1101. // static $front_end_language = false;
  1102. $has_translation = 0;
  1103. if ( defined( 'DOING_AJAX' ) ) {
  1104. $current_language = $sitepress->get_language_cookie();
  1105. } elseif ( is_admin() ) {
  1106. $current_language = $sitepress->get_admin_language();
  1107. } else {
  1108. // if(!$front_end_language) {
  1109. $current_language = $sitepress->get_current_language();
  1110. // $front_end_language = $current_language;
  1111. // } else {
  1112. // $current_language = $front_end_language;
  1113. // }
  1114. if ($current_language == $sitepress_settings['st']['strings_language'] ) {
  1115. return $translation;
  1116. }
  1117. }
  1118. $cache_name = $translation . $text . $domain . $current_language;
  1119. $ret_translation = wp_cache_get( $cache_name );
  1120. if ( $ret_translation ) {
  1121. return $ret_translation;
  1122. }
  1123. if(!defined('ICL_STRING_TRANSLATION_DYNAMIC_CONTEXT')) {
  1124. define('ICL_STRING_TRANSLATION_DYNAMIC_CONTEXT', 'wpml_string');
  1125. }
  1126. $register_dynamic_string = false;
  1127. if($domain == ICL_STRING_TRANSLATION_DYNAMIC_CONTEXT) {
  1128. $register_dynamic_string = true;
  1129. }
  1130. static $gettext_calls = array( '__', '_e', '_ex', '_n', '_n_noop', '_nx', '_nx_noop', '_x', 'esc_attr__', 'esc_attr_e', 'esc_attr_x', 'esc_html__', 'esc_html_e', 'esc_html_x', );
  1131. $dbt = $sitepress->get_backtrace(6);
  1132. $dbt4 = isset( $dbt[ 4 ][ 'file' ] ) ? str_replace( '\\', '/', $dbt[ 4 ][ 'file' ] ) : '';
  1133. $dbt5 = isset( $dbt[ 5 ][ 'file' ] ) ? str_replace( '\\', '/', $dbt[ 5 ][ 'file' ] ) : '';
  1134. $wp_plugin_dir = str_replace( '\\', '/', WP_PLUGIN_DIR );
  1135. $wpmu_plugin_dir = str_replace( '\\', '/', WPMU_PLUGIN_DIR );
  1136. if ( 0 === strpos( $dbt4, $wp_plugin_dir ) ) {
  1137. if ( dirname( $dbt4 ) == $wp_plugin_dir ) {
  1138. $plugin_folder = basename( str_replace( $wp_plugin_dir, '', $dbt4 ) );
  1139. } else {
  1140. $exp = explode( '/', ltrim( str_replace( $wp_plugin_dir, '', $dbt4 ), '/' ) );
  1141. $plugin_folder = $exp[ 0 ];
  1142. }
  1143. $context = 'plugin ' . $plugin_folder;
  1144. } elseif ( 0 === strpos( $dbt5, $wp_plugin_dir ) && in_array( $dbt[ 5 ][ 'function' ], $gettext_calls ) ) {
  1145. if ( dirname( $dbt4 ) == $wp_plugin_dir ) {
  1146. $plugin_folder = basename( str_replace( $wp_plugin_dir, '', $dbt5 ) );
  1147. } else {
  1148. $exp = explode( '/', ltrim( str_replace( $wp_plugin_dir, '', $dbt5 ), '/' ) );
  1149. $plugin_folder = $exp[ 0 ];
  1150. }
  1151. $context = 'plugin ' . $plugin_folder;
  1152. } elseif ( 0 === strpos( $dbt4, $wpmu_plugin_dir ) ) {
  1153. $context = ( $domain != 'default' ) ? 'plugin ' . $domain : 'plugin';
  1154. } elseif ( 0 === strpos( $dbt5, $wpmu_plugin_dir ) && in_array( $dbt[ 5 ][ 'function' ], $gettext_calls ) ) {
  1155. $context = ( $domain != 'default' ) ? 'plugin ' . $domain : 'plugin';
  1156. } else {
  1157. $context = ( $domain != 'default' ) ? 'theme ' . $domain : 'WordPress';
  1158. }
  1159. if ( isset( $sitepress_settings[ 'st' ][ 'track_strings' ] ) && $sitepress_settings[ 'st' ][ 'track_strings' ] && current_user_can( 'edit_others_posts' ) ) {
  1160. // track strings if the user has enabled this and if it's and editor or admin
  1161. icl_st_track_string( $text, $context, ICL_STRING_TRANSLATION_STRING_TRACKING_TYPE_PAGE );
  1162. }
  1163. if($register_dynamic_string) {
  1164. // register strings if the user has used ICL_STRING_TRANSLATION_DYNAMIC_CONTEXT (or it's value) as a text domain
  1165. icl_register_string($context, $name, $text);
  1166. }
  1167. if ( empty( $name ) ) {
  1168. $name = md5( $text );
  1169. }
  1170. $ret_translation = icl_t( $context, $name, $text, $has_translation );
  1171. if ( false === $has_translation ) {
  1172. $ret_translation = $translation;
  1173. }
  1174. if ( isset( $_GET[ 'icl_string_track_value' ] ) && isset( $_GET[ 'icl_string_track_context' ] )
  1175. && stripslashes( $_GET[ 'icl_string_track_context' ] ) == $context && stripslashes( $_GET[ 'icl_string_track_value' ] ) == $text
  1176. ) {
  1177. $ret_translation = '<span style="background-color:' . $sitepress_settings[ 'st' ][ 'hl_color' ] . '">' . $ret_translation . '</span>';
  1178. }
  1179. wp_cache_set( $cache_name, $ret_translation );
  1180. return $ret_translation;
  1181. }
  1182. function icl_sw_filters_gettext_with_context($translation, $text, $_gettext_context, $domain){
  1183. return icl_sw_filters_gettext($translation, $text, $domain, $_gettext_context . ': ' . $text);
  1184. }
  1185. function icl_sw_filters_ngettext($translation, $single, $plural, $number, $domain, $_gettext_context = false){
  1186. if($number == 1){
  1187. return icl_sw_filters_gettext($translation, $single, $domain, $_gettext_context);
  1188. }else{
  1189. return icl_sw_filters_gettext($translation, $plural, $domain, $_gettext_context);
  1190. }
  1191. }
  1192. function icl_sw_filters_nxgettext($translation, $single, $plural, $number, $_gettext_context, $domain){
  1193. return icl_sw_filters_ngettext($translation, $single, $plural, $number, $domain, $_gettext_context);
  1194. }
  1195. function icl_st_author_first_name_filter($value, $user_id){
  1196. global $sitepress_settings;
  1197. if(false === $user_id){
  1198. global $authordata;
  1199. $user_id = $authordata->data->ID;
  1200. }
  1201. $user = new WP_User($user_id);
  1202. if ( is_array( $user->roles ) && array_intersect($user->roles, (array)$sitepress_settings['st']['translated-users'])){
  1203. $value = icl_st_translate_author_fields('first_name', $value, $user_id);
  1204. }
  1205. return $value;
  1206. }
  1207. function icl_st_author_last_name_filter($value, $user_id){
  1208. global $sitepress_settings;
  1209. if(false === $user_id){
  1210. global $authordata;
  1211. $user_id = $authordata->data->ID;
  1212. }
  1213. $user = new WP_User($user_id);
  1214. if ( is_array( $user->roles ) && array_intersect($user->roles, (array)$sitepress_settings['st']['translated-users'])){
  1215. $value = icl_st_translate_author_fields('last_name', $value, $user_id);
  1216. }
  1217. return $value;
  1218. }
  1219. function icl_st_author_nickname_filter($value, $user_id){
  1220. global $sitepress_settings;
  1221. if(false === $user_id){
  1222. global $authordata;
  1223. $user_id = $authordata->data->ID;
  1224. }
  1225. $user = new WP_User($user_id);
  1226. if ( is_array( $user->roles ) && array_intersect($user->roles, (array)$sitepress_settings['st']['translated-users'])){
  1227. $value = icl_st_translate_author_fields('nickname', $value, $user_id);
  1228. }
  1229. return $value;
  1230. }
  1231. function icl_st_author_description_filter($value, $user_id){
  1232. global $sitepress_settings;
  1233. if(false === $user_id){
  1234. global $authordata;
  1235. if(empty($authordata->data)) return $value;
  1236. $user_id = $authordata->data->ID;
  1237. }
  1238. $user = new WP_User($user_id);
  1239. if(!isset($sitepress_settings['st']['translated-users'])) $sitepress_settings['st']['translated-users'] = array();
  1240. if ( is_array( $user->roles ) && is_array($sitepress_settings['st']['translated-users']) && array_intersect($user->roles, $sitepress_settings['st']['translated-users'])){
  1241. $value = icl_st_translate_author_fields('description', $value, $user_id);
  1242. }
  1243. return $value;
  1244. }
  1245. function icl_st_author_displayname_filter($value){
  1246. global $authordata, $sitepress_settings;
  1247. if(isset($authordata->ID)){
  1248. $user = new WP_User($authordata->ID);
  1249. if ( is_array( $user->roles ) && isset($sitepress_settings['st']['translated-users']) && array_intersect($user->roles, (array)$sitepress_settings['st']['translated-users'])){
  1250. $value = icl_st_translate_author_fields('display_name', $value, isset($authordata->ID)?$authordata->ID:null);
  1251. }
  1252. }
  1253. return $value;
  1254. }
  1255. function icl_st_translate_author_fields($field, $value, $user_id){
  1256. global $sitepress_settings, $sitepress;
  1257. $current_user = $sitepress->get_current_user();
  1258. if(empty($user_id)) $user_id = $current_user->ID;
  1259. if(!isset($sitepress_settings['st']['translated-users'])) $sitepress_settings['st']['translated-users'] = array();
  1260. $user = new WP_User($user_id);
  1261. if ( is_array( $user->roles ) && is_array($sitepress_settings['st']['translated-users']) && array_intersect($user->roles, (array)$sitepress_settings['st']['translated-users'])){
  1262. $value = icl_translate('Authors', $field . '_' . $user_id, $value, true);
  1263. }
  1264. return $value;
  1265. }
  1266. function icl_st_register_user_strings($user_id){
  1267. global $sitepress_settings;
  1268. $user = new WP_User($user_id);
  1269. if(!isset($sitepress_settings['st']['translated-users'])) $sitepress_settings['st']['translated-users'] = array();
  1270. if ( is_array( $user->roles ) && is_array($sitepress_settings['st']['translated-users']) && array_intersect($user->roles, (array)$sitepress_settings['st']['translated-users'])){
  1271. $fields = array('first_name', 'last_name', 'nickname', 'description');
  1272. foreach($fields as $field){
  1273. icl_register_string('Authors', $field . '_' . $user_id, get_the_author_meta($field, $user_id), true, true);
  1274. }
  1275. icl_register_string('Authors', 'display_name_' . $user_id, $user->display_name, true, true);
  1276. }
  1277. }
  1278. function icl_st_register_user_strings_all(){
  1279. global $wpdb;
  1280. $users = get_users(array('blog_id'=>$wpdb->blogid, 'fields'=>'ID'));
  1281. foreach($users as $uid){
  1282. icl_st_register_user_strings($uid);
  1283. }
  1284. }
  1285. function icl_st_update_string_actions($context, $name, $old_value, $new_value, $force_complete = false){
  1286. global $wpdb;
  1287. if($new_value != $old_value){
  1288. $string = $wpdb->get_row($wpdb->prepare("SELECT id, value, status FROM {$wpdb->prefix}icl_strings WHERE context=%s AND name=%s", $context, $name));
  1289. if(!$string){
  1290. icl_register_string($context, $name, $new_value);
  1291. return;
  1292. }
  1293. $wpdb->update($wpdb->prefix . 'icl_strings', array('value'=>$new_value), array('id'=>$string->id));
  1294. if($string->status == ICL_STRING_TRANSLATION_COMPLETE || $string->status == ICL_STRING_TRANSLATION_PARTIAL){
  1295. /*if $force_complete is set to true, all translations will be marked as complete even if a string's original value is updated
  1296. This is currently only used to allow editing tagline and blogname for one language, without influencing other languages
  1297. */
  1298. if ( $force_complete ) {
  1299. $new_status = ICL_STRING_TRANSLATION_COMPLETE;
  1300. } else {
  1301. $new_status = ICL_STRING_TRANSLATION_NEEDS_UPDATE;
  1302. }
  1303. $wpdb->update($wpdb->prefix . 'icl_string_translations', array('status'=>$new_status), array('string_id'=>$string->id));
  1304. $wpdb->update($wpdb->prefix . 'icl_strings', array('status'=>$new_status), array('id'=>$string->id));
  1305. }
  1306. if($context == 'Widgets' && $new_value){
  1307. if(0 === strpos($name, 'widget title - ')){
  1308. icl_rename_string('Widgets', 'widget title - ' . md5($old_value), 'widget title - ' . md5($new_value));
  1309. }elseif(0 === strpos($name, 'widget body - ')){
  1310. icl_rename_string('Widgets', 'widget body - ' . md5($old_value), 'widget body - ' . md5($new_value));
  1311. }
  1312. }
  1313. }
  1314. }
  1315. function icl_st_update_blogname_actions($old, $new){
  1316. icl_st_update_string_actions('WP', 'Blog Title', $old, $new, true );
  1317. }
  1318. function icl_st_update_blogdescription_actions($old, $new){
  1319. icl_st_update_string_actions('WP', 'Tagline', $old, $new, true );
  1320. }
  1321. function icl_st_update_widget_title_actions($old_options, $new_options){
  1322. if(isset($new_options['title'])){ // case of 1 instance only widgets
  1323. $buf = $new_options;
  1324. unset($new_options);
  1325. $new_options[0] = $buf;
  1326. unset($buf);
  1327. $buf = $old_options;
  1328. unset($old_options);
  1329. $old_options[0] = $buf;
  1330. unset($buf);
  1331. }
  1332. foreach($new_options as $k=>$o){
  1333. if(isset($o['title'])){
  1334. if(isset($old_options[$k]['title']) && $old_options[$k]['title']){
  1335. icl_st_update_string_actions('Widgets', 'widget title - ' . md5($old_options[$k]['title']), $old_options[$k]['title'], $o['title']);
  1336. }else{
  1337. if($new_options[$k]['title']){
  1338. icl_register_string('Widgets', 'widget title - ' . md5($new_options[$k]['title']), $new_options[$k]['title']);
  1339. }
  1340. }
  1341. }
  1342. }
  1343. }
  1344. function icl_st_update_text_widgets_actions($old_options, $new_options){
  1345. global $sitepress_settings, $wpdb;
  1346. // remove filter for showing permalinks instead of sticky links while saving
  1347. $GLOBALS['__disable_absolute_links_permalink_filter'] = 1;
  1348. $widget_text = get_option('widget_text');
  1349. if(is_array($widget_text)){
  1350. foreach($widget_text as $k=>$w){
  1351. if(isset($old_options[$k]['text']) && trim($old_options[$k]['text']) && $old_options[$k]['text'] != $w['text']){
  1352. $old_md5 = md5($old_options[$k]['text']);
  1353. $string = $wpdb->get_row($wpdb->prepare("SELECT id, value, status FROM {$wpdb->prefix}icl_strings WHERE context=%s AND name=%s", 'Widgets', 'widget body - ' . $old_md5));
  1354. if ($string) {
  1355. icl_st_update_string_actions('Widgets', 'widget body - ' . $old_md5, $old_options[$k]['text'], $w['text']);
  1356. } else {
  1357. icl_register_string('Widgets', 'widget body - ' . md5($w['text']), $w['text']);
  1358. }
  1359. }elseif(isset($new_options[$k]['text']) && $old_options[$k]['text']!=$new_options[$k]['text']){
  1360. icl_register_string('Widgets', 'widget body - ' . md5($new_options[$k]['text']), $new_options[$k]['text']);
  1361. }
  1362. }
  1363. }
  1364. // add back the filter for showing permalinks instead of sticky links after saving
  1365. unset($GLOBALS['__disable_absolute_links_permalink_filter']);
  1366. }
  1367. function icl_t_cache_lookup($context, $name){
  1368. global $sitepress, $wpdb;
  1369. // static $front_end_language = false;
  1370. static $icl_st_cache;
  1371. $ret_value = false;
  1372. $blog_id = 0;
  1373. if (isset($GLOBALS['blog_id'])) {
  1374. $blog_id = $GLOBALS['blog_id'];
  1375. }
  1376. $current_language = get_current_string_language( $name );
  1377. if(!isset($icl_st_cache[$blog_id][$current_language][$context])){ //CACHE MISS (context)
  1378. $icl_st_cache[$blog_id][$current_language][$context] = array();
  1379. // workaround for multi-site setups - part i
  1380. // @todo find out why somebody added this workaround, now workarounded again by konrad (part $name != "Blog Title" )
  1381. global $switched, $_wp_switched_stack;
  1382. if(isset($switched) && $switched && $_wp_switched_stack && $name != "Blog Title"){
  1383. $prev_blog_id = $wpdb->blogid;
  1384. $wpdb->set_blog_id($_wp_switched_stack[0]);
  1385. }
  1386. // THE QUERY
  1387. $res = $wpdb->get_results($wpdb->prepare("
  1388. SELECT s.name, s.value, t.value AS translation_value, t.status
  1389. FROM {$wpdb->prefix}icl_strings s
  1390. LEFT JOIN {$wpdb->prefix}icl_string_translations t ON s.id = t.string_id
  1391. WHERE s.context = %s
  1392. AND (t.language = %s OR t.language IS NULL)
  1393. ", $context, $current_language), ARRAY_A);
  1394. // workaround for multi-site setups - part ii
  1395. if(isset($switched) && $switched && $_wp_switched_stack && $name != "Blog Title"){
  1396. $wpdb->set_blog_id($prev_blog_id);
  1397. }
  1398. // SAVE QUERY RESULTS
  1399. if($res){
  1400. foreach($res as $row){
  1401. if($row['status'] != ICL_STRING_TRANSLATION_COMPLETE || empty($row['translation_value'])){
  1402. $icl_st_cache[$blog_id][$current_language][$context][$row['name']]['translated'] = false;
  1403. $icl_st_cache[$current_language][$context][$row['name']]['value'] = $row['value'];
  1404. }else{
  1405. $icl_st_cache[$blog_id][$current_language][$context][$row['name']]['translated'] = true;
  1406. $icl_st_cache[$blog_id][$current_language][$context][$row['name']]['value'] = $row['translation_value'];
  1407. $icl_st_cache[$blog_id][$current_language][$context][$row['name']]['original'] = $row['value'];
  1408. }
  1409. }
  1410. }
  1411. }
  1412. if(isset($icl_st_cache[$blog_id][$current_language][$context][$name])){
  1413. $ret_value = $icl_st_cache[$blog_id][$current_language][$context][$name];
  1414. }
  1415. return $ret_value;
  1416. }
  1417. function icl_st_get_contexts($status){
  1418. global $wpdb, $sitepress, $sitepress_settings;
  1419. $extra_cond = '';
  1420. $joins = '';
  1421. $results = false;
  1422. $current_user = $sitepress->get_current_user();
  1423. if($status !== false){
  1424. if($status == ICL_STRING_TRANSLATION_COMPLETE){
  1425. $extra_cond .= " AND s.status = " . ICL_STRING_TRANSLATION_COMPLETE;
  1426. }else{
  1427. $extra_cond .= " AND s.status IN (" . ICL_STRING_TRANSLATION_PARTIAL . "," . ICL_STRING_TRANSLATION_NEEDS_UPDATE . "," . ICL_STRING_TRANSLATION_NOT_TRANSLATED . ")";
  1428. }
  1429. }
  1430. if(icl_st_is_translator()){
  1431. $user_langs = get_user_meta($current_user->ID, $wpdb->prefix.'language_pairs', true);
  1432. $active_langs = $sitepress->get_active_languages();
  1433. if(!empty($user_langs[$sitepress_settings['st']['strings_language']])){
  1434. foreach($user_langs[$sitepress_settings['st']['strings_language']] as $lang=>$one){
  1435. if(isset($active_langs[$lang])){
  1436. $lcode_alias = str_replace('-', '', $lang);
  1437. $joins[] = " JOIN {$wpdb->prefix}icl_string_translations {$lcode_alias}_str ON {$lcode_alias}_str.string_id = s.id AND {$lcode_alias}_str.language='{$lcode_alias}' AND
  1438. (
  1439. {$lcode_alias}_str.status = " . ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR .
  1440. " OR {$lcode_alias}_str.translator_id = " . $current_user->ID
  1441. . ")" . "\n";
  1442. }
  1443. }
  1444. $sql = "
  1445. SELECT s.context, COUNT(s.context) AS c FROM {$wpdb->prefix}icl_strings s
  1446. ".join("\n", $joins)."
  1447. WHERE 1 {$extra_cond}
  1448. GROUP BY context
  1449. ORDER BY context ASC
  1450. ";
  1451. $results = $wpdb->get_results($sql);
  1452. }
  1453. }else{
  1454. $results = $wpdb->get_results( $wpdb->prepare("
  1455. SELECT context, COUNT(context) AS c
  1456. FROM {$wpdb->prefix}icl_strings s
  1457. WHERE language=%s {$extra_cond}
  1458. GROUP BY context
  1459. ORDER BY context ASC", $sitepress_settings['st']['strings_language']));
  1460. }
  1461. return $results;
  1462. }
  1463. function icl_st_admin_notices(){
  1464. global $icl_st_err_str;
  1465. if($icl_st_err_str){
  1466. echo '<div class="error"><p>' . $icl_st_err_str . '</p></div>';
  1467. }
  1468. }
  1469. function icl_st_scan_theme_files($dir = false, $recursion = 0){
  1470. require_once ICL_PLUGIN_PATH . '/inc/potx.php';
  1471. static $scan_stats = false;
  1472. static $recursion, $scanned_files = array();
  1473. global $icl_scan_theme_found_domains, $sitepress, $sitepress_settings;
  1474. if($dir === false){
  1475. $dir = TEMPLATEPATH;
  1476. }
  1477. if(!$scan_stats){
  1478. $scan_stats = sprintf(__('Scanning theme folder: %s', 'wpml-string-translation'),$dir) . PHP_EOL;
  1479. }
  1480. $dh = opendir($dir);
  1481. while(false !== ($file = readdir($dh))){
  1482. if(0 === strpos($file, '.')) continue;
  1483. if(is_dir($dir . "/" . $file)){
  1484. $recursion++;
  1485. $scan_stats .= str_repeat("\t",$recursion) . sprintf(__('Opening folder: %s', 'wpml-string-translation'), $dir . "/" . $file) . PHP_EOL;
  1486. icl_st_scan_theme_files($dir . "/" . $file, $recursion);
  1487. $recursion--;
  1488. }elseif(preg_match('#(\.php|\.inc)$#i', $file)){
  1489. // THE potx way
  1490. $scan_stats .= str_repeat("\t",$recursion) . sprintf(__('Scanning file: %s', 'wpml-string-translation'), $dir . "/" . $file) . PHP_EOL;
  1491. $scanned_files[] = $dir . "/" . $file;
  1492. _potx_process_file($dir . "/" . $file, 0, '__icl_st_scan_theme_files_store_results','_potx_save_version', POTX_API_7);
  1493. }else{
  1494. $scan_stats .= str_repeat("\t",$recursion) . sprintf(__('Skipping file: %s', 'wpml-string-translation'), $dir . "/" . $file) . PHP_EOL;
  1495. }
  1496. }
  1497. if($dir == TEMPLATEPATH && TEMPLATEPATH != STYLESHEETPATH){
  1498. static $double_scan = true;
  1499. icl_st_scan_theme_files(STYLESHEETPATH);
  1500. $double_scan = false;
  1501. }
  1502. if(!$recursion && (empty($double_scan) || !$double_scan)){
  1503. global $__icl_registered_strings;
  1504. $scan_stats .= __('Done scanning files', 'wpml-string-translation') . PHP_EOL;
  1505. $sitepress_settings['st']['theme_localization_domains'] = array_keys($icl_scan_theme_found_domains);
  1506. $sitepress->save_settings($sitepress_settings);
  1507. closedir($dh);
  1508. $scan_stats_all = __('= Your theme was scanned for texts =', 'wpml-string-translation') . '<br />' .
  1509. __('The following files were processed:', 'wpml-string-translation') . '<br />' .
  1510. '<ol style="font-size:10px;"><li>' . join('</li><li>', $scanned_files) . '</li></ol>' .
  1511. sprintf(__('WPML found %s strings. They were added to the string translation table.','wpml-string-translation'),count($__icl_registered_strings)) .
  1512. '<br /><a href="#" onclick="jQuery(this).next().toggle();return false;">' . __('More details', 'wpml-string-translation') . '</a>'.
  1513. '<textarea style="display:none;width:100%;height:150px;font-size:10px;">' . $scan_stats . '</textarea>';
  1514. return $scan_stats_all;
  1515. }
  1516. }
  1517. function __icl_st_scan_theme_files_store_results($string, $domain, $_gettext_context, $file, $line){
  1518. global $icl_scan_theme_found_domains;
  1519. $string = str_replace(array('\"',"\\'"), array('"',"'"), $string);
  1520. //replace extra backslashes added by _potx_process_file
  1521. $string = str_replace(array('\\\\'), array('\\'), $string);
  1522. if(!isset($icl_scan_theme_found_domains[$domain])){
  1523. $icl_scan_theme_found_domains[$domain] = true;
  1524. }
  1525. global $wpdb, $__icl_registered_strings;
  1526. $context = false;
  1527. if(!isset($__icl_registered_strings)){
  1528. $__icl_registered_strings = array();
  1529. // clear existing entries (both source and page type)
  1530. $context = $domain ? 'theme ' . $domain : 'WordPress';
  1531. $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}icl_string_positions WHERE string_id IN
  1532. (SELECT id FROM {$wpdb->prefix}icl_strings WHERE context = %s)", $context));
  1533. }
  1534. if(!isset($__icl_registered_strings[$domain.'||'.$string.'||'.$_gettext_context])){
  1535. if(!$domain){
  1536. $context = 'WordPress';
  1537. }else{
  1538. $context = 'theme ' . $domain;
  1539. }
  1540. $name = $_gettext_context ? $_gettext_context . ': ' . $string : md5($string);
  1541. icl_register_string($context, $name, $string);
  1542. $__icl_registered_strings[$domain.'||'.$string.'||'.$_gettext_context] = true;
  1543. }
  1544. // store position in source
  1545. icl_st_track_string($string, $context, ICL_STRING_TRANSLATION_STRING_TRACKING_TYPE_SOURCE, $file, $line);
  1546. }
  1547. function icl_st_scan_plugin_files($plugin, $recursion = 0){
  1548. require_once ICL_PLUGIN_PATH . '/inc/potx.php';
  1549. static $recursion, $scanned_files = array();
  1550. static $scan_stats = false;
  1551. global $icl_scan_plugin_found_domains, $icl_st_p_scan_plugin_id,
  1552. $sitepress, $sitepress_settings;
  1553. if(!$recursion){
  1554. $icl_st_p_scan_plugin_id = str_replace(WP_PLUGIN_DIR .'/', '', $plugin);
  1555. $icl_st_p_scan_plugin_id = str_replace(WPMU_PLUGIN_DIR .'/', '', $icl_st_p_scan_plugin_id);
  1556. }
  1557. if(is_file($plugin) && !$recursion){ // case of one-file plugins
  1558. $scan_stats = sprintf(__('Scanning file: %s', 'wpml-string-translation'), $plugin) . PHP_EOL;
  1559. _potx_process_file($plugin, 0, '__icl_st_scan_plugin_files_store_results','_potx_save_version', POTX_API_7);
  1560. $scanned_files[] = $plugin;
  1561. }else{
  1562. $dh = opendir($plugin);
  1563. while(false !== ($file = readdir($dh))){
  1564. if(0 === strpos($file, '.')) continue;
  1565. if(is_dir($plugin . "/" . $file)){
  1566. $recursion++;
  1567. $scan_stats .= str_repeat("\t",$recursion-1) . sprintf(__('Opening folder: %s', 'wpml-string-translation'), "/" . $file) . PHP_EOL;
  1568. icl_st_scan_plugin_files($plugin . "/" . $file, $recursion);
  1569. $recursion--;
  1570. }elseif(preg_match('#(\.php|\.inc)$#i', $file)){
  1571. $scan_stats .= str_repeat("\t",$recursion) . sprintf(__('Scanning file: %s', 'wpml-string-translation'), "/" . $file) . PHP_EOL;
  1572. $scanned_files[] = "/" . $file;
  1573. _potx_process_file($plugin . "/" . $file, 0, '__icl_st_scan_plugin_files_store_results','_potx_save_version', POTX_API_7);
  1574. }else{
  1575. $scan_stats .= str_repeat("\t",$recursion) . sprintf(__('Skipping file: %s', 'wpml-string-translation'), "/" . $file) . PHP_EOL;
  1576. }
  1577. }
  1578. }
  1579. if(!$recursion){
  1580. global $__icl_registered_strings;
  1581. if(is_null($__icl_registered_strings)){
  1582. $__icl_registered_strings = array();
  1583. }
  1584. $scan_stats .= __('Done scanning files', 'wpml-string-translation') . PHP_EOL;
  1585. /*
  1586. if(is_array($icl_scan_plugin_found_domains)){
  1587. $existing_domains = $sitepress_settings['st']['plugins_localization_domains'];
  1588. if(is_array($existing_domains)){
  1589. $sitepress_settings['st']['plugins_localization_domains'] = array_unique(array_merge(array_keys($icl_scan_plugin_found_domains), $existing_domains));
  1590. }else{
  1591. $sitepress_settings['st']['plugins_localization_domains'] = array_keys($icl_scan_plugin_found_domains);
  1592. }
  1593. $sitepress->save_settings($sitepress_settings);
  1594. }
  1595. */
  1596. unset($icl_st_p_scan_plugin_id);
  1597. $scan_stats = '<textarea style="width:100%;height:150px;font-size:10px;">' . $scan_stats . "\n" .
  1598. count($scanned_files) . ' scanned files' . "\n";
  1599. if(count($__icl_registered_strings)){
  1600. $scan_stats .= sprintf(__('WPML found %s strings. They were added to the string translation table.','wpml-string-translation'),count($__icl_registered_strings)) . "\n";
  1601. }else{
  1602. $scan_stats .= __('No strings found.','wpml-string-translation') . "\n";
  1603. }
  1604. $scan_stats .= '</textarea>';
  1605. $scan_stats_ret = $scan_stats;
  1606. $scan_stats = false;
  1607. return $scan_stats_ret;
  1608. }
  1609. }
  1610. function __icl_st_scan_plugin_files_store_results($string, $domain, $_gettext_context, $file, $line){
  1611. global $icl_scan_plugin_found_domains, $icl_st_p_scan_plugin_id;
  1612. $string = str_replace(array('\"',"\\'"), array('"',"'"), $string);
  1613. //replace extra backslashes added by _potx_process_file
  1614. $string = str_replace(array('\\\\'), array('\\'), $string);
  1615. //if(!isset($icl_scan_plugin_found_domains[$domain])){
  1616. // $icl_scan_plugin_found_domains[$domain] = true;
  1617. //}
  1618. global $wpdb, $__icl_registered_strings;
  1619. if(empty($__icl_registered_strings) ){
  1620. $__icl_registered_strings = array();
  1621. // clear existing entries (both source and page type)
  1622. $context = $icl_st_p_scan_plugin_id ? 'plugin ' . $icl_st_p_scan_plugin_id : 'plugins';
  1623. $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}icl_string_positions WHERE string_id IN
  1624. (SELECT id FROM {$wpdb->prefix}icl_strings WHERE context = %s)", $context));
  1625. }
  1626. if(!isset($__icl_registered_strings[$icl_st_p_scan_plugin_id.'||'.$string])){
  1627. $name = $_gettext_context ? $_gettext_context . ': ' . $string : md5($string);
  1628. if(!$domain){
  1629. icl_register_string('plugins', $name, $string);
  1630. }else{
  1631. icl_register_string('plugin ' . $icl_st_p_scan_plugin_id, $name, $string);
  1632. }
  1633. $__icl_registered_strings[$icl_st_p_scan_plugin_id.'||'.$string] = true;
  1634. }
  1635. // store position in source
  1636. icl_st_track_string($string, 'plugin ' . $icl_st_p_scan_plugin_id, ICL_STRING_TRANSLATION_STRING_TRACKING_TYPE_SOURCE, $file, $line);
  1637. }
  1638. function get_theme_localization_stats(){
  1639. global $sitepress_settings, $wpdb;
  1640. $stats = false;
  1641. if(isset($sitepress_settings['st']['theme_localization_domains'])){
  1642. foreach((array)$sitepress_settings['st']['theme_localization_domains'] as $domain){
  1643. $domains[] = $domain ? 'theme ' . $domain : 'theme';
  1644. }
  1645. $results = $wpdb->get_results("
  1646. SELECT context, status, COUNT(id) AS c
  1647. FROM {$wpdb->prefix}icl_strings
  1648. WHERE context IN ('".join("','",$domains)."')
  1649. GROUP BY context, status
  1650. ");
  1651. foreach($results as $r){
  1652. if(!isset($stats[$r->context]['complete'])){
  1653. $stats[$r->context]['complete'] = 0;
  1654. }
  1655. if(!isset($stats[$r->context]['incomplete'])){
  1656. $stats[$r->context]['incomplete'] = 0;
  1657. }
  1658. if($r->status == ICL_STRING_TRANSLATION_COMPLETE){
  1659. $stats[$r->context]['complete'] = $r->c;
  1660. }else{
  1661. $stats[$r->context]['incomplete'] += $r->c;
  1662. }
  1663. }
  1664. }
  1665. return $stats;
  1666. }
  1667. function get_plugin_localization_stats(){
  1668. global $sitepress_settings, $wpdb;
  1669. $stats = false;
  1670. $results = $wpdb->get_results("
  1671. SELECT context, status, COUNT(id) AS c
  1672. FROM {$wpdb->prefix}icl_strings
  1673. WHERE context LIKE ('plugin %')
  1674. GROUP BY context, status
  1675. ");
  1676. foreach($results as $r){
  1677. if(!isset($stats[$r->context]['complete'])){
  1678. $stats[$r->context]['complete'] = 0;
  1679. }
  1680. if(!isset($stats[$r->context]['incomplete'])){
  1681. $stats[$r->context]['incomplete'] = 0;
  1682. }
  1683. if($r->status == ICL_STRING_TRANSLATION_COMPLETE){
  1684. $stats[$r->context]['complete'] = $r->c;
  1685. }else{
  1686. $stats[$r->context]['incomplete'] += $r->c;
  1687. }
  1688. }
  1689. return $stats;
  1690. }
  1691. function icl_st_generate_po_file($strings, $potonly = false){
  1692. require_once('po_parser.class.php');
  1693. $po = po_parser::create_po( $strings, $potonly = false );
  1694. return $po;
  1695. }
  1696. function icl_st_track_string($text, $context, $kind = ICL_STRING_TRANSLATION_STRING_TRACKING_TYPE_PAGE, $file = null, $line = null){
  1697. global $wpdb;
  1698. // get string id
  1699. $string_id = $wpdb->get_var("SELECT id FROM {$wpdb->prefix}icl_strings WHERE context='".esc_sql($context)."' AND value='".esc_sql($text)."'");
  1700. if($string_id){
  1701. // get existing records
  1702. $string_records_count = $wpdb->get_var("SELECT COUNT(id)
  1703. FROM {$wpdb->prefix}icl_string_positions
  1704. WHERE string_id = '{$string_id}' AND kind = " . $kind);
  1705. if(ICL_STRING_TRANSLATION_STRING_TRACKING_THRESHOLD > $string_records_count){
  1706. if($kind == ICL_STRING_TRANSLATION_STRING_TRACKING_TYPE_PAGE){
  1707. // get page url
  1708. $https = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's':'';
  1709. $position = 'http' . $https . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  1710. }else{
  1711. $position = $file . '::' . $line;
  1712. }
  1713. if(!$wpdb->get_var("SELECT id FROM {$wpdb->prefix}icl_string_positions
  1714. WHERE string_id='{$string_id}' AND position_in_page='".esc_sql($position)."' AND kind='".$kind."'")){
  1715. $wpdb->insert($wpdb->prefix . 'icl_string_positions', array(
  1716. 'string_id' => $string_id,
  1717. 'kind' => $kind,
  1718. 'position_in_page' => $position
  1719. ));
  1720. }
  1721. }
  1722. }
  1723. }
  1724. function icl_st_string_in_page($string_id){
  1725. global $wpdb;
  1726. // get urls
  1727. $urls = $wpdb->get_col($wpdb->prepare("SELECT position_in_page
  1728. FROM {$wpdb->prefix}icl_string_positions
  1729. WHERE string_id = %d AND kind = %d", $string_id, ICL_STRING_TRANSLATION_STRING_TRACKING_TYPE_PAGE));
  1730. if(!empty($urls)){
  1731. $string = $wpdb->get_row($wpdb->prepare("SELECT context, value FROM {$wpdb->prefix}icl_strings WHERE id=%d", $string_id));
  1732. echo '<div id="icl_show_source_top">';
  1733. for($i = 0; $i < count($urls); $i++){
  1734. $c = $i+1;
  1735. if(strpos($urls[$i], '?') !== false){
  1736. $urls[$i] .= '&icl_string_track_value=' . $string->value;
  1737. }else{
  1738. $urls[$i] .= '?icl_string_track_value=' . $string->value;
  1739. }
  1740. $urls[$i] .= '&icl_string_track_context=' . $string->context;
  1741. echo '<a href="#" onclick="jQuery(\'#icl_string_track_frame_wrap iframe\').attr(\'src\',\''.esc_url($urls[$i]).'\');jQuery(\'#icl_string_track_url a\').html(\''.esc_url($urls[$i]).'\').attr(\'href\', \''.esc_url($urls[$i]).'\'); return false;">'.$c.'</a><br />';
  1742. }
  1743. echo '</div>';
  1744. echo '<div id="icl_string_track_frame_wrap">';
  1745. echo '<iframe onload="iclResizeIframe()" src="'.$urls[0].'" width="10" height="10" frameborder="0" marginheight="0" marginwidth="0"></iframe>';
  1746. echo '<div id="icl_string_track_url" class="icl_string_track_url"><a href="'.esc_url($urls[0]).'">' . esc_html($urls[0]) . "</a></div>\n";
  1747. echo '</div>';
  1748. }else{
  1749. _e('No records found', 'wpml-string-translation');
  1750. }
  1751. }
  1752. function icl_st_string_in_source($string_id){
  1753. global $wpdb, $sitepress_settings;
  1754. // get positions
  1755. $files = $wpdb->get_col($wpdb->prepare("SELECT position_in_page
  1756. FROM {$wpdb->prefix}icl_string_positions
  1757. WHERE string_id = %d AND kind = %d", $string_id, ICL_STRING_TRANSLATION_STRING_TRACKING_TYPE_SOURCE));
  1758. if(!empty($files)){
  1759. $string = $wpdb->get_row($wpdb->prepare("SELECT context, value FROM {$wpdb->prefix}icl_strings WHERE id=%d",$string_id));
  1760. echo '<div id="icl_show_source_top">';
  1761. for($i = 0; $i < count($files); $i++){
  1762. $c = $i+1;
  1763. $exp = explode('::', $files[$i]);
  1764. $line = $exp[1];
  1765. echo '<a href="#" onclick="icl_show_in_source('.$i.','.$line.')">'.$c.'</a><br />';
  1766. }
  1767. echo '</div>';
  1768. echo '<div id="icl_show_source_wrap">';
  1769. for($i = 0; $i < count($files); $i++){
  1770. $exp = explode('::', $files[$i]);
  1771. $file = $exp[0];
  1772. if(!file_exists($file) || !is_readable($file)) continue;
  1773. $line = $exp[1];
  1774. echo '<div class="icl_string_track_source" id="icl_string_track_source_'.$i.'"';
  1775. if($i > 0){
  1776. echo 'style="display:none"';
  1777. }else{
  1778. $first_pos = $line;
  1779. }
  1780. echo '>';
  1781. if($i == 0){
  1782. echo '<script type="text/javascript">icl_show_in_source_scroll_once = ' . $line . '</script>';
  1783. }
  1784. echo '<div class="icl_string_track_filename">' . $file . "</div>\n";
  1785. echo '<pre>';
  1786. $content = file($file);
  1787. echo '<ol>';
  1788. $hl_color = !empty($sitepress_settings['st']['hl_color'])?$sitepress_settings['st']['hl_color']:'#FFFF00';
  1789. foreach($content as $k=>$l){
  1790. if($k == $line-1){
  1791. $hl = ' style="background-color:'.$hl_color.';"';
  1792. }else{
  1793. $hl = '';
  1794. }
  1795. echo '<li id="icl_source_line_'.$i.'_'.$k.'"'.$hl.'">' . esc_html($l) . '&nbsp;</li>';
  1796. }
  1797. echo '</ol>';
  1798. echo '</pre>';
  1799. echo '</div>';
  1800. }
  1801. echo '</div>';
  1802. }else{
  1803. _e('No records found', 'wpml-string-translation');
  1804. }
  1805. }
  1806. function _icl_st_hide_random($str){
  1807. $str = preg_replace('#^((.+)( - ))?([a-z0-9]{32})$#', '$2', $str);
  1808. return $str;
  1809. }
  1810. function _icl_st_get_options_writes($path){
  1811. static $found_writes = array();
  1812. if(is_dir($path)){
  1813. $dh = opendir($path);
  1814. while($file = readdir($dh)){
  1815. if($file=="." || $file=="..") continue;
  1816. if(is_dir($path . '/' . $file)){
  1817. _icl_st_get_options_writes($path . '/' . $file);
  1818. }elseif(preg_match('#(\.php|\.inc)$#i', $file)){
  1819. $content = file_get_contents($path . '/' . $file);
  1820. $int = preg_match_all('#(add|update)_option\(([^,]+),([^)]+)\)#im', $content, $matches);
  1821. if($int){
  1822. foreach($matches[2] as $m){
  1823. $option_name = trim($m);
  1824. if(0 === strpos($option_name, '"') || 0 === strpos($option_name, "'")){
  1825. $option_name = trim($option_name, "\"'");
  1826. }elseif(false === strpos($option_name, '$')){
  1827. if(false !== strpos($option_name, '::')){
  1828. $cexp = explode('::', $option_name);
  1829. if (class_exists($cexp[0])){
  1830. if (defined($cexp[0].'::'. $cexp[1])){
  1831. $option_name = constant($cexp[0].'::'. $cexp[1]);
  1832. }
  1833. }
  1834. }else{
  1835. if (defined( $option_name )){
  1836. $option_name = constant($option_name);
  1837. }
  1838. }
  1839. }else{
  1840. $option_name = false;
  1841. }
  1842. if($option_name){
  1843. $found_writes[] = $option_name;
  1844. }
  1845. }
  1846. }
  1847. }
  1848. }
  1849. }
  1850. return $found_writes;
  1851. }
  1852. function icl_st_scan_options_strings(){
  1853. global $wpdb;
  1854. $options = array();
  1855. // scan theme php file for update_option(), add_option()
  1856. $options_names = _icl_st_get_options_writes(ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY);
  1857. $options_names = array_merge($options_names, _icl_st_get_options_writes(ICL_STRING_TRANSLATION_STYLESHEET_DIRECTORY));
  1858. $options_names = array_unique($options_names);
  1859. $options_names = array_map('esc_sql', $options_names);
  1860. if(!empty($options_names)){
  1861. $res = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE option_name IN ('".join("','", $options_names)."')");
  1862. foreach($res as $row){
  1863. $options[$row->option_name] = maybe_unserialize($row->option_value);
  1864. // try unserializing twice - just in case (see Arras Theme)
  1865. $options[$row->option_name] = maybe_unserialize($options[$row->option_name]);
  1866. }
  1867. }
  1868. $_icl_admin_option_names = get_option('_icl_admin_option_names', array());
  1869. $_icl_admin_option_names = @array_merge_recursive($_icl_admin_option_names, $options_names);
  1870. $_icl_admin_option_names = __array_unique_recursive($_icl_admin_option_names);
  1871. update_option('_icl_admin_option_names', $_icl_admin_option_names);
  1872. return $options;
  1873. }
  1874. function icl_st_render_option_writes($option_name, $option_value, $option_key=''){
  1875. $has_translations = '';
  1876. if(is_array($option_value) || is_object($option_value)){
  1877. echo '<h4><a class="icl_stow_toggler" href="#">- ' . $option_name . '</a></h4>';
  1878. echo '<ul class="icl_st_option_writes">';
  1879. foreach($option_value as $key=>$value){
  1880. echo '<li>';
  1881. icl_st_render_option_writes($key, $value, $option_key . '[' . $option_name . ']');
  1882. echo '</li>';
  1883. }
  1884. echo '</ul>';
  1885. }elseif(is_string($option_value) || is_numeric($option_value)){
  1886. if(icl_st_is_registered_string('admin_texts_theme_' . get_option('template'), $option_key . $option_name)){
  1887. $checked = ' checked="checked"';
  1888. if(icl_st_string_has_translations('admin_texts_theme_' . get_option('template'), $option_key . $option_name)){
  1889. $has_translations = ' class="icl_st_has_translations"';
  1890. }else{
  1891. $has_translations = '';
  1892. }
  1893. }else{
  1894. $checked = '';
  1895. }
  1896. if(is_numeric($option_value)){
  1897. $class = 'icl_st_numeric';
  1898. }else{
  1899. $class = 'icl_st_string';
  1900. }
  1901. global $iclTranslationManagement;
  1902. $int = preg_match_all('#\[([^\]]+)\]#', $option_key.'['.$option_name.']', $matches);
  1903. $_v = $iclTranslationManagement->admin_texts_to_translate;
  1904. if($int){
  1905. foreach($matches[1] as $m){
  1906. if(isset($_v[$m])){
  1907. $_v = $_v[$m];
  1908. }else{
  1909. $_v = 0;
  1910. break;
  1911. }
  1912. }
  1913. }
  1914. if($_v){
  1915. $disabled = ' disabled="disabled"';
  1916. }else{
  1917. $disabled = '';
  1918. }
  1919. echo '<div class="icl_st_admin_string '.$class.'">';
  1920. echo '<input'.$disabled.' type="hidden" name="icl_admin_options'.$option_key.'['.$option_name.']" value="" />';
  1921. echo '<input'.$disabled.$has_translations.' type="checkbox" name="icl_admin_options'.$option_key.'['.$option_name.']" value="'.esc_attr($option_value).'"
  1922. '.$checked.' />';
  1923. echo '<input type="text" readonly="readonly" value="'.$option_name.'" size="32" />';
  1924. echo '<input type="text" value="'.esc_attr($option_value).'" readonly="readonly" size="48" />';
  1925. //echo '<br /><input type="text" size="100" value="icl_admin_options'.$option_key.'['.$option_name.']" />';
  1926. echo '</div><br clear="all" />';
  1927. }
  1928. }
  1929. function icl_register_admin_options($array, $key=""){
  1930. foreach($array as $k=>$v){
  1931. if(is_array($v)){
  1932. icl_register_admin_options($v, $key . '['.$k.']');
  1933. }else{
  1934. if($v === ''){
  1935. icl_unregister_string('admin_texts_theme_' . get_option('template'), $key . $k);
  1936. }else{
  1937. icl_register_string('admin_texts_theme_' . get_option('template'), $key . $k, $v);
  1938. $int = preg_match_all('#\[([^\]]+)\]#', $key, $matches);
  1939. $vals = array();
  1940. if(count($matches[1]) > 0){
  1941. $vals[] = $k;
  1942. for($i = count($matches[1]) - 1; $i >= 0 ; $i--){
  1943. $tmp = $vals;
  1944. unset($vals);
  1945. $vals[$matches[1][$i]] = $tmp;
  1946. }
  1947. }else{
  1948. $vals[0] = $k;
  1949. }
  1950. $_icl_admin_option_names = get_option('_icl_admin_option_names');
  1951. $_icl_admin_option_names['theme'][get_option('template')] =
  1952. array_merge_recursive((array)$_icl_admin_option_names['theme'][get_option('template')], $vals);
  1953. $_icl_admin_option_names['theme'][get_option('template')] = __array_unique_recursive($_icl_admin_option_names['theme'][get_option('template')]);
  1954. update_option('_icl_admin_option_names', $_icl_admin_option_names);
  1955. }
  1956. }
  1957. }
  1958. }
  1959. function __array_unique_recursive($array){
  1960. $scalars = array();
  1961. foreach($array as $key=>$value){
  1962. if(is_scalar($value)){
  1963. if(isset($scalars[$value])){
  1964. unset($array[$key]);
  1965. }else{
  1966. $scalars[$value] = true;
  1967. }
  1968. }elseif(is_array($value)){
  1969. $array[$key] = __array_unique_recursive($value);
  1970. }
  1971. }
  1972. return $array;
  1973. }
  1974. function _icl_st_filter_empty_options_out($array){
  1975. $empty_found = false;
  1976. foreach($array as $k=>$v){
  1977. if(is_array($v) && !empty($v)){
  1978. list($array[$k], $empty_found) = _icl_st_filter_empty_options_out($v);
  1979. }else{
  1980. if(empty($v)){
  1981. unset($array[$k]);
  1982. $empty_found = true;
  1983. }
  1984. }
  1985. }
  1986. return array($array, $empty_found);
  1987. }
  1988. function wpml_register_admin_strings($serialized_array){
  1989. try{
  1990. icl_register_admin_options(unserialize($serialized_array));
  1991. }catch(Exception $e){
  1992. trigger_error($e->getMessage(), E_USER_WARNING);
  1993. }
  1994. }
  1995. add_action('plugins_loaded', 'icl_st_set_admin_options_filters', 10);
  1996. function icl_st_set_admin_options_filters() {
  1997. static $option_names;
  1998. if ( empty( $option_names ) ) {
  1999. $option_names = get_option( '_icl_admin_option_names' );
  2000. }
  2001. if ( !empty( $option_names[ 'theme' ] ) && !empty( $option_names[ 'theme' ][ basename( ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY ) ] ) ) {
  2002. foreach ( $option_names[ 'theme' ][ basename( ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY ) ] as $option_key => $option ) {
  2003. add_filter( 'option_' . $option_key, 'icl_st_translate_admin_string' );
  2004. }
  2005. if ( ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY != ICL_STRING_TRANSLATION_STYLESHEET_DIRECTORY && !empty( $option_names[ 'theme' ][ basename( ICL_STRING_TRANSLATION_STYLESHEET_DIRECTORY ) ] ) ) {
  2006. foreach ( (array)$option_names[ 'theme' ][ basename( ICL_STRING_TRANSLATION_STYLESHEET_DIRECTORY ) ] as $option_key => $option ) {
  2007. add_filter( 'option_' . $option_key, 'icl_st_translate_admin_string' );
  2008. }
  2009. }
  2010. }
  2011. if ( !empty( $option_names[ 'plugin' ] ) ) {
  2012. foreach ( $option_names[ 'plugin' ] as $plugin => $options ) {
  2013. foreach ( (array)$options as $option_key => $option ) {
  2014. add_filter( 'option_' . $option_key, 'icl_st_translate_admin_string' );
  2015. }
  2016. }
  2017. }
  2018. }
  2019. function icl_st_translate_admin_string($option_value, $key="", $name="", $rec_level = 0){
  2020. if ( !defined( 'ICL_SITEPRESS_VERSION' ) || ICL_PLUGIN_INACTIVE ) {
  2021. return $option_value;
  2022. }
  2023. // determine option name
  2024. if ( !$name && $rec_level == 0 ) {
  2025. $ob = debug_backtrace();
  2026. if ( is_scalar( $ob[ 2 + $rec_level ][ 'args' ][ 0 ] ) ) {
  2027. $name = preg_replace( '@^option_@', '', $ob[ 2 + $rec_level ][ 'args' ][ 0 ] );
  2028. }
  2029. }
  2030. // cache - phase 1 - check/get
  2031. static $__icl_st_cache;
  2032. if($rec_level == 0){
  2033. if(isset($__icl_st_cache[$name]) && apply_filters( 'icl_st_admin_string_return_cached', true, $name ) ) {
  2034. //echo "FROM CACHE $name<br />";
  2035. return $__icl_st_cache[$name];
  2036. }
  2037. }
  2038. // case of double-serialized options (See Arras theme)
  2039. $serialized = false;
  2040. if(is_serialized( $option_value )){
  2041. $option_value = @unserialize($option_value);
  2042. $serialized = true;
  2043. }
  2044. //if(is_object($option_value)){
  2045. //$option_value = (array)$option_value;
  2046. //}
  2047. if(is_array($option_value) || is_object($option_value)){
  2048. foreach($option_value as $k=>$value){
  2049. $val = icl_st_translate_admin_string($value, $key . '[' . $name . ']' , $k, $rec_level+1);
  2050. if(is_object($option_value)){
  2051. $option_value->$k = $val;
  2052. }else{
  2053. $option_value[$k] = $val;
  2054. }
  2055. }
  2056. }else{
  2057. static $option_names;
  2058. if(empty($option_names)) $option_names = get_option('_icl_admin_option_names');
  2059. // determine theme/plugin name
  2060. if(!empty($option_names['theme']) && !empty($option_names['theme'][basename(ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY)])){
  2061. if(isset($option_names['theme'][basename(ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY)]))
  2062. foreach((array)$option_names['theme'][basename(ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY)] as $ops=>$val){
  2063. if(!empty($key)){
  2064. $int = preg_match_all('#\[([^\]]+)\]#', $key, $matches);
  2065. if($int) $opname = $matches[1][0];
  2066. }else{
  2067. $opname = $name;
  2068. }
  2069. if($ops == $opname){
  2070. $key_suff = 'theme_' . basename(ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY);
  2071. break;
  2072. }
  2073. }
  2074. if(ICL_STRING_TRANSLATION_TEMPLATE_DIRECTORY != ICL_STRING_TRANSLATION_STYLESHEET_DIRECTORY){
  2075. if(isset($option_names['theme'][basename(ICL_STRING_TRANSLATION_STYLESHEET_DIRECTORY)]))
  2076. foreach((array)$option_names['theme'][basename(ICL_STRING_TRANSLATION_STYLESHEET_DIRECTORY)] as $ops=>$val){
  2077. if(!empty($key)){
  2078. $int = preg_match_all('#\[([^\]]+)\]#', $key, $matches);
  2079. if($int) $opname = $matches[1][0];
  2080. }else{
  2081. $opname = $name;
  2082. }
  2083. if($ops == $opname){
  2084. $key_suff = 'theme_' . ICL_STRING_TRANSLATION_STYLESHEET_DIRECTORY;
  2085. break;
  2086. }
  2087. }
  2088. }
  2089. }
  2090. if(!empty($option_names['plugin'])){
  2091. foreach((array)$option_names['plugin'] as $plugin => $options){
  2092. foreach($options as $kops=>$ops){
  2093. if(is_array($ops)){
  2094. $arrkey = explode('][', trim($key, '[]'));
  2095. $_val = $options;
  2096. for($i=0; $i<count($arrkey); $i++){
  2097. if(isset($_val[$arrkey[$i]])){
  2098. $_val = $_val[$arrkey[$i]];
  2099. }else{
  2100. break;
  2101. }
  2102. }
  2103. if(in_array($name, $_val)){ // seems not work since WPML 3.1, added next elseif which works
  2104. $key_suff = 'plugin_' . $plugin;
  2105. break;
  2106. }elseif (in_array($name, array_keys($_val))) {
  2107. $key_suff = 'plugin_' . $plugin;
  2108. break;
  2109. }
  2110. }elseif($ops == $name){ // seems not work since WPML 3.1, added next elseif which works
  2111. $key_suff = 'plugin_' . $plugin;
  2112. break;
  2113. }elseif ($kops == $name) {
  2114. $key_suff = 'plugin_' . $plugin;
  2115. break;
  2116. }
  2117. }
  2118. }
  2119. }
  2120. if(!empty($key_suff)){
  2121. $tr = icl_t('admin_texts_' . $key_suff, $key . $name, $option_value, $hast, true);
  2122. }
  2123. if(isset($tr)){
  2124. $option_value = $tr;
  2125. }
  2126. }
  2127. // case of double-serialized options (See Arras theme)
  2128. if($serialized){
  2129. $option_value = serialize($option_value);
  2130. }
  2131. // cache - phase 2 - set
  2132. if($rec_level == 0){
  2133. $__icl_st_cache[$name] = $option_value;
  2134. }
  2135. /*
  2136. * if sticky links plugin is enabled and set to change links into sticky
  2137. * in strings, change those links back into permalinks when displayed
  2138. */
  2139. if (is_string($option_value) and class_exists("WPML_Sticky_links")) {
  2140. global $WPML_Sticky_Links;
  2141. if(isset($WPML_Sticky_Links)) {
  2142. if ($WPML_Sticky_Links->settings['sticky_links_strings']) {
  2143. $option_value = $WPML_Sticky_Links->show_permalinks($option_value);
  2144. }
  2145. }
  2146. }
  2147. return $option_value;
  2148. }
  2149. function icl_st_get_mo_files($path){
  2150. static $mo_files = array();
  2151. if ( function_exists('realpath') )
  2152. $path = realpath($path);
  2153. if(is_dir($path) && is_readable($path)){
  2154. $dh = opendir($path);
  2155. if($dh !== false){
  2156. while($f = readdir($dh)){
  2157. if(0 !== strpos($f, '.')){
  2158. if(is_dir($path . '/' . $f)){
  2159. icl_st_get_mo_files($path . '/' . $f);
  2160. }else{
  2161. if(preg_match('#\.mo$#', $f)){
  2162. $mo_files[] = $path . '/' . $f;
  2163. }
  2164. }
  2165. }
  2166. }
  2167. }
  2168. }
  2169. return $mo_files;
  2170. }
  2171. function icl_st_load_translations_from_mo($mo_file){
  2172. $translations = array();
  2173. $mo = new MO();
  2174. $mo->import_from_file( $mo_file );
  2175. foreach($mo->entries as $str=>$v){
  2176. $str = str_replace("\n",'\n', $str);
  2177. $translations[$str] = $v->translations[0];
  2178. }
  2179. return $translations;
  2180. }
  2181. // fix links in existing strings according to the new translation added
  2182. function icl_st_fix_links_in_strings($post_id){
  2183. static $runnonce = false;
  2184. if($runnonce){
  2185. return;
  2186. }
  2187. $runonce = true;
  2188. if(isset($_POST['autosave']) && $_POST['autosave']) return;
  2189. if(isset($_POST['post_ID'])){
  2190. $post_id = $_POST['post_ID'];
  2191. }
  2192. global $wpdb, $sitepress;
  2193. $language = $wpdb->get_var($wpdb->prepare("SELECT language_code FROM {$wpdb->prefix}icl_translations WHERE element_type='post' AND element_id=%d", $post_id));
  2194. if($language){
  2195. if($sitepress->get_default_language()==$language){
  2196. $strings = $wpdb->get_col($wpdb->prepare("SELECT id FROM {$wpdb->prefix}icl_strings WHERE language=%s",$language));
  2197. }else{
  2198. $strings = $wpdb->get_col($wpdb->prepare("SELECT id FROM {$wpdb->prefix}icl_string_translations WHERE language=%s",$language));
  2199. }
  2200. foreach($strings as $string_id){
  2201. _icl_content_fix_links_to_translated_content($string_id, $language, 'string');
  2202. }
  2203. }
  2204. }
  2205. function icl_translation_send_strings($string_ids, $target_languages) {
  2206. global $WPML_String_Translation;
  2207. $errors = 0;
  2208. // send to each language
  2209. foreach($target_languages as $target=>$service){
  2210. if($service == 'icanlocalize'){
  2211. if( !_icl_translation_send_strings_icanlocalize($string_ids, $target, $service) ) $errors++;
  2212. }elseif($service == 'local'){
  2213. if( ! _icl_translation_send_strings_local($string_ids, $target, $service) ) $errors++;
  2214. }
  2215. }
  2216. if($errors == count($target_languages)){
  2217. $WPML_String_Translation->add_message(__('No string was sent to translation.','wpml-string-translation'), 'error');
  2218. }elseif($errors > 0){
  2219. $WPML_String_Translation->add_message(__('Some strings were not sent to translation.','wpml-string-translation'), 'error');
  2220. }else{
  2221. if(count($string_ids) > 1){
  2222. $WPML_String_Translation->add_message(__('All strings were sent to translation.','wpml-string-translation'));
  2223. }else{
  2224. $WPML_String_Translation->add_message(__('The string was sent to translation.','wpml-string-translation'));
  2225. }
  2226. }
  2227. }
  2228. function _icl_translation_send_strings_local($string_ids, $target) {
  2229. global $wpdb, $sitepress_settings;
  2230. static $site_translators;
  2231. $site_translators = TranslationManagement::get_blog_translators();
  2232. $mkey = $wpdb->prefix . 'strings_notification';
  2233. $lkey = $wpdb->prefix . 'language_pairs';
  2234. $slang =& $sitepress_settings['st']['strings_language'];
  2235. foreach($string_ids as $string_id) {
  2236. $added = icl_add_string_translation($string_id, $target, NULL , ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR);
  2237. if($added)
  2238. foreach($site_translators as $key=>$st){
  2239. $ulangs = isset($st->$lkey) ? $st->$lkey : false;
  2240. if(!empty($ulangs) && !empty($ulangs[$slang][$target])){
  2241. $enot = isset($st->$mkey) ? $st->$mkey : false;
  2242. if(empty($enot[$sitepress_settings['st']['strings_language']][$target])){
  2243. _icl_st_translator_notification($st, $sitepress_settings['st']['strings_language'], $target);
  2244. $enot[$sitepress_settings['st']['strings_language']][$target] = 1;
  2245. $site_translators[$key]->$mkey = $enot;
  2246. update_option($wpdb->prefix . 'icl_translators_cached', $site_translators);
  2247. //printf("Notify %d for %s -> %s <br />", $st->ID, $sitepress_settings['st']['strings_language'], $target);
  2248. }else{
  2249. //printf("Already notified %d for %s -> %s <br />", $st->ID, $sitepress_settings['st']['strings_language'], $target);
  2250. }
  2251. }
  2252. }
  2253. }
  2254. return 1;
  2255. }
  2256. function _icl_st_translator_notification($user, $source, $target){
  2257. global $wpdb, $sitepress;
  2258. $_ldetails = $sitepress->get_language_details($source);
  2259. $source_en = $_ldetails['english_name'];
  2260. $_ldetails = $sitepress->get_language_details($target);
  2261. $target_en = $_ldetails['english_name'];
  2262. $message = __("You have been assigned to new translation job from %s to %s.
  2263. Start editing: %s
  2264. You can view your other translation jobs here: %s
  2265. This message was automatically sent by Translation Management running on WPML. To stop receiving these notifications contact the system administrator at %s.
  2266. This email is not monitored for replies.
  2267. - The folks at ICanLocalize
  2268. 101 Convention Center Dr., Las Vegas, Nevada, 89109, USA
  2269. ", 'sitepress');
  2270. $to = $user->user_email;
  2271. $subject = sprintf(__("You have been assigned to new translation job on %s.", 'sitepress'), get_bloginfo('name'));
  2272. $body = sprintf($message,
  2273. $source_en, $target_en, admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php'),
  2274. admin_url('admin.php?page='.WPML_TM_FOLDER.'/menu/translations-queue.php'), home_url());
  2275. wp_mail($to, $subject, $body);
  2276. $meta = get_user_meta($user->ID, $wpdb->prefix . 'strings_notification', 1);
  2277. $meta[$source][$target] = 1;
  2278. update_user_meta($user->ID, $wpdb->prefix . 'strings_notification', $meta);
  2279. }
  2280. function icl_st_reset_current_trasnslator_notifications(){
  2281. global $sitepress, $wpdb;
  2282. $current_user = $sitepress->get_current_user();
  2283. $mkey = $wpdb->prefix . 'strings_notification';
  2284. if(!empty($current_user->$mkey)){
  2285. update_user_meta($current_user->ID, $mkey, array());
  2286. }
  2287. }
  2288. function _icl_translation_send_strings_icanlocalize($string_ids, $target) {
  2289. global $wpdb, $sitepress, $sitepress_settings;
  2290. if(!$sitepress_settings['st']['strings_language'])
  2291. $sitepress_settings['st']['strings_language'] = $sitepress->get_default_language();
  2292. $target_details = $sitepress->get_language_details($target);
  2293. // get all the untranslated strings
  2294. $untranslated = array();
  2295. foreach($string_ids as $st_id) {
  2296. $status = $wpdb->get_var($wpdb->prepare("SELECT status FROM {$wpdb->prefix}icl_string_translations WHERE string_id=%d and language=%s", $st_id, $target));
  2297. if ($status != ICL_STRING_TRANSLATION_COMPLETE) {
  2298. $untranslated[] = $st_id;
  2299. }
  2300. }
  2301. if (sizeof($untranslated) > 0) {
  2302. // Something to translate.
  2303. $target_for_server = array(ICL_Pro_Translation::server_languages_map($target_details['english_name'])); //filter some language names to match the names on the server
  2304. $data = array(
  2305. 'url'=>'',
  2306. 'target_languages' => $target_for_server,
  2307. );
  2308. $string_values = array();
  2309. foreach($untranslated as $st_id) {
  2310. $string = $wpdb->get_row($wpdb->prepare("SELECT context, name, value FROM {$wpdb->prefix}icl_strings WHERE id=%d", $st_id));
  2311. $string_values[$st_id] = $string->value;
  2312. $data['contents']['string-'.$st_id.'-context'] = array(
  2313. 'translate'=>0,
  2314. 'data'=>base64_encode(esc_attr($string->context)),
  2315. 'format'=>'base64',
  2316. );
  2317. $data['contents']['string-'.$st_id.'-name'] = array(
  2318. 'translate'=>0,
  2319. 'data'=>base64_encode(esc_attr($string->name)),
  2320. 'format'=>'base64',
  2321. );
  2322. $data['contents']['string-'.$st_id.'-value'] = array(
  2323. 'translate'=>1,
  2324. 'data'=>base64_encode(esc_attr($string->value)),
  2325. 'format'=>'base64',
  2326. );
  2327. }
  2328. $iclq = new ICanLocalizeQuery($sitepress_settings['site_id'], $sitepress_settings['access_key']);
  2329. $orig_lang = $sitepress->get_language_details($sitepress_settings['st']['strings_language']);
  2330. $orig_lang_for_server = ICL_Pro_Translation::server_languages_map($orig_lang['english_name']);
  2331. $timestamp = date('Y-m-d H:i:s');
  2332. $xml = $iclq->build_cms_request_xml($data, $orig_lang_for_server);
  2333. $args = array(
  2334. 'xml' => $xml,
  2335. 'title' => "String translations",
  2336. 'to_languages' => $target_for_server,
  2337. 'orig_language' => $orig_lang_for_server
  2338. );
  2339. $res = $iclq->send_request($args);
  2340. if($res > 0){
  2341. foreach($string_values as $st_id => $value){
  2342. $wpdb->insert($wpdb->prefix.'icl_string_status',
  2343. array('rid'=>$res, 'string_translation_id'=>$st_id, 'timestamp'=>$timestamp, 'md5'=>md5($value))); //insert rid
  2344. }
  2345. $wpdb->insert($wpdb->prefix.'icl_core_status', array('rid'=>$res,
  2346. 'origin'=>$orig_lang['code'],
  2347. 'target'=>$target,
  2348. 'status'=>CMS_REQUEST_WAITING_FOR_PROJECT_CREATION));
  2349. return $res;
  2350. }else{
  2351. return 0;
  2352. }
  2353. }
  2354. }
  2355. function icl_decode_translation_status_id($status){
  2356. switch($status){
  2357. case CMS_TARGET_LANGUAGE_CREATED: $st = __('Waiting for translator','wpml-string-translation');break;
  2358. case CMS_TARGET_LANGUAGE_ASSIGNED: $st = __('In progress','wpml-string-translation');break;
  2359. case CMS_TARGET_LANGUAGE_TRANSLATED: $st = __('Translation received','wpml-string-translation');break;
  2360. case CMS_TARGET_LANGUAGE_DONE: $st = __('Translation complete','wpml-string-translation');break;
  2361. case CMS_REQUEST_FAILED: $st = __('Request failed','wpml-string-translation');break;
  2362. default: $st = __('Not translated','wpml-string-translation');
  2363. }
  2364. return $st;
  2365. }
  2366. function icl_translation_get_string_translation_status($string_id) {
  2367. global $wpdb;
  2368. $status = $wpdb->get_var($wpdb->prepare("
  2369. SELECT
  2370. MIN(cs.status)
  2371. FROM
  2372. {$wpdb->prefix}icl_core_status cs
  2373. JOIN
  2374. {$wpdb->prefix}icl_string_status ss
  2375. ON
  2376. ss.rid = cs.rid
  2377. WHERE
  2378. ss.string_translation_id=%d
  2379. ", $string_id
  2380. ));
  2381. if ($status === null){
  2382. return "";
  2383. }
  2384. $status = icl_decode_translation_status_id($status);
  2385. return $status;
  2386. }
  2387. function icl_translation_send_untranslated_strings($target_languages) {
  2388. global $wpdb;
  2389. $untranslated = $wpdb->get_col($wpdb->prepare("SELECT id FROM {$wpdb->prefix}icl_strings WHERE status <> %d", ICL_STRING_TRANSLATION_COMPLETE));
  2390. icl_translation_send_strings($untranslated, $target_languages);
  2391. }
  2392. function icl_is_string_translation($translation) {
  2393. // determine if the $translation data is for string translation.
  2394. foreach($translation as $key => $value) {
  2395. if($key == 'body' or $key == 'title') {
  2396. return false;
  2397. }
  2398. if (preg_match("/string-.*?-value/", $key)){
  2399. return true;
  2400. }
  2401. }
  2402. // if we get here assume it's not a string.
  2403. return false;
  2404. }
  2405. function icl_translation_add_string_translation($rid, $translation, $lang_code){
  2406. global $wpdb, $sitepress_settings, $sitepress;
  2407. foreach($translation as $key => $value) {
  2408. if (preg_match("/string-(.*?)-value/", $key, $match)){
  2409. $string_id = $match[1];
  2410. $md5_when_sent = $wpdb->get_var($wpdb->prepare("SELECT md5 FROM {$wpdb->prefix}icl_string_status
  2411. WHERE string_translation_id=%d AND rid=%d", $string_id, $rid));
  2412. $current_string_value = $wpdb->get_var($wpdb->prepare("SELECT value FROM {$wpdb->prefix}icl_strings WHERE id=%d", $string_id));
  2413. if ($md5_when_sent == md5($current_string_value)) {
  2414. $status = ICL_STRING_TRANSLATION_COMPLETE;
  2415. } else {
  2416. $status = ICL_STRING_TRANSLATION_NEEDS_UPDATE;
  2417. }
  2418. $value = str_replace ( '&#0A;', "\n", $value );
  2419. icl_add_string_translation($string_id, $lang_code, html_entity_decode($value), $status, 0);
  2420. }
  2421. }
  2422. // update translation status
  2423. $wpdb->update($wpdb->prefix.'icl_core_status', array('status'=>CMS_TARGET_LANGUAGE_DONE), array('rid'=>$rid, 'target'=>$lang_code));
  2424. return true;
  2425. }
  2426. function icl_st_get_pending_string_translations_stats(){
  2427. global $wpdb, $sitepress, $sitepress_settings;
  2428. $current_user = $sitepress->get_current_user();
  2429. $user_lang_pairs = get_user_meta($current_user->ID, $wpdb->prefix.'language_pairs', true);
  2430. $stats = array();
  2431. if(!empty($user_lang_pairs[$sitepress_settings['st']['strings_language']])){
  2432. $results = $wpdb->get_results($wpdb->prepare("
  2433. SELECT COUNT(id) AS c, language
  2434. FROM {$wpdb->prefix}icl_string_translations
  2435. WHERE status=%d AND language IN ('".join("','", array_keys($user_lang_pairs[$sitepress_settings['st']['strings_language']]))."')
  2436. AND (translator_id IS NULL or translator_id > 0)
  2437. GROUP BY language
  2438. ORDER BY c DESC
  2439. ",
  2440. ICL_STRING_TRANSLATION_WAITING_FOR_TRANSLATOR
  2441. ));
  2442. foreach($results as $r){
  2443. $_stats[$r->language] = $r->c;
  2444. }
  2445. foreach($user_lang_pairs[$sitepress_settings['st']['strings_language']] as $lang=>$one){
  2446. $stats[$lang] = isset($_stats[$lang]) ? $_stats[$lang] : 0;
  2447. }
  2448. }
  2449. return $stats;
  2450. }
  2451. function icl_st_is_translator(){
  2452. return current_user_can('translate') && !current_user_can('manage_options');
  2453. }
  2454. function icl_st_debug($str){
  2455. trigger_error($str, E_USER_WARNING);
  2456. }
  2457. function icl_st_admin_notices_string_updated() {
  2458. ?>
  2459. <div class="updated">
  2460. <p><?php _e( 'Strings translations updated', 'wpml-string-translation' ); ?></p>
  2461. </div>
  2462. <?php
  2463. }