weekly release 4.0dev
[moodle.git] / filter / multilang / filter.php
CommitLineData
4317f92f 1<?php
71c235bc 2
35716b86
PS
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
173377e5 19 * @package filter_multilang
35716b86
PS
20 * @copyright Gaetan Frenoy <gaetan@frenoy.net>
21 * @copyright 2004 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
71c235bc 26
27// Given XML multilinguage text, return relevant text according to
f16242ce 28// current language:
29// - look for multilang blocks in the text.
71c235bc 30// - if there exists texts in the currently active language, print them.
31// - else, if there exists texts in the current parent language, print them.
71c235bc 32// - else, print the first language in the text.
9fecfdfb 33// Please note that English texts are not used as default anymore!
71c235bc 34//
f16242ce 35// This version is based on original multilang filter by Gaetan Frenoy,
36// rewritten by Eloy and skodak.
37//
38// Following new syntax is not compatible with old one:
39// <span lang="XX" class="multilang">one lang</span><span lang="YY" class="multilang">another language</span>
71c235bc 40
587c0772
TH
41
42/**
41bf80a6
TH
43 * Implementation of the Moodle filter API for the Multi-lang filter.
44 *
587c0772
TH
45 * @copyright Gaetan Frenoy <gaetan@frenoy.net>
46 * @copyright 2004 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
47 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
48 */
35716b86 49class filter_multilang extends moodle_text_filter {
dcfffe30 50 function filter($text, array $options = array()) {
9e3f34d1 51 global $CFG;
f16242ce 52
9e3f34d1 53 // [pj] I don't know about you but I find this new implementation funny :P
54 // [skodak] I was laughing while rewriting it ;-)
55 // [nicolasconnault] Should support inverted attributes: <span class="multilang" lang="en"> (Doesn't work curently)
4317f92f 56 // [skodak] it supports it now, though it is slower - any better idea?
af2fc69d 57
9e3f34d1 58 if (empty($text) or is_numeric($text)) {
59 return $text;
60 }
61
62 if (empty($CFG->filter_multilang_force_old) and !empty($CFG->filter_multilang_converted)) {
63 // new syntax
64 $search = '/(<span(\s+lang="[a-zA-Z0-9_-]+"|\s+class="multilang"){2}\s*>.*?<\/span>)(\s*<span(\s+lang="[a-zA-Z0-9_-]+"|\s+class="multilang"){2}\s*>.*?<\/span>)+/is';
65 } else {
66 // old syntax
67 $search = '/(<(?:lang|span) lang="[a-zA-Z0-9_-]*".*?>.*?<\/(?:lang|span)>)(\s*<(?:lang|span) lang="[a-zA-Z0-9_-]*".*?>.*?<\/(?:lang|span)>)+/is';
68 }
af2fc69d 69
587c0772 70 $result = preg_replace_callback($search, [$this, 'process_match'], $text);
af2fc69d 71
9e3f34d1 72 if (is_null($result)) {
73 return $text; //error during regex processing (too many nested spans?)
74 } else {
75 return $result;
76 }
af2fc69d 77 }
f16242ce 78
587c0772
TH
79 /**
80 * This is the callback used by the preg_replace_callback call above.
81 *
82 * @param array $langblock one of the matches from the regex match.
83 * @return string the replacement string (one of the possible translations).
84 */
85 protected function process_match(array $langblock): string {
587c0772 86 $searchtosplit = '/<(?:lang|span)[^>]+lang="([a-zA-Z0-9_-]+)"[^>]*>(.*?)<\/(?:lang|span)>/is';
f16242ce 87
587c0772 88 if (!preg_match_all($searchtosplit, $langblock[0], $rawlanglist)) {
41bf80a6 89 // Skip malformed blocks.
587c0772
TH
90 return $langblock[0];
91 }
9fecfdfb 92
587c0772 93 $langlist = array();
41bf80a6
TH
94 foreach ($rawlanglist[1] as $index => $lang) {
95 $lang = str_replace('-', '_', strtolower($lang)); // Normalize languages.
587c0772
TH
96 $langlist[$lang] = $rawlanglist[2][$index];
97 }
71c235bc 98
41bf80a6
TH
99 // Follow the stream of parent languages.
100 $lang = current_language();
101 do {
102 if (isset($langlist[$lang])) {
103 return $langlist[$lang];
104 }
105 } while ($lang = $this->get_parent_lang($lang));
106
107 // If we don't find a match, default to the first provided translation.
108 return array_shift($langlist);
109 }
110
111 /**
112 * Puts some caching around get_parent_language().
113 *
114 * Also handle parent == 'en' in a way that works better for us.
115 *
116 * @param string $lang a Moodle language code, e.g. 'fr'.
117 * @return string the parent language.
118 */
119 protected function get_parent_lang(string $lang): string {
120 static $parentcache;
121 if (!isset($parentcache)) {
122 $parentcache = ['en' => ''];
123 }
124 if (!isset($parentcache[$lang])) {
125 $parentcache[$lang] = get_parent_language($lang);
126 // The standard get_parent_language method returns '' for parent == 'en'.
127 // That is less helpful for us, so change it back.
128 if ($parentcache[$lang] === '') {
129 $parentcache[$lang] = 'en';
130 }
587c0772 131 }
41bf80a6 132 return $parentcache[$lang];
9fecfdfb 133 }
71c235bc 134}