summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorlsces <lester@lsces.co.uk>2025-08-27 15:01:45 +0100
committerlsces <lester@lsces.co.uk>2025-08-27 15:01:45 +0100
commit6e24ce632d3bfaf09bf6aaffe2055fb1d485c17e (patch)
tree9c02b29e21f8f620f5366c39d08ff46077fbfa08 /includes
parentb01baded7e661fa6cdf217c5d7cb04e6dbf8e2b2 (diff)
downloadlanguages-6e24ce632d3bfaf09bf6aaffe2055fb1d485c17e.tar.gz
languages-6e24ce632d3bfaf09bf6aaffe2055fb1d485c17e.tar.bz2
languages-6e24ce632d3bfaf09bf6aaffe2055fb1d485c17e.zip
Restructure fo namespace layout
Diffstat (limited to 'includes')
-rwxr-xr-xincludes/classes/Babelfish.php177
-rwxr-xr-xincludes/classes/Bablotron.php172
-rwxr-xr-xincludes/classes/LibertyTranslations.php173
3 files changed, 522 insertions, 0 deletions
diff --git a/includes/classes/Babelfish.php b/includes/classes/Babelfish.php
new file mode 100755
index 0000000..8029db5
--- /dev/null
+++ b/includes/classes/Babelfish.php
@@ -0,0 +1,177 @@
+<?php
+/**
+ * @package languages
+ * @version $Header$
+ *
+ * Tiki is copyright (c) 2002-2003, Luis Argerich, Garland Foster, Eduardo Polidor, et. al.
+ * All Rights Reserved. See below for details and a complete list of authors.
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See http://www.gnu.org/copyleft/lesser.html for details.
+ *
+ * This file copyright (c) 2002-2003, Ross Smith II
+ */
+
+/**
+ * @package languages
+ */
+class Babelfish {
+ /**
+ * Return the host name of the server
+ *
+ * @todo move to BitBase class
+ */
+ function host() {
+ if (isset($_SERVER['HTTP_HOST'])) {
+ // HTTP_HOST already includes a ':port' if it is used
+ return $_SERVER['HTTP_HOST'];
+ }
+
+ if (!isset($_SERVER['SERVER_NAME'])) {
+ return false;
+ }
+
+ $rv = $_SERVER['SERVER_NAME'];
+
+ if (!isset($_SERVER['SERVER_PORT'])) {
+ return $rv;
+ }
+
+ if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) {
+ if ($_SERVER['SERVER_PORT'] != 443) {
+ $rv .= ':' . $_SERVER['SERVER_PORT'];
+ }
+ } else {
+ if ($_SERVER['SERVER_PORT'] != 80) {
+ $rv .= ':' . $_SERVER['SERVER_PORT'];
+ }
+ }
+
+ return $rv;
+ }
+
+ /**
+ * Return babelfish URL to translate \c $lang_from to \c $lang_to
+ *
+ * @param lang_from
+ * @param lang_to
+ */
+ function url($lang_from, $lang_to) {
+ static $url_map = array(
+ 'en' => 'english',
+ 'fr' => 'french',
+ 'de' => 'german',
+ 'it' => 'italian',
+ 'es' => 'spanish',
+ 'pt' => 'portugese',
+ );
+
+ $lang_from = strtolower($lang_from);
+ $lang_to = strtolower($lang_to);
+
+ if (!isset($url_map[$lang_from])) {
+ return '';
+ }
+
+ $url = 'http://jump.altavista.com/translate_' . $url_map[$lang_from] . '.go' .
+ '?http://babelfish.altavista.com/babelfish/tr?doit=done' .
+ '&amp;lp=' . $lang_from . '_' . $lang_to .
+ '&amp;urltext=http';
+ if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
+ $url .= 's';
+ }
+ $url .= '://' . Babelfish::host() . $_SERVER['REQUEST_URI'] .
+ (strpos('?', $_SERVER['REQUEST_URI']) ? '&amp;' : '?') .
+ 'babelfish=' . $lang_from . '_' . $lang_to;
+
+ return $url;
+ }
+
+ /**
+ * Return HTML of babelfish links
+ *
+ * @param lang_from Language to translate from
+ */
+ function links($lang_from = 'en') {
+ static $fishes = array(
+ 'en' => array( # English
+ 'de' => '&Uuml;bersetzen&nbsp;Sie&nbsp;diese&nbsp;Seite&nbsp;ins&nbsp;Deutsche',
+ 'es' => 'Traduzca&nbsp;esta&nbsp;paginaci&oacute;n&nbsp;a&nbsp;espa&ntilde;ol',
+ 'fr' => 'Traduisez&nbsp;cette&nbsp;page&nbsp;en&nbsp;fran&ccedil;ais',
+ 'it' => 'Tradurre&nbsp;questa&nbsp;pagina&nbsp;in&nbsp;italiano',
+ 'pt' => 'Traduza&nbsp;esta&nbsp;p&aacute;gina&nbsp;em&nbsp;portugu&ecirc;ses',
+ 'zh' => '&#x7ffb;&#x8bd1;&#x8fd9;&#x9875;&#x6210;&#x6c49;&#x8bed;&nbsp;(CN)',
+ 'ja' => '&#x65e5;&#x672c;&#x8a9e;&#x306b;&#x3053;&#x306e;&#x30da;&#x30fc;&#x30b8;&#x3092;&#x7ffb;&#x8a33;&#x3057;&#x306a;&#x3055;&#x3044;&nbsp;(Nihongo)',
+ 'ko' => '&#xd55c;&#xad6d;&#xc778;&#xc73c;&#xb85c;&nbsp;&#xc774;&nbsp;&#xd398;&#xc774;&#xc9c0;&#xb97c;&nbsp;&#xbc88;&#xc5ed;&#xd558;&#xc2ed;&#xc2dc;&#xc694;&nbsp;(Hangul)',
+ ),
+ 'fr' => array( # French
+ 'de' => '&Uuml;bersetzen&nbsp;Sie&nbsp;diese&nbsp;Seite&nbsp;in&nbsp;Deutschen',
+ 'en' => 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;English',
+ ),
+ 'de' => array( # German
+ 'en' => 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;English',
+ 'fr' => 'Traduisez&nbsp;cette&nbsp;page&nbsp;en&nbsp;fran&ccedil;ais',
+ ),
+ 'it' => array( # Italian
+ 'en' => 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;English',
+ ),
+ 'es' => array( # Spanish
+ 'en' => 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;English',
+ ),
+ 'pt' => array( # Portugese
+ 'en' => 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;English',
+ ),
+ 'ru' => array( # Russian
+ 'en' => 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;English',
+ ),
+ );
+
+ // \todo Use phpsniff or PEAR's Net_UserAgent_Detect to detect the browser type
+ // as Netscape 4.x and possibly others displays '&#xabcd;' literally
+// if (preg_match('/(mozilla\/4)/i', $_SERVER['HTTP_USER_AGENT'])) {
+// $fishes['en']['zh'] = 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;Chinese&nbsp;(CN)';
+// $fishes['en']['ja'] = 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;Japenese&nbsp;(Nihongo)';
+// $fishes['en']['ko'] = 'Translate&nbsp;this&nbsp;page&nbsp;into&nbsp;Korean&nbsp;(Hangul)';
+// }
+
+ // If we have already translated this page (babelfish=en_fr), then don't display the strings again
+ if (!isset($fishes[$lang_from]) || isset($_GET['babelfish'])) {
+ return [];
+ }
+
+ $a = [];
+ foreach ($fishes[$lang_from] as $lang_to => $msg) {
+ $a[] = array('target' => $lang_to,
+ 'href' => Babelfish::url($lang_from, $lang_to),
+ 'msg' => $msg);
+ }
+
+ return $a;
+ }
+
+ /**
+ * Return javascript code to display babelfish logo
+ *
+ * \static
+ */
+ function logo($lang = 'en') {
+ static $s = "<script language=\"JavaScript1.2\" src=\"http://www.altavista.com/r?%str\"></script>";
+
+ $lang = strtolower($lang);
+
+ switch ($lang) {
+ case 'en':
+ case 'de':
+ case 'fr':
+ case 'it':
+ return sprintf($s, $lang);
+ case 'es':
+ return sprintf($s, 'esp');
+ case 'pt':
+ return sprintf($s, 'port');
+ }
+
+ return '';
+ }
+
+}
+
+?>
diff --git a/includes/classes/Bablotron.php b/includes/classes/Bablotron.php
new file mode 100755
index 0000000..ca33be6
--- /dev/null
+++ b/includes/classes/Bablotron.php
@@ -0,0 +1,172 @@
+<?php
+/**
+ * Spellcheck Library
+ *
+ * @package kernel
+ * @version $Header$
+ *
+ * Copyright (c) 2004 bitweaver.org
+ * Copyright (c) 2003 tikwiki.org
+ * Copyright (c) 2002-2003, Luis Argerich, Garland Foster, Eduardo Polidor, et. al.
+ * All Rights Reserved. See below for details and a complete list of authors.
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See http://www.gnu.org/copyleft/lesser.html for details
+ *
+ * $Id$
+ *
+ * A spell checking library.
+ *
+ * Currently used for BitBase.
+ * @author lrargerich <lrargerich@yahoo.com>
+ * created 2002/11/14
+ */
+
+/**
+ * Spellcheck Library
+ *
+ * @package kernel
+ * @todo does not need to inherit BitBase class. Should hold a BitDb connection as a
+ * global variable.
+ */
+class Bablotron extends BitBase
+{
+ /**
+ * @todo Variable is scoped here but not really used in this scope below.
+ */
+ public $words;
+ /**
+ * Used to store the current language.
+ *
+ * @todo Not sure where this gets set from. Is used in other libraries.
+ */
+ public $lan;
+ /**
+ * @todo Empty variable - does nothing
+ */
+ public $db;
+ /**
+ * Spellchecking and finding of alternative words
+ */
+ function __construct( $lan )
+ {
+ parent::__construct();
+ $this->lan = $lan;
+ }
+ /**
+ * @todo Empty function - does nothing
+ */
+ function sql_error($query, $result)
+ {
+ return;
+ }
+ /**
+ * Spellchecks a line of text
+ * @param text line of text
+ * @param threshold the similarity threshold
+ * @returns array a list of alternative words if spelt incorrectly
+ */
+ function spellcheck_text($text, $threshold = 5)
+ {
+ $words = preg_split("/\s/", $text);
+ $results = [];
+ foreach ($words as $word)
+ {
+ if (!$this->word_exists($word))
+ {
+ $results[$word] = $this->find_similar_words($word, $threshold);
+ }
+ }
+ return $results;
+ }
+ /**
+ * Spellchecks a word
+ * @param word the word
+ * @param threshold the similarity threshold
+ * @returns array a list of alternative words if spelt incorrectly
+ */
+ function spellcheck_word($word, $threshold = 5)
+ {
+ $results = [];
+ if (!$this->word_exists($word))
+ {
+ $results[$word] = $this->find_similar_words($word, $threshold);
+ }
+ return $results;
+ }
+ /**
+ * Spellchecks a line of text
+ * @param text line of text
+ * @param threshold Not used @todo param threshold Not used
+ * @return array a list of incorrectly spelt words or words not found in the database
+ */
+ function quick_spellcheck_text($text, $threshold = 5)
+ {
+ $words = preg_split("/\s/", $text);
+ $results = [];
+ foreach ($words as $word)
+ {
+ if (!$this->word_exists($word))
+ {
+ $results[] = $word;
+ }
+ }
+ return $results;
+ }
+ /**
+ * Lists similar words by relevance threshold.
+ * @param word the word
+ * @param threshold the similarity threshold
+ * @return array of similar words and Levenshtein distance
+ */
+ function find_similar_words($word, $threshold)
+ {
+ $similar = [];
+ $tbl = 'babl_words_' . $this->lan;
+ $word = addslashes( ( trim( $word ) ) );
+ $sndx = substr($word, 0, 2);
+ $query = "select `word` AS word from `$tbl` where `di`=?";
+ @$result = $this->mDb->query($query, array($sndx));
+ while ($res = $result->fetchRow() )
+ {
+ $tword = $res["word"];
+ $lev = levenshtein($tword, $word);
+ if (count($similar) < $threshold)
+ {
+ $similar[$tword] = $lev;
+ asort ($similar);
+ }
+ else
+ {
+ // If the array is full then if the lev is better than the worst lev
+ // then update $keys = array_keys($similar);
+ $last_key = $keys[count($keys) - 1];
+ if ($lev < $similar[$last_key])
+ {
+ unset ($similar[$last_key]);
+ $similar[$tword] = $lev;
+ asort ($similar);
+ }
+ }
+ }
+ return $similar;
+ }
+ /**
+ * Checks if a word exists
+ * @param word the word
+ * @return int number of matches
+ */
+ function word_exists($word)
+ {
+ $tbl = 'babl_words_' . $this->lan;
+ $word = addslashes( ( trim( $word ) ) );
+ $query = "select `word` AS word from `$tbl` where `word`=?";
+ $result = $this->mDb->query($query,array($word));
+ return $result->numRows();
+ }
+ /**
+ * @todo Empty function - does nothing
+ */
+ function find_similar($word, $threshold)
+ {
+ }
+}
+?>
diff --git a/includes/classes/LibertyTranslations.php b/includes/classes/LibertyTranslations.php
new file mode 100755
index 0000000..0527b9b
--- /dev/null
+++ b/includes/classes/LibertyTranslations.php
@@ -0,0 +1,173 @@
+<?php
+/**
+ * @package languages
+ * @version $Header$
+ *
+ * @author ?
+ */
+
+namespace Bitweaver\Languages;
+use Bitweaver\BitBase;
+use Bitweaver\Liberty\LibertyBase;
+
+ /**
+ * @package languages
+ */
+ class LibertyTranslations extends LibertyBase {
+ public function __construct( $pContentId = null ) {
+ $this->mContentId = $pContentId;
+ parent::__construct();
+ }
+
+ public function getContentTranslations() {
+ global $gBitSystem, $gBitLanguage;
+ $ret = [];
+ if( BitBase::verifyId( $this->mContentId ) ) {
+ $translationId = $this->mDb->getOne( "SELECT `translation_id` FROM `".BIT_DB_PREFIX."i18n_content_trans_map` WHERE `content_id`=?", array( $this->mContentId ) );
+ if( BitBase::verifyId( $translationId ) ) {
+ $query = "SELECT lc.`content_id`, lc.`title`, lc.`lang_code`, ictm.`translation_id`
+ FROM `".BIT_DB_PREFIX."i18n_content_trans_map` ictm
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lc.`content_id`=ictm.`content_id` )
+ WHERE ictm.`translation_id`=?";
+ $result = $this->mDb->query( $query, array( $translationId ) );
+ while( $aux = $result->fetchRow() ) {
+ // default to site language
+ if( empty( $aux['lang_code'] )) {
+ $aux['lang_code'] = $gBitLanguage->mLanguage;
+ }
+ $ret[$aux['lang_code']] = $aux;
+ }
+ }
+ }
+ return $ret;
+ }
+
+ public function storeTranslation( $pParamHash ) {
+ if( $this->verify( $pParamHash ) ) {
+ $table = BIT_DB_PREFIX."i18n_content_trans_map";
+ if( !BitBase::verifyId( $pParamHash['translation_store']['translation_id'] ?? 0 ) && is_array( $pParamHash['translation_store'] ) ) {
+ foreach( $pParamHash['translation_store'] as $store ) {
+ $result = $this->mDb->associateInsert( $table, $store );
+ }
+ } else {
+ $result = $this->mDb->associateInsert( $table, $pParamHash['translation_store'] );
+ }
+ }
+ }
+
+ public function verify( array &$pParamHash ): bool {
+ $i = 0;
+
+ // make sure we don't have a translation_id for this content yet
+ if( BitBase::verifyId( $pParamHash['from_id'] ?? 0 ) ) {
+ $pParamHash['translation_id'] = $this->mDb->getOne( "SELECT `translation_id` FROM `".BIT_DB_PREFIX."i18n_content_trans_map` WHERE `content_id`=?", array( $pParamHash['from_id'] ) );
+ }
+
+ // if we have this page in this translation, we should inform the user somehow.
+ // in theory, this shouldn't happen, but there might be a situation where we end up with 2 users translating the same page at the same time. (is this true?)
+
+ // if we have a translation_id, we add this content to the same group of translations
+ if( BitBase::verifyId( $pParamHash['translation_id'] ?? 0 ) ) {
+ $pParamHash['translation_store']['translation_id'] = $pParamHash['translation_id'];
+ $pParamHash['translation_store']['content_id'] = $pParamHash['content_id'];
+ } elseif( BitBase::verifyId( $pParamHash['from_id'] ?? 0 ) ) {
+ // we have a from_id but no translation_id, this is a new entry in the translation map and we need both, the original and the new content_id entered
+ // we can simply use the from_id as the translation_id
+ $pParamHash['translation_store'][$i]['translation_id'] = $pParamHash['from_id'];
+ $pParamHash['translation_store'][$i]['content_id'] = $pParamHash['from_id'];
+ $i++;
+ $pParamHash['translation_store'][$i]['translation_id'] = $pParamHash['from_id'];
+ $pParamHash['translation_store'][$i]['content_id'] = $pParamHash['content_id'];
+ }
+ return count( $this->mErrors ) == 0;
+ }
+
+ public function expunge(): bool {
+ if( BitBase::verifyId( $this->mContentId ) ) {
+ $result = $this->mDb->query( "DELETE FROM `".BIT_DB_PREFIX."i18n_content_trans_map` WHERE `content_id`=?", $this->mContentId );
+ }
+ return true;
+ }
+}
+
+// ================== service functions ==================
+
+function translation_content_display( &$pObject ) {
+ global $gBitSmarty, $gBitLanguage;
+ $trans = new LibertyTranslations( $pObject->mContentId );
+ $translations = $trans->getContentTranslations();
+ // merge this information that we can display the appropriate flags
+ if( count( $translations ) > 1 ) {
+ foreach( $translations as $key => $trans ) {
+ $translations[$key] = array_merge( $gBitLanguage->mLanguageList[$trans['lang_code']], $trans );
+ }
+ $gBitSmarty->assign( 'i18nTranslations', $translations );
+ }
+}
+
+function translation_content_edit( &$pObject, &$pParamHash ) {
+ global $gBitLanguage, $gBitSmarty, $gBitUser;
+ $trans = new LibertyTranslations( $pObject->mContentId );
+ $translationId = null;
+ $translations = $trans->getContentTranslations();
+ foreach( $gBitLanguage->mLanguageList as $lang_code => $language ) {
+ $translationsList[$lang_code] = $language;
+ if( !empty( $translations[$lang_code]['content_id'] ) ) {
+ $translationsList[$lang_code]['content_id'] = $translations[$lang_code]['content_id'];
+ $translationsList[$lang_code]['title'] = $translations[$lang_code]['title'];
+ $translationId = $translations[$lang_code]['translation_id'];
+ }
+ }
+ $gBitSmarty->assign( 'translationsList', $translationsList );
+ $gBitSmarty->assign( 'translationId', $translationId );
+
+ if( BitBase::verifyId( $_REQUEST['i18n']['from_id'] ?? 0 ) ) {
+ // load the content we're translating from
+ $transObject = LibertyBase::getLibertyObject( $_REQUEST['i18n']['from_id'] );
+ $gBitSmarty->assign( "translateFrom", $transObject );
+
+ // attempt google translation
+ if( !empty( $_REQUEST['i18n']['google'] ) && !empty( $transObject->mInfo['data'] )) {
+ // temporarily replace \n with a string
+ $nl = 'nlnlnlnlnl';
+ // initiate some variables
+ $transObject->mInfo['google_guess'] = '';
+ // we need to split the strings into small chunks due to url length limitations
+ $strings = str_split( $transObject->mInfo['data'], 1500 );
+ foreach( $strings as $string ) {
+ $requestUrl = "http://translate.google.com/translate_t?ie=UTF-8&oe=UTF-8&text=".urlencode( preg_replace( '/[\n]/', $nl, $string ))."&langpair=en|{$_REQUEST['i18n']['lang_code']}";
+ if( $handle = fopen( $requestUrl, "r" )) {
+ $data = '';
+ while( !feof( $handle )) {
+ $data .= fread( $handle, 8192 );
+ }
+ fclose( $handle );
+ preg_match_all( "!<div id=result_box[^>]*>([^<]*)</div>.*!", $data, $matches );
+ if( isset( $matches[1][0] )) {
+ $transObject->mInfo['google_guess'] .= preg_replace( "/".preg_quote( $nl, "/" )."/", "\n", $matches[1][0] );
+ }
+ }
+ }
+die;
+ }
+ }
+}
+
+// store the content
+function translation_content_store( $pObject, $pParamHash ) {
+ // if we are creating this content and we have a from_id, we know that we're translating a page
+ // mInfo['content_id'] isn't set when content is created
+ if( empty( $pObject->mInfo['content_id'] ) && BitBase::verifyId( $_REQUEST['i18n']['from_id'] ?? 0 ) ) {
+ $trans = new LibertyTranslations();
+ $storeHash = $_REQUEST['i18n'];
+ $storeHash['content_id'] = $pParamHash['content_id'];
+ if( !$trans->storeTranslation( $storeHash ) ) {
+ // error
+ }
+ }
+}
+
+function translation_content_expunge( $pObject, $pParamHash ) {
+ $trans = new LibertyTranslations( $pObject->mContentId );
+ $trans->expunge();
+} \ No newline at end of file