Wikimedia Forum/Archives/2008-11/GlobalContextVariables Extension
This page is kept for historical interest. Any policies mentioned may be obsolete. If you want to revive the topic, you can use the talk page or start a discussion on the community forum. |
Global Context Variables: Proposal and Discussions
Global Context Variables: Initial proposal
[edit]Initial proposals in French and English
|
---|
Global Context Variables: French original (don't modify)Please don't reply in the middle of this original text frame. You may insert your comments (in any language) or fix translation typos in the English section below. Je propose de poster une spécification d'extension pour MediaWiki de façon à supporter ces variables de contexte, et je vais l'écrire sur Méta. Comme je ne connais rien à la façon d'écrire une telle extension, même si j'ai lu un peu de code source PHP de certaines, j'attendrai que quelqu'un qui s'y connait mieux l'implémente. En revanche je voudrais documenter les exemples d'emploi et l'intérêt que cela aurait, notamment pour les Wiktionnaires qui gagneraient énormément à avoir ces variables de contexte. Par exemple on n'aurait plus à préciser partout un paramètre de langue dans les appels de modèle, si la valeur de ce paramètre pouvait être lue directement dans une variable de contexte (au lieu d'un paramètre explicite à passer chaque fois) dont la valeur a été positionnée par un moddèle comme {{=fr=}} (sur le Wiktionnaire français) qui définirait la variable de contexte suivante : {{#v:set:lang|fr}} utilisée ensuite avec {{#v:get:lang}} ou modifiée et utilisée sur place avec {{v:get:lang|fr}} Un raccourci possible, en supposant que l'action "get" soit celle par défaut : {{#v::lang}} pour lire et {{#v::lang|fr}} pour modifier et utiliser immédiatement. Toujours dans cette extension, que je nommerais GlobalContextVariables et utilisant la syntaxe générale {{#v:action:variable|paramètres optionnels}}, les variables pourraient être des listes ou tableaux indicés, et gérées chacune comme une pile (dont on n'utilise par défaut que la valeur au sommet, en position 0 du tableau indicé ou de la liste, et les actions push et pop seraient définies pour modifier ces variables en permettant de les faire se comporter comme des variables locales de contexte. Concernant les noms de variables, ils seraient restreint à des identifiants valides commençant par une lettre et faits de lettres ou chiffres, les autres caractères (notamment de ponctuation) restant réservés pour gérer des espaces de noms par exemple (on utiliserait le point "." ou ":" comme séparateur d'espace), ou pour lire des variables de contexte internes au reste de la MediaWiki si celui-ci définit des espaces de noms spéciaux pour ses propres extensions. En revanche il n'y aurait pas de limitation dans la valeur des variables (tout ce qu'on écrit en syntaxe wiki, y compris les appels de sous-modèles qui seraient évalués normalement, serait possible). Quel intérêt pour nous ?
En principe on commence par une spécification avant d'écrire le code. Elle doit être suffisamment générale pour être extensible, mais pas trop compliquée à utiliser pour les cas simples comme le notre. Qu'en pensez vous ? Il serait bon de discuter ensemble de ce qu'on veut en faire, et de ce que l'extension pour MediaWiki devrait gérer (en garder en tête le fait que des extensions sont possibles pour d'autres utilisations hors du Wiktionnaire, y compris sur Wikipédia, Commons, Wikispecies où je vois pleins de possibilités, ou des wikis hébergés hors de la Fondation Wikimedia. Je propose de poster cette discussion aussi sur Meta (si vous voulez vous pouvez y faire un tour et faire référence à ce message qui est une première ébauche de proposition d'extension. verdy_p 12 novembre 2008 à 18:26 (UTC)
Global Context Variables: English translationI propose to post a specification for a MediaWiki extension in order to support context variables, and I will write it on Meta. As I don't know much about the way to write such an extension, even if I have read some PHP code for some of these extensions, I will wait for someone better qualified to implement it. However, I'd like to document some exampels of use and the interest about what such extension would provide, notably for the Wiktionaries that would gain a lot if they could use those context variables. But the extension is not specifically tuned to focus Wiktionary. For example, we would no longer have to pass everywhere a language parameter when calling Wiktionary templates, if the value of this parameter could be read directly from a context variable (instead of an explicit parameter to pass each time) whose value would have been preset in a former call to another template like {{=fr=}} (on French Wiktionary) that would internally define the value of the following context variable: {{#v:set:lang|fr}}, then used with {{#v:get:lang}}, or (optionally) modified and reused directly in place with {{v:get:lang|fr}} A possible shortcut, supposing that the action "get" is the one used by default for this extension : {{#v::lang}} to read the context variable named "lang" and {{#v::lang|fr}} to modify and use immediately the value set in this variable. Still in this extension, that I would name GlobalContextVariables and using the general syntax {{#v:action:variable |
Global Context Variables: Analysis and Discussions
[edit]Analysis and Discussions
|
---|
Global Context Variables: The problem and why we need absolutely need this extension for large multilingual projects
Let's solve the problem cleanly for the immediate future : please offer support for context variables to our pages. The current situation is not maintainable for the long medium term, and it already affects (in short term) large mature multilingual projects like Wiktionary and Commons (and Meta itself for the multilingual MediaWiki documentation or support). verdy_p 20:15, 13 November 2008 (UTC) Global Context Variables: Preliminary analysis about complexity and cost on the serverYou will immediately see that, in terms of complexity and memory cost on the server, the cost is transfered from the size in meory of the template parameters, to the size of the values stored in the array of context variables. However, this is mitigated by the fact that the variables will store the result of the expression assigned to them, for cases where contect variables are needed: to store the result of complex expressions full of parameters that will finally not be used, and with the code of many #if and #switch case branches. The concept here is to have a simple value computed once, and then reused without having to worry about how they were computed or set (though subtemplates, or complex tests of default values, missing parameters, default values, and so on). Reusing an already assigned context variable named "x" is just {{#v::x}} instead of {{{x}}} or more complex expressions where there are tests to see if the parameter is defined, or to set its default value. This does not make the code much more complicate to read, but this extension avoids the complexity of the many embedded braces. It becomes possible to define the value to use for a variable by successive uses of {{#v:set:x}} instead of embedding them within complexly paired collections of {braces} (and no more need to count them, and much less confusion between the syntax of parameter expansion and template references (3 or 2 braces ?), because, in most cases, the "embedding style" can be avoided. verdy_p 21:38, 12 November 2008 (UTC) Global Context Variables: Monitoring and capping the memory size requirement on the serverIn terms of memory space complexity, this means that the parameter sizes (given to the ParserFunction evaluating this MediaWiki extension) will be shorter than with the existing template parameter calls (no more need to use separate internal subtemplates to "factorize" the common code) or existing uses with embedded #if, #expr, and #switch... What the server just need to monitor, is the total size of the values that are curerntly assigned in the current block of context variables, in addition to the separate total size of template parameters. I also think that the extension is quite simple to implement, and clear for users. It can also save a lot of new "magic" words, specific for some extensions (for example, localization templates). It would be interesting to test it on a Test wiki containing a partial copy of Wikipedia using complex templates (for example those computing date elements, and selecting subpages to render within an article, depending on some magic value or explicit parameter specific to the page using it. It has already been seen that the most complex templates are those using #expr, or performing many #switch, whose case branches need to be maintained separately, despite they need to reuse the same complex expression. verdy_p 21:38, 12 November 2008 (UTC) Global Context Variables: Much less complexity for authors of complex templatesMy proposal would simplify a lot those templates, and would reduce their total size a lot. In addition, it will be much more easier to edit them without so many errors as they exist today. Currently the horrors found in code are coming from the need to embed the #if's, and impossibility to reuse the values determined by those tests outside of the #if itself. This is really ugly, and this also results in a severe limitation for the expansion, if many embedded #if are then needed. Using context variables, you can just use successive #if's instead to compute the same value. And most of the reusable code is written only in one place: where the variable is first set, but is still modifiable later in another separate #if. This simplifies, each time, the code to write to handle the default values and specific cases or exceptions controled by other template parameters (no need to duplicate the existing code to specialize it). Just insert a code using a context variable to modify it in situ. verdy_p 21:38, 12 November 2008 (UTC) Global Context Variables: The data/view separation principle in actionFinally this also allows the separation between the code that prepares the data, and the code that renders it (this is a good principle, including for HTML, just like with the separation of page content, and style in CSS): this is the document/view separation principle. Prepare the data in context variables, then render the computed variables directly without complication. Clean and simple to understand. verdy_p 22:09, 12 November 2008 (UTC) Global Context Variables: Interest for the collaboration across wikisThis extension will also facilitate a lot the reuse of code fragments across templates, and easier adaptation of currently too complex templates that need to be imported and adapted on another project. The code being more "linear" (no many embedded braces), it is simpler to fix in one place for such adaptation. In other words, it will facilitate the collaboration across wikis, so that wikis with less experimented admins can more easily work on these templates when importing the useful (but complex) templates used on English Wikipedia or on Commons. verdy_p 21:47, 12 November 2008 (UTC) Global Context Variables: Scope of projects using this extensionI want to precise that it is not absolutely necessary to extend the scope of projets using this extension to all wikis using MediaWiki. What I propose is an optional extension, a ParserFunction, that acn be activated on selected projects that would benefit the most from it, with less dangers of misusing it. In addition, some other restrictions for the extension itself could be enforced. Wiktionaries are such projects that would most probably use it first, but it may be experimented first on a Multilangual project like Meta or WikiSpecies (where the use of context variables would facilitate the edition of pages, that are built essentially using templates). And I think that other external (less popular but better controlled) non-Wikimedia projects would like to have it and experiment it as well, and see the benefit they can take from it (notably for closed wikis that are publishing lots of data with automated scripts and complex data organisation, without suffering the burden of the required template parameters and of the too complex wiki code in their templates. |
Global Context Variables: Implementation Summary
[edit]My opinion is that this extension is very simple to implement, because all the infrastructure is already there: the PHP code just need to be able to instanciate a single variable containining an empty associative array at the begining of analysis for storing the context variables that the ParserFunction will be able to reference to store the context variables and their values.
The ParserFunction code itself is quite simple to write: it just has to parse the parameters and take the indicated action, and use the single variable instanciated at the begining of the page. The ParserFunction will return the value expected by "get", or nothing for "set", and it will be alone to store and retreive data in this unique PHP array variable.
At end of parsing a page, the context variables block has no more use and can be dropped, just like all other PHP variables used in Mediawiki for parsing and generating a single page. I don't think that this has any implication elsewhere in the existing MediaWiki code, because it will use the existing mechanism for ParserFunctions, but I may be wrong (there are certainly lots of tricks in MediaWiki to handle special cases in some parser functions and their interaction with other components of MediaWiki or with other ParserFunctions). verdy_p 16:58, 14 November 2008 (UTC)
Global Context Variables: Implementation in PHP (alpha version)
[edit]This is just an alpha source code, to be fully tested and debugged. Note: the syntax implemented here varies a little compared to the discussion above as it uses:
- {{#v:action|variable|optional value}} instead of:
- {{#v:action:variable|optional value}}.
It currently does not implement any policy (except then trying to monitor and cap the memory needed for storing strings), does not enforce any naming convention. It implements some additional (very basic) non essential actions.
ContextVars.php
|
---|
<?php
/**
* Enhance parser with variables storing contextual information.
*
* @addtogroup Extensions
* @author Philippe Verdy
* LICENCE 2008-11-13: This source is licenced under the same terms as those
* for the MediaWiki software source files package of the Wikimedia Foundation.
*/
if (!defined('MEDIAWIKI')) {
die('This file is an extension to the MediaWiki software and cannot be used standalone.\n');
}
$wgExtensionFunctions[] = 'wfSetupContextVars';
$wgExtensionCredits['parserhook'][] = array(
'name' => 'ContextVariables',
'version' => '0.9',
'url' => 'http://meta.wikimedia.org/wiki/ContextVars',
'author' => 'Philippe Verdy',
'description' =>
'A function that allows pages and templates to store values in reusable variables' .
' that will be set in one place to store contextual information, and whose value' .
' can then be retrieved and reused on the rest of the Wiki code that follows.',
'descriptionmsg' => 'contextVars_desc',
);
$wgExtensionMessagesFiles['ContextVars'] = dirname(__FILE__) . '/ContextVars.i18n.php';
$wgHooks['LanguageGetMagic'][] = 'wfContextVarsLanguageGetMagic';
$wgParserTestFiles[] = dirname(__FILE__) . '/funcsContextVars.txt';
// Define as 0 if Total Size not monitored
define(EXTCONTEXTVARS_MAX_TOTAL_SIZE, 0x40000); // 256 kibibytes should be enough for storing context info
// Load all internationalizable magic words (for functions or actions) from <ContextVars.i18n.magic.php>
function wfContextVarsLanguageGetMagic(&$magicWords, $langCode, $actions = 0) {
require_once(dirname(__FILE__) . '/ContextVars.i18n.magic.php');
$efWords = $actions ? efContextVarsActionWords($langCode) : efContextVarsWords($langCode);
foreach($efWords as $magicWord => $magicTrans)
$magicWords[$magicWord] = $magicTrans;
return true;
}
// Token types for functions
define(EXTCONTEXTVARS_V, 0); // essential function
// Token types for actions
define(EXTCONTEXTVARS_GET, 1); // essential action
define(EXTCONTEXTVARS_SET, 2); // essential action, to monitor and cap
define(EXTCONTEXTVARS_UNSET, 3); // useful action, should be monitored
define(EXTCONTEXTVARS_ISSET, 4); // useful action
define(EXTCONTEXTVARS_ISENABLED, 5); // optional utility action, using 'get' action
define(EXTCONTEXTVARS_ISDISABLED, 6); // optional utility action, using 'get' action
define(EXTCONTEXTVARS_ENABLE, 7); // optional utility action, using 'set' action
define(EXTCONTEXTVARS_DISABLE, 8); // optional utility action, using 'set' action
// Extension declaration and loading
function wfSetupContextVars() {
global $wgParser, $wgExtContextVars, $wgHooks;
$wgExtContextVars = new ExtContextVars;
// Check for SFH_OBJECT_ARGS capability
if (defined('MW_SUPPORTS_PARSERFIRSTCALLINIT')) {
$wgHooks['ParserFirstCallInit'][] = array(&$wgExtContextVars, 'registerParser');
} else {
if (class_exists('StubObject') && !StubObject::isRealObject($wgParser)) {
$wgParser->_unstub();
}
$wgExtContextVars->registerParser($wgParser);
}
$wgHooks['ContextVarsClearState'][] = array(&$wgExtContextVars, 'clearState');
}
// Builds an internationalizable message by delayed (on demand) loading of <ContextVars.i18n.php>
class ExtContextVarsError extends Exception {
public function __construct($msg, $parameter = '') {
wfLoadExtensionMessages('ContextVars');
$this->message = wfMsgForContent("contextvars_$msg", htmlspecialchars($parameter));
}
}
// Main class
class ExtContextVars {
// The list of context variables that have been set.
var $mContextVars = array();
// Basic monitoring and capping of total storage size.
var $mTotalSize = 0;
function getActionTokens($langCode) {
var $words = array();
wfContextVarsLanguageGetMagic(&$words, $langCode, 1);
// assign token ids to action names and translations
var $actionTokens = array();
function mapActions(&$actionTokens, $words, $token) {
foreach($words as $word) {
if ($word !== 0) $actionTokens[$word] = $token;
}
}
mapActions($actionTokens, 'get' , EXTCONTEXTVARS_GET);
mapActions($actionTokens, 'set' , EXTCONTEXTVARS_SET);
mapActions($actionTokens, 'unset' , EXTCONTEXTVARS_UNSET);
mapActions($actionTokens, 'isset' , EXTCONTEXTVARS_ISSET);
mapActions($actionTokens, 'isenabled' , EXTCONTEXTVARS_ISENABLED);
mapActions($actionTokens, 'isdisabled', EXTCONTEXTVARS_ISDISABLED);
mapActions($actionTokens, 'enable' , EXTCONTEXTVARS_ENABLE);
mapActions($actionTokens, 'disable' , EXTCONTEXTVARS_DISABLE);
return $actionTokens;
}
var $actionTokens = getActionTokens('en');
// Register parser function hooks
function registerParser(&$parser) {
if (defined(get_class($parser) . '::SFH_OBJECT_ARGS')) {
// These functions accept DOM-style arguments
$parser->setFunctionHook('v', array(&$this, 'vObj'), SFH_OBJECT_ARGS);
} else {
$parser->setFunctionHook('v', array(&$this, 'vHook'));
}
return true;
}
function clearState(&$parser) {
$this->mContextVars = array();
// Basic monitoring and capping of total storage size.
$this->mTotalSize = 0;
return true;
}
// Perform 'get' action: Get and return the value stored in the named context variable.
// Also used by 'isenabled' and 'isdisabled' actions (using implicit default values).
// Return the optional default value if this context variable is not set.
// Throws an error if no valid variable name is given or variable is not set and no default value given.
function vGet($action, $var, $value) {
if (!isset($var) || $var == '')
throw new ExtContextVarsError('var_name_required_for', $action);
if (!isset($this->mContextVars[$var])) {
if (!isset($value))
throw new ExtContextVarsError('value_needed_for_var', $var);
// Remove HTML-style comments
// Not necessary in versions where StringUtils::delimiterReplace didn't exist
if (is_callable(array('StringUtils', 'delimiterReplace'))) {
$value = StringUtils::delimiterReplace('<'.'!--', '--'.'>', '', $value);
}
return $value; // default value from parameter
} else {
return $mContextVars[$var];
}
}
// Perform 'set' action: Set the value of the named context variable, and return this value.
// Also used by 'enable' and 'disable' actions (using implicit values).
// Throws an error if no valid variable name is given.
function vSet($action, $var, $value) {
if (!isset($var) || $var == '')
throw new ExtContextVarsError('var_needed_for_action', $action);
if (!isset($value)) {
throw new ExtContextVarsError('value_needed_for_var', $var);
// Remove HTML-style comments.
// Not necessary in versions where StringUtils::delimiterReplace didn't exist.
if (is_callable(array('StringUtils', 'delimiterReplace'))) {
$value = StringUtils::delimiterReplace('<'.'!--', '--'.'>', '', $value);
}
// TODO: access restrictions.
// Basic monitoring and capping of total storage size.
$delta = strlen($value) - (isset($this->mContextVars[$var]) ? strlen($this->mContextVars[$var]) : 0);
if (EXTCONTEXTVARS_MAX_TOTAL_LENGTH > 0) {
if ($mTotalSize + $delta > EXTCONTEXTVARS_MAX_TOTAL_LENGTH)
throw new ExtContextVarsError('memory_overflow', $var);
}
$this->mTotalSize += $delta;
return $this->mContextVars[$var] = $value;
}
// Perform 'unset' action: Unset the named context variable.
// Throws an error if no valid variable name is given.
function vUnset($action, $var) {
if (!isset($var) || $var == '')
throw new ExtContextVarsError('var_needed_for_action', $action);
if (!isset($this->mContextVars[$var])) {
throw new ExtContextVarsError('var_is_not_set', $var);
// Basic monitoring and capping of total memory size.
$this->mTotalSize -= strlen($this->mContextVars[$var]);
unset($this->mContextVars[$var]);
}
// Perform 'isset' action: Check if a value is stored in a named context variable.
// Return 1 if this context variable is set, 0 otherwise.
// Throws an error if no valid variable name is given.
function vIsSet($action, $action, $var, $value) {
if (!isset($var) || $var == '')
throw new ExtContextVarsError('var_needed_for_action', $action);
return !isset($this->mContextVars[$var]);
}
// Main parser function
function vParse(&$parser, $action = '', $var = '', $value) {
# Remove HTML-style comments.
# Not necessary in versions where StringUtils::delimiterReplace didn't exist.
if (is_callable(array('StringUtils', 'delimiterReplace'))) {
$action = StringUtils::delimiterReplace('<'.'!--', '--'.'>', '', $action);
$var = StringUtils::delimiterReplace('<'.'!--', '--'.'>', '', $var);
}
try {
if ($action == '') {
$actionToken = EXTCONTEXTVARS_GET; // default action
} else if (!isset($this->actionTokens[$action])) {
throw new ExtContextVarsError('unrecognized_action', $action);
} else
$actionToken = $this->actionTokens[$action];
}
switch ($actionToken) {
// constant
case EXTCONTEXTVARS_GET: // Requires an existing valid variable name.
// An exception is thrown if var is not set and no default value given.
if (isset($value)) return vSet($action, $var, $value);
return vGet($action, $var, $value);
case EXTCONTEXTVARS_SET: // Requires any valid variable name and a value.
vSet($action, $var, $value);
return '';
case EXTCONTEXTVARS_UNSET: // Requires an existing valid variable name.
vUnset($action, $var);
return '';
case EXTCONTEXTVARS_ISSET: // Requires any valid variable name.
return vIsSet($action, $var);
case EXTCONTEXTVARS_ISENABLED: // Requires any valid variable name.
// Utility: Return 1 when var is set with a non zero value.
// When var is not set: does not throw exception, return 0.
return !!vGet($action, $var, 0);
case EXTCONTEXTVARS_ISDISABLED: // Requires any valid variable name.
// Utility: Return 1 when var is set with a zero value.
// When var is not set: does not throw exception, return 0.
return !vGet($action, $var, 1);
case EXTCONTEXTVARS_ENABLE: // Requires any valid variable name.
return vSet($action, $var, 1);
case EXTCONTEXTVARS_DISABLE: // Requires any valid variable name.
return vSet($action, $var, 0);
}
} catch (ExtContextVarsError $e) {
return '<strong class="error">' . $e->getMessage() . '</strong>';
}
}
// Parser function entry using classic semantics
function vHook(&$parser, $action = '', $var = '', $value) {
return vParse(&$parser, $action, $var, $value);
}
// Parser function entry using object semantics
function vObj(&$parser, $frame, $args) {
return vParse(&$parser,
isset($args[0]) ? $args[0] : '', // action
isset($args[1]) ? $args[1] : null, // var
isset($args[2]) ? $args[2] : null); // value
}
}
|
ContextVars.i18n.php
|
---|
<?php
/**
* Internationalisation file for extension ContextVars.
*
* @addtogroup Extensions
* @author Philippe Verdy
* LICENCE 2008-11-13: This source is licenced under the same terms as those
* for the MediaWiki software source files package of the Wikimedia Foundation.
*/
$messages = array();
/** Message documentation (for helping translators on BetaWiki)
* @author Philippe Verdy
*/
$messages['qqq'] = array(
'contextvars_desc' => 'Short description of the ContextVars extension, shown on [[Special:Version]].',
'contextvars_unrecognized_action' =>
'* Error message displayed when an unknown action is specified before the context variable.\n' .
'* $1 is replaced by the actual action string specified in the wiki source.\n',
'contextvars_var_needed_for_action' =>
'* Error message displayed when an action requires the name of a context variable.\n' .
'* $1 is replaced by the action that could not be performed.\n',
'contextvars_value_needed_for_var' =>
'* Displayed when no value parameter is specified an action is specified before the context variable.\n' .
'* $1 is replaced by the actual variable name specified in the wiki source.\n',
'contextvars_var_is_not_set' =>
'* Displayed when no value an unknown action is specified before the context variable.\n' .
'* $1 is replaced by the actual variable name specified in the wiki source.\n',
);
/** English
* @author Philippe Verdy
*/
$messages['en'] = array(
'contextvars_desc' => 'Enhance parser with variables storing contextual information.',
'contextvars_unrecognized_action' => 'Error: Unrecognized action "$1" on context variables.',
'contextvars_var_needed_for_action' => 'Error: Context variable name needed for action "$1".',
'contextvars_value_needed_for_var' => 'Error: No value specified, context variable "$1" is not set.',
'contextvars_var_is_not_set' => 'Error: Context variable "$1" is not set.',
);
/** French
* @author Philippe Verdy
*/
$messages['en'] = array(
'contextvars_desc' => 'Améliore le parseur avec des variables stockant des informations contextuelles.',
'contextvars_unrecognized_action' => 'Erreur : action "$1" non reconnue sur les variables de contexte.',
'contextvars_var_needed_for_action' => 'Erreur : nom de variable de contexte nécessaire pour l’action "$1".',
'contextvars_value_needed_for_var' => 'Erreur : pas de valeur indiquée, variable de contexte "$1" non définie.',
'contextvars_var_not_set' => 'Erreur : variable de contexte "$1" non définie.',
);
|
ContextVars.i18n.magic.php
|
---|
<?php
/**
* Get translated magic function words for extension ContextVars, if available.
*
* @param string $lang Language code
* @return array
* @addtogroup Extensions
* @author Philippe Verdy
* LICENCE 2008-11-13: This source is licenced under the same terms as those
* for the MediaWiki software source files package of the Wikimedia Foundation.
*/
function efContextVarsWords($lang) {
$words = array();
/** English
* @author Philippe Verdy
*/
$words['en'] = array(
'v' => array(0, 'v'),
);
/** French
* @author Philippe Verdy
*/
$words['en'] = array(
'v' => array(0, 'v'),
);
# English is used as a fallback, and the English synonyms are
# used if a translation has not been provided for a given word
return ($lang == 'en' || !isset($words[$lang]))
? $words['en']
: array_merge($words['en'], $words[$lang]);
}
/**
* Get translated magic action words for extension ContextVars, if available.
*
* @param string $lang Language code
* @return array
* @addtogroup Extensions
* @author Philippe Verdy
* LICENCE 2008-11-13: This source is licenced under the same terms as those
* for the MediaWiki software source files package of the Wikimedia Foundation.
*/
function efContextVarsActionWords($lang) {
$words = array();
/** English
* @author Philippe Verdy
*/
$words['en'] = array(
'get' => array(0, 'get'),
'set' => array(0, 'set'),
'unset' => array(0, 'unset'),
'isset' => array(0, 'isset'),
'isenabled' => array(0, 'isenabled'),
'isdisabled' => array(0, 'isdisabled'),
'enable' => array(0, 'enable'),
'disable' => array(0, 'disable'),
);
/** French
* @author Philippe Verdy
*/
$words['fr'] = array(
'get' => array(0, 'lit', 'get'),
'set' => array(0, 'met' 'set'),
'unset' => array(0, 'ôte', 'unset'),
'isset' => array(0, 'estmis', 'isset'),
'isenabled' => array(0, 'estactif', 'isenabled'),
'isdisabled' => array(0, 'estinactif', 'isdisabled'),
'enable' => array(0, 'active', 'enable'),
'disable' => array(0, 'désactive', 'disable'),
);
# English is used as a fallback, and the English synonyms are
# used if a translation has not been provided for a given word
return ($lang == 'en' || !isset($words[$lang]))
? $words['en']
: array_merge($words['en'], $words[$lang]);
}
|