1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
translate_tools.php
См. документацию.
1<?php
7
8
10$arDirs = NULL;
11$arFiles = NULL;
12$arTLangs = NULL;
16
26function GetLangDirs($arDirs, $showTranslationDifferences = false)
27{
28 global $arLangDirs;
29 if (is_array($arDirs))
30 {
31 if ($showTranslationDifferences)
32 {
33 foreach ($arDirs as $arr1)
34 {
35 if($arr1["IS_LANG"])
36 {
37 $arLangDirs[] = $arr1;
38 }
39 }
40 }
41 else
42 {
44 }
45 }
46}
47
48
49
63function GetTDirList($path, $subDirs = false, $restructLanguageList = array())
64{
65 global $arDirs, $arFiles;
66
67 $fullPath = Translate\IO\Path::tidy(Main\Application::getDocumentRoot(). '/'. $path. '/');
68
69 if (preg_match('|^' . preg_quote(realpath(Main\Application::getDocumentRoot() . '/upload'), '|') . '|iu', $fullPath))
70 {
71 return false;
72 }
73
75
76 if ($isLang)
77 {
79 if (
81 in_array($langId, Translate\Config::getTranslationRepositoryLanguages())
82 )
83 {
84 $fullPath = Main\Localization\Translation::convertLangPath($fullPath, $langId);
85 }
86 else
87 {
88 $fullPath = realpath($fullPath);
89 }
90 }
91 else
92 {
93 $fullPath = realpath($fullPath);
94 }
95
96 $fullPath = Translate\IO\Path::tidy($fullPath);
97
98
99 $handle = @opendir($fullPath);
100 if($handle)
101 {
102 $parent = Translate\IO\Path::tidy('/'. $path. '/');
103 $absParent = Main\Localization\Translation::convertLangPath(Main\Application::getDocumentRoot(). $parent, $langId);
104
105 $arList = array();
106 while (false !== ($file = readdir($handle)))
107 {
108 if (in_array($file, Translate\IGNORE_FS_NAMES))
109 {
110 continue;
111 }
112
113 $isDir = is_dir($absParent. $file);
114 $pathPrepared = $parent. $file;
115
116 if ($isDir && in_array($pathPrepared, Translate\IGNORE_BX_NAMES))
117 {
118 continue;
119 }
120 if (!$isDir && (mb_substr($file, -4) !== '.php'))
121 {
122 continue;
123 }
124
125 $arList[$pathPrepared] = array(
126 'IS_DIR' => ($isDir ? 'Y' : 'N'),
127 'PARENT' => $parent,
128 'PATH' => ($isDir ? $pathPrepared."/" : $pathPrepared),
129 'FILE' => $file,
130 'IS_LANG' => $isLang,
131 'FULL_PATH' => $absParent. $file,
132 );
133 if (!$isDir)
134 {
135 $arList[$pathPrepared]['LANG'] = $isLang ? Translate\IO\Path::extractLangId($pathPrepared) : '';
136 }
137
138 if (!$isDir && $isLang && Main\Localization\Translation::useTranslationRepository())
139 {
140 foreach (Translate\Config::getTranslationRepositoryLanguages() as $langId)
141 {
142 if (!empty($restructLanguageList) && !in_array($langId, $restructLanguageList))
143 {
144 continue;
145 }
146 $langParent = Translate\IO\Path::replaceLangId($arList[$pathPrepared]['PARENT'], $langId);
147 $langPathPrepared = $langParent . $arList[$pathPrepared]['FILE'];
148
149 $langPath = Main\Localization\Translation::convertLangPath(Main\Application::getDocumentRoot(). $langPathPrepared, $langId);
150
151 if (file_exists($langPath))
152 {
153 $arList[$langPath] = array(
154 'IS_DIR' => 'N',
155 'PARENT' => $langParent,
156 'PATH' => $langPathPrepared,
157 'FILE' => $arList[$pathPrepared]['FILE'],
158 'FULL_PATH' => $langPath,
159 'IS_LANG' => true,
160 'IS_LANG_REP' => true,
161 'LANG' => $langId,
162 );
163 }
164 }
165 }
166 }
167 closedir($handle);
168
169 ksort($arList);
170
171 foreach($arList as $pathPrepared => $arr)
172 {
173 if($arr['IS_DIR'] == 'Y')
174 {
175 if($subDirs)
176 {
177 $arr['IS_LANG'] |= GetTDirList($pathPrepared. '/', $subDirs, $restructLanguageList);
178 }
179
180 $arDirs[] = $arr;
181 //dir is lang if any of it's children is lang
182 $isLang = $isLang || $arr['IS_LANG'];
183 }
184 elseif(Translate\IO\Path::isLangDir($pathPrepared))
185 {
186 if(mb_substr($arr['FILE'], -4) == '.php')
187 {
188 $arFiles[] = $arr;
189 }
190 }
191 }
192 }
193
194 //flag for parent
195 return $isLang;
196}
197
210function GetTCSVArray($filterKeyIndex, $targetEncoding = '', $restructLanguageList = array())
211{
213 global $arFiles;
214
215 $arr = array();
216
221 foreach ($arFiles as $file)
222 {
223 $key = Translate\IO\Path::replaceLangId($file['PATH'], '#LANG_ID#');
224 if ($key != $filterKeyIndex)
225 {
226 continue;
227 }
228
229 if (isset($file['LANG']))
230 {
231 $langId = $file['LANG'];
232 }
233 else
234 {
235 $langId = Translate\IO\Path::extractLangId($file['PATH']);
236 }
237
238 if (!empty($restructLanguageList) && !in_array($langId, $restructLanguageList))
239 {
240 continue;
241 }
242
243 if (isset($file['FULL_PATH']))
244 {
245 $fname = $file['FULL_PATH'];
246 }
247 else
248 {
249 $fname = Main\Application::getDocumentRoot(). $file['PATH'];
250 $fname = Main\Localization\Translation::convertLangPath($fname, $langId);
251 }
252
253 $sourceEncoding = Main\Localization\Translation::getSourceEncoding($langId);
254
255 $MESS = array();
256
257 include($fname);
258
259 if (!empty($MESS) && is_array($MESS))
260 {
261 foreach ($MESS as $phraseCode => $phrase)
262 {
263 $phraseCode = (string)$phraseCode;
264 if ($phraseCode != '')
265 {
266 if ($targetEncoding != '' && $sourceEncoding != $targetEncoding)
267 {
268 $errorMessage = '';
269 $phrase = Encoding::convertEncoding($phrase, $sourceEncoding, $targetEncoding, $errorMessage);
270 /*
271 if (!$phrase && !empty($errorMessage))
272 {
273 $this->addError(new Error($errorMessage));
274 }
275 */
276 }
277 $arr[$key][$phraseCode][$langId] = $phrase;
278 }
279 }
280 }
281 }
282
283 return $arr;
284}
285
295function SaveTCSVFile($filePath, $encodingIn, $rewriteMode, $mergeMode, &$errors)
296{
298 $isUtfMode = Translate\Config::isUtfMode();
300
301
302 $phraseList = array();
303 $columnList = [];
304 $fileIndex = null;
305 $keyIndex = null;
306
307 $csvFile = new Translate\IO\CsvFile($filePath);
308 if (!$csvFile->openLoad())
309 {
310 $errors[] = Loc::getMessage('TR_TOOLS_ERROR_EMPTY_FILE');
311 return false;
312 }
313
314 if ($csvFile->hasUtf8Bom())
315 {
316 $encodingIn = 'utf-8';
317 }
318
319 $csvFile
320 ->setFieldsType(Translate\IO\CsvFile::FIELDS_TYPE_WITH_DELIMITER)
321 ->setFirstHeader(false)
322 ->setFieldDelimiter(Translate\IO\CsvFile::DELIMITER_TZP);
323
324 $rowHead = $csvFile->fetch();
325 if (
326 !is_array($rowHead) ||
327 empty($rowHead) ||
328 (count($rowHead) == 1 && ($rowHead[0] === null || $rowHead[0] === ''))
329 )
330 {
331 $errors[] = Loc::getMessage('BX_TRANSLATE_IMPORT_ERR_EMPTY_FIRST_ROW');
332 }
333 else
334 {
335 $columnList = array_flip($rowHead);
336 foreach ($languageList as $keyLang => $langID)
337 {
338 if (!isset($columnList[$langID]))
339 {
340 unset($languageList[$keyLang]);
341 }
342 }
343 if (!isset($columnList['file']))
344 {
345 $errors[] = Loc::getMessage('BX_TRANSLATE_IMPORT_ERR_DESTINATION_FIELD_ABSENT');
346 }
347 else
348 {
349 $fileIndex = $columnList['file'];
350 }
351 if (!isset($columnList['key']))
352 {
353 $errors[] = Loc::getMessage('BX_TRANSLATE_IMPORT_ERR_PHRASE_CODE_FIELD_ABSENT');
354 }
355 else
356 {
357 $keyIndex = $columnList['key'];
358 }
359 if (empty($languageList))
360 {
361 $errors[] = Loc::getMessage('BX_TRANSLATE_IMPORT_ERR_LANGUAGE_LIST_ABSENT');
362 }
363 }
364
365 if (empty($errors))
366 {
367 $csvRowCounter = 1;
368 while ($csvRow = $csvFile->fetch())
369 {
370 $csvRowCounter ++;
371 if (
372 !is_array($csvRow) ||
373 empty($csvRow) ||
374 (count($csvRow) == 1 && ($csvRow[0] === null || $csvRow[0] === ''))
375 )
376 {
377 continue;
378 }
379 $file = (isset($csvRow[$fileIndex]) ? $csvRow[$fileIndex] : '');
380 $key = (isset($csvRow[$keyIndex]) ? $csvRow[$keyIndex] : '');
381 if ($file == '' || $key == '')
382 {
383 $rowErrors = [];
384 if ($file == '')
385 {
386 $rowErrors[] = Loc::getMessage('BX_TRANSLATE_IMPORT_ERR_DESTINATION_FILEPATH_ABSENT');
387 }
388 if ($key == '')
389 {
390 $rowErrors[] = Loc::getMessage('BX_TRANSLATE_IMPORT_ERR_PHRASE_CODE_ABSENT');
391 }
392 $errors[] = Loc::getMessage(
393 'TR_TOOLS_ERROR_LINE_FILE_EXT',
394 ['#LINE#' => $csvRowCounter, '#ERROR#' => implode('; ', $rowErrors)]
395 );
396 unset($rowErrors);
397 continue;
398 }
399
400
401
402 $rowErrors = [];
403
404 if (!isset($phraseList[$file]))
405 {
406 $phraseList[$file] = [];
407 }
408 foreach ($languageList as $languageId)
409 {
410 if (!isset($phraseList[$file][$languageId]))
411 {
412 $phraseList[$file][$languageId] = [];
413 }
414
415 $langIndex = $columnList[$languageId];
416 if (!isset($csvRow[$langIndex]))
417 {
418 $rowErrors[] = Loc::getMessage(
419 'BX_TRANSLATE_IMPORT_ERR_ROW_LANG_ABSENT',
420 ['#LANG#' => $languageId]
421 );
422 continue;
423 }
424 if ($csvRow[$langIndex] === '')
425 {
426 continue;
427 }
428
429 $phrase = str_replace("\\\\", "\\", $csvRow[$langIndex]);
430
431 if ($useTranslationRepository)
432 {
433 $encodingOut = Main\Localization\Translation::getSourceEncoding($languageId);
434 }
435 elseif ($isUtfMode)
436 {
437 $encodingOut = 'utf-8';
438 }
439 else
440 {
441 $encodingOut = Translate\Config::getCultureEncoding($languageId);
442 if (!$encodingOut)
443 {
445 }
446 }
447
448 if (
449 $encodingIn !== '' &&
450 $encodingOut !== '' &&
451 $encodingIn !== $encodingOut
452 )
453 {
454 $errorMessage = '';
455 $phrase = Encoding::convertEncoding($phrase, $encodingIn, $encodingOut, $errorMessage);
456
457 if (!$phrase && !empty($errorMessage))
458 {
459 $rowErrors[] = $errorMessage;
460 continue;
461 }
462 }
463
464 $checked = true;
465 if ($encodingOut == 'utf-8')
466 {
467 $validPhrase = preg_replace("/[^\x01-\x7F]/",'', $phrase);// remove ASCII characters
468 if ($validPhrase !== $phrase)
469 {
470 $checked = \Bitrix\Main\Text\Encoding::detectUtf8($phrase);
471 }
472 unset($validPhrase);
473 }
474
475 if ($checked)
476 {
477 $phraseList[$file][$languageId][$key] = $phrase;
478 }
479 else
480 {
481 $rowErrors[] = Loc::getMessage(
482 'BX_TRANSLATE_IMPORT_ERR_NO_VALID_UTF8_PHRASE',
483 ['#LANG#' => $languageId]
484 );
485 }
486
487 unset($checked, $phrase);
488 }
489
490 if (!empty($rowErrors))
491 {
492 $errors[] = Loc::getMessage(
493 'TR_TOOLS_ERROR_LINE_FILE_BIG',
494 [
495 '#LINE#' => $csvRowCounter,
496 '#FILENAME#' => $file,
497 '#PHRASE#' => $key,
498 '#ERROR#' => implode('; ', $rowErrors),
499 ]
500 );
501 }
502 unset($rowErrors);
503 }
504 unset($csvRow);
505 }
506 $csvFile->close();
507 unset($csvFile);
508
509 foreach ($phraseList as $fileIndex => $translationList)
510 {
511 if (Translate\IO\Path::isLangDir($fileIndex, true) !== true)
512 {
513 $errors[] = Loc::getMessage('TR_TOOLS_ERROR_FILE_NOT_LANG', array('%FILE%' => $fileIndex));
514 continue;
515 }
516 foreach ($translationList as $languageId => $fileMessages)
517 {
518 if (empty($fileMessages))
519 {
520 continue;
521 }
522
523 $rawFile = Translate\IO\Path::replaceLangId($fileIndex, $languageId);
524 $file = Rel2Abs('/', $rawFile);
525 if ($file !== $rawFile)
526 {
527 $errors[] = Loc::getMessage(
528 'BX_TRANSLATE_IMPORT_ERR_BAD_FILEPATH',
529 ['#FILE#' => $fileIndex]
530 );
531 break;
532 }
533
534 $fullPath = Main\Application::getDocumentRoot(). $file;
535
537 {
538 if (in_array($languageId, Translate\Config::getTranslationRepositoryLanguages()))
539 {
540 $fullPath = Main\Localization\Translation::convertLangPath($fullPath, $languageId);
541 }
542 else
543 {
544 $fullPath = realpath($fullPath);
545 }
546 }
547 else
548 {
549 $fullPath = realpath($fullPath);
550 }
551
552 $fullPath = Translate\IO\Path::tidy($fullPath);
553
554 $MESS = [];
555 if (!$rewriteMode && file_exists($fullPath))
556 {
557
558 include $fullPath;
559
560 if (!is_array($MESS))
561 {
562 $MESS = [];
563 }
564 else
565 {
566 foreach (array_keys($MESS) as $index)
567 {
568 if ($MESS[$index] === '')
569 {
570 unset($MESS[$index]);
571 }
572 }
573 unset($index);
574 }
575 }
576
577 if ($mergeMode)
578 {
579 $MESS = array_merge($MESS, $fileMessages);
580 }
581 else
582 {
583 $MESS = array_merge($fileMessages, $MESS);
584 }
585
586 if (!empty($MESS))
587 {
588 saveTranslationFile($file, $MESS, $errors);
589 }
590 }
591 }
592
593 return empty($errors);
594}
595
596
607function GetTLangFiles($path, $IS_LANG_DIR = false)
608{
610
611 if (is_dir(Translate\IO\Path::tidy($_SERVER["DOCUMENT_ROOT"]."/".$path."/")))
612 {
613 if ($IS_LANG_DIR)
614 {
615 if (is_array($arTLangs))
616 {
617 foreach ($arTLangs as $lng)
618 {
620 $path_l = mb_strlen($path);
621
624 foreach($arFiles as $arr)
625 {
626 if($arr["IS_DIR"]=="N" && (strncmp($arr["PATH"], $path, $path_l) == 0))
627 {
628 $arDirFiles[] = $arr["PATH"];
629 }
630 }
631 }
632 }
633 }
634 else
635 {
636 if (is_array($arLangDirFiles))
637 {
638 $path_l = mb_strlen($path);
639
640 foreach ($arLangDirFiles as $arr)
641 {
642 if($arr["IS_DIR"]=="N" && (strncmp($arr["PATH"], $path, $path_l) == 0))
643 {
644 $arDirFiles[] = $arr["PATH"];
645 }
646 }
647 }
648 }
649 }
650 else
651 {
652 foreach ($arTLangs as $lng)
653 {
655 }
656 }
657}
658
667function TSEARCH($arFile, &$count)
668{
669 global $arSearchParam;
670
671 if (isset($arFile['LANG']))
672 {
673 $langId = $arFile['LANG'];
674 }
675 else
676 {
677 $langId = Translate\IO\Path::extractLangId($arFile['PATH']);
678 }
679
680 $sourceEncoding = Main\Localization\Translation::getSourceEncoding($langId);
682
683 $MESS = [];
684 include $arFile['FULL_PATH'];
685
686
687 if (empty($MESS))
688 {
689 return false;
690 }
691
692 $_phrase = $phrase = $arSearchParam['search'];
693 if (!$arSearchParam['bCaseSens'])
694 {
695 $_phrase = mb_strtolower($arSearchParam['search']);
696 }
697 $I_PCRE_MODIFIER = $arSearchParam['bCaseSens'] ? '' : 'i';
698
699 $_bMessage = true;
700 $_bMnemonic = false;
701 $_arSearchData = array();
702 if ($arSearchParam['bSearchMessage'] && $arSearchParam['bSearchMnemonic'])
703 {
704 $_bMessage = true;
705 $_bMnemonic = true;
706 }
707 elseif ($arSearchParam['bSearchMnemonic'])
708 {
709 $_bMnemonic = true;
710 }
711
712 $_bResult = false;
713 $count = 0;
714 foreach ($MESS as $_sMn => $_sMe)
715 {
716 if ($targetEncoding != '' && $sourceEncoding != $targetEncoding)
717 {
718 $errorMessage = '';
719 $_sMe = Encoding::convertEncoding($_sMe, $sourceEncoding, $targetEncoding, $errorMessage);
720 }
721
722 $__sMe = $_sMe;
723 $__sMn = $_sMn;
724 if (!$arSearchParam['bCaseSens'])
725 {
726 $__sMe = mb_strtolower($_sMe);
727 $__sMn = mb_strtolower($_sMn);
728 }
729
730 $_bSearch = false;
731
732 if ($_bMessage)
733 {
734 if (mb_strpos($__sMe, $_phrase) !== false)
735 $_bSearch = true;
736 }
737 if ($_bMnemonic)
738 {
739 if (mb_strpos($__sMn, $_phrase) !== false)
740 $_bSearch = true;
741 }
742
743 if ($_bSearch)
744 {
745 $_bResult = true;
746 $res = array();
747 //Replace
748 if ($arSearchParam['is_replace'])
749 {
750 $pattern = '/'.preg_quote($phrase, '/').'/Su'.$I_PCRE_MODIFIER;
751
752 TR_BACKUP($arFile['PATH']);
753 if ($_bMessage)
754 {
755 preg_match_all($pattern, $_sMe, $res);
756 $count += count($res[0]);
757 $_sMe = preg_replace($pattern, $arSearchParam['replace'], $_sMe);
758 }
759 if ($_bMnemonic)
760 {
761 preg_match_all($pattern, $_sMn, $res);
762 $count += count($res[0]);
763 $_sMn = preg_replace($pattern, $arSearchParam['replace'], $_sMn);
764 }
765 }
766 else
767 {
768 $pattern = '/'.preg_quote($phrase, '/').'/u'.$I_PCRE_MODIFIER;
769 if ($_bMessage)
770 {
771 preg_match_all($pattern, $_sMe, $res);
772 $count += count($res[0]);
773 }
774 if ($_bMnemonic)
775 {
776 preg_match_all($pattern, $_sMn, $res);
777 $count += count($res[0]);
778 }
779 }
780 }
781
782 if ($arSearchParam['is_replace'])
783 {
784 $_arSearchData[$_sMn] = $_sMe;
785 }
786 }
787
788 if ($arSearchParam['is_replace'] && $_bResult)
789 {
790 $errorCollection = [];
791 saveTranslationFile($arFile['PATH'], $_arSearchData, $errorCollection);
792 $_bResult = empty($errorCollection);
793 }
794
795 return $_bResult;
796}
797
805{
806 if (Main\Config\Option::get('translate', 'BACKUP_FILES', 'N') !== 'Y')
807 {
808 return true;
809 }
810
812
813 $fullPath = Translate\IO\Path::tidy(Main\Application::getDocumentRoot(). $langFile);
814
816 {
817 if (in_array($langId, Translate\Config::getTranslationRepositoryLanguages()))
818 {
819 $fullPath = Main\Localization\Translation::convertLangPath($fullPath, $langId);
820 }
821 else
822 {
823 $fullPath = realpath($fullPath);
824 }
825 }
826 else
827 {
828 $fullPath = realpath($fullPath);
829 }
830
831 $fullPath = Translate\IO\Path::tidy($fullPath);
832 if (!file_exists($fullPath))
833 {
834 return true;
835 }
836
837 $endpointBackupFolder = Translate\Config::getBackupFolder(). '/'. dirname($langFile). '/';
838 Translate\IO\Path::checkCreatePath($endpointBackupFolder);
839 if (!file_exists($endpointBackupFolder) || !is_dir($endpointBackupFolder))
840 {
841 return false;
842 }
843
844 $sourceFilename = basename($langFile);
845 $prefix = date('YmdHi');
846 $endpointBackupFilename = $prefix. '_'. $sourceFilename;
847 if (file_exists($endpointBackupFolder. $endpointBackupFilename))
848 {
849 $i = 1;
850 while (file_exists($endpointBackupFolder. '/'. $endpointBackupFilename))
851 {
852 $i ++;
853 $endpointBackupFilename = $prefix. '_'. $i. '_'. $sourceFilename;
854 }
855 }
856
857 $isSuccessfull = (bool) @copy($fullPath, $endpointBackupFolder. '/'. $endpointBackupFilename);
858 @chmod($endpointBackupFolder. '/'. $endpointBackupFilename, BX_FILE_PERMISSIONS);
859
860 return $isSuccessfull;
861}
862
863
868{
873 {
874 \UnRegisterModuleDependences('main', 'OnPanelCreate', 'translate', 'CTranslateEventHandlers', 'TranslatOnPanelCreate');
875 \RegisterModuleDependences('main', 'OnPanelCreate', 'translate', '\\Bitrix\\Translate\\Ui\\Panel', 'onPanelCreate');
876
878 }
879}
880
881
885class CTranslateUtils
886{
887 public const LANGUAGES_DEFAULT = 0;
888 public const LANGUAGES_EXIST = 1;
889 public const LANGUAGES_ACTIVE = 2;
890 public const LANGUAGES_CUSTOM = 3;
891
892 protected static array $languageList = [
893 'ru',
894 'en',
895 'de',
896 ];
897
898 public static function setLanguageList(int $languages = self::LANGUAGES_DEFAULT, $customList = [])
899 {
900 if ($languages == self::LANGUAGES_ACTIVE || $languages == self::LANGUAGES_EXIST)
901 {
902 self::$languageList = [];
903 if ($languages === self::LANGUAGES_ACTIVE)
904 {
905 $languageIterator = LanguageTable::getList([
906 'select' => [
907 'ID',
908 ],
909 'filter' => [
910 '=ACTIVE' => 'Y',
911 ],
912 ]);
913 }
914 else
915 {
916 $languageIterator = LanguageTable::getList([
917 'select' => [
918 'ID',
919 ],
920 ]);
921 }
922 while ($lang = $languageIterator->fetch())
923 {
924 self::$languageList[] = $lang['ID'];
925 }
926 unset($lang, $languageIterator);
927 }
928 elseif ($languages === self::LANGUAGES_CUSTOM)
929 {
930 if (!is_array($customList))
931 {
932 $customList = [$customList];
933 }
934 self::$languageList = $customList;
935 }
936 else
937 {
938 self::$languageList = [
939 'ru',
940 'en',
941 'de',
942 ];
943 }
944
945 }
946
947 public static function CopyMessage($code, $fileFrom, $fileTo, $newCode = '')
948 {
949 $newCode = (string)$newCode;
950 if ($newCode === '')
951 $newCode = $code;
952 $langDir = $fileName = "";
953 $filePath = $fileFrom;
954 while(($slashPos = mb_strrpos($filePath, "/")) !== false)
955 {
956 $filePath = mb_substr($filePath, 0, $slashPos);
957 if(is_dir($filePath."/lang"))
958 {
959 $langDir = $filePath."/lang";
960 $fileName = mb_substr($fileFrom, $slashPos);
961 break;
962 }
963 }
964 if($langDir <> '')
965 {
966 $langDirTo = $fileNameTo = "";
967 $filePath = $fileTo;
968 while(($slashPos = mb_strrpos($filePath, "/")) !== false)
969 {
970 $filePath = mb_substr($filePath, 0, $slashPos);
971 if(is_dir($filePath."/lang"))
972 {
973 $langDirTo = $filePath."/lang";
974 $fileNameTo = mb_substr($fileTo, $slashPos);
975 break;
976 }
977 }
978
979 if($langDirTo <> '')
980 {
981 $langs = self::$languageList;
982 foreach($langs as $lang)
983 {
984 $MESS = array();
985 if (file_exists($langDir."/".$lang.$fileName))
986 {
987 include($langDir."/".$lang.$fileName);
988 if(isset($MESS[$code]))
989 {
991 $MESS = array();
992 if (file_exists($langDirTo."/".$lang.$fileNameTo))
993 {
994 include($langDirTo."/".$lang.$fileNameTo);
995 }
996 else
997 {
998 @mkdir(dirname($langDirTo."/".$lang.$fileNameTo), 0777, true);
999 }
1000 $MESS[$newCode] = $message;
1001 $s = "<?php\n";
1002 foreach($MESS as $c => $m)
1003 {
1004 $s .= "\$MESS['".EscapePHPString($c)."'] = \"".EscapePHPString($m)."\";\n";
1005 }
1006 file_put_contents($langDirTo."/".$lang.$fileNameTo, $s);
1007 }
1008 }
1009 }
1010 }
1011 }
1012 }
1013
1014 public static function FindAndCopy($sourceDir, $lang, $pattern, $destinationFile)
1015 {
1016 $insideLangDir = (mb_strpos($sourceDir."/", "/lang/".$lang."/") !== false);
1017
1018 foreach(scandir($sourceDir) as $file)
1019 {
1020 if($file == "." || $file == "..")
1021 {
1022 continue;
1023 }
1024
1025 if($file == ".description.php" || $file == ".parameters.php")
1026 {
1027 continue;
1028 }
1029
1030 if($sourceDir."/".$file == $destinationFile)
1031 {
1032 continue;
1033 }
1034
1035 if(is_dir($sourceDir."/".$file))
1036 {
1037 self::FindAndCopy($sourceDir."/".$file, $lang, $pattern, $destinationFile);
1038 }
1039 elseif($insideLangDir)
1040 {
1041 $MESS = array();
1042 include($sourceDir."/".$file);
1043
1044 $copyMess = array();
1045 foreach($MESS as $code => $val)
1046 {
1047 if(preg_match($pattern, $val))
1048 {
1049 $copyMess[$code] = $val;
1050 }
1051 }
1052
1053 if(!empty($copyMess))
1054 {
1055 foreach(self::$languageList as $destLang)
1056 {
1057 if($destLang <> $lang)
1058 {
1059 $MESS = array();
1060 $sourceFile = str_replace("/lang/".$lang."/", "/lang/".$destLang."/", $sourceDir."/".$file);
1061 if(file_exists($sourceFile))
1062 {
1063 include($sourceFile);
1064 }
1065
1066 $destMess = array();
1067 foreach($MESS as $code => $val)
1068 {
1069 if(isset($copyMess[$code]))
1070 {
1071 $destMess[$code] = $val;
1072 }
1073 }
1074 $destFile = str_replace("/lang/".$lang."/", "/lang/".$destLang."/", $destinationFile);
1075 }
1076 else
1077 {
1078 $destMess = $copyMess;
1079 $destFile = $destinationFile;
1080 }
1081
1082 $MESS = array();
1083 if(file_exists($destFile))
1084 {
1085 include($destFile);
1086 }
1087 else
1088 {
1089 @mkdir(dirname($destFile), 0777, true);
1090 }
1091
1092 foreach($destMess as $code => $val)
1093 {
1094 if(isset($MESS[$code]) && $MESS[$code] <> $val)
1095 {
1096 echo $sourceDir."/".$file.": ".$code." already exists in the destination file.\n";
1097 }
1098 else
1099 {
1100 $MESS[$code] = $val;
1101 }
1102 }
1103
1104 $s = "<?php\n";
1105 foreach($MESS as $c => $m)
1106 {
1107 $s .= "\$MESS['".EscapePHPString($c)."'] = \"".EscapePHPString($m)."\";\n";
1108 }
1109 file_put_contents($destFile, $s);
1110 }
1111 }
1112 }
1113 }
1114 }
1115}
1116
1117
1130function GetPhraseCounters($arCommon, $entry, $enabledLanguages)
1131{
1132 global $arCommonCounter, $Counter;
1133 $Counter++;
1134
1135 $path = $entry["PATH"];
1136 $key = Translate\IO\Path::removeLangId($path, $enabledLanguages);
1137
1138
1139 $arDirFiles = array();
1140
1141 // is directory
1142 //if (is_dir(Translate\IO\Path::tidy($_SERVER["DOCUMENT_ROOT"]."/".$path."/")))
1143 if ($entry['IS_DIR'] === 'Y')
1144 {
1145 if (\Bitrix\Translate\IO\Path::isLangDir($path))
1146 {
1147 // files array for directory language
1148 foreach ($enabledLanguages as $lng)
1149 {
1151 $pathLength = mb_strlen($path);
1152
1153 foreach($arCommon as $arr)
1154 {
1155 if($arr['IS_DIR'] == 'N' && (strncmp($arr['PATH'], $path, $pathLength) == 0))
1156 {
1157 $arDirFiles[$arr['PATH']] = $arr['FULL_PATH'];
1158 }
1159 }
1160 }
1161 }
1162 else
1163 {
1164 if (is_array($arCommon))
1165 {
1166 $pathLength = mb_strlen($path);
1167 // array files for directory
1168 foreach ($arCommon as $arr)
1169 {
1170 if($arr['IS_DIR']=='N' && (strncmp($arr['PATH'], $path, $pathLength) == 0))
1171 {
1172 $arDirFiles[$arr['PATH']] = $arr["FULL_PATH"];
1173 }
1174 }
1175 }
1176 }
1177 }
1178 else
1179 {
1180 foreach ($enabledLanguages as $lng)
1181 {
1182 //$arDirFiles[] = \Bitrix\Translate\IO\Path::replaceLangId($path, $lng);
1184 $pathLength = mb_strlen($path);
1185
1186 foreach($arCommon as $arr)
1187 {
1188 if($arr['IS_DIR'] == 'N' && (strncmp($arr['PATH'], $path, $pathLength) == 0))
1189 {
1190 $arDirFiles[$arr['PATH']] = $arr['FULL_PATH'];
1191 }
1192 }
1193 }
1194 }
1195
1196 $arFilesLng = array();
1197 // array for every files
1198 foreach ($arDirFiles as $fpath => $file)
1199 {
1200 //if(file_exists($_SERVER["DOCUMENT_ROOT"].$file) && preg_match("#/lang/([^/]*?)/#", $file, $arMatch))
1201 if(file_exists($file) && preg_match("#/lang/([^/]*?)/#", $file, $arMatch))
1202 {
1203 $file_lang = $arMatch[1];
1204 if(in_array($file_lang, $enabledLanguages))
1205 {
1206 if(mb_substr($file, -4) != '.php')
1207 {
1208 continue;
1209 }
1210 $MESS = array();
1211 include $file;
1212 $fileName = \Bitrix\Translate\IO\Path::removeLangId($fpath, $enabledLanguages);
1213 $arFilesLng[$fileName][$file_lang] = array_keys($MESS);
1214 }
1215 }
1216 }
1217
1218 $arFilesLngCounter = array();
1219 // rashogdenia for files
1220 foreach($arFilesLng as $fileName => $arLns)
1221 {
1222 $total_arr = array();
1223
1224 // summarize
1225 foreach($arLns as $ln => $arLn)
1226 {
1227 $total_arr = array_merge($total_arr, $arLn);
1228 }
1229 $total_arr = array_unique($total_arr);
1230 $total = count($total_arr);
1231
1232 foreach($enabledLanguages as $lang)
1233 {
1234 $arr = array();
1235 $arLn = is_array($arLns[$lang]) ? $arLns[$lang] : array();
1236 $diff = array_diff($total_arr, $arLn);
1237 $arr["TOTAL"] = $total;
1238 $arr["DIFF"] = count($diff);
1239 $arFilesLngCounter[$fileName][$lang] = $arr;
1240 }
1241 }
1242
1243 foreach($arFilesLngCounter as $fileName => $arCount)
1244 {
1245 foreach($arCount as $ln => $arLn)
1246 {
1247 $file_path = str_replace("/lang/", "/lang/".$ln."/", $fileName);
1248 $arCommonCounter[$key][$ln][$file_path]["TOTAL"] += $arLn["TOTAL"];
1249 $arCommonCounter[$key][$ln][$file_path]["DIFF"] += $arLn["DIFF"];
1250 }
1251 }
1252}
1253
1262function removePhrasesByMasterFile($masterLanguage, $listIds, &$errorCollection)
1263{
1265 global $arFiles;
1266
1267 if (empty($arFiles))
1268 {
1269 return false;
1270 }
1271
1272 $currentFileList = [];
1273 $currentFileListAbs = [];
1274 $masterFileList = [];
1275 foreach ($arFiles as $row)
1276 {
1277 if (!$row['IS_LANG'])
1278 {
1279 continue;
1280 }
1281 $file = $row['FILE'];
1282 if (!isset($currentFileList[$file]))
1283 {
1284 $currentFileList[$file] = [];
1285 $currentFileListAbs[$file] = [];
1286 }
1287 $currentFileList[$file][$row['LANG']] = $row['PATH'];
1288 $currentFileListAbs[$file][$row['LANG']] = $row['FULL_PATH'];
1289 if ($row['LANG'] == $masterLanguage)
1290 {
1291 $masterFileList[$file] = true;
1292 }
1293 }
1294 unset($file, $row);
1295
1296 if (empty($masterFileList))
1297 {
1298 return false;
1299 }
1300
1301 foreach ($listIds as $file)
1302 {
1303 $masterFileIsFounded = false;
1304 $masterMask = [];
1305 if (isset($masterFileList[$file]))
1306 {
1307 $MESS = [];
1308 if (file_exists($currentFileListAbs[$file][$masterLanguage]))
1309 {
1310 $masterFileIsFounded = true;
1312 include($currentFileListAbs[$file][$masterLanguage]);
1313 }
1314 if (!empty($MESS))
1315 {
1316 $masterMask = array_fill_keys(array_keys($MESS), true);
1317 }
1318 }
1319 if (!$masterFileIsFounded || empty($masterMask))
1320 {
1321 continue;
1322 }
1323
1324 $newList = [];
1325 $newListAbs = [];
1326 foreach ($currentFileList[$file] as $phraseLanguage => $phrasePath)
1327 {
1328 if ($phraseLanguage == $masterLanguage)
1329 {
1330 continue;
1331 }
1332
1333 $MESS = [];
1334 $phrasePathAbs = $currentFileListAbs[$file][$phraseLanguage];
1335 if (file_exists($phrasePathAbs))
1336 {
1338 include($phrasePathAbs);
1339 }
1340 if (!empty($MESS))
1341 {
1342 $MESS = array_intersect_key($MESS, $masterMask);
1343 }
1344
1345 $newList[$phrasePath] = $MESS;
1346 $newListAbs[$phrasePath] = $phrasePathAbs;
1347 }
1348 unset($phrasePath, $phrasePathAbs);
1349
1350 if (empty($newList))
1351 {
1352 continue;
1353 }
1354
1355 foreach ($newList as $langFileName => $phrases)
1356 {
1357 saveTranslationFile($langFileName, $phrases, $errorCollection);
1358 }
1359 unset($langFileName, $phrases, $newList);
1360 }
1361
1362 return true;
1363}
1364
1365
1375function saveTranslationFile($langFileName, $phrases, &$errorCollection)
1376{
1377 $langId = Translate\IO\Path::extractLangId($langFileName);
1378
1379 // sort phrases by key, except russian
1380 if ($langId != 'ru')
1381 {
1382 ksort($phrases, SORT_STRING);
1383 }
1384
1385 $content = '';
1386 foreach ($phrases as $phraseId => $phrase)
1387 {
1388 $phrase = str_replace(["\r\n", "\r"], ["\n", ''], $phrase);
1389 $row = "\$MESS[\"". EscapePHPString($phraseId). "\"] = \"". EscapePHPString($phrase). "\"";
1390 $content .= "\n". $row. ';';
1391 }
1392 unset($phraseId, $phrase, $row);
1393
1394 if (!TR_BACKUP($langFileName))
1395 {
1396 $errorCollection[] = Loc::getMessage('TR_CREATE_BACKUP_ERROR', array('%FILE%' => $langFileName));
1397 }
1398 else
1399 {
1400 $fullPath = Translate\IO\Path::tidy(Main\Application::getDocumentRoot(). $langFileName);
1402 {
1403 if (in_array($langId, Translate\Config::getTranslationRepositoryLanguages()))
1404 {
1405 $fullPath = Main\Localization\Translation::convertLangPath($fullPath, $langId);
1406 }
1407 }
1408
1409 $checkFullPath = realpath($fullPath);
1410 //if ($checkFullPath === false)
1411
1412
1413 $file = new Translate\IO\File(Translate\IO\Path::tidy($fullPath));
1414
1415 if ($content <> '')
1416 {
1417 if ($file->putContents('<?'. $content. "\n?". '>') === false)
1418 {
1419 $errorCollection[] = Loc::getMessage('TR_TOOLS_ERROR_WRITE_FILE', array('%FILE%' => $langFileName));
1420 }
1421 }
1422 else
1423 {
1424 if ($file->isExists())
1425 {
1426 $file->markWritable();
1427 $file->delete();
1428 }
1429 }
1430 }
1431
1432 return true;
1433}
$path
Определения access_edit.php:21
$count
Определения admin_tab.php:4
static getDocumentRoot()
Определения application.php:736
static getSourceEncoding($lang)
Определения translation.php:59
static useTranslationRepository()
Определения translation.php:173
static getCurrentEncoding()
Определения translation.php:104
static convertLangPath($langFile, $language)
Определения translation.php:267
static detectUtf8($string, $replaceHex=true)
Определения encoding.php:154
static getCultureEncoding(string $languageId)
Определения config.php:162
static getEnabledLanguages()
Определения config.php:211
static getBackupFolder()
Определения config.php:411
static isUtfMode()
Определения config.php:77
static replaceLangId(string $path, string $langId)
Определения path.php:98
static tidy(string $path)
Определения path.php:16
static isLangDir(string $path, bool $additionalCheck=false)
Определения path.php:45
static extractLangId(string $path)
Определения path.php:78
static checkCreatePath(string $path)
Определения path.php:180
static removeLangId(string $path, ?array $langs=null)
Определения path.php:114
static onPanelCreate()
Определения panel.php:18
TranslatOnPanelCreate()
Определения translate_tools.php:872
$content
Определения commerceml.php:144
$langFile
Определения .description.php:2
$arr
Определения file_new.php:624
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$handle
Определения include.php:55
$errors
Определения iblock_catalog_edit.php:74
while($arParentIBlockProperty=$dbParentIBlockProperty->Fetch()) $errorMessage
global $MESS
Определения bill.php:2
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
if(!defined('SITE_ID')) $lang
Определения include.php:91
EscapePHPString($str, $encloser='"')
Определения tools.php:4917
RegisterModuleDependences($FROM_MODULE_ID, $MESSAGE_ID, $TO_MODULE_ID, $TO_CLASS="", $TO_METHOD="", $SORT=100, $TO_PATH="", $TO_METHOD_ARG=[])
Определения tools.php:5295
UnRegisterModuleDependences($FROM_MODULE_ID, $MESSAGE_ID, $TO_MODULE_ID, $TO_CLASS="", $TO_METHOD="", $TO_PATH="", $TO_METHOD_ARG=[])
Определения tools.php:5289
Rel2Abs($curdir, $relpath)
Определения tools.php:3297
Определения directory.php:3
Определения autoload.php:3
const IGNORE_BX_NAMES
Определения autoload.php:56
const IGNORE_FS_NAMES
Определения autoload.php:41
$message
Определения payment.php:8
$arFiles
Определения options.php:60
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$fileName
Определения quickway.php:305
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$columnList
Определения template.php:276
$val
Определения options.php:1793
if(!Loader::includeModule('sale')) $pattern
Определения index.php:20
$langs
Определения options.php:141
$arDirFiles
Определения translate_tools.php:13
SaveTCSVFile($filePath, $encodingIn, $rewriteMode, $mergeMode, &$errors)
Определения translate_tools.php:295
GetTDirList($path, $subDirs=false, $restructLanguageList=array())
Определения translate_tools.php:63
GetLangDirs($arDirs, $showTranslationDifferences=false)
Определения translate_tools.php:26
$arLangDirs
Определения translate_tools.php:9
$arDirs
Определения translate_tools.php:10
$arLangDirFiles
Определения translate_tools.php:14
TSEARCH($arFile, &$count)
Определения translate_tools.php:667
TR_BACKUP($langFile)
Определения translate_tools.php:804
$arTLangs
Определения translate_tools.php:12
$arSearchParam
Определения translate_tools.php:15