| [ Index ] |
PHP Cross Reference of Moodle 310 |
[Summary view] [Print] [Text view]
1 // This file is part of Moodle - http://moodle.org/ 2 // 3 // Moodle is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // Moodle is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 15 16 /** 17 * Fetch and return language strings. 18 * 19 * @module core/str 20 * @copyright 2015 Damyon Wiese <damyon@moodle.com> 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 * @since 2.9 23 * 24 */ 25 import $ from 'jquery'; 26 import Ajax from 'core/ajax'; 27 import LocalStorage from 'core/localstorage'; 28 29 // Module cache for the promises so that we don't make multiple 30 // unnecessary requests. 31 let promiseCache = []; 32 33 /* eslint-disable no-restricted-properties */ 34 35 /** 36 * Return a Promise that resolves to a string. 37 * 38 * If the string has previously been cached, then the Promise will be resolved immediately, otherwise it will be fetched 39 * from the server and resolved when available. 40 * 41 * @method get_string 42 * @param {string} key The language string key 43 * @param {string} component The language string component 44 * @param {string} param The param for variable expansion in the string. 45 * @param {string} lang The users language - if not passed it is deduced. 46 * @return {Promise} 47 * 48 * @example <caption>Fetching a string</caption> 49 * 50 * import {get_string as getString} from 'core/str'; 51 * get_string('cannotfindteacher', 'error') 52 * .then(str => { 53 * window.console.log(str); // Cannot find teacher 54 * }) 55 * .catch(); 56 */ 57 // eslint-disable-next-line camelcase 58 export const get_string = (key, component, param, lang) => { 59 return get_strings([{key, component, param, lang}]) 60 .then(results => results[0]); 61 }; 62 63 /** 64 * Make a batch request to load a set of strings. 65 * 66 * Any missing string will be fetched from the server. 67 * The Promise will only be resolved once all strings are available, or an attempt has been made to fetch them. 68 * 69 * @method get_strings 70 * @param {Object[]} requests List of strings to fetch 71 * @param {string} requests.key The string identifer to fetch 72 * @param {string} [requests.component='core'] The componet to fetch from 73 * @param {string} [requests.lang] The language to fetch a string for. Defaults to current page language. 74 * @param {object|string} [requests.param] The param for variable expansion in the string. 75 * @return {Promise[]} 76 * 77 * @example <caption>Fetching a set of strings</caption> 78 * 79 * import {get_strings as getStrings} from 'core/str'; 80 * get_strings([ 81 * { 82 * key: 'cannotfindteacher', 83 * component: 'error', 84 * }, 85 * { 86 * key: 'yes', 87 * component: 'core', 88 * }, 89 * { 90 * key: 'no', 91 * component: 'core', 92 * }, 93 * ]) 94 * .then((cannotFindTeacher, yes, no) => { 95 * window.console.log(cannotFindTeacher); // Cannot find teacher 96 * window.console.log(yes); // Yes 97 * window.console.log(no); // No 98 * }) 99 * .catch(); 100 */ 101 // eslint-disable-next-line camelcase 102 export const get_strings = (requests) => { 103 let requestData = []; 104 const pageLang = $('html').attr('lang').replace(/-/g, '_'); 105 // Helper function to construct the cache key. 106 const getCacheKey = ({key, component, lang = pageLang}) => { 107 if (!component) { 108 component = 'core'; 109 } 110 return `core_str/$key}/$component}/$lang}`; 111 }; 112 113 const stringPromises = requests.map((request) => { 114 const cacheKey = getCacheKey(request); 115 const {component, key, param, lang = pageLang} = request; 116 // Helper function to add the promise to cache. 117 const buildReturn = (promise) => { 118 // Make sure the promise cache contains our promise. 119 promiseCache[cacheKey] = promise; 120 return promise; 121 }; 122 123 // Check if we can serve the string straight from M.str. 124 if (component in M.str && key in M.str[component]) { 125 return buildReturn(new Promise((resolve) => { 126 resolve(M.util.get_string(key, component, param, lang)); 127 })); 128 } 129 130 // Check if the string is in the browser's local storage. 131 const cached = LocalStorage.get(cacheKey); 132 if (cached) { 133 M.str[component] = {...M.str[component], [key]: cached}; 134 return buildReturn(new Promise((resolve) => { 135 resolve(M.util.get_string(key, component, param, lang)); 136 })); 137 } 138 139 // Check if we've already loaded this string from the server. 140 if (cacheKey in promiseCache) { 141 return buildReturn(promiseCache[cacheKey]).then(() => { 142 return M.util.get_string(key, component, param, lang); 143 }); 144 } else { 145 // We're going to have to ask the server for the string so 146 // add this string to the list of requests to be sent. 147 return buildReturn(new Promise((resolve, reject) => { 148 requestData.push({ 149 methodname: 'core_get_string', 150 args: { 151 stringid: key, 152 stringparams: [], 153 component, 154 lang, 155 }, 156 done: (str) => { 157 // When we get the response from the server 158 // we should update M.str and the browser's 159 // local storage before resolving this promise. 160 M.str[component] = {...M.str[component], [key]: str}; 161 LocalStorage.set(cacheKey, str); 162 resolve(M.util.get_string(key, component, param, lang)); 163 }, 164 fail: reject 165 }); 166 })); 167 } 168 }); 169 170 if (requestData.length) { 171 // If we need to load any strings from the server then send 172 // off the request. 173 Ajax.call(requestData, true, false, false, 0, M.cfg.langrev); 174 } 175 176 // We need to use jQuery here because some calling code uses the 177 // .done handler instead of the .then handler. 178 return $.when.apply($, stringPromises) 179 .then((...strings) => strings); 180 }; 181 182 /** 183 * Add a list of strings to the caches. 184 * 185 * This function should typically only be called from core APIs to pre-cache values. 186 * 187 * @method cache_strings 188 * @protected 189 * @param {Object[]} strings List of strings to fetch 190 * @param {string} strings.key The string identifer to fetch 191 * @param {string} strings.value The string value 192 * @param {string} [strings.component='core'] The componet to fetch from 193 * @param {string} [strings.lang] The language to fetch a string for. Defaults to current page language. 194 */ 195 // eslint-disable-next-line camelcase 196 export const cache_strings = (strings) => { 197 const defaultLang = $('html').attr('lang').replace(/-/g, '_'); 198 199 strings.forEach(({key, component, value, lang = defaultLang}) => { 200 const cacheKey = ['core_str', key, component, lang].join('/'); 201 202 // Check M.str caching. 203 if (!(component in M.str) || !(key in M.str[component])) { 204 if (!(component in M.str)) { 205 M.str[component] = {}; 206 } 207 208 M.str[component][key] = value; 209 } 210 211 // Check local storage. 212 if (!LocalStorage.get(cacheKey)) { 213 LocalStorage.set(cacheKey, value); 214 } 215 216 // Check the promises cache. 217 if (!(cacheKey in promiseCache)) { 218 promiseCache[cacheKey] = $.Deferred().resolve(value).promise(); 219 } 220 }); 221 }; 222 /* eslint-enable no-restricted-properties */
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 22 11:59:49 2025 | Cross-referenced by PHPXref 0.7.1 |