PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.7
VikBooking Hotel Booking Engine & PMS v1.6.7
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
vikbooking / site / helpers / translator.php

translator.php in VikBooking Hotel Booking Engine & PMS 1.6.7, at site/helpers/translator.php

821 lines 21.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 /**
14 * Global translator class for VikBooking contents.
15 */
16 class VikBookingTranslator
17 {
18 /**
19 * @var string
20 */
21 public $current_lang;
22
23 /**
24 * @var string
25 */
26 public $default_lang;
27
28 /**
29 * @var int
30 */
31 public $lim = 5;
32
33 /**
34 * @var int
35 */
36 public $lim0 = 0;
37
38 /**
39 * @var string
40 */
41 public $navigation = '';
42
43 /**
44 * @var string
45 */
46 public $error = '';
47
48 /**
49 * @var string
50 */
51 private $xml = '';
52
53 /**
54 * @var array
55 */
56 private $all_langs = [];
57
58 /**
59 * @var object
60 */
61 private $dbo;
62
63 /**
64 * @var string
65 */
66 private $translations_path_file;
67
68 /**
69 * @var array
70 */
71 private $translations_buffer = [];
72
73 /**
74 * @var string
75 *
76 * @since 1.16.6 (J) - 1.6.6 (WP)
77 */
78 private $keysearch = '';
79
80 /**
81 * @var array
82 *
83 * @since 1.16.6 (J) - 1.6.6 (WP)
84 */
85 private $cached_cols = [];
86
87 /**
88 * @var string
89 */
90 public static $force_tolang = null;
91
92 /**
93 * Class constructor.
94 */
95 public function __construct()
96 {
97 $app = JFactory::getApplication();
98
99 $this->current_lang = $this->getCurrentLang();
100 $this->default_lang = $this->getDefaultLang();
101 $this->lim = $app->input->getInt('limit', 5);
102 $this->lim0 = $app->input->getInt('limitstart', 0);
103 $this->dbo = JFactory::getDbo();
104 $this->translations_path_file = VBO_ADMIN_PATH . DIRECTORY_SEPARATOR . 'fields' . DIRECTORY_SEPARATOR . 'translations.xml';
105 }
106
107 /**
108 * Gets the language for the current execution.
109 *
110 * @return string
111 */
112 public function getCurrentLang()
113 {
114 if (!$this->current_lang) {
115 $this->current_lang = JFactory::getLanguage()->getTag();
116 }
117
118 return $this->current_lang;
119 }
120
121 /**
122 * Gets the default language for the requested section.
123 *
124 * @param string $section either site or administrator.
125 *
126 * @return string
127 */
128 public function getDefaultLang($section = 'site')
129 {
130 if (VBOPlatformDetection::isWordPress()) {
131 /**
132 * @wponly import the JComponentHelper class
133 */
134 jimport('joomla.application.component.helper');
135 }
136
137 if (!$this->default_lang && $section == 'site') {
138 $this->default_lang = JComponentHelper::getParams('com_languages')->get($section);
139 }
140
141 if ($section == 'site') {
142 return $this->default_lang;
143 }
144
145 return JComponentHelper::getParams('com_languages')->get($section);
146 }
147
148 /**
149 * Returns a list of translation INI files.
150 *
151 * @return array
152 */
153 public function getIniFiles()
154 {
155 // Keys = Lang Def composed as VBINIEXPL.strtoupper(Key)
156 // Values = Paths to INI Files
157
158 if (VBOPlatformDetection::isWordPress()) {
159 /**
160 * @wponly nothing to return
161 */
162 return [];
163 }
164
165 return [
166 'com_vikbooking_front' => ['path' => JPATH_SITE . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.com_vikbooking.ini'],
167 'com_vikbooking_admin' => ['path' => JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.com_vikbooking.ini'],
168 'com_vikbooking_admin_sys' => ['path' => JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.com_vikbooking.sys.ini'],
169 'mod_vikbooking_search' => ['path' => JPATH_SITE . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.mod_vikbooking_search.ini'],
170 'mod_vikbooking_horizontalsearch' => ['path' => JPATH_SITE . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'en-GB' . DIRECTORY_SEPARATOR . 'en-GB.mod_vikbooking_horizontalsearch.ini'],
171 ];
172 }
173
174 /**
175 * Builds a list of known languages.
176 *
177 * @return array
178 */
179 public function getLanguagesList()
180 {
181 $langs = [];
182 $known_langs = VikBooking::getVboApplication()->getKnownLanguages();
183
184 foreach ($known_langs as $ltag => $ldet) {
185 if ($ltag == $this->default_lang) {
186 $langs = [$ltag => $ldet] + $langs;
187 } else {
188 $langs[$ltag] = $ldet;
189 }
190 }
191
192 $this->all_langs = $langs;
193
194 return $this->all_langs;
195 }
196
197 /**
198 * Returns a list of known language tags.
199 *
200 * @return array
201 */
202 public function getLanguagesTags()
203 {
204 return array_keys($this->all_langs);
205 }
206
207 /**
208 * Replaces the prefix from a given table name.
209 *
210 * @param string $str the prefixed name.
211 *
212 * @return string
213 */
214 public function replacePrefix($str)
215 {
216 return $this->dbo->replacePrefix($str);
217 }
218
219 /**
220 * Helper method that makes sure the table name starts with the prefix placeholder.
221 * In order to avoid issues with queries containing the prefix placeholder ("#__"),
222 * the name of the table for the translated record is removed from the placeholder prefix.
223 *
224 * @param string $table_name the table name to adjust.
225 *
226 * @return string the adjust table name with the prefix placeholder.
227 *
228 * @since 1.16.0 (J) - 1.6.0 (WP)
229 */
230 public function adjustTablePrefix($table_name)
231 {
232 if (empty($table_name) || !is_string($table_name)) {
233 // nothing to do with the given value
234 return $table_name;
235 }
236
237 if (preg_match("/^#__/", $table_name)) {
238 // default prefix placeholder found at the beginning of the string
239 return $table_name;
240 }
241
242 if (strpos($table_name, 'vikbooking_') === false) {
243 // nothing to do with this table name
244 return $table_name;
245 }
246
247 // make the table name start with the prefix placeholder
248 $table_nm_parts = explode('vikbooking_', $table_name);
249 $table_nm_parts[0] = '#__';
250
251 return implode('vikbooking_', $table_nm_parts);
252 }
253
254 /**
255 * Fixer method for BC. The old structure was storing the table names for
256 * the translated records without the default prefix placeholder ('#__'),
257 * but this is invalid for the backup features. This method converts all
258 * table names for the translated records so that they will contain the
259 * default prefix placeholder at the beginning of the string.
260 *
261 * @return boolean
262 *
263 * @since 1.16.0 (J) - 1.6.0 (WP)
264 */
265 public function normalizeTnTableNames()
266 {
267 $query = $this->dbo->getQuery(true);
268
269 $query->select($this->dbo->qn('t.id'));
270 $query->select($this->dbo->qn('t.table'));
271
272 $query->from($this->dbo->qn('#__vikbooking_translations', 't'));
273
274 $this->dbo->setQuery($query);
275 $translations = $this->dbo->loadObjectList();
276
277 if (!$translations) {
278 // no translation records found
279 return false;
280 }
281
282 foreach ($translations as $tn_record) {
283 // normalize table name with prefix
284 $tn_record->table = $this->adjustTablePrefix($tn_record->table);
285
286 // update record on db
287 $this->dbo->updateObject('#__vikbooking_translations', $tn_record, 'id');
288 }
289
290 return true;
291 }
292
293 /**
294 * Builds an associative list of translation tables.
295 *
296 * @return mixed array or false.
297 */
298 public function getTranslationTables()
299 {
300 $xml = $this->getTranslationsXML();
301 if ($xml === false) {
302 return false;
303 }
304 $tables = [];
305 foreach ($xml->Translation as $translation) {
306 $attr = $translation->attributes();
307 $tables[(string)$attr->table] = JText::translate((string)$attr->name);
308 }
309
310 return $tables;
311 }
312
313 /**
314 * Returns the translated name of the table given the prefix
315 *
316 * @param string $table
317 */
318 public function getTranslationTableName($table)
319 {
320 $xml = $this->getTranslationsXML();
321 $table_name = '';
322 foreach ($xml->Translation as $translation) {
323 $attr = $translation->attributes();
324 if ((string)$attr->table == $table) {
325 return JText::translate((string)$attr->name);
326 }
327 }
328 return $table_name;
329 }
330
331 /**
332 * Returns an array with the XML Columns of the given table
333 *
334 * @param string $table
335 *
336 * @return array
337 */
338 public function getTableColumns($table)
339 {
340 if (isset($this->cached_cols[$table])) {
341 return $this->cached_cols[$table];
342 }
343
344 $xml = $this->getTranslationsXML();
345 $cols = [];
346 foreach ($xml->Translation as $translation) {
347 $attr = $translation->attributes();
348 if ((string)$attr->table == $table) {
349 foreach ($translation->Column as $column) {
350 $col_attr = $column->attributes();
351 if (!property_exists($col_attr, 'name')) {
352 continue;
353 }
354 $ind = (string)$col_attr->name;
355 $cols[$ind]['jlang'] = JText::translate((string)$column);
356 foreach ($col_attr as $key => $val) {
357 $cols[$ind][(string)$key] = (string)$val;
358 }
359 }
360 }
361 }
362
363 // cache table columns
364 $this->cached_cols[$table] = $cols;
365
366 return $cols;
367 }
368
369 /**
370 * Gets the name of the reference column for the given table.
371 *
372 * @param string $table the name of the table.
373 *
374 * @return string
375 *
376 * @since 1.16.6 (J) - 1.6.6 (WP)
377 */
378 public function getTableReferenceColumn($table)
379 {
380 foreach ($this->getTableColumns($table) as $col_name => $col_values) {
381 if (isset($col_values['reference'])) {
382 return $col_name;
383 }
384 }
385
386 return '';
387 }
388
389 /**
390 * Returns the db column marked as reference, of the record. Ex. the name of the Room in this record
391 *
392 * @param array $cols
393 * @param array $record
394 */
395 public function getRecordReferenceName($cols, $record)
396 {
397 foreach ($cols as $key => $values) {
398 if (array_key_exists('reference', $values)) {
399 if (array_key_exists($key, $record)) {
400 return $record[$key];
401 }
402 }
403 }
404 // if not found, not present or empty, return first value of the record
405 return $record[key($record)];
406 }
407
408 /**
409 * Returns the current records for the default language and this table
410 *
411 * @param string $table the name of the table.
412 * @param array $cols array containing the db fields to fetch,
413 * result of array_keys($this->getTableColumns()).
414 *
415 * @return array
416 */
417 public function getTableDefaultDbValues($table, $cols = [])
418 {
419 $def_vals = [];
420
421 if (!$cols) {
422 $cols = array_keys($this->getTableColumns($table));
423 if (!$cols) {
424 $this->setError("Table $table has no Columns.");
425 }
426 }
427
428 if ($cols) {
429 $cols = array_map([$this->dbo, 'qn'], $cols);
430
431 $reference_column = $this->getTableReferenceColumn($table);
432
433 $q = $this->dbo->getQuery(true)
434 ->select('SQL_CALC_FOUND_ROWS ' . $this->dbo->qn('id'))
435 ->select($cols)
436 ->from($this->dbo->qn($table))
437 ->order($this->dbo->qn(($reference_column ?: 'id')) . ' ASC');
438
439 if (!empty($this->keysearch) && $reference_column) {
440 $q->where($this->dbo->qn($reference_column) . ' LIKE ' . $this->dbo->q("%{$this->keysearch}%"));
441 }
442
443 $this->dbo->setQuery($q, $this->lim0, $this->lim);
444 $records = $this->dbo->loadAssocList();
445
446 if ($records) {
447 $this->dbo->setQuery('SELECT FOUND_ROWS();');
448 $this->setPagination($this->dbo->loadResult());
449 foreach ($records as $record) {
450 $ref_id = $record['id'];
451 unset($record['id']);
452 $def_vals[$ref_id] = $record;
453 }
454 } else {
455 $this->setError("Table " . $this->getTranslationTableName($table) . " has no Records.");
456 }
457 }
458
459 return $def_vals;
460 }
461
462 /**
463 * Sets the pagination HTML value for the current
464 * translation list, by using the Joomla native functions.
465 *
466 * @param int $tot_rows
467 */
468 private function setPagination($tot_rows)
469 {
470 jimport('joomla.html.pagination');
471 $pageNav = new JPagination($tot_rows, $this->lim0, $this->lim);
472 $this->navigation = $pageNav->getListFooter();
473 }
474
475 /**
476 * Returns the current pagination HTML value.
477 */
478 public function getPagination()
479 {
480 return $this->navigation;
481 }
482
483 /**
484 * Returns the translated records for this table and language
485 *
486 * @param string $table
487 * @param string $lang
488 *
489 * @return array
490 */
491 public function getTranslatedTable($table, $lang)
492 {
493 $translated = [];
494
495 $q = $this->dbo->getQuery(true);
496
497 $q->select($this->dbo->qn('t') . '.*')
498 ->from($this->dbo->qn('#__vikbooking_translations', 't'))
499 ->where($this->dbo->qn('t.table') . ' = ' . $this->dbo->q($this->adjustTablePrefix($table)))
500 ->where($this->dbo->qn('t.lang') . ' = ' . $this->dbo->q($lang))
501 ->order($this->dbo->qn('t.reference_id') . ' ASC');
502
503 $this->dbo->setQuery($q);
504
505 foreach ($this->dbo->loadAssocList() as $record) {
506 $record['content'] = json_decode($record['content'], true);
507 $translated[$record['reference_id']] = $record;
508 }
509
510 return $translated;
511 }
512
513 /**
514 * Main function to translate contents saved in the database.
515 *
516 * @param array $content The array taken from the database with the default values to be translated, passed as reference.
517 * @param string $table The name of the table containing the translation values, should match with the XML table name.
518 * @param array $alias_keys Key-Value pairs where Key is the ALIAS used and Value is the original field name. Opposite instead for the ID (reference_id).
519 * The key 'id' is always treated differently than the other keys. Correct usage: array('id' => 'idroom', 'room_name' => 'name')
520 * @param array $ids The reference_IDs to be translated, the IDs of the records. Taken from the content array if empty array passed.
521 * @param string $lang Force the translation to a specific language tag like it-IT.
522 *
523 * @return array The initial array with translated values (if applicable).
524 */
525 public function translateContents(&$content, $table, $alias_keys = array(), $ids = array(), $lang = null)
526 {
527 $to_lang = is_null($lang) ? $this->current_lang : $lang;
528 $to_lang = !is_null(self::$force_tolang) ? self::$force_tolang : $to_lang;
529
530 // multilang may be disabled
531 if (!$this->allowMultiLanguage()) {
532 return $content;
533 }
534
535 // check that requested lang is not the default lang
536 if ($to_lang == $this->default_lang || !$content) {
537 return $content;
538 }
539
540 // get all translatable columns of this table
541 $cols = $this->getTableColumns($table);
542
543 // get the reference ids to be translated
544 if (!count($ids)) {
545 $ids = $this->getReferencesFromContents($content, $alias_keys);
546 }
547
548 // load translations buffer for this table or set the var to an empty array
549 $translated = $this->getTranslationsBuffer($table, $ids, $to_lang);
550
551 if (!count($translated)) {
552 // load translations from db
553 $q = "SELECT * FROM `#__vikbooking_translations` WHERE `table`=" . $this->dbo->quote($this->adjustTablePrefix($table)) . " AND `lang`=" . $this->dbo->quote($to_lang) . (count($ids) ? " AND `reference_id` IN (" . implode(",", $ids) . ")" : "") . ";";
554 $this->dbo->setQuery($q);
555 $records = $this->dbo->loadAssocList();
556 foreach ($records as $record) {
557 $record['content'] = json_decode($record['content'], true);
558 if (is_array($record['content']) && $record['content']) {
559 $translated[$record['reference_id']] = $record['content'];
560 }
561 }
562 }
563
564 if (count($translated)) {
565 // set translations buffer
566 $this->translations_buffer[$table][$to_lang] = $translated;
567
568 // fetch reference_id to be translated and replace default lang values
569 $reference_key = array_key_exists('id', $alias_keys) ? $alias_keys['id'] : 'id';
570 foreach ($content as $ckey => $cvals) {
571 $reference_id = 0;
572 if (is_array($cvals)) {
573 foreach ($cvals as $subckey => $subcvals) {
574 if ($subckey == $reference_key) {
575 $reference_id = (int)$subcvals;
576 break;
577 }
578 }
579 $content[$ckey] = $this->translateArrayValues($cvals, $cols, $reference_id, $alias_keys, $translated);
580 } elseif ($ckey == $reference_key) {
581 $reference_id = (int)$cvals;
582 $content = $this->translateArrayValues($content, $cols, $reference_id, $alias_keys, $translated);
583 break;
584 }
585 }
586 }
587
588 return $content;
589 }
590
591 /**
592 * Compares the array to be translated with the translation and replaces the array values if not empty.
593 *
594 * @param array $content default lang values to be translated.
595 * @param array $alias_keys Key_Values pairs where Key is the ALIAS used and Value is the original
596 * field name. Opposite instead for the ID (reference_id).
597 *
598 * @return array
599 */
600 private function getReferencesFromContents($content, $alias_keys)
601 {
602 $references = [];
603 $reference_key = array_key_exists('id', $alias_keys) ? $alias_keys['id'] : 'id';
604
605 if (!is_array($content) || !$content) {
606 return [];
607 }
608
609 foreach ($content as $ckey => $cvals) {
610 if (is_array($cvals)) {
611 foreach ($cvals as $subckey => $subcvals) {
612 if ($subckey == $reference_key) {
613 $references[] = (int)$subcvals;
614 break;
615 }
616 }
617 } elseif ($ckey == $reference_key) {
618 $references[] = (int)$cvals;
619 break;
620 }
621 }
622
623 if ($references) {
624 $references = array_unique($references);
625 }
626
627 return $references;
628 }
629
630 /**
631 * Check whether these reference IDs were already fetched from the db for this table
632 *
633 * @param string $table
634 * @param array $ids
635 * @param string $lang
636 *
637 * @return array
638 */
639 private function getTranslationsBuffer($table, $ids, $lang)
640 {
641 if (!count($this->translations_buffer) || !isset($this->translations_buffer[$table]) || !isset($this->translations_buffer[$table][$lang])) {
642 return array();
643 }
644
645 $missing = false;
646 foreach ($ids as $id) {
647 if (!isset($this->translations_buffer[$table][$lang][$id])) {
648 $missing = true;
649 break;
650 }
651 }
652
653 return $missing === false ? $this->translations_buffer[$table][$lang] : array();
654 }
655
656 /**
657 * Compares the array to be translated with the translation and replaces the array values if not empty.
658 *
659 * @param array $content default lang values to be translated.
660 * @param array $cols the columns of this table.
661 * @param int $reference_id reference_id.
662 * @param array $alias_keys Key_Values pairs where Key is the ALIAS used and Value is the original field name.
663 * Opposite instead for the ID (reference_id).
664 * @param array $translated translated.
665 */
666 private function translateArrayValues($content, $cols, $reference_id, $alias_keys, $translated)
667 {
668 if (empty($reference_id)) {
669 return $content;
670 }
671
672 if (!array_key_exists($reference_id, $translated)) {
673 return $content;
674 }
675
676 foreach ($content as $key => $value) {
677 $native_key = $key;
678 if (count($alias_keys) > 0 && array_key_exists($key, $alias_keys) && $key != 'id') {
679 $key = $alias_keys[$key];
680 }
681 if (!array_key_exists($key, $cols)) {
682 continue;
683 }
684 if (array_key_exists($key, $translated[$reference_id]) && strlen($translated[$reference_id][$key]) > 0) {
685 $type = $cols[$key]['type'];
686 if ($type == 'json') {
687 // only the translated and not empty keys will be taken from the translation
688 $tn_json = json_decode($translated[$reference_id][$key], true);
689 $content_json = json_decode($value, true);
690 $jkeys = !empty($cols[$key]['keys']) ? explode(',', $cols[$key]['keys']) : array();
691 if (is_array($tn_json) && $tn_json && is_array($content_json) && $content_json) {
692 foreach ($content_json as $jk => $jv) {
693 if (array_key_exists($jk, $tn_json) && strlen($tn_json[$jk]) > 0) {
694 $content_json[$jk] = $tn_json[$jk];
695 }
696 }
697 $content[$native_key] = json_encode($content_json);
698 }
699 } else {
700 // field is a text type or a text-derived one
701 $content[$native_key] = $translated[$reference_id][$key];
702 }
703 }
704 }
705
706 return $content;
707 }
708
709 /**
710 * Sets and Returns the SimpleXML object for the translations
711 */
712 public function getTranslationsXML()
713 {
714 if (!is_file($this->translations_path_file)) {
715 $this->setError($this->translations_path_file . ' does not exist or is not readable');
716 return false;
717 }
718 if (!function_exists('simplexml_load_file')) {
719 $this->setError('Function simplexml_load_file is not available on the server.');
720 return false;
721 }
722 if (is_object($this->xml)) {
723 return $this->xml;
724 }
725 libxml_use_internal_errors(true);
726 if (($xml = simplexml_load_file($this->translations_path_file)) === false) {
727 $this->setError("Error reading XML:\n".$this->libxml_display_errors());
728 return false;
729 }
730 $this->xml = $xml;
731 return $xml;
732 }
733
734 /**
735 * Tells if the multi-language environment is enabled.
736 *
737 * @return bool
738 */
739 private function allowMultiLanguage()
740 {
741 return VikBooking::allowMultiLanguage();
742 }
743
744 /**
745 * Explanation of the XML error
746 *
747 * @param $error
748 */
749 public function libxml_display_error($error)
750 {
751 $return = "\n";
752 switch ($error->level) {
753 case LIBXML_ERR_WARNING :
754 $return .= "Warning ".$error->code.": ";
755 break;
756 case LIBXML_ERR_ERROR :
757 $return .= "Error ".$error->code.": ";
758 break;
759 case LIBXML_ERR_FATAL :
760 $return .= "Fatal Error ".$error->code.": ";
761 break;
762 }
763 $return .= trim($error->message);
764 if ($error->file) {
765 $return .= " in ".$error->file;
766 }
767 $return .= " on line ".$error->line."\n";
768 return $return;
769 }
770
771 /**
772 * Get the XML errors occurred
773 */
774 public function libxml_display_errors()
775 {
776 $errorstr = "";
777 $errors = libxml_get_errors();
778 foreach ($errors as $error) {
779 $errorstr .= $this->libxml_display_error($error);
780 }
781 libxml_clear_errors();
782 return $errorstr;
783 }
784
785 /**
786 * Concatenates an error to the errors string.
787 *
788 * @param string $str the error string to add.
789 *
790 * @return void
791 */
792 private function setError($str)
793 {
794 $this->error .= $str."\n";
795 }
796
797 /**
798 * Returns the current error string in HTML format.
799 *
800 * @return string
801 */
802 public function getError()
803 {
804 return nl2br(rtrim($this->error, "\n"));
805 }
806
807 /**
808 * Sets a key value to search/filter translations for.
809 *
810 * @param string $key the term to search/filter.
811 *
812 * @return self
813 */
814 public function setKeySearch($key)
815 {
816 $this->keysearch = (string) $key;
817
818 return $this;
819 }
820 }
821