Русский Текст Обрезается С Крякозябрами

Статус
В этой теме нельзя размещать новые ответы.

Tias

Постоялец
Регистрация
26 Дек 2007
Сообщения
436
Реакции
152
Замечал во многих движках и скриптах такой косяк. Сейчас проблема с joomla и модулем "JoomlaXTC News Pro Module
".
Модуль выводит новости из разделов и показывает заданное количество символов текста первой новости.
С латиницей скрипт работает нормально, а вот когда статьи на русском, то случается, что обрезаются слова криво и в конце обрезанного слова ставится иероглиф.
Как можно убрать эту ошибку? Ниже код модуля:
PHP:
<?PHP
/*
 JoomlaXTC News Pro Module
 version 1.0 (Joomla 1.5)
 copyright (c) 2008 JoomlaXTC   www.joomlaxtc.com
*/
defined('_JEXEC') or die('Restricted access');
require_once (JPATH_SITE.DS.'components'.DS.'com_content'.DS.'helpers'.DS.'route.php');
if (!function_exists('jxtcParseRow')) {
	function jxtcParseRow($row,$html,$aid,$maxintro) {
			if($row->access <= $aid) {
				$link = JRoute::_(ContentHelperRoute::getArticleRoute($row->slug, $row->catslug, $row->sectionid));
			} else {
				$link = JRoute::_('index.php?option=com_user&view=login');
			}
			$intro = $row->introtext;
			$ini=strpos(strtolower($row->introtext),'<img');
			if ($ini === false) $img = '';
			else {
				$ini = strpos($row->introtext,'src="',$ini)+5;
				$fin = strpos($row->introtext,'"',$ini);
				$img = substr($row->introtext,$ini,$fin-$ini);
				$fin = strpos($row->introtext,'>',$fin);
				$intro = substr($row->introtext,$fin+1);
			}
			if (!empty($maxintro)) $intro = trim(substr($intro,0,$maxintro)).'...';
			$hold = $html;
			$hold = str_replace( '{link}', $link, $hold );
			$hold = str_replace( '{title}', htmlspecialchars($row->title), $hold );
			$hold = str_replace( '{intro}', $row->introtext, $hold );
			$hold = str_replace( '{introtext}', '<p class="jnpp">'.$intro.'</p>', $hold );
			$hold = str_replace( '{introimage}', $img, $hold );
			$hold = str_replace( '{section}', $row->sec_title, $hold );
			$hold = str_replace( '{category}', $row->cat_title, $hold );
			$hold = str_replace( '{date}', $row->created, $hold );
			$hold = str_replace( '{moddate}', $row->modified, $hold );
			$hold = str_replace( '{author}', $row->author, $hold );
			$hold = str_replace( '{authorid}', $row->authorid, $hold );
		return $hold;
	}
}
global $mainframe;
$db				=& JFactory::getDBO();
$user			=& JFactory::getUser();
$userId		= $user->get('id');
$columns	= trim( $params->get('columns',3) );
$lines		= $params->get('lines', 1);
$pages		= $params->get('pages', 1);
$more			= $params->get('more', 0);
$moretext	= trim($params->get('moretext', ''));
$morehtml	= $params->get('morehtml', '{title}');
$morecols	= trim( $params->get('morecols',1) );
$morergb	= trim( $params->get('morergb','cccccc') );
$catid		= trim( $params->get('catid') );
$secid		= trim( $params->get('secid') );
$button		= $params->get('button','default');
$html			= trim( $params->get('html','{intro}') );
$maxintro	= trim( $params->get('maxintro') );
$show_front	= $params->get('show_front', 1);
$class 		= trim($params->get('moduleclass_sfx'));
$autoscroll	= $params->get('autoscroll',0);
$autospeed	= $params->get('autospeed',1000);
$autopause	= $params->get('autopause',800);
$scrollstep	= $params->get('scrollstep',1);
$mouse	= $params->get('mouse',0);
$easingtype	= $params->get('easingtype','none');
$easingspeed	= $params->get('easingspeed',0);
$speed	= $params->get('speed',0);
$scrolltype	= $params->get('scrolltype','h');
$circular	= $params->get('circular',1);
$layout	= $params->get('layout',1);
$aid			= $user->get('aid', 0);
$contentConfig = &JComponentHelper::getParams( 'com_content' );
$access		= !$contentConfig->get('show_noauth');
$nullDate	= $db->getNullDate();
$date =& JFactory::getDate();
$now = $date->toMySQL();
$where		= 'a.state = 1'
	. ' AND ( a.publish_up = '.$db->Quote($nullDate).' OR a.publish_up <= '.$db->Quote($now).' )'
	. ' AND ( a.publish_down = '.$db->Quote($nullDate).' OR a.publish_down >= '.$db->Quote($now).' )'
	;
// User Filter
switch ($params->get( 'user_id' ))
{
	case 'by_me':
		$where .= ' AND (created_by = ' . (int) $userId . ' OR modified_by = ' . (int) $userId . ')';
		break;
	case 'not_me':
		$where .= ' AND (created_by <> ' . (int) $userId . ' AND modified_by <> ' . (int) $userId . ')';
		break;
}
// Ordering
switch ($params->get( 'ordering' )) {
	case 'm_dsc':
		$ordering		= 'a.modified DESC, a.created DESC';
		break;
	case 'c_dsc':
	default:
		$ordering		= 'a.created DESC';
		break;
}
if ($catid) {
	$ids = explode( ',', $catid );
	JArrayHelper::toInteger( $ids );
	$catCondition = ' AND (cc.id=' . implode( ' OR cc.id=', $ids ) . ')';
}
if ($secid) {
	$ids = explode( ',', $secid );
	JArrayHelper::toInteger( $ids );
	$secCondition = ' AND (s.id=' . implode( ' OR s.id=', $ids ) . ')';
}
// Content Items only
$query = 'SELECT a.*, cc.title as cat_title, s.title as sec_title, u.name as author, u.username as authorid,' .
	' CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(":", a.id, a.alias) ELSE a.id END as slug,'.
	' CASE WHEN CHAR_LENGTH(cc.alias) THEN CONCAT_WS(":", cc.id, cc.alias) ELSE cc.id END as catslug'.
	' FROM #__content AS a' .
	($show_front == '0' ? ' LEFT JOIN #__content_frontpage AS f ON f.content_id = a.id' : '') .
	' INNER JOIN #__categories AS cc ON cc.id = a.catid' .
	' INNER JOIN #__sections AS s ON s.id = a.sectionid' .
	' INNER JOIN #__users AS u ON u.id = a.created_by' .
	' WHERE '. $where .' AND s.id > 0' .
	($access ? ' AND a.access <= ' .(int) $aid. ' AND cc.access <= ' .(int) $aid. ' AND s.access <= ' .(int) $aid : '').
	($catid ? $catCondition : '').
	($secid ? $secCondition : '').
	($show_front == '0' ? ' AND f.content_id IS NULL ' : '').
	' AND s.published = 1' .
	' AND cc.published = 1' .
	' ORDER BY '. $ordering;
	$limit = $columns*$lines*$pages;
$db->setQuery($query, 0, $limit+$more);
$items = $db->loadObjectList();
if (count($items) == 0) return;	// Return empty
$i=1;
$c=1;
$r=1;
$p=1;
$rows = array_slice($items,0,$limit);
$mores = array_slice($items,$limit);
if ($pages > 1) {
	$jshdr = '<script src="modules/mod_jxtc_newspro/js/jquery.js" type="text/javascript"></script>
	<script src="modules/mod_jxtc_newspro/js/jcarousellite.js" type="text/javascript"></script>';
	$jscall = '<script language="javascript">
		jQuery.noConflict();
		jQuery(window).load(function(){
	  	jQuery(".jnp'.$class.'main").jCarouselLite({';
	if ($autoscroll == 1) {
		$jscall .= 'auto: '.$autopause.', speed: '.$autospeed.',';
	}
	if ($scrollstep != 1) {
		$jscall .= 'scroll: '.$scrollstep.',';
	}
	if ($mouse == 1) {
		$jshdr .= '<script src="modules/mod_jxtc_newspro/js/jquery.mousewheel.js" type="text/javascript"></script>';
		$jscall .= 'mouseWheel: true,';
	}
	if ($easingtype != 'none') {
		$jshdr .= '<script src="modules/mod_jxtc_newspro/js/jquery.easing.js" type="text/javascript"></script>';
		$jscall .= 'easing: "'.$easingtype.'", speed: '.$easingspeed.',';
	}
	if ($speed > 0) {
		$jscall .= 'speed: '.$speed.',';
	}
	if ($scrolltype == 'v') {
		$jscall .= 'vertical: true,';
	}
	if ($circular == 0) {
		$jscall .= 'circular: false,';
	}
	$jscall .= '
	      btnNext: ".jnp'.$class.'prev",
	      btnPrev: ".jnp'.$class.'next"
	  });
	});
	</script>';
	echo $jshdr.$jscall;
//
// wrapper div for all newspro module, closest thing to css taming
//
	echo '<div style="position:relative; width:100% !important ;overflow:hidden !important; margin-right:auto;">';
	switch ($layout) {
		case "0":	// none
		echo '<div class="jnp'.$class.'main">';
		break;
		case "1":	// left/right
		echo '<img class="jnp'.$class.'prev" src="modules/mod_jxtc_newspro/buttons/'.$button.'/prev.gif" style="float:left"/>';
		echo '<div class="jnp'.$class.'main" style="float:left;">';
		break;
		case "2":	// top
		echo '<div><img class="jnp'.$class.'prev" src="modules/mod_jxtc_newspro/buttons/'.$button.'/prev.gif" style="float:left"/>';
		echo '<img class="jnp'.$class.'next" src="modules/mod_jxtc_newspro/buttons/'.$button.'/next.gif" style="float:right"/></div>';
		echo '<div class="jnp'.$class.'main">';
		break;
		case "3":	// bottom
		echo '<div class="jnp'.$class.'main">';
		break;
		case "4":	// top/bottom
		echo '<img class="jnp'.$class.'prev" src="modules/mod_jxtc_newspro/buttons/'.$button.'/prev.gif" />';
		echo '<div class="jnp'.$class.'main">';
		break;
	}
	echo '<ul>';
	foreach ( $rows as $row ) {
		if ($c==1 && $r==1) {
			echo '<li><table width="100%" border="0" cellpadding="0" cellspacing="0">';
		}
		if ($c==1) {
			echo '<tr>';
		}
		echo '<td valign="top">'.jxtcParseRow($row,$html,$aid,$maxintro).'</td>';
		$i++;$c++;
		if ($c > $columns) {
			echo '</tr>';
			$c=1;
			$r++;
			if ($r > $lines && $i < $limit) {
				echo '</table></li>';
				$r=1;
				$p++;
			}
		}
	}
	if ($r > 1) echo '</table></li>';
	echo '</ul>';
	switch ($layout) {
		case "0": // none
		echo '</div>';
		break;
		case "1":	// left/right
		echo '</div>';
		echo '<img class="jnp'.$class.'next" src="modules/mod_jxtc_newspro/buttons/'.$button.'/next.gif" style="float:left"/>';
		break;
		case "2": // top
		echo '</div>';
		break;
		case "3": // bottom
		echo '</div>';
		echo '<div style="margin:-6px 0px 0px 0px; padding-right:15px; background:url(modules/mod_jxtc_newspro/dotted.gif) 50px 0px no-repeat;"><img class="jnp'.$class.'prev" src="modules/mod_jxtc_newspro/buttons/'.$button.'/prev.gif"/>';
		echo '<img class="jnp'.$class.'next" src="modules/mod_jxtc_newspro/buttons/'.$button.'/next.gif"/></div>';
		break;
		case "4": // top/bottom
		echo '</div>';
		echo '<img class="jnp'.$class.'next" src="modules/mod_jxtc_newspro/buttons/'.$button.'/next.gif" />';
		break;
	}
	echo '</div>';
}
else {
	echo '<table width="100%" border="0" cellpadding="0" cellspacing="0"><tr>';
	foreach ( $rows as $row ) {
		if ($c==1) {
			echo '<tr>';
		}
		echo '<td valign="top">'.jxtcParseRow($row,$html,$aid,$maxintro).'</td>';
		$i++;$c++;
		if ($c > $columns) {
			echo '</tr>';
			$c=1;
		}
	}
	if ($c > 1) echo '</tr>';
	echo '</table>';
}
if (count ($mores) > 0) {
	if ($moretext) {
		echo '<img src="modules/mod_jxtc_newspro/images/article-grey.gif">&nbsp;&nbsp;<span style="color:#'.$morergb.'">'.$moretext.'</span><br/>';
	}
	echo '<table width="100%" border="0" cellpadding="0" cellspacing="0"><tr>';
	$i=1;
	$c=1;
	foreach ( $mores as $row ) {
		if ($c==1) {
			echo '<tr>';
		}
		echo '<td valign="top">'.jxtcParseRow($row,$morehtml,$aid,$maxintro).'</td>';
		$i++;$c++;
		if ($c > $morecols) {
			echo '</tr>';
			$c=1;
		}
	}
	if ($c > 1) echo '</tr>';
	echo '</table>';
}
 
просто те функции работают с однобайтными символами и двухбайтный символ из кириллицы обрезается пополам до одного и получается однобайтный символ неизвестно чего.

решение например включить внутреннюю кодировку utf8 если не включена
PHP:
mb_internal_encoding("UTF-8");
и дальше заменить функции которые работают с текстом на мультибайтные (приставка mb_:(

PHP:
//было
print substr('авбхдеёшзи', 3, 3);
//стало
print mb_substr('авбхдеёшзи', 3, 3);
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху