summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/ParserFunctions
diff options
context:
space:
mode:
authorYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
committerYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
commitfc7369835258467bf97eb64f184b93691f9a9fd5 (patch)
treedaabd60089d2dd76d9f5fb416b005fbe159c799d /www/wiki/extensions/ParserFunctions
first commit
Diffstat (limited to 'www/wiki/extensions/ParserFunctions')
-rw-r--r--www/wiki/extensions/ParserFunctions/CODE_OF_CONDUCT.md1
-rw-r--r--www/wiki/extensions/ParserFunctions/COPYING283
-rw-r--r--www/wiki/extensions/ParserFunctions/Expr.php682
-rw-r--r--www/wiki/extensions/ParserFunctions/Gruntfile.js34
-rw-r--r--www/wiki/extensions/ParserFunctions/ParserFunctions.hooks.php59
-rw-r--r--www/wiki/extensions/ParserFunctions/ParserFunctions.i18n.magic.php785
-rw-r--r--www/wiki/extensions/ParserFunctions/ParserFunctions.library.php23
-rw-r--r--www/wiki/extensions/ParserFunctions/ParserFunctions.php16
-rw-r--r--www/wiki/extensions/ParserFunctions/ParserFunctions_body.php891
-rw-r--r--www/wiki/extensions/ParserFunctions/README21
-rw-r--r--www/wiki/extensions/ParserFunctions/composer.json23
-rw-r--r--www/wiki/extensions/ParserFunctions/extension.json46
-rw-r--r--www/wiki/extensions/ParserFunctions/funcsParserTests.txt343
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ace.json10
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ady-cyrl.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/af.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ais.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/aln.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/an.json25
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/anp.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ar.json31
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/arc.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/arq.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/arz.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/as.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ast.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/atj.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/av.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/awa.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/az.json22
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/azb.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ba.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/bcc.json25
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/bcl.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/be-tarask.json31
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/be.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/bg.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/bgn.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/bho.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/bn.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/bqi.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/br.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/bs.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ca.json31
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ce.json16
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ceb.json10
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ckb.json16
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/cs.json33
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/csb.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/cv.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/cy.json21
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/da.json32
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/de-ch.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/de.json34
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/din.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/diq.json32
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/dsb.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/dty.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ee.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/el.json32
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/en-gb.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/en.json26
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/eo.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/es.json35
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/et.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/eu.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/fa.json32
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/fi.json32
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/fo.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/fr.json36
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/frp.json26
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/frr.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/fur.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/gcr.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/gd.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/gl.json31
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/glk.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/gom-deva.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/gom-latn.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/gor.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/grc.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/gsw.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/gu.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/hak.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/he.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/hi.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/hif-latn.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/hr.json32
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/hsb.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ht.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/hu.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/hy.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/hyw.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ia.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/id.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ie.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ilo.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/inh.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/io.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/is.json24
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/it.json32
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ja.json33
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/jam.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/jut.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/jv.json26
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ka.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/kab.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/kbp.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/khw.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/kk-arab.json18
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/kk-cyrl.json26
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/kk-latn.json18
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/km.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/kn.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ko.json33
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/krc.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/krl.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ksh.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/kum.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/la.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/lb.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/lfn.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/li.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/lij.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/lki.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/lrc.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/lt.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/luz.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/lv.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mai.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mg.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mhr.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/min.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mk.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ml.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mr.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ms.json31
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mt.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mui.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mwl.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/my.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/myv.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/mzn.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nah.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nan.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nap.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nb.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nds-nl.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nds.json25
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ne.json18
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nl.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nn.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/nys.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/oc.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/olo.json12
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/or.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/pa.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/pfl.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/pl.json33
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/pms.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/pnb.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ps.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/pt-br.json31
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/pt.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/qqq.json34
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/qu.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ro.json32
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/roa-tara.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ru.json31
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/rue.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sa.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sah.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sat.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/scn.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sco.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sd.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sdh.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sgs.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sh.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/shn.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/si.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sk.json26
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/skr-arab.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sl.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sq.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sr-ec.json30
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sr-el.json28
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/stq.json26
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sty.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/su.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/sv.json34
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/szl.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ta.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tay.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tcy.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/te.json23
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tg-cyrl.json23
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tg-latn.json23
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/th.json25
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tk.json26
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tl.json26
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tr.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tt-cyrl.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tt-latn.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/tyv.json8
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/udm.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ug-arab.json10
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/uk.json31
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/ur.json27
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/vec.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/vep.json10
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/vi.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/vo.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/vro.json13
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/wa.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/war.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/wo.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/wuu.json14
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/xal.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/xmf.json11
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/yi.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/yo.json15
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/yue.json29
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/zgh.json9
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/zh-hans.json35
-rw-r--r--www/wiki/extensions/ParserFunctions/i18n/zh-hant.json35
-rw-r--r--www/wiki/extensions/ParserFunctions/includes/ExprError.php33
-rw-r--r--www/wiki/extensions/ParserFunctions/includes/ExprParser.php673
-rw-r--r--www/wiki/extensions/ParserFunctions/includes/ExtParserFunctions.php891
-rw-r--r--www/wiki/extensions/ParserFunctions/includes/ParserFunctionsHooks.php59
-rw-r--r--www/wiki/extensions/ParserFunctions/includes/Scribunto_LuaParserFunctionsLibrary.php23
-rw-r--r--www/wiki/extensions/ParserFunctions/includes/mw.ext.ParserFunctions.lua22
-rw-r--r--www/wiki/extensions/ParserFunctions/mw.ext.ParserFunctions.lua22
-rw-r--r--www/wiki/extensions/ParserFunctions/phpcs.xml17
-rw-r--r--www/wiki/extensions/ParserFunctions/stringFunctionTests.txt32
-rw-r--r--www/wiki/extensions/ParserFunctions/tests/ExpressionTest.php76
-rw-r--r--www/wiki/extensions/ParserFunctions/tests/parser/funcsParserTests.txt343
-rw-r--r--www/wiki/extensions/ParserFunctions/tests/parser/stringFunctionTests.txt50
-rw-r--r--www/wiki/extensions/ParserFunctions/tests/phan/config.php19
-rw-r--r--www/wiki/extensions/ParserFunctions/tests/phpunit/ExpressionTest.php79
240 files changed, 9790 insertions, 0 deletions
diff --git a/www/wiki/extensions/ParserFunctions/CODE_OF_CONDUCT.md b/www/wiki/extensions/ParserFunctions/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..d8e5d087
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/CODE_OF_CONDUCT.md
@@ -0,0 +1 @@
+The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Code_of_Conduct).
diff --git a/www/wiki/extensions/ParserFunctions/COPYING b/www/wiki/extensions/ParserFunctions/COPYING
new file mode 100644
index 00000000..27a8f1d2
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/COPYING
@@ -0,0 +1,283 @@
+The ParserFunctions extension may be copied and redistributed under the GNU
+General Public License, version 2.0 or, at your option, any later version.
+
+-------------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/www/wiki/extensions/ParserFunctions/Expr.php b/www/wiki/extensions/ParserFunctions/Expr.php
new file mode 100644
index 00000000..e305b59d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/Expr.php
@@ -0,0 +1,682 @@
+<?php
+
+use UtfNormal\Validator;
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ die( 'This file is a MediaWiki extension, it is not a valid entry point' );
+}
+
+// Character classes
+define( 'EXPR_WHITE_CLASS', " \t\r\n" );
+define( 'EXPR_NUMBER_CLASS', '0123456789.' );
+
+// Token types
+define( 'EXPR_WHITE', 1 );
+define( 'EXPR_NUMBER', 2 );
+define( 'EXPR_NEGATIVE', 3 );
+define( 'EXPR_POSITIVE', 4 );
+define( 'EXPR_PLUS', 5 );
+define( 'EXPR_MINUS', 6 );
+define( 'EXPR_TIMES', 7 );
+define( 'EXPR_DIVIDE', 8 );
+define( 'EXPR_MOD', 9 );
+define( 'EXPR_OPEN', 10 );
+define( 'EXPR_CLOSE', 11 );
+define( 'EXPR_AND', 12 );
+define( 'EXPR_OR', 13 );
+define( 'EXPR_NOT', 14 );
+define( 'EXPR_EQUALITY', 15 );
+define( 'EXPR_LESS', 16 );
+define( 'EXPR_GREATER', 17 );
+define( 'EXPR_LESSEQ', 18 );
+define( 'EXPR_GREATEREQ', 19 );
+define( 'EXPR_NOTEQ', 20 );
+define( 'EXPR_ROUND', 21 );
+define( 'EXPR_EXPONENT', 22 );
+define( 'EXPR_SINE', 23 );
+define( 'EXPR_COSINE', 24 );
+define( 'EXPR_TANGENS', 25 );
+define( 'EXPR_ARCSINE', 26 );
+define( 'EXPR_ARCCOS', 27 );
+define( 'EXPR_ARCTAN', 28 );
+define( 'EXPR_EXP', 29 );
+define( 'EXPR_LN', 30 );
+define( 'EXPR_ABS', 31 );
+define( 'EXPR_FLOOR', 32 );
+define( 'EXPR_TRUNC', 33 );
+define( 'EXPR_CEIL', 34 );
+define( 'EXPR_POW', 35 );
+define( 'EXPR_PI', 36 );
+define( 'EXPR_FMOD', 37 );
+define( 'EXPR_SQRT', 38 );
+
+class ExprError extends Exception {
+ /**
+ * @param $msg string
+ * @param $parameter string
+ */
+ public function __construct( $msg, $parameter = '' ) {
+ // Give grep a chance to find the usages:
+ // pfunc_expr_stack_exhausted, pfunc_expr_unexpected_number, pfunc_expr_preg_match_failure,
+ // pfunc_expr_unrecognised_word, pfunc_expr_unexpected_operator, pfunc_expr_missing_operand,
+ // pfunc_expr_unexpected_closing_bracket, pfunc_expr_unrecognised_punctuation,
+ // pfunc_expr_unclosed_bracket, pfunc_expr_division_by_zero, pfunc_expr_invalid_argument,
+ // pfunc_expr_invalid_argument_ln, pfunc_expr_unknown_error, pfunc_expr_not_a_number
+ $this->message = wfMessage( "pfunc_expr_$msg", $parameter )->inContentLanguage()->text();
+ }
+}
+
+class ExprParser {
+ public $maxStackSize = 100;
+
+ public $precedence = [
+ EXPR_NEGATIVE => 10,
+ EXPR_POSITIVE => 10,
+ EXPR_EXPONENT => 10,
+ EXPR_SINE => 9,
+ EXPR_COSINE => 9,
+ EXPR_TANGENS => 9,
+ EXPR_ARCSINE => 9,
+ EXPR_ARCCOS => 9,
+ EXPR_ARCTAN => 9,
+ EXPR_EXP => 9,
+ EXPR_LN => 9,
+ EXPR_ABS => 9,
+ EXPR_FLOOR => 9,
+ EXPR_TRUNC => 9,
+ EXPR_CEIL => 9,
+ EXPR_NOT => 9,
+ EXPR_SQRT => 9,
+ EXPR_POW => 8,
+ EXPR_TIMES => 7,
+ EXPR_DIVIDE => 7,
+ EXPR_MOD => 7,
+ EXPR_FMOD => 7,
+ EXPR_PLUS => 6,
+ EXPR_MINUS => 6,
+ EXPR_ROUND => 5,
+ EXPR_EQUALITY => 4,
+ EXPR_LESS => 4,
+ EXPR_GREATER => 4,
+ EXPR_LESSEQ => 4,
+ EXPR_GREATEREQ => 4,
+ EXPR_NOTEQ => 4,
+ EXPR_AND => 3,
+ EXPR_OR => 2,
+ EXPR_PI => 0,
+ EXPR_OPEN => -1,
+ EXPR_CLOSE => -1,
+ ];
+
+ public $names = [
+ EXPR_NEGATIVE => '-',
+ EXPR_POSITIVE => '+',
+ EXPR_NOT => 'not',
+ EXPR_TIMES => '*',
+ EXPR_DIVIDE => '/',
+ EXPR_MOD => 'mod',
+ EXPR_FMOD => 'fmod',
+ EXPR_PLUS => '+',
+ EXPR_MINUS => '-',
+ EXPR_ROUND => 'round',
+ EXPR_EQUALITY => '=',
+ EXPR_LESS => '<',
+ EXPR_GREATER => '>',
+ EXPR_LESSEQ => '<=',
+ EXPR_GREATEREQ => '>=',
+ EXPR_NOTEQ => '<>',
+ EXPR_AND => 'and',
+ EXPR_OR => 'or',
+ EXPR_EXPONENT => 'e',
+ EXPR_SINE => 'sin',
+ EXPR_COSINE => 'cos',
+ EXPR_TANGENS => 'tan',
+ EXPR_ARCSINE => 'asin',
+ EXPR_ARCCOS => 'acos',
+ EXPR_ARCTAN => 'atan',
+ EXPR_LN => 'ln',
+ EXPR_EXP => 'exp',
+ EXPR_ABS => 'abs',
+ EXPR_FLOOR => 'floor',
+ EXPR_TRUNC => 'trunc',
+ EXPR_CEIL => 'ceil',
+ EXPR_POW => '^',
+ EXPR_PI => 'pi',
+ EXPR_SQRT => 'sqrt',
+ ];
+
+ public $words = [
+ 'mod' => EXPR_MOD,
+ 'fmod' => EXPR_FMOD,
+ 'and' => EXPR_AND,
+ 'or' => EXPR_OR,
+ 'not' => EXPR_NOT,
+ 'round' => EXPR_ROUND,
+ 'div' => EXPR_DIVIDE,
+ 'e' => EXPR_EXPONENT,
+ 'sin' => EXPR_SINE,
+ 'cos' => EXPR_COSINE,
+ 'tan' => EXPR_TANGENS,
+ 'asin' => EXPR_ARCSINE,
+ 'acos' => EXPR_ARCCOS,
+ 'atan' => EXPR_ARCTAN,
+ 'exp' => EXPR_EXP,
+ 'ln' => EXPR_LN,
+ 'abs' => EXPR_ABS,
+ 'trunc' => EXPR_TRUNC,
+ 'floor' => EXPR_FLOOR,
+ 'ceil' => EXPR_CEIL,
+ 'pi' => EXPR_PI,
+ 'sqrt' => EXPR_SQRT,
+ ];
+
+ /**
+ * Evaluate a mathematical expression
+ *
+ * The algorithm here is based on the infix to RPN algorithm given in
+ * http://montcs.bloomu.edu/~bobmon/Information/RPN/infix2rpn.shtml
+ * It's essentially the same as Dijkstra's shunting yard algorithm.
+ * @param $expr string
+ * @throws ExprError
+ * @return string
+ */
+ public function doExpression( $expr ) {
+ $operands = [];
+ $operators = [];
+
+ # Unescape inequality operators
+ $expr = strtr( $expr, [ '&lt;' => '<', '&gt;' => '>',
+ '&minus;' => '-', '−' => '-' ] );
+
+ $p = 0;
+ $end = strlen( $expr );
+ $expecting = 'expression';
+ $name = '';
+
+ while ( $p < $end ) {
+ if ( count( $operands ) > $this->maxStackSize || count( $operators ) > $this->maxStackSize ) {
+ throw new ExprError( 'stack_exhausted' );
+ }
+ $char = $expr[$p];
+ $char2 = substr( $expr, $p, 2 );
+
+ // Mega if-elseif-else construct
+ // Only binary operators fall through for processing at the bottom, the rest
+ // finish their processing and continue
+
+ // First the unlimited length classes
+
+ if ( false !== strpos( EXPR_WHITE_CLASS, $char ) ) {
+ // Whitespace
+ $p += strspn( $expr, EXPR_WHITE_CLASS, $p );
+ continue;
+ } elseif ( false !== strpos( EXPR_NUMBER_CLASS, $char ) ) {
+ // Number
+ if ( $expecting !== 'expression' ) {
+ throw new ExprError( 'unexpected_number' );
+ }
+
+ // Find the rest of it
+ $length = strspn( $expr, EXPR_NUMBER_CLASS, $p );
+ // Convert it to float, silently removing double decimal points
+ $operands[] = (float)substr( $expr, $p, $length );
+ $p += $length;
+ $expecting = 'operator';
+ continue;
+ } elseif ( ctype_alpha( $char ) ) {
+ // Word
+ // Find the rest of it
+ $remaining = substr( $expr, $p );
+ if ( !preg_match( '/^[A-Za-z]*/', $remaining, $matches ) ) {
+ // This should be unreachable
+ throw new ExprError( 'preg_match_failure' );
+ }
+ $word = strtolower( $matches[0] );
+ $p += strlen( $word );
+
+ // Interpret the word
+ if ( !isset( $this->words[$word] ) ) {
+ throw new ExprError( 'unrecognised_word', $word );
+ }
+ $op = $this->words[$word];
+ switch ( $op ) {
+ // constant
+ case EXPR_EXPONENT:
+ if ( $expecting !== 'expression' ) {
+ continue;
+ }
+ $operands[] = exp( 1 );
+ $expecting = 'operator';
+ continue 2;
+ case EXPR_PI:
+ if ( $expecting !== 'expression' ) {
+ throw new ExprError( 'unexpected_number' );
+ }
+ $operands[] = pi();
+ $expecting = 'operator';
+ continue 2;
+ // Unary operator
+ case EXPR_NOT:
+ case EXPR_SINE:
+ case EXPR_COSINE:
+ case EXPR_TANGENS:
+ case EXPR_ARCSINE:
+ case EXPR_ARCCOS:
+ case EXPR_ARCTAN:
+ case EXPR_EXP:
+ case EXPR_LN:
+ case EXPR_ABS:
+ case EXPR_FLOOR:
+ case EXPR_TRUNC:
+ case EXPR_CEIL:
+ case EXPR_SQRT:
+ if ( $expecting !== 'expression' ) {
+ throw new ExprError( 'unexpected_operator', $word );
+ }
+ $operators[] = $op;
+ continue 2;
+ }
+ // Binary operator, fall through
+ $name = $word;
+ }
+
+ // Next the two-character operators
+ elseif ( $char2 === '<=' ) {
+ $name = $char2;
+ $op = EXPR_LESSEQ;
+ $p += 2;
+ } elseif ( $char2 === '>=' ) {
+ $name = $char2;
+ $op = EXPR_GREATEREQ;
+ $p += 2;
+ } elseif ( $char2 === '<>' || $char2 === '!=' ) {
+ $name = $char2;
+ $op = EXPR_NOTEQ;
+ $p += 2;
+ }
+
+ // Finally the single-character operators
+ elseif ( $char === '+' ) {
+ ++$p;
+ if ( $expecting === 'expression' ) {
+ // Unary plus
+ $operators[] = EXPR_POSITIVE;
+ continue;
+ } else {
+ // Binary plus
+ $op = EXPR_PLUS;
+ }
+ } elseif ( $char === '-' ) {
+ ++$p;
+ if ( $expecting === 'expression' ) {
+ // Unary minus
+ $operators[] = EXPR_NEGATIVE;
+ continue;
+ } else {
+ // Binary minus
+ $op = EXPR_MINUS;
+ }
+ } elseif ( $char === '*' ) {
+ $name = $char;
+ $op = EXPR_TIMES;
+ ++$p;
+ } elseif ( $char === '/' ) {
+ $name = $char;
+ $op = EXPR_DIVIDE;
+ ++$p;
+ } elseif ( $char === '^' ) {
+ $name = $char;
+ $op = EXPR_POW;
+ ++$p;
+ } elseif ( $char === '(' ) {
+ if ( $expecting === 'operator' ) {
+ throw new ExprError( 'unexpected_operator', '(' );
+ }
+ $operators[] = EXPR_OPEN;
+ ++$p;
+ continue;
+ } elseif ( $char === ')' ) {
+ $lastOp = end( $operators );
+ while ( $lastOp && $lastOp != EXPR_OPEN ) {
+ $this->doOperation( $lastOp, $operands );
+ array_pop( $operators );
+ $lastOp = end( $operators );
+ }
+ if ( $lastOp ) {
+ array_pop( $operators );
+ } else {
+ throw new ExprError( 'unexpected_closing_bracket' );
+ }
+ $expecting = 'operator';
+ ++$p;
+ continue;
+ } elseif ( $char === '=' ) {
+ $name = $char;
+ $op = EXPR_EQUALITY;
+ ++$p;
+ } elseif ( $char === '<' ) {
+ $name = $char;
+ $op = EXPR_LESS;
+ ++$p;
+ } elseif ( $char === '>' ) {
+ $name = $char;
+ $op = EXPR_GREATER;
+ ++$p;
+ } else {
+ throw new ExprError( 'unrecognised_punctuation', Validator::cleanUp( $char ) );
+ }
+
+ // Binary operator processing
+ if ( $expecting === 'expression' ) {
+ throw new ExprError( 'unexpected_operator', $name );
+ }
+
+ // Shunting yard magic
+ $lastOp = end( $operators );
+ while ( $lastOp && $this->precedence[$op] <= $this->precedence[$lastOp] ) {
+ $this->doOperation( $lastOp, $operands );
+ array_pop( $operators );
+ $lastOp = end( $operators );
+ }
+ $operators[] = $op;
+ $expecting = 'expression';
+ }
+
+ // Finish off the operator array
+ // @codingStandardsIgnoreStart
+ while ( $op = array_pop( $operators ) ) {
+ // @codingStandardsIgnoreEnd
+ if ( $op == EXPR_OPEN ) {
+ throw new ExprError( 'unclosed_bracket' );
+ }
+ $this->doOperation( $op, $operands );
+ }
+
+ return implode( "<br />\n", $operands );
+ }
+
+ /**
+ * @param $op int
+ * @param $stack array
+ * @throws ExprError
+ */
+ public function doOperation( $op, &$stack ) {
+ switch ( $op ) {
+ case EXPR_NEGATIVE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = -$arg;
+ break;
+ case EXPR_POSITIVE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ break;
+ case EXPR_TIMES:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = $left * $right;
+ break;
+ case EXPR_DIVIDE:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ if ( !$right ) {
+ throw new ExprError( 'division_by_zero', $this->names[$op] );
+ }
+ $stack[] = $left / $right;
+ break;
+ case EXPR_MOD:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = (int)array_pop( $stack );
+ $left = (int)array_pop( $stack );
+ if ( !$right ) {
+ throw new ExprError( 'division_by_zero', $this->names[$op] );
+ }
+ $stack[] = $left % $right;
+ break;
+ case EXPR_FMOD:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = (double)array_pop( $stack );
+ $left = (double)array_pop( $stack );
+ if ( !$right ) {
+ throw new ExprError( 'division_by_zero', $this->names[$op] );
+ }
+ $stack[] = fmod( $left, $right );
+ break;
+ case EXPR_PLUS:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = $left + $right;
+ break;
+ case EXPR_MINUS:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = $left - $right;
+ break;
+ case EXPR_AND:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left && $right ) ? 1 : 0;
+ break;
+ case EXPR_OR:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left || $right ) ? 1 : 0;
+ break;
+ case EXPR_EQUALITY:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left == $right ) ? 1 : 0;
+ break;
+ case EXPR_NOT:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = ( !$arg ) ? 1 : 0;
+ break;
+ case EXPR_ROUND:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $digits = (int)array_pop( $stack );
+ $value = array_pop( $stack );
+ $stack[] = round( $value, $digits );
+ break;
+ case EXPR_LESS:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left < $right ) ? 1 : 0;
+ break;
+ case EXPR_GREATER:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left > $right ) ? 1 : 0;
+ break;
+ case EXPR_LESSEQ:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left <= $right ) ? 1 : 0;
+ break;
+ case EXPR_GREATEREQ:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left >= $right ) ? 1 : 0;
+ break;
+ case EXPR_NOTEQ:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left != $right ) ? 1 : 0;
+ break;
+ case EXPR_EXPONENT:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = $left * pow( 10, $right );
+ break;
+ case EXPR_SINE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = sin( $arg );
+ break;
+ case EXPR_COSINE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = cos( $arg );
+ break;
+ case EXPR_TANGENS:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = tan( $arg );
+ break;
+ case EXPR_ARCSINE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ if ( $arg < -1 || $arg > 1 ) {
+ throw new ExprError( 'invalid_argument', $this->names[$op] );
+ }
+ $stack[] = asin( $arg );
+ break;
+ case EXPR_ARCCOS:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ if ( $arg < -1 || $arg > 1 ) {
+ throw new ExprError( 'invalid_argument', $this->names[$op] );
+ }
+ $stack[] = acos( $arg );
+ break;
+ case EXPR_ARCTAN:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = atan( $arg );
+ break;
+ case EXPR_EXP:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = exp( $arg );
+ break;
+ case EXPR_LN:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ if ( $arg <= 0 ) {
+ throw new ExprError( 'invalid_argument_ln', $this->names[$op] );
+ }
+ $stack[] = log( $arg );
+ break;
+ case EXPR_ABS:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = abs( $arg );
+ break;
+ case EXPR_FLOOR:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = floor( $arg );
+ break;
+ case EXPR_TRUNC:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = (int)$arg;
+ break;
+ case EXPR_CEIL:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = ceil( $arg );
+ break;
+ case EXPR_POW:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $result = pow( $left, $right );
+ if ( $result === false ) {
+ throw new ExprError( 'division_by_zero', $this->names[$op] );
+ }
+ $stack[] = $result;
+ break;
+ case EXPR_SQRT:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $result = sqrt( $arg );
+ if ( is_nan( $result ) ) {
+ throw new ExprError( 'not_a_number', $this->names[$op] );
+ }
+ $stack[] = $result;
+ break;
+ default:
+ // Should be impossible to reach here.
+ throw new ExprError( 'unknown_error' );
+ }
+ }
+}
diff --git a/www/wiki/extensions/ParserFunctions/Gruntfile.js b/www/wiki/extensions/ParserFunctions/Gruntfile.js
new file mode 100644
index 00000000..af2402e4
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/Gruntfile.js
@@ -0,0 +1,34 @@
+/*!
+ * Grunt file
+ *
+ * @package ParserFunctions
+ */
+
+/*jshint node:true */
+module.exports = function ( grunt ) {
+ grunt.loadNpmTasks( 'grunt-banana-checker' );
+ grunt.loadNpmTasks( 'grunt-jsonlint' );
+ grunt.loadNpmTasks( 'grunt-contrib-jshint' );
+
+ var conf = grunt.file.readJSON( 'extension.json' );
+ grunt.initConfig( {
+ banana: conf.MessagesDirs,
+ jshint: {
+ all: [
+ '**/*.js',
+ '!node_modules/**',
+ '!vendor/**'
+ ]
+ },
+ jsonlint: {
+ all: [
+ '**/*.json',
+ '!node_modules/**',
+ '!vendor/**'
+ ]
+ }
+ } );
+
+ grunt.registerTask( 'test', [ 'jsonlint', 'banana', 'jshint' ] );
+ grunt.registerTask( 'default', 'test' );
+};
diff --git a/www/wiki/extensions/ParserFunctions/ParserFunctions.hooks.php b/www/wiki/extensions/ParserFunctions/ParserFunctions.hooks.php
new file mode 100644
index 00000000..646f8e7a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/ParserFunctions.hooks.php
@@ -0,0 +1,59 @@
+<?php
+
+class ParserFunctionsHooks {
+
+ /**
+ * Enable string functions, when running Wikimedia Jenkins unit tests.
+ *
+ * Running Jenkins unit tests without setting $wgPFEnableStringFunctions = true;
+ * will cause all the parser tests for string functions to be skipped.
+ */
+ public static function onRegistration() {
+ if ( isset( $GLOBALS['wgWikimediaJenkinsCI'] ) && $GLOBALS['wgWikimediaJenkinsCI'] === true ) {
+ $GLOBALS['wgPFEnableStringFunctions'] = true;
+ }
+ }
+
+ /**
+ * @param $parser Parser
+ * @return bool
+ */
+ public static function onParserFirstCallInit( $parser ) {
+ global $wgPFEnableStringFunctions;
+
+ // These functions accept DOM-style arguments
+ $parser->setFunctionHook( 'if', 'ExtParserFunctions::ifObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'ifeq', 'ExtParserFunctions::ifeqObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'switch', 'ExtParserFunctions::switchObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'ifexist', 'ExtParserFunctions::ifexistObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'ifexpr', 'ExtParserFunctions::ifexprObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'iferror', 'ExtParserFunctions::iferrorObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'time', 'ExtParserFunctions::timeObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'timel', 'ExtParserFunctions::localTimeObj', Parser::SFH_OBJECT_ARGS );
+
+ $parser->setFunctionHook( 'expr', 'ExtParserFunctions::expr' );
+ $parser->setFunctionHook( 'rel2abs', 'ExtParserFunctions::rel2abs' );
+ $parser->setFunctionHook( 'titleparts', 'ExtParserFunctions::titleparts' );
+
+ // String Functions
+ if ( $wgPFEnableStringFunctions ) {
+ $parser->setFunctionHook( 'len', 'ExtParserFunctions::runLen' );
+ $parser->setFunctionHook( 'pos', 'ExtParserFunctions::runPos' );
+ $parser->setFunctionHook( 'rpos', 'ExtParserFunctions::runRPos' );
+ $parser->setFunctionHook( 'sub', 'ExtParserFunctions::runSub' );
+ $parser->setFunctionHook( 'count', 'ExtParserFunctions::runCount' );
+ $parser->setFunctionHook( 'replace', 'ExtParserFunctions::runReplace' );
+ $parser->setFunctionHook( 'explode', 'ExtParserFunctions::runExplode' );
+ $parser->setFunctionHook( 'urldecode', 'ExtParserFunctions::runUrlDecode' );
+ }
+
+ return true;
+ }
+
+ public static function onScribuntoExternalLibraries( $engine, array &$extraLibraries ) {
+ if ( $engine === 'lua' ) {
+ $extraLibraries['mw.ext.ParserFunctions'] = 'Scribunto_LuaParserFunctionsLibrary';
+ }
+ return true;
+ }
+}
diff --git a/www/wiki/extensions/ParserFunctions/ParserFunctions.i18n.magic.php b/www/wiki/extensions/ParserFunctions/ParserFunctions.i18n.magic.php
new file mode 100644
index 00000000..36892cef
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/ParserFunctions.i18n.magic.php
@@ -0,0 +1,785 @@
+<?php
+/**
+ * Internationalisation file for extension ParserFunctions.
+ *
+ * @file
+ * @ingroup Extensions
+ */
+
+$magicWords = [];
+
+/** English (English) */
+$magicWords['en'] = [
+ 'expr' => [ 0, 'expr' ],
+ 'if' => [ 0, 'if' ],
+ 'ifeq' => [ 0, 'ifeq' ],
+ 'ifexpr' => [ 0, 'ifexpr' ],
+ 'iferror' => [ 0, 'iferror' ],
+ 'switch' => [ 0, 'switch' ],
+ 'default' => [ 0, '#default' ],
+ 'ifexist' => [ 0, 'ifexist' ],
+ 'time' => [ 0, 'time' ],
+ 'timel' => [ 0, 'timel' ],
+ 'rel2abs' => [ 0, 'rel2abs' ],
+ 'titleparts' => [ 0, 'titleparts' ],
+ 'len' => [ 0, 'len' ],
+ 'pos' => [ 0, 'pos' ],
+ 'rpos' => [ 0, 'rpos' ],
+ 'sub' => [ 0, 'sub' ],
+ 'count' => [ 0, 'count' ],
+ 'replace' => [ 0, 'replace' ],
+ 'explode' => [ 0, 'explode' ],
+ 'urldecode' => [ 0, 'urldecode' ],
+];
+
+/** Arabic (العربية) */
+$magicWords['ar'] = [
+ 'expr' => [ 0, 'تعبير' ],
+ 'if' => [ 0, 'لو' ],
+ 'ifeq' => [ 0, 'لومعادلة' ],
+ 'ifexpr' => [ 0, 'لوتعبير' ],
+ 'iferror' => [ 0, 'لوخطأ' ],
+ 'switch' => [ 0, 'تبديل' ],
+ 'default' => [ 0, '#افتراضي' ],
+ 'ifexist' => [ 0, 'لوموجود' ],
+ 'time' => [ 0, 'وقت' ],
+ 'timel' => [ 0, 'تيمل' ],
+ 'rel2abs' => [ 0, 'ريلتوآبس' ],
+ 'titleparts' => [ 0, 'أجزاء_العنوان' ],
+ 'len' => [ 0, 'لين' ],
+ 'pos' => [ 0, 'بوس' ],
+ 'rpos' => [ 0, 'آربوس' ],
+ 'sub' => [ 0, 'متفرع' ],
+ 'count' => [ 0, 'عدد' ],
+ 'replace' => [ 0, 'استبدال' ],
+ 'explode' => [ 0, 'انفجار' ],
+ 'urldecode' => [ 0, 'فك_مسار' ],
+];
+
+/** Egyptian Arabic (مصرى) */
+$magicWords['arz'] = [
+ 'expr' => [ 0, 'تعبير' ],
+ 'if' => [ 0, 'لو' ],
+ 'ifeq' => [ 0, 'لومعادلة' ],
+ 'ifexpr' => [ 0, 'لوتعبير' ],
+ 'iferror' => [ 0, 'لوخطأ' ],
+ 'switch' => [ 0, 'تبديل' ],
+ 'default' => [ 0, '#افتراضي' ],
+ 'ifexist' => [ 0, 'لوموجود' ],
+ 'time' => [ 0, 'وقت' ],
+ 'timel' => [ 0, 'تيمل' ],
+ 'rel2abs' => [ 0, 'ريلتوآبس' ],
+ 'titleparts' => [ 0, 'أجزاء_العنوان' ],
+ 'len' => [ 0, 'لين' ],
+ 'pos' => [ 0, 'بوس' ],
+ 'rpos' => [ 0, 'آربوس' ],
+ 'sub' => [ 0, 'متفرع' ],
+ 'count' => [ 0, 'عدد' ],
+ 'replace' => [ 0, 'استبدال' ],
+ 'explode' => [ 0, 'انفجار' ],
+ 'urldecode' => [ 0, 'فك_مسار' ],
+];
+
+/** South Azerbaijani (تۆرکجه) */
+$magicWords['azb'] = [
+ 'ifeq' => [ 0, 'ایربیر' ],
+ 'ifexpr' => [ 0, 'ایرحساب' ],
+ 'iferror' => [ 0, 'ایریالنیش' ],
+ 'ifexist' => [ 0, 'ایراولسا' ],
+];
+
+/** Breton (brezhoneg) */
+$magicWords['br'] = [
+ 'time' => [ 0, 'amzer' ],
+ 'count' => [ 0, 'kontañ' ],
+ 'replace' => [ 0, 'erlec\'hiañ' ],
+];
+
+/** Chechen (нохчийн) */
+$magicWords['ce'] = [
+ 'time' => [ 0, 'хан' ],
+ 'replace' => [ 0, 'хийцарна', 'замена' ],
+];
+
+/** Czech (čeština) */
+$magicWords['cs'] = [
+ 'expr' => [ 0, 'výraz' ],
+ 'if' => [ 0, 'když' ],
+ 'ifexist' => [ 0, 'kdyžexist' ],
+ 'time' => [ 0, 'čas' ],
+ 'len' => [ 0, 'délka' ],
+ 'count' => [ 0, 'počet' ],
+ 'replace' => [ 0, 'nahradit' ],
+];
+
+/** Chuvash (Чӑвашла) */
+$magicWords['cv'] = [
+ 'expr' => [ 0, 'expr' ],
+ 'if' => [ 0, 'if' ],
+ 'ifeq' => [ 0, 'ifeq' ],
+ 'ifexpr' => [ 0, 'ifexpr' ],
+ 'iferror' => [ 0, 'iferror' ],
+ 'switch' => [ 0, 'switch' ],
+ 'default' => [ 0, '#default' ],
+ 'ifexist' => [ 0, 'ifexist' ],
+ 'time' => [ 0, 'time' ],
+ 'timel' => [ 0, 'timel' ],
+ 'rel2abs' => [ 0, 'rel2abs' ],
+ 'titleparts' => [ 0, 'titleparts' ],
+ 'len' => [ 0, 'len' ],
+ 'pos' => [ 0, 'pos' ],
+ 'rpos' => [ 0, 'rpos' ],
+ 'sub' => [ 0, 'sub' ],
+ 'count' => [ 0, 'count' ],
+ 'replace' => [ 0, 'replace' ],
+ 'explode' => [ 0, 'explode' ],
+ 'urldecode' => [ 0, 'urldecode' ],
+];
+
+/** German (Deutsch) */
+$magicWords['de'] = [
+ 'switch' => [ 0, 'wechsle' ],
+ 'default' => [ 0, '#standard' ],
+ 'count' => [ 0, 'zähle' ],
+ 'replace' => [ 0, 'ersetze' ],
+ 'urldecode' => [ 0, 'URLDEKODIERT:' ],
+];
+
+/** Zazaki (Zazaki) */
+$magicWords['diq'] = [
+ 'expr' => [ 0, 'ifade' ],
+ 'if' => [ 0, 'se' ],
+ 'ifeq' => [ 0, 'sek' ],
+ 'ifexpr' => [ 0, 'ifadeyose' ],
+ 'iferror' => [ 0, 'çınyose' ],
+ 'switch' => [ 0, 'rayek' ],
+ 'default' => [ 0, '#hesıbyaye' ],
+ 'time' => [ 0, 'zeman' ],
+ 'sub' => [ 0, 'bın' ],
+ 'count' => [ 0, 'hesabk' ],
+ 'replace' => [ 0, 'vırnayen' ],
+];
+
+/** Esperanto (Esperanto) */
+$magicWords['eo'] = [
+ 'expr' => [ 0, 'espr', 'esprimo', 'esprime' ],
+ 'if' => [ 0, 'se' ],
+ 'ifeq' => [ 0, 'seekv', 'seekvacio', 'seeglas', 'laŭsamvalorade', 'lauxsamvalorade' ],
+ 'ifexpr' => [ 0, 'seespr', 'seeksprimo', 'seesprimo', 'laŭevaluade', 'laŭevaluade' ],
+ 'iferror' => [ 0, 'seeraras', 'laŭerarade', 'lauxerarade' ],
+ 'switch' => [ 0, 'ŝaltu', 'ŝalti', 'sxaltu', 'sxalti', 'ŝalte', 'sxalte' ],
+ 'default' => [ 0, '#apriore', '#defaŭlte', '#defauxlte' ],
+ 'ifexist' => [ 0, 'seekzistas', 'laŭasignade', 'lauxasignade' ],
+ 'time' => [ 0, 'tempo', 'datformu' ],
+ 'timel' => [ 0, 'tempoo', 'lokaĵdatdonu', 'lokajxdatdonu' ],
+ 'len' => [ 0, 'lungo', 'longo', 'longdonu', 'pesu', 'pese' ],
+ 'replace' => [ 0, 'anstataŭigi', 'anstataŭigu', 'anstatauxigi', 'anstatauxigu' ],
+ 'rel2abs' => [ 0, 'absolutvojdonu', 'malrelativige' ],
+ 'titleparts' => [ 0, 'titolpartdonu' ],
+ 'pos' => [ 0, 'ejdonu', 'lokdonu' ],
+ 'rpos' => [ 0, 'lastejdonu', 'lastlokdonu' ],
+ 'sub' => [ 0, 'subĉendonu', 'subcxendonu' ],
+ 'count' => [ 0, 'subĉennombru', 'subcxennombru' ],
+ 'explode' => [ 0, 'disĉenigu' ],
+ 'urldecode' => [ 0, 'URL-malkodu', 'URI-malkodu' ],
+];
+
+/** Spanish (español) */
+$magicWords['es'] = [
+ 'if' => [ 0, 'si' ],
+ 'ifeq' => [ 0, 'siigual' ],
+ 'ifexpr' => [ 0, 'siexpr' ],
+ 'iferror' => [ 0, 'sierror' ],
+ 'switch' => [ 0, 'según' ],
+ 'default' => [ 0, '#predeterminado' ],
+ 'ifexist' => [ 0, 'siexiste' ],
+ 'time' => [ 0, 'tiempo' ],
+ 'timel' => [ 0, 'tiempol' ],
+ 'len' => [ 0, 'long', 'longitud' ],
+ 'replace' => [ 0, 'reemplazar' ],
+ 'explode' => [ 0, 'separar' ],
+];
+
+/** Persian (فارسی) */
+$magicWords['fa'] = [
+ 'expr' => [ 0, 'حساب' ],
+ 'if' => [ 0, 'اگر' ],
+ 'ifeq' => [ 0, 'اگرمساوی' ],
+ 'ifexpr' => [ 0, 'اگرحساب' ],
+ 'iferror' => [ 0, 'اگرخطا' ],
+ 'switch' => [ 0, 'گزینه' ],
+ 'default' => [ 0, '#پیش‌فرض' ],
+ 'ifexist' => [ 0, 'اگرموجود' ],
+ 'time' => [ 0, 'زمان' ],
+ 'timel' => [ 0, 'زمان‌بلند' ],
+ 'rel2abs' => [ 0, 'نسبی‌به‌مطلق' ],
+ 'titleparts' => [ 0, 'پاره‌عنوان' ],
+ 'len' => [ 0, 'طول' ],
+ 'pos' => [ 0, 'جا' ],
+ 'rpos' => [ 0, 'جار' ],
+ 'sub' => [ 0, 'تکه' ],
+ 'count' => [ 0, 'شمار' ],
+ 'replace' => [ 0, 'جایگزین' ],
+ 'explode' => [ 0, 'گسترش' ],
+ 'urldecode' => [ 0, 'نشانی‌بی‌کد' ],
+];
+
+/** French (français) */
+$magicWords['fr'] = [
+ 'expr' => [ 0, 'expr' ],
+ 'if' => [ 0, 'si' ],
+ 'ifeq' => [ 0, 'si=' ],
+ 'ifexpr' => [ 0, 'siexpr' ],
+ 'iferror' => [ 0, 'sierreur' ],
+ 'switch' => [ 0, 'selon' ],
+ 'default' => [ 0, '#défaut' ],
+ 'ifexist' => [ 0, 'siexiste' ],
+ 'time' => [ 0, 'heure' ],
+ 'timel' => [ 0, 'heurel' ],
+ 'rel2abs' => [ 0, 'relenabs' ],
+ 'titleparts' => [ 0, 'partiestitre' ],
+ 'len' => [ 0, 'nbcar' ],
+ 'pos' => [ 0, 'pos' ],
+ 'rpos' => [ 0, 'posr' ],
+ 'sub' => [ 0, 'stxt' ],
+ 'count' => [ 0, 'nb' ],
+ 'replace' => [ 0, 'remplacer' ],
+ 'explode' => [ 0, 'exploser' ],
+ 'urldecode' => [ 0, 'décoderurl', 'decodeurl' ],
+];
+
+/** Western Frisian (Frysk) */
+$magicWords['fy'] = [
+ 'expr' => [ 0, 'ekspresje' ],
+ 'if' => [ 0, 'as' ],
+ 'ifeq' => [ 0, 'asgelyk' ],
+ 'ifexpr' => [ 0, 'asekspresje' ],
+ 'iferror' => [ 0, 'asflater' ],
+ 'switch' => [ 0, 'skeakelje' ],
+ 'default' => [ 0, '#standert' ],
+ 'ifexist' => [ 0, 'asbestiet' ],
+ 'time' => [ 0, 'tiid' ],
+ 'timel' => [ 0, 'tiidl' ],
+];
+
+/** Hebrew (עברית) */
+$magicWords['he'] = [
+ 'expr' => [ 0, 'חשב' ],
+ 'if' => [ 0, 'תנאי' ],
+ 'ifeq' => [ 0, 'שווה' ],
+ 'ifexpr' => [ 0, 'חשב תנאי' ],
+ 'iferror' => [ 0, 'תנאי שגיאה' ],
+ 'switch' => [ 0, 'בחר' ],
+ 'default' => [ 0, '#ברירת מחדל' ],
+ 'ifexist' => [ 0, 'קיים' ],
+ 'time' => [ 0, 'זמן' ],
+ 'timel' => [ 0, 'זמןמ' ],
+ 'rel2abs' => [ 0, 'יחסי למוחלט' ],
+ 'titleparts' => [ 0, 'חלק בכותרת' ],
+ 'count' => [ 0, 'מספר' ],
+];
+
+/** Hindi (हिन्दी) */
+$magicWords['hi'] = [
+ 'expr' => [ 0, 'सूत्र' ],
+ 'if' => [ 0, 'यदि' ],
+ 'ifeq' => [ 0, 'यदिसम', 'यदि_समान', 'यदि_बराबर' ],
+ 'ifexpr' => [ 0, 'यदि_सूत्र' ],
+ 'iferror' => [ 0, 'यदि_त्रुटि' ],
+ 'switch' => [ 0, 'बदलें' ],
+ 'default' => [ 0, '#मूल' ],
+ 'ifexist' => [ 0, 'यदि_मौजूद' ],
+ 'time' => [ 0, 'समय' ],
+ 'timel' => [ 0, 'समय_स्थानीय' ],
+ 'rel2abs' => [ 0, 'सम्बन्धित_से_पूर्ण', 'संबंधित_से_पूर्ण' ],
+ 'titleparts' => [ 0, 'शीर्षक_भाग' ],
+];
+
+/** Hungarian (magyar) */
+$magicWords['hu'] = [
+ 'expr' => [ 0, 'kif', 'expr' ],
+ 'if' => [ 0, 'ha', 'if' ],
+ 'ifeq' => [ 0, 'haegyenlő', 'ifeq' ],
+ 'ifexpr' => [ 0, 'hakif', 'ifexpr' ],
+ 'iferror' => [ 0, 'hahibás', 'iferror' ],
+ 'default' => [ 0, '#alapértelmezett', '#default' ],
+ 'ifexist' => [ 0, 'halétezik', 'ifexist' ],
+ 'time' => [ 0, 'idő', 'time' ],
+ 'len' => [ 0, 'hossz', 'len' ],
+ 'pos' => [ 0, 'pozíció', 'pos' ],
+ 'rpos' => [ 0, 'jpozíció', 'rpos' ],
+];
+
+/** Indonesian (Bahasa Indonesia) */
+$magicWords['id'] = [
+ 'expr' => [ 0, 'hitung' ],
+ 'if' => [ 0, 'jika' ],
+ 'ifeq' => [ 0, 'jikasama' ],
+ 'ifexpr' => [ 0, 'jikahitung' ],
+ 'iferror' => [ 0, 'jikasalah' ],
+ 'switch' => [ 0, 'pilih' ],
+ 'default' => [ 0, '#baku' ],
+ 'ifexist' => [ 0, 'jikaada' ],
+ 'time' => [ 0, 'waktu' ],
+ 'timel' => [ 0, 'waktu1' ],
+ 'titleparts' => [ 0, 'bagianjudul' ],
+];
+
+/** Igbo (Igbo) */
+$magicWords['ig'] = [
+ 'if' => [ 0, 'ȯ_bú', 'if' ],
+ 'time' => [ 0, 'ógè', 'time' ],
+ 'timel' => [ 0, 'ógèl', 'timel' ],
+];
+
+/** Italian (italiano) */
+$magicWords['it'] = [
+ 'expr' => [ 0, 'espr' ],
+ 'if' => [ 0, 'se' ],
+ 'ifeq' => [ 0, 'seeq' ],
+ 'ifexpr' => [ 0, 'seespr' ],
+ 'iferror' => [ 0, 'seerrore' ],
+ 'ifexist' => [ 0, 'seesiste' ],
+ 'time' => [ 0, 'tempo' ],
+ 'titleparts' => [ 0, 'patititolo' ],
+ 'count' => [ 0, 'conto' ],
+ 'replace' => [ 0, 'sostituisci' ],
+];
+
+/** Japanese (日本語) */
+$magicWords['ja'] = [
+ 'expr' => [ 0, '式' ],
+ 'if' => [ 0, 'もし' ],
+ 'ifeq' => [ 0, 'もし等しい' ],
+ 'ifexpr' => [ 0, 'もし式' ],
+ 'iferror' => [ 0, 'もしエラー' ],
+ 'switch' => [ 0, '切り替え' ],
+ 'default' => [ 0, '#既定' ],
+ 'ifexist' => [ 0, 'もし存在' ],
+ 'time' => [ 0, '時間' ],
+ 'timel' => [ 0, '時間地方' ],
+ 'rel2abs' => [ 0, '参照から絶対' ],
+ 'titleparts' => [ 0, 'タイトル部分' ],
+ 'len' => [ 0, '長さ' ],
+ 'pos' => [ 0, '位置' ],
+ 'rpos' => [ 0, '最後の位置' ],
+ 'sub' => [ 0, '切り取り' ],
+ 'count' => [ 0, '回数' ],
+ 'replace' => [ 0, '置き換え' ],
+ 'explode' => [ 0, '分割' ],
+ 'urldecode' => [ 0, 'URLデコード', 'URLデコード' ],
+];
+
+/** Georgian (ქართული) */
+$magicWords['ka'] = [
+ 'time' => [ 0, 'დრო' ],
+];
+
+/** Korean (한국어) */
+$magicWords['ko'] = [
+ 'expr' => [ 0, '수식' ],
+ 'if' => [ 0, '만약' ],
+ 'ifeq' => [ 0, '만약일치' ],
+ 'ifexpr' => [ 0, '만약계산' ],
+ 'iferror' => [ 0, '만약오류' ],
+ 'switch' => [ 0, '스위치' ],
+ 'default' => [ 0, '#기본값' ],
+ 'ifexist' => [ 0, '만약존재' ],
+ 'time' => [ 0, '시간' ],
+ 'timel' => [ 0, '현지시간' ],
+ 'rel2abs' => [ 0, '상대를절대로' ],
+ 'titleparts' => [ 0, '제목부분' ],
+ 'len' => [ 0, '길이' ],
+ 'pos' => [ 0, '위치' ],
+ 'rpos' => [ 0, '오른위치' ],
+ 'sub' => [ 0, '자르기' ],
+ 'count' => [ 0, '개수' ],
+ 'replace' => [ 0, '바꾸기', '교체' ],
+ 'explode' => [ 0, '분리' ],
+ 'urldecode' => [ 0, '주소디코딩:' ],
+];
+
+/** Kurdish (Latin script) (Kurdî (latînî)‎) */
+$magicWords['ku-latn'] = [
+ 'len' => [ 0, '#ziman' ],
+];
+
+/** Cornish (kernowek) */
+$magicWords['kw'] = [
+ 'if' => [ 0, 'mar' ],
+ 'time' => [ 0, 'termyn' ],
+];
+
+/** Ladino (Ladino) */
+$magicWords['lad'] = [
+ 'switch' => [ 0, 'asegún', 'según', 'switch' ],
+];
+
+/** Malagasy (Malagasy) */
+$magicWords['mg'] = [
+ 'if' => [ 0, 'raha', 'if' ],
+ 'ifeq' => [ 0, 'rahamitovy', 'ifeq' ],
+ 'ifexpr' => [ 0, 'rahamarina', 'ifexpr' ],
+ 'iferror' => [ 0, 'rahadiso', 'iferror' ],
+ 'default' => [ 0, '#tsipalotra', '#default' ],
+ 'ifexist' => [ 0, 'rahamisy', 'ifexist' ],
+ 'time' => [ 0, 'lera', 'time' ],
+];
+
+/** Macedonian (македонски) */
+$magicWords['mk'] = [
+ 'expr' => [ 0, 'израз' ],
+ 'if' => [ 0, 'ако' ],
+ 'ifeq' => [ 0, 'акоисто' ],
+ 'ifexpr' => [ 0, 'акоизраз' ],
+ 'iferror' => [ 0, 'акогрешка' ],
+ 'switch' => [ 0, 'префрли' ],
+ 'default' => [ 0, '#поосновно' ],
+ 'ifexist' => [ 0, 'акопостои' ],
+ 'time' => [ 0, 'време' ],
+ 'timel' => [ 0, 'времел' ],
+ 'rel2abs' => [ 0, 'релдоапс' ],
+ 'titleparts' => [ 0, 'насловделови' ],
+ 'len' => [ 0, 'долж' ],
+ 'pos' => [ 0, 'пол' ],
+ 'rpos' => [ 0, 'впол' ],
+ 'sub' => [ 0, 'зам' ],
+ 'count' => [ 0, 'сметај' ],
+ 'replace' => [ 0, 'замени' ],
+ 'explode' => [ 0, 'разложи' ],
+ 'urldecode' => [ 0, 'urlдекод' ],
+];
+
+/** Malayalam (മലയാളം) */
+$magicWords['ml'] = [
+ 'expr' => [ 0, 'ദ്യോതകം' ],
+ 'if' => [ 0, 'എങ്കിൽ' ],
+ 'ifeq' => [ 0, 'സമമെങ്കിൽ' ],
+ 'ifexpr' => [ 0, 'എക്സ്പ്രെഷനെങ്കിൽ' ],
+ 'iferror' => [ 0, 'പിഴവെങ്കിൽ' ],
+ 'switch' => [ 0, 'മാറ്റുക' ],
+ 'default' => [ 0, '#സ്വതേ' ],
+ 'ifexist' => [ 0, 'ഉണ്ടെങ്കിൽ' ],
+ 'time' => [ 0, 'സമയം' ],
+ 'timel' => [ 0, 'സമയം|' ],
+ 'len' => [ 0, 'നീളം' ],
+ 'pos' => [ 0, 'സ്ഥാനം' ],
+ 'rpos' => [ 0, 'ആപേക്ഷികസ്ഥാനം' ],
+ 'sub' => [ 0, 'ഉപം' ],
+ 'count' => [ 0, 'എണ്ണുക' ],
+ 'replace' => [ 0, 'മാറ്റിച്ചേർക്കുക' ],
+ 'explode' => [ 0, 'വിസ്ഫോടനം' ],
+ 'urldecode' => [ 0, 'വിലാസഗൂഢീകരണമൊഴിവാക്കൽ' ],
+];
+
+/** Marathi (मराठी) */
+$magicWords['mr'] = [
+ 'expr' => [ 0, 'करण' ],
+ 'if' => [ 0, 'जर', 'इफ' ],
+ 'ifeq' => [ 0, 'जरसम' ],
+ 'ifexpr' => [ 0, 'जरकरण' ],
+ 'iferror' => [ 0, 'जरत्रुटी' ],
+ 'switch' => [ 0, 'कळ', 'सांगकळ', 'असेलतरसांग', 'असलेतरसांग', 'स्वीच' ],
+ 'default' => [ 0, '#अविचल' ],
+ 'ifexist' => [ 0, 'जरअसेल', 'जरआहे' ],
+ 'time' => [ 0, 'वेळ' ],
+ 'timel' => [ 0, 'वेळस्था' ],
+ 'titleparts' => [ 0, 'शीर्षकखंड', 'टाइटलपार्ट्स' ],
+ 'len' => [ 0, 'लांबी' ],
+ 'pos' => [ 0, 'स्थशोध' ],
+ 'rpos' => [ 0, 'माग्चास्थशोध' ],
+ 'sub' => [ 0, 'उप' ],
+ 'count' => [ 0, 'मोज', 'मोजा' ],
+ 'replace' => [ 0, 'नेबदल', 'रिप्लेस' ],
+ 'explode' => [ 0, 'एकफोड' ],
+];
+
+/** Low Saxon (Netherlands) (Nedersaksies) */
+$magicWords['nds-nl'] = [
+ 'if' => [ 0, 'as' ],
+ 'ifeq' => [ 0, 'asgelieke' ],
+ 'ifexpr' => [ 0, 'asexpressie' ],
+ 'iferror' => [ 0, 'asfout' ],
+ 'default' => [ 0, '#standard' ],
+ 'ifexist' => [ 0, 'asbesteet' ],
+ 'time' => [ 0, 'tied' ],
+ 'timel' => [ 0, 'tiedl' ],
+ 'rel2abs' => [ 0, 'relatiefnaorabseluut' ],
+];
+
+/** Dutch (Nederlands) */
+$magicWords['nl'] = [
+ 'expr' => [ 0, 'expressie' ],
+ 'if' => [ 0, 'als' ],
+ 'ifeq' => [ 0, 'alsgelijk' ],
+ 'ifexpr' => [ 0, 'alsexpressie' ],
+ 'iferror' => [ 0, 'alsfout' ],
+ 'switch' => [ 0, 'schakelen' ],
+ 'default' => [ 0, '#standaard' ],
+ 'ifexist' => [ 0, 'alsbestaat' ],
+ 'time' => [ 0, 'tijd' ],
+ 'timel' => [ 0, 'tijdl' ],
+ 'rel2abs' => [ 0, 'relatiefnaarabsoluut' ],
+ 'titleparts' => [ 0, 'paginanaamdelen' ],
+ 'count' => [ 0, 'telling' ],
+ 'replace' => [ 0, 'vervangen' ],
+ 'explode' => [ 0, 'exploderen' ],
+ 'urldecode' => [ 0, 'urldecoderen' ],
+];
+
+/** Norwegian Nynorsk (norsk nynorsk) */
+$magicWords['nn'] = [
+ 'expr' => [ 0, 'uttrykk', 'uttr' ],
+ 'if' => [ 0, 'om' ],
+ 'ifeq' => [ 0, 'omlik' ],
+ 'ifexpr' => [ 0, 'omuttrykk', 'omuttr' ],
+ 'iferror' => [ 0, 'omfeil' ],
+ 'switch' => [ 0, 'byt' ],
+ 'ifexist' => [ 0, 'omfinst' ],
+ 'time' => [ 0, 'tid' ],
+ 'timel' => [ 0, 'tidl' ],
+ 'rel2abs' => [ 0, 'reltilabs' ],
+ 'titleparts' => [ 0, 'titteldelar' ],
+ 'len' => [ 0, 'lengd' ],
+ 'replace' => [ 0, 'byt_ut', 'erstatt' ],
+];
+
+/** Oriya (ଓଡ଼ିଆ) */
+$magicWords['or'] = [
+ 'time' => [ 0, 'ସମୟ' ],
+];
+
+/** Punjabi (ਪੰਜਾਬੀ) */
+$magicWords['pa'] = [
+ 'time' => [ 0, 'ਸਮੇ' ],
+];
+
+/** Pashto (پښتو) */
+$magicWords['ps'] = [
+ 'if' => [ 0, 'که', 'if' ],
+ 'time' => [ 0, 'وخت', 'time' ],
+ 'count' => [ 0, 'شمېرل', 'count' ],
+];
+
+/** Portuguese (português) */
+$magicWords['pt'] = [
+ 'if' => [ 0, 'se' ],
+ 'ifeq' => [ 0, 'seigual' ],
+ 'ifexpr' => [ 0, 'seexpr' ],
+ 'iferror' => [ 0, 'seerro' ],
+ 'default' => [ 0, '#padrão', '#padrao' ],
+ 'ifexist' => [ 0, 'seexiste' ],
+ 'titleparts' => [ 0, 'partesdotítulo', 'partesdotitulo' ],
+ 'len' => [ 0, 'comprimento' ],
+];
+
+/** Quechua (Runa Simi) */
+$magicWords['qu'] = [
+ 'expr' => [ 0, 'rikuchiy' ],
+ 'if' => [ 0, 'kaptin' ],
+ 'ifeq' => [ 0, 'kaqllakaptin' ],
+ 'ifexpr' => [ 0, 'rikuchiykaptin' ],
+ 'iferror' => [ 0, 'pantasqakaptin' ],
+ 'switch' => [ 0, 'winkuy' ],
+ 'default' => [ 0, '#kikinmanta' ],
+ 'ifexist' => [ 0, 'kachkaptin' ],
+ 'time' => [ 0, 'pacha' ],
+ 'timel' => [ 0, 'pachal' ],
+ 'len' => [ 0, 'suni' ],
+ 'pos' => [ 0, 'tiyay' ],
+ 'replace' => [ 0, 'rantichay', 'huknachay' ],
+ 'explode' => [ 0, 'phatmay' ],
+];
+
+/** Russian (русский) */
+$magicWords['ru'] = [
+ 'if' => [ 0, 'если' ],
+ 'iferror' => [ 0, 'еслиошибка' ],
+ 'switch' => [ 0, 'переключатель' ],
+ 'default' => [ 0, '#умолчание' ],
+ 'time' => [ 0, 'время' ],
+ 'timel' => [ 0, 'мвремя' ],
+ 'replace' => [ 0, 'замена' ],
+];
+
+/** Serbian (Cyrillic script) (српски (ћирилица)‎) */
+$magicWords['sr-ec'] = [
+ 'default' => [ 0, '#подразумевано' ],
+ 'time' => [ 0, 'време' ],
+ 'pos' => [ 0, 'поз' ],
+ 'count' => [ 0, 'број' ],
+ 'replace' => [ 0, 'замени' ],
+];
+
+/** Swedish (svenska) */
+$magicWords['sv'] = [
+ 'expr' => [ 0, 'utr', 'expr' ],
+ 'if' => [ 0, 'om', 'if' ],
+ 'ifeq' => [ 0, 'omlika', 'ifeq' ],
+ 'ifexpr' => [ 0, 'omutr', 'ifexpr' ],
+ 'iferror' => [ 0, 'omfel', 'iferror' ],
+ 'switch' => [ 0, 'växel', 'switch' ],
+ 'default' => [ 0, '#standard', '#default' ],
+ 'ifexist' => [ 0, 'omfinns', 'ifexist' ],
+ 'time' => [ 0, 'tid', 'time' ],
+ 'timel' => [ 0, 'tidl', 'timel' ],
+ 'replace' => [ 0, 'ersätt', 'replace' ],
+ 'explode' => [ 0, 'explodera', 'explode' ],
+];
+
+/** Tamil (தமிழ்) */
+$magicWords['ta'] = [
+ 'count' => [ 0, 'எண்ணிக்கை' ],
+];
+
+/** Turkish (Türkçe) */
+$magicWords['tr'] = [
+ 'expr' => [ 0, 'işlem', 'islem', 'ifade' ],
+ 'if' => [ 0, 'eğer', 'eger' ],
+ 'switch' => [ 0, 'değiştir', 'degistir' ],
+ 'default' => [ 0, '#vas' ],
+];
+
+/** Ukrainian (українська) */
+$magicWords['uk'] = [
+ 'expr' => [ 0, 'вираз' ],
+ 'if' => [ 0, 'якщо', 'если' ],
+ 'ifeq' => [ 0, 'якщорівні', 'рівні' ],
+ 'ifexpr' => [ 0, 'якщовираз' ],
+ 'iferror' => [ 0, 'якщопомилка', 'еслиошибка' ],
+ 'switch' => [ 0, 'вибірка', 'переключатель' ],
+ 'default' => [ 0, '#інакше', '#за_замовчуванням', '#умолчание' ],
+ 'ifexist' => [ 0, 'якщоіснує' ],
+ 'replace' => [ 0, 'заміна', 'замена' ],
+];
+
+/** Urdu (اردو) */
+$magicWords['ur'] = [
+ 'expr' => [ 0, 'اظہار' ],
+ 'if' => [ 0, 'اگر' ],
+ 'ifeq' => [ 0, 'اگربرابر' ],
+ 'ifexpr' => [ 0, 'اگراظہار' ],
+ 'iferror' => [ 0, 'اگرنقص' ],
+ 'switch' => [ 0, 'منتقل' ],
+ 'default' => [ 0, '#ابتدائی' ],
+ 'ifexist' => [ 0, 'اگرموجود' ],
+ 'time' => [ 0, 'وقت' ],
+ 'timel' => [ 0, 'وقت_لمبائی' ],
+ 'rel2abs' => [ 0, 'اضافی_تا_مطلق' ],
+ 'titleparts' => [ 0, 'اجزاء_عنوان' ],
+ 'len' => [ 0, 'لمبائی' ],
+ 'pos' => [ 0, 'جگہ' ],
+ 'rpos' => [ 0, 'جگہ_واپس' ],
+ 'sub' => [ 0, 'ذیلی' ],
+ 'count' => [ 0, 'شمار' ],
+ 'replace' => [ 0, 'تبدیلی' ],
+ 'explode' => [ 0, 'انتشار' ],
+ 'urldecode' => [ 0, 'بلاکوڈیوآرایل' ],
+];
+
+/** Uzbek (oʻzbekcha/ўзбекча) */
+$magicWords['uz'] = [
+ 'expr' => [ 0, 'ifoda' ],
+ 'if' => [ 0, 'agar' ],
+ 'ifeq' => [ 0, 'agarteng' ],
+ 'ifexpr' => [ 0, 'agarifoda' ],
+ 'iferror' => [ 0, 'agarxato' ],
+ 'switch' => [ 0, 'tanlov' ],
+ 'default' => [ 0, '#boshlangʻich' ],
+ 'ifexist' => [ 0, 'agarbor' ],
+ 'time' => [ 0, 'vaqt' ],
+ 'len' => [ 0, 'uzunlik' ],
+ 'pos' => [ 0, 'oʻrin' ],
+ 'count' => [ 0, 'miqdor' ],
+ 'replace' => [ 0, 'almashtirish' ],
+];
+
+/** Vietnamese (Tiếng Việt) */
+$magicWords['vi'] = [
+ 'expr' => [ 0, 'công_thức', 'côngthức' ],
+ 'if' => [ 0, 'nếu' ],
+ 'ifeq' => [ 0, 'nếu_bằng', 'nếubằng' ],
+ 'ifexpr' => [ 0, 'nếu_công_thức', 'nếucôngthức' ],
+ 'iferror' => [ 0, 'nếu_lỗi', 'nếulỗi' ],
+ 'default' => [ 0, '#mặc_định', '#mặcđịnh' ],
+ 'ifexist' => [ 0, 'nếu_tồn_tại', 'nếutồntại' ],
+ 'time' => [ 0, 'giờ' ],
+ 'timel' => [ 0, 'giờ_địa_phương', 'giờđịaphương' ],
+ 'len' => [ 0, 'số_chữ', 'sốchữ', 'số_ký_tự', 'sốkýtự', 'số_kí_tự', 'sốkítự' ],
+ 'pos' => [ 0, 'vị_trí', 'vịtrí' ],
+ 'rpos' => [ 0, 'vị_trí_phải', 'vịtríphải' ],
+ 'sub' => [ 0, 'chuỗi_con', 'chuỗicon' ],
+ 'count' => [ 0, 'số' ],
+ 'replace' => [ 0, 'thay_thế', 'thaythế' ],
+ 'urldecode' => [ 0, 'giải_mã_url', 'giảimãurl' ],
+];
+
+/** Yiddish (ייִדיש) */
+$magicWords['yi'] = [
+ 'expr' => [ 0, 'רעכן' ],
+ 'if' => [ 0, 'תנאי' ],
+ 'ifeq' => [ 0, 'גלייך' ],
+ 'ifexpr' => [ 0, 'אויברעכן' ],
+ 'switch' => [ 0, 'קלייב' ],
+ 'default' => [ 0, '#גרונט' ],
+ 'ifexist' => [ 0, 'עקזיסט' ],
+ 'time' => [ 0, 'צייט' ],
+ 'timel' => [ 0, 'צייטל' ],
+ 'count' => [ 0, 'צאל' ],
+];
+
+/** Chinese (中文) */
+$magicWords['zh'] = [
+ 'expr' => [ 0, '计算式' ],
+ 'if' => [ 0, '非空式' ],
+ 'ifeq' => [ 0, '相同式', '匹配式' ],
+ 'iferror' => [ 0, '错误式' ],
+ 'switch' => [ 0, '多选式', '多条件式', '双射式' ],
+ 'default' => [ 0, '#默认' ],
+ 'ifexist' => [ 0, '存在式' ],
+ 'len' => [ 0, '长度' ],
+ 'pos' => [ 0, '位置' ],
+ 'rpos' => [ 0, '最近位置' ],
+ 'sub' => [ 0, '截取' ],
+ 'count' => [ 0, '计数' ],
+ 'replace' => [ 0, '替换' ],
+ 'explode' => [ 0, '爆炸', '炸开' ],
+];
+
+/** Simplified Chinese (中文(简体)‎) */
+$magicWords['zh-hans'] = [
+ 'expr' => [ 0, '表达式' ],
+ 'if' => [ 0, '若', '如果' ],
+ 'ifeq' => [ 0, '若相等', '如果相等' ],
+ 'ifexpr' => [ 0, '若表达式' ],
+ 'iferror' => [ 0, '如果错误' ],
+ 'switch' => [ 0, '开关', '转换' ],
+ 'default' => [ 0, '#默认' ],
+ 'ifexist' => [ 0, '若有', '如有' ],
+ 'time' => [ 0, '时间' ],
+ 'timel' => [ 0, '时间l' ],
+ 'titleparts' => [ 0, '标题组成部分' ],
+ 'len' => [ 0, '长度' ],
+ 'pos' => [ 0, '终端' ],
+ 'rpos' => [ 0, '反终端' ],
+ 'sub' => [ 0, 'PF子' ],
+ 'count' => [ 0, '计数' ],
+ 'replace' => [ 0, '取代' ],
+ 'explode' => [ 0, '粉碎' ],
+ 'urldecode' => [ 0, 'url解码' ],
+];
+
+/** Traditional Chinese (中文(繁體)‎) */
+$magicWords['zh-hant'] = [
+ 'expr' => [ 0, '表達式' ],
+ 'if' => [ 0, '若' ],
+ 'ifexpr' => [ 0, '若表達式' ],
+ 'iferror' => [ 0, '如果錯誤' ],
+ 'switch' => [ 0, '轉換' ],
+ 'default' => [ 0, '#默認' ],
+ 'time' => [ 0, '時間' ],
+ 'timel' => [ 0, '時間L' ],
+ 'len' => [ 0, '長度' ],
+ 'count' => [ 0, '計算' ],
+ 'urldecode' => [ 0, 'URI解碼' ],
+];
diff --git a/www/wiki/extensions/ParserFunctions/ParserFunctions.library.php b/www/wiki/extensions/ParserFunctions/ParserFunctions.library.php
new file mode 100644
index 00000000..7dc7c598
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/ParserFunctions.library.php
@@ -0,0 +1,23 @@
+<?php
+
+class Scribunto_LuaParserFunctionsLibrary extends Scribunto_LuaLibraryBase {
+ public function register() {
+ $lib = [
+ 'expr' => [ $this, 'expr' ],
+ ];
+
+ return $this->getEngine()->registerInterface(
+ __DIR__ . '/mw.ext.ParserFunctions.lua', $lib, []
+ );
+ }
+
+ public function expr( $expression = null ) {
+ $this->checkType( 'mw.ext.ParserFunctions.expr', 1, $expression, 'string' );
+ try {
+ return [ ExtParserFunctions::getExprParser()->doExpression( $expression ) ];
+ } catch ( ExprError $e ) {
+ throw new Scribunto_LuaError( $e->getMessage() );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/ParserFunctions/ParserFunctions.php b/www/wiki/extensions/ParserFunctions/ParserFunctions.php
new file mode 100644
index 00000000..ea526bd8
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/ParserFunctions.php
@@ -0,0 +1,16 @@
+<?php
+
+if ( function_exists( 'wfLoadExtension' ) ) {
+ wfLoadExtension( 'ParserFunctions' );
+ // Keep i18n globals so mergeMessageFileList.php doesn't break
+ $wgMessagesDirs['ParserFunctions'] = __DIR__ . '/i18n';
+ $wgExtensionMessagesFiles['ParserFunctionsMagic'] = __DIR__ . '/ParserFunctions.i18n.magic.php';
+ /* wfWarn(
+ 'Deprecated PHP entry point used for ParserFunctions extension. ' .
+ 'Please use wfLoadExtension instead, ' .
+ 'see https://www.mediawiki.org/wiki/Extension_registration for more details.'
+ ); */
+ return true;
+} else {
+ die( 'This version of the ParserFunctions extension requires MediaWiki 1.25+' );
+}
diff --git a/www/wiki/extensions/ParserFunctions/ParserFunctions_body.php b/www/wiki/extensions/ParserFunctions/ParserFunctions_body.php
new file mode 100644
index 00000000..a28604bb
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/ParserFunctions_body.php
@@ -0,0 +1,891 @@
+<?php
+
+class ExtParserFunctions {
+ public static $mExprParser;
+ public static $mTimeCache = [];
+ public static $mTimeChars = 0;
+ public static $mMaxTimeChars = 6000; # ~10 seconds
+
+ /**
+ * @param $parser Parser
+ * @return bool
+ */
+ public static function clearState( $parser ) {
+ self::$mTimeChars = 0;
+ return true;
+ }
+
+ /**
+ * Register ParserClearState hook.
+ * We defer this until needed to avoid the loading of the code of this file
+ * when no parser function is actually called.
+ */
+ public static function registerClearHook() {
+ static $done = false;
+ if ( !$done ) {
+ global $wgHooks;
+ $wgHooks['ParserClearState'][] = __CLASS__ . '::clearState';
+ $done = true;
+ }
+ }
+
+ /**
+ * @return ExprParser
+ */
+ public static function &getExprParser() {
+ if ( !isset( self::$mExprParser ) ) {
+ self::$mExprParser = new ExprParser;
+ }
+ return self::$mExprParser;
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $expr string
+ * @return string
+ */
+ public static function expr( $parser, $expr = '' ) {
+ try {
+ return self::getExprParser()->doExpression( $expr );
+ } catch ( ExprError $e ) {
+ return '<strong class="error">' . htmlspecialchars( $e->getMessage() ) . '</strong>';
+ }
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $expr string
+ * @param $then string
+ * @param $else string
+ * @return string
+ */
+ public static function ifexpr( $parser, $expr = '', $then = '', $else = '' ) {
+ try {
+ $ret = self::getExprParser()->doExpression( $expr );
+ if ( is_numeric( $ret ) ) {
+ $ret = (float)$ret;
+ }
+ if ( $ret ) {
+ return $then;
+ } else {
+ return $else;
+ }
+ } catch ( ExprError $e ) {
+ return '<strong class="error">' . htmlspecialchars( $e->getMessage() ) . '</strong>';
+ }
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $args array
+ * @return string
+ */
+ public static function ifexprObj( $parser, $frame, $args ) {
+ $expr = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $then = isset( $args[1] ) ? $args[1] : '';
+ $else = isset( $args[2] ) ? $args[2] : '';
+ $result = self::ifexpr( $parser, $expr, $then, $else );
+ if ( is_object( $result ) ) {
+ $result = trim( $frame->expand( $result ) );
+ }
+ return $result;
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $args array
+ * @return string
+ */
+ public static function ifObj( $parser, $frame, $args ) {
+ $test = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ if ( $test !== '' ) {
+ return isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : '';
+ } else {
+ return isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '';
+ }
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $args array
+ * @return string
+ */
+ public static function ifeqObj( $parser, $frame, $args ) {
+ $left = isset( $args[0] ) ? self::decodeTrimExpand( $args[0], $frame ) : '';
+ $right = isset( $args[1] ) ? self::decodeTrimExpand( $args[1], $frame ) : '';
+
+ // Strict compare is not possible here. 01 should equal 1 for example.
+ /** @noinspection TypeUnsafeComparisonInspection */
+ if ( $left == $right ) {
+ return isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '';
+ } else {
+ return isset( $args[3] ) ? trim( $frame->expand( $args[3] ) ) : '';
+ }
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $test string
+ * @param $then string
+ * @param $else bool
+ * @return bool|string
+ */
+ public static function iferror( $parser, $test = '', $then = '', $else = false ) {
+ if ( preg_match(
+ '/<(?:strong|span|p|div)\s(?:[^\s>]*\s+)*?class="(?:[^"\s>]*\s+)*?error(?:\s[^">]*)?"/',
+ $test )
+ ) {
+ return $then;
+ } elseif ( $else === false ) {
+ return $test;
+ } else {
+ return $else;
+ }
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $args array
+ * @return string
+ */
+ public static function iferrorObj( $parser, $frame, $args ) {
+ $test = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $then = isset( $args[1] ) ? $args[1] : false;
+ $else = isset( $args[2] ) ? $args[2] : false;
+ $result = self::iferror( $parser, $test, $then, $else );
+ if ( $result === false ) {
+ return '';
+ } else {
+ return trim( $frame->expand( $result ) );
+ }
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $args
+ * @return string
+ */
+ public static function switchObj( $parser, $frame, $args ) {
+ if ( count( $args ) === 0 ) {
+ return '';
+ }
+ $primary = self::decodeTrimExpand( array_shift( $args ), $frame );
+ $found = $defaultFound = false;
+ $default = null;
+ $lastItemHadNoEquals = false;
+ $lastItem = '';
+ $mwDefault =& MagicWord::get( 'default' );
+ foreach ( $args as $arg ) {
+ $bits = $arg->splitArg();
+ $nameNode = $bits['name'];
+ $index = $bits['index'];
+ $valueNode = $bits['value'];
+
+ if ( $index === '' ) {
+ # Found "="
+ $lastItemHadNoEquals = false;
+ if ( $found ) {
+ # Multiple input match
+ return trim( $frame->expand( $valueNode ) );
+ } else {
+ $test = self::decodeTrimExpand( $nameNode, $frame );
+ /** @noinspection TypeUnsafeComparisonInspection */
+ if ( $test == $primary ) {
+ # Found a match, return now
+ return trim( $frame->expand( $valueNode ) );
+ } elseif ( $defaultFound || $mwDefault->matchStartToEnd( $test ) ) {
+ $default = $valueNode;
+ $defaultFound = false;
+ } # else wrong case, continue
+ }
+ } else {
+ # Multiple input, single output
+ # If the value matches, set a flag and continue
+ $lastItemHadNoEquals = true;
+ // $lastItem is an "out" variable
+ $decodedTest = self::decodeTrimExpand( $valueNode, $frame, $lastItem );
+ /** @noinspection TypeUnsafeComparisonInspection */
+ if ( $decodedTest == $primary ) {
+ $found = true;
+ } elseif ( $mwDefault->matchStartToEnd( $decodedTest ) ) {
+ $defaultFound = true;
+ }
+ }
+ }
+ # Default case
+ # Check if the last item had no = sign, thus specifying the default case
+ if ( $lastItemHadNoEquals ) {
+ return $lastItem;
+ } elseif ( !is_null( $default ) ) {
+ return trim( $frame->expand( $default ) );
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Returns the absolute path to a subpage, relative to the current article
+ * title. Treats titles as slash-separated paths.
+ *
+ * Following subpage link syntax instead of standard path syntax, an
+ * initial slash is treated as a relative path, and vice versa.
+ *
+ * @param $parser Parser
+ * @param $to string
+ * @param $from string
+ *
+ * @return string
+ */
+ public static function rel2abs( $parser , $to = '' , $from = '' ) {
+ $from = trim( $from );
+ if ( $from === '' ) {
+ $from = $parser->getTitle()->getPrefixedText();
+ }
+
+ $to = rtrim( $to, ' /' );
+
+ // if we have an empty path, or just one containing a dot
+ if ( $to === '' || $to === '.' ) {
+ return $from;
+ }
+
+ // if the path isn't relative
+ if ( substr( $to, 0, 1 ) !== '/' &&
+ substr( $to, 0, 2 ) !== './' &&
+ substr( $to, 0, 3 ) !== '../' &&
+ $to !== '..'
+ ) {
+ $from = '';
+ }
+ // Make a long path, containing both, enclose it in /.../
+ $fullPath = '/' . $from . '/' . $to . '/';
+
+ // remove redundant current path dots
+ $fullPath = preg_replace( '!/(\./)+!', '/', $fullPath );
+
+ // remove double slashes
+ $fullPath = preg_replace( '!/{2,}!', '/', $fullPath );
+
+ // remove the enclosing slashes now
+ $fullPath = trim( $fullPath, '/' );
+ $exploded = explode( '/', $fullPath );
+ $newExploded = [];
+
+ foreach ( $exploded as $current ) {
+ if ( $current === '..' ) { // removing one level
+ if ( !count( $newExploded ) ) {
+ // attempted to access a node above root node
+ $msg = wfMessage( 'pfunc_rel2abs_invalid_depth', $fullPath )
+ ->inContentLanguage()->escaped();
+ return '<strong class="error">' . $msg . '</strong>';
+ }
+ // remove last level from the stack
+ array_pop( $newExploded );
+ } else {
+ // add the current level to the stack
+ $newExploded[] = $current;
+ }
+ }
+
+ // we can now join it again
+ return implode( '/', $newExploded );
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $titletext string
+ * @param $then string
+ * @param $else string
+ *
+ * @return string
+ */
+ public static function ifexistCommon(
+ $parser, $frame, $titletext = '', $then = '', $else = ''
+ ) {
+ global $wgContLang;
+ $title = Title::newFromText( $titletext );
+ $wgContLang->findVariantLink( $titletext, $title, true );
+ if ( $title ) {
+ if ( $title->getNamespace() === NS_MEDIA ) {
+ /* If namespace is specified as NS_MEDIA, then we want to
+ * check the physical file, not the "description" page.
+ */
+ if ( !$parser->incrementExpensiveFunctionCount() ) {
+ return $else;
+ }
+ $file = wfFindFile( $title );
+ if ( !$file ) {
+ return $else;
+ }
+ $parser->mOutput->addImage(
+ $file->getName(), $file->getTimestamp(), $file->getSha1() );
+ return $file->exists() ? $then : $else;
+ } elseif ( $title->getNamespace() === NS_SPECIAL ) {
+ /* Don't bother with the count for special pages,
+ * since their existence can be checked without
+ * accessing the database.
+ */
+ return SpecialPageFactory::exists( $title->getDBkey() ) ? $then : $else;
+ } elseif ( $title->isExternal() ) {
+ /* Can't check the existence of pages on other sites,
+ * so just return $else. Makes a sort of sense, since
+ * they don't exist _locally_.
+ */
+ return $else;
+ } else {
+ $pdbk = $title->getPrefixedDBkey();
+ $lc = LinkCache::singleton();
+ $id = $lc->getGoodLinkID( $pdbk );
+ if ( $id !== 0 ) {
+ $parser->mOutput->addLink( $title, $id );
+ return $then;
+ } elseif ( $lc->isBadLink( $pdbk ) ) {
+ $parser->mOutput->addLink( $title, 0 );
+ return $else;
+ }
+ if ( !$parser->incrementExpensiveFunctionCount() ) {
+ return $else;
+ }
+ $id = $title->getArticleID();
+ $parser->mOutput->addLink( $title, $id );
+
+ // bug 70495: don't just check whether the ID != 0
+ if ( $title->exists() ) {
+ return $then;
+ }
+ }
+ }
+ return $else;
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $args array
+ * @return string
+ */
+ public static function ifexistObj( $parser, $frame, $args ) {
+ $title = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $then = isset( $args[1] ) ? $args[1] : null;
+ $else = isset( $args[2] ) ? $args[2] : null;
+
+ $result = self::ifexistCommon( $parser, $frame, $title, $then, $else );
+ if ( $result === null ) {
+ return '';
+ } else {
+ return trim( $frame->expand( $result ) );
+ }
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $format string
+ * @param $date string
+ * @param $language string
+ * @param $local string|bool
+ * @return string
+ */
+ public static function timeCommon(
+ $parser, $frame = null, $format = '', $date = '', $language = '', $local = false
+ ) {
+ global $wgLocaltimezone;
+ self::registerClearHook();
+ if ( $date === '' ) {
+ $cacheKey = $parser->getOptions()->getTimestamp();
+ $timestamp = new MWTimestamp( $cacheKey );
+ $date = $timestamp->getTimestamp( TS_ISO_8601 );
+ $useTTL = true;
+ } else {
+ $cacheKey = $date;
+ $useTTL = false;
+ }
+ if ( isset( self::$mTimeCache[$format][$cacheKey][$language][$local] ) ) {
+ $cachedVal = self::$mTimeCache[$format][$cacheKey][$language][$local];
+ if ( $useTTL
+ && $cachedVal[1] !== null && $frame && is_callable( [ $frame, 'setTTL' ] )
+ ) {
+ $frame->setTTL( $cachedVal[1] );
+ }
+ return $cachedVal[0];
+ }
+
+ # compute the timestamp string $ts
+ # PHP >= 5.2 can handle dates before 1970 or after 2038 using the DateTime object
+
+ $invalidTime = false;
+
+ # the DateTime constructor must be used because it throws exceptions
+ # when errors occur, whereas date_create appears to just output a warning
+ # that can't really be detected from within the code
+ try {
+
+ # Default input timezone is UTC.
+ $utc = new DateTimeZone( 'UTC' );
+
+ # Correct for DateTime interpreting 'XXXX' as XX:XX o'clock
+ if ( preg_match( '/^[0-9]{4}$/', $date ) ) {
+ $date = '00:00 '.$date;
+ }
+
+ # Parse date
+ # UTC is a default input timezone.
+ $dateObject = new DateTime( $date, $utc );
+
+ # Set output timezone.
+ if ( $local ) {
+ if ( isset( $wgLocaltimezone ) ) {
+ $tz = new DateTimeZone( $wgLocaltimezone );
+ } else {
+ $tz = new DateTimeZone( date_default_timezone_get() );
+ }
+ } else {
+ $tz = $utc;
+ }
+ $dateObject->setTimezone( $tz );
+ # Generate timestamp
+ $ts = $dateObject->format( 'YmdHis' );
+
+ } catch ( Exception $ex ) {
+ $invalidTime = true;
+ }
+
+ $ttl = null;
+ # format the timestamp and return the result
+ if ( $invalidTime ) {
+ $result = '<strong class="error">' .
+ wfMessage( 'pfunc_time_error' )->inContentLanguage()->escaped() .
+ '</strong>';
+ } else {
+ self::$mTimeChars += strlen( $format );
+ if ( self::$mTimeChars > self::$mMaxTimeChars ) {
+ return '<strong class="error">' .
+ wfMessage( 'pfunc_time_too_long' )->inContentLanguage()->escaped() .
+ '</strong>';
+ } else {
+ if ( $ts < 0 ) { // Language can't deal with BC years
+ return '<strong class="error">' .
+ wfMessage( 'pfunc_time_too_small' )->inContentLanguage()->escaped() .
+ '</strong>';
+ } elseif ( $ts < 100000000000000 ) { // Language can't deal with years after 9999
+ if ( $language !== '' && Language::isValidBuiltInCode( $language ) ) {
+ // use whatever language is passed as a parameter
+ $langObject = Language::factory( $language );
+ } else {
+ // use wiki's content language
+ $langObject = $parser->getFunctionLang();
+ // $ttl is passed by reference, which doesn't work right on stub objects
+ StubObject::unstub( $langObject );
+ }
+ $result = $langObject->sprintfDate( $format, $ts, $tz, $ttl );
+ } else {
+ return '<strong class="error">' .
+ wfMessage( 'pfunc_time_too_big' )->inContentLanguage()->escaped() .
+ '</strong>';
+ }
+ }
+ }
+ self::$mTimeCache[$format][$cacheKey][$language][$local] = [ $result, $ttl ];
+ if ( $useTTL && $ttl !== null && $frame && is_callable( [ $frame, 'setTTL' ] ) ) {
+ $frame->setTTL( $ttl );
+ }
+ return $result;
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $format string
+ * @param $date string
+ * @param $language string
+ * @param $local string|bool
+ * @return string
+ */
+ public static function time(
+ $parser, $format = '', $date = '', $language = '', $local = false
+ ) {
+ return self::timeCommon( $parser, null, $format, $date, $language, $local );
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $args array
+ * @return string
+ */
+ public static function timeObj( $parser, $frame, $args ) {
+ $format = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $date = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : '';
+ $language = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '';
+ $local = isset( $args[3] ) && trim( $frame->expand( $args[3] ) );
+ return self::timeCommon( $parser, $frame, $format, $date, $language, $local );
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $format string
+ * @param $date string
+ * @param $language string
+ * @return string
+ */
+ public static function localTime( $parser, $format = '', $date = '', $language = '' ) {
+ return self::timeCommon( $parser, null, $format, $date, $language, true );
+ }
+
+ /**
+ * @param $parser Parser
+ * @param $frame PPFrame
+ * @param $args array
+ * @return string
+ */
+ public static function localTimeObj( $parser, $frame, $args ) {
+ $format = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $date = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : '';
+ $language = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '';
+ return self::timeCommon( $parser, $frame, $format, $date, $language, true );
+ }
+
+ /**
+ * Obtain a specified number of slash-separated parts of a title,
+ * e.g. {{#titleparts:Hello/World|1}} => "Hello"
+ *
+ * @param $parser Parser Parent parser
+ * @param $title string Title to split
+ * @param $parts int Number of parts to keep
+ * @param $offset int Offset starting at 1
+ * @return string
+ */
+ public static function titleparts( $parser, $title = '', $parts = 0, $offset = 0 ) {
+ $parts = (int)$parts;
+ $offset = (int)$offset;
+ $ntitle = Title::newFromText( $title );
+ if ( $ntitle instanceof Title ) {
+ $bits = explode( '/', $ntitle->getPrefixedText(), 25 );
+ if ( count( $bits ) <= 0 ) {
+ return $ntitle->getPrefixedText();
+ } else {
+ if ( $offset > 0 ) {
+ --$offset;
+ }
+ if ( $parts === 0 ) {
+ return implode( '/', array_slice( $bits, $offset ) );
+ } else {
+ return implode( '/', array_slice( $bits, $offset, $parts ) );
+ }
+ }
+ } else {
+ return $title;
+ }
+ }
+
+ /**
+ * Verifies parameter is less than max string length.
+ * @param $text
+ * @return bool
+ */
+ private static function checkLength( $text ) {
+ global $wgPFStringLengthLimit;
+ return ( mb_strlen( $text ) < $wgPFStringLengthLimit );
+ }
+
+ /**
+ * Generates error message. Called when string is too long.
+ * @return string
+ */
+ private static function tooLongError() {
+ global $wgPFStringLengthLimit;
+ $msg = wfMessage( 'pfunc_string_too_long' )->numParams( $wgPFStringLengthLimit );
+ return '<strong class="error">' . $msg->inContentLanguage()->escaped() . '</strong>';
+ }
+
+ /**
+ * {{#len:string}}
+ *
+ * Reports number of characters in string.
+ * @param $parser Parser
+ * @param $inStr string
+ * @return int
+ */
+ public static function runLen( $parser, $inStr = '' ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ return mb_strlen( $inStr );
+ }
+
+ /**
+ * {{#pos: string | needle | offset}}
+ *
+ * Finds first occurrence of "needle" in "string" starting at "offset".
+ *
+ * Note: If the needle is an empty string, single space is used instead.
+ * Note: If the needle is not found, empty string is returned.
+ * @param $parser Parser
+ * @param $inStr string
+ * @param $inNeedle int|string
+ * @param $inOffset int
+ * @return int|string
+ */
+ public static function runPos( $parser, $inStr = '', $inNeedle = '', $inOffset = 0 ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inNeedle = $parser->killMarkers( (string)$inNeedle );
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inNeedle ) ) {
+ return self::tooLongError();
+ }
+
+ if ( $inNeedle === '' ) {
+ $inNeedle = ' ';
+ }
+
+ $pos = mb_strpos( $inStr, $inNeedle, (int)$inOffset );
+ if ( $pos === false ) {
+ $pos = '';
+ }
+
+ return $pos;
+ }
+
+ /**
+ * {{#rpos: string | needle}}
+ *
+ * Finds last occurrence of "needle" in "string".
+ *
+ * Note: If the needle is an empty string, single space is used instead.
+ * Note: If the needle is not found, -1 is returned.
+ * @param $parser Parser
+ * @param $inStr string
+ * @param $inNeedle int|string
+ * @return int|string
+ */
+ public static function runRPos( $parser, $inStr = '', $inNeedle = '' ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inNeedle = $parser->killMarkers( (string)$inNeedle );
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inNeedle ) ) {
+ return self::tooLongError();
+ }
+
+ if ( $inNeedle === '' ) {
+ $inNeedle = ' ';
+ }
+
+ $pos = mb_strrpos( $inStr, $inNeedle );
+ if ( $pos === false ) {
+ $pos = -1;
+ }
+
+ return $pos;
+ }
+
+ /**
+ * {{#sub: string | start | length }}
+ *
+ * Returns substring of "string" starting at "start" and having
+ * "length" characters.
+ *
+ * Note: If length is zero, the rest of the input is returned.
+ * Note: A negative value for "start" operates from the end of the
+ * "string".
+ * Note: A negative value for "length" returns a string reduced in
+ * length by that amount.
+ *
+ * @param $parser Parser
+ * @param $inStr string
+ * @param $inStart int
+ * @param $inLength int
+ * @return string
+ */
+ public static function runSub( $parser, $inStr = '', $inStart = 0, $inLength = 0 ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+
+ if ( !self::checkLength( $inStr ) ) {
+ return self::tooLongError();
+ }
+
+ if ( (int)$inLength === 0 ) {
+ $result = mb_substr( $inStr, (int)$inStart );
+ } else {
+ $result = mb_substr( $inStr, (int)$inStart, (int)$inLength );
+ }
+
+ return $result;
+ }
+
+ /**
+ * {{#count: string | substr }}
+ *
+ * Returns number of occurrences of "substr" in "string".
+ *
+ * Note: If "substr" is empty, a single space is used.
+ * @param $parser Parser
+ * @param $inStr string
+ * @param $inSubStr string
+ * @return int|string
+ */
+ public static function runCount( $parser, $inStr = '', $inSubStr = '' ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inSubStr = $parser->killMarkers( (string)$inSubStr );
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inSubStr ) ) {
+ return self::tooLongError();
+ }
+
+ if ( $inSubStr === '' ) {
+ $inSubStr = ' ';
+ }
+
+ $result = mb_substr_count( $inStr, $inSubStr );
+
+ return $result;
+ }
+
+ /**
+ * {{#replace:string | from | to | limit }}
+ *
+ * Replaces each occurrence of "from" in "string" with "to".
+ * At most "limit" replacements are performed.
+ *
+ * Note: Armored against replacements that would generate huge strings.
+ * Note: If "from" is an empty string, single space is used instead.
+ * @param $parser Parser
+ * @param $inStr string
+ * @param $inReplaceFrom string
+ * @param $inReplaceTo string
+ * @param $inLimit int
+ * @return mixed|string
+ */
+ public static function runReplace( $parser, $inStr = '',
+ $inReplaceFrom = '', $inReplaceTo = '', $inLimit = -1 ) {
+ global $wgPFStringLengthLimit;
+
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inReplaceFrom = $parser->killMarkers( (string)$inReplaceFrom );
+ $inReplaceTo = $parser->killMarkers( (string)$inReplaceTo );
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inReplaceFrom ) ||
+ !self::checkLength( $inReplaceTo ) ) {
+ return self::tooLongError();
+ }
+
+ if ( $inReplaceFrom === '' ) {
+ $inReplaceFrom = ' ';
+ }
+
+ // Precompute limit to avoid generating enormous string:
+ $diff = mb_strlen( $inReplaceTo ) - mb_strlen( $inReplaceFrom );
+ if ( $diff > 0 ) {
+ $limit = ( ( $wgPFStringLengthLimit - mb_strlen( $inStr ) ) / $diff ) + 1;
+ } else {
+ $limit = -1;
+ }
+
+ $inLimit = (int)$inLimit;
+ if ( $inLimit >= 0 ) {
+ if ( $limit > $inLimit || $limit == -1 ) {
+ $limit = $inLimit;
+ }
+ }
+
+ // Use regex to allow limit and handle UTF-8 correctly.
+ $inReplaceFrom = preg_quote( $inReplaceFrom, '/' );
+ $inReplaceTo = StringUtils::escapeRegexReplacement( $inReplaceTo );
+
+ $result = preg_replace( '/' . $inReplaceFrom . '/u',
+ $inReplaceTo, $inStr, $limit );
+
+ if ( !self::checkLength( $result ) ) {
+ return self::tooLongError();
+ }
+
+ return $result;
+ }
+
+ /**
+ * {{#explode:string | delimiter | position | limit}}
+ *
+ * Breaks "string" into chunks separated by "delimiter" and returns the
+ * chunk identified by "position".
+ *
+ * Note: Negative position can be used to specify tokens from the end.
+ * Note: If the divider is an empty string, single space is used instead.
+ * Note: Empty string is returned if there are not enough exploded chunks.
+ * @param $parser Parser
+ * @param $inStr string
+ * @param $inDiv string
+ * @param $inPos int
+ * @param $inLim int|null
+ * @return string
+ */
+ public static function runExplode(
+ $parser, $inStr = '', $inDiv = '', $inPos = 0, $inLim = null
+ ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inDiv = $parser->killMarkers( (string)$inDiv );
+
+ if ( $inDiv === '' ) {
+ $inDiv = ' ';
+ }
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inDiv ) ) {
+ return self::tooLongError();
+ }
+
+ $inDiv = preg_quote( $inDiv, '/' );
+
+ $matches = preg_split( '/' . $inDiv . '/u', $inStr, $inLim );
+
+ if ( $inPos >= 0 && isset( $matches[$inPos] ) ) {
+ $result = $matches[$inPos];
+ } elseif ( $inPos < 0 && isset( $matches[count( $matches ) + $inPos] ) ) {
+ $result = $matches[count( $matches ) + $inPos];
+ } else {
+ $result = '';
+ }
+
+ return $result;
+ }
+
+ /**
+ * {{#urldecode:string}}
+ *
+ * Decodes URL-encoded (like%20that) strings.
+ * @param $parser Parser
+ * @param $inStr string
+ * @return string
+ */
+ public static function runUrlDecode( $parser, $inStr = '' ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ if ( !self::checkLength( $inStr ) ) {
+ return self::tooLongError();
+ }
+
+ return urldecode( $inStr );
+ }
+
+ /**
+ * Take a PPNode (-ish thing), expand it, remove entities, and trim.
+ *
+ * For use when doing string comparisions, where user expects entities
+ * to be equal for what they stand for (e.g. comparisions with {{PAGENAME}})
+ *
+ * @param $obj PPNode|string Thing to expand
+ * @param $frame PPFrame
+ * @param &$trimExpanded String Expanded and trimmed version of PPNode,
+ * but with char refs intact
+ * @return String The trimmed, expanded and entity reference decoded version of the PPNode
+ */
+ private static function decodeTrimExpand( $obj, $frame, &$trimExpanded = null ) {
+ $expanded = $frame->expand( $obj );
+ $trimExpanded = trim( $expanded );
+ return trim( Sanitizer::decodeCharReferences( $expanded ) );
+ }
+}
diff --git a/www/wiki/extensions/ParserFunctions/README b/www/wiki/extensions/ParserFunctions/README
new file mode 100644
index 00000000..6794781c
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/README
@@ -0,0 +1,21 @@
+ParserFunctions v1.4.0
+
+1. Licensing
+2. How to install
+3. Tests
+
+1. Licensing
+Licensed under GNU GPL 2.0 or any later version. See COPYING for more license information.
+
+2. How to install
+ a. Download this tarbell and extract the contents to $IP/extensions/ParserFunctions/
+ where $IP is your root wiki install
+ b. Add 'require_once( "$IP/extensions/ParserFunctions/ParserFunctions.php");' to the
+ end of your LocalSettings (without the single quotes)
+ c. Enjoy
+
+3. Tests
+ParserFunctions ships with two tests
+- Parser tests. These get added to the main parser tests, see there for docs
+- Expression tests. These are designed to test the math-related functions
+ See testExpr.php
diff --git a/www/wiki/extensions/ParserFunctions/composer.json b/www/wiki/extensions/ParserFunctions/composer.json
new file mode 100644
index 00000000..b822010c
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/composer.json
@@ -0,0 +1,23 @@
+{
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "1.0.0",
+ "jakub-onderka/php-console-highlighter": "0.3.2",
+ "mediawiki/mediawiki-codesniffer": "18.0.0",
+ "mediawiki/minus-x": "0.3.1",
+ "mediawiki/mediawiki-phan-config": "0.2.0"
+ },
+ "scripts": {
+ "fix": [
+ "phpcbf",
+ "minus-x fix ."
+ ],
+ "test": [
+ "parallel-lint . --exclude node_modules --exclude vendor",
+ "phpcs -p -s",
+ "minus-x check ."
+ ]
+ },
+ "extra": {
+ "phan-taint-check-plugin": "1.2.0"
+ }
+}
diff --git a/www/wiki/extensions/ParserFunctions/extension.json b/www/wiki/extensions/ParserFunctions/extension.json
new file mode 100644
index 00000000..9f9f165e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/extension.json
@@ -0,0 +1,46 @@
+{
+ "name": "ParserFunctions",
+ "version": "1.6.0",
+ "author": [
+ "Tim Starling",
+ "Robert Rohde",
+ "Ross McClure",
+ "Juraj Simlovic"
+ ],
+ "url": "https://www.mediawiki.org/wiki/Extension:ParserFunctions",
+ "descriptionmsg": "pfunc_desc",
+ "license-name": "GPL-2.0-or-later",
+ "type": "parserhook",
+ "requires": {
+ "MediaWiki": ">= 1.25.0"
+ },
+ "config": {
+ "PFEnableStringFunctions": false,
+ "PFStringLengthLimit": 1000
+ },
+ "callback": "ParserFunctionsHooks::onRegistration",
+ "ExtensionMessagesFiles": {
+ "ParserFunctionsMagic": "ParserFunctions.i18n.magic.php"
+ },
+ "MessagesDirs": {
+ "ParserFunctions": [
+ "i18n"
+ ]
+ },
+ "Hooks": {
+ "ParserFirstCallInit": [
+ "ParserFunctionsHooks::onParserFirstCallInit"
+ ],
+ "ScribuntoExternalLibraries": [
+ "ParserFunctionsHooks::onScribuntoExternalLibraries"
+ ]
+ },
+ "AutoloadClasses": {
+ "ExtParserFunctions": "includes/ExtParserFunctions.php",
+ "ExprParser": "includes/ExprParser.php",
+ "ExprError": "includes/ExprError.php",
+ "Scribunto_LuaParserFunctionsLibrary": "includes/Scribunto_LuaParserFunctionsLibrary.php",
+ "ParserFunctionsHooks": "includes/ParserFunctionsHooks.php"
+ },
+ "manifest_version": 1
+}
diff --git a/www/wiki/extensions/ParserFunctions/funcsParserTests.txt b/www/wiki/extensions/ParserFunctions/funcsParserTests.txt
new file mode 100644
index 00000000..b66b6b4a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/funcsParserTests.txt
@@ -0,0 +1,343 @@
+# Force the test runner to ensure the extension is loaded
+# fixme... this doesn't seem to work :D
+#!! functionhooks
+#time
+#!! endfunctionhooks
+
+# fixme: #time seems to be accepting input as local time, which strikes me as wrong
+
+!! article
+ParserFunctions page
+!! text
+A sample page so we can test ifexist.
+
+This used to be a Main Page, but that caused duplicate article
+warnings when running the normal tests at the same time.
+!! endarticle
+
+!! article
+File:Dionysos-Brunnen am Kölner Dom.jpg
+!! text
+blah blah
+!! endarticle
+
+!! article
+File:Redirect_to_Foobar.jpg
+!! text
+#REDIRECT[[File:Foobar.jpg]]
+!! endarticle
+
+!! article
+File:Redirect_to_nowhere.jpg
+!! text
+#REDIRECT[[File:Missing target file.jpg]]
+!! endarticle
+
+!! test
+Input times are UTC, not local time
+!! input
+{{#time:c|15 January 2001}}
+!!result
+<p>2001-01-15T00:00:00+00:00
+</p>
+!! end
+
+!! test
+Time test in traditional range...
+!! input
+{{#time:Y|15 January 2001}}
+!! result
+<p>2001
+</p>
+!! end
+
+!! test
+Time test prior to 1970 Unix creation myth
+!! input
+{{#time:Y|5 April 1967}}
+!! result
+<p>1967
+</p>
+!! end
+
+!! test
+Time test after the 2038 32-bit Apocalype
+!! input
+{{#time:Y|28 July 2061}}
+!! result
+<p>2061
+</p>
+!! end
+
+!! test
+Explicitly specified timezone: UTC
+!! input
+{{#time:Y-m-d H:i| 2011-11-12 23:00 UTC }}
+!! result
+<p>2011-11-12 23:00
+</p>
+!! end
+
+!! test
+Explicitly specified timezone: Europe/Paris (UTC+1)
+!! input
+{{#time:Y-m-d H:i| 2011-11-12 23:00 Europe/Paris }}
+!! result
+<p>2011-11-12 22:00
+</p>
+!! end
+
+!! test
+Explicitly specified timezone: America/New_York (UTC-5)
+!! input
+{{#time:Y-m-d H:i| 2011-11-12 23:00 America/New_York }}
+!! result
+<p>2011-11-13 04:00
+</p>
+!! end
+
+!! test
+Explicitely specified output language (Dutch)
+!! input
+{{#time:d F Y|1988-02-28|nl}}
+!! result
+<p>28 februari 1988
+</p>
+!! end
+
+!! test
+Preserve tags in #switch default value
+!! input
+{{#switch:a|b|<div>c</div>}}
+!! result
+<div>c</div>
+
+!! end
+
+!! test
+Bug 19093: Default values don't fall through in switch
+!! input
+<{{#switch: foo | bar | #default = DEF }}>
+<{{#switch: foo | #default | bar = DEF }}>
+!! result
+<p>&lt;DEF&gt;
+&lt;DEF&gt;
+</p>
+!! end
+
+!! test
+{{#ifexist}}
+!! input
+{{#ifexist:Media:Foobar.jpg|Found|Not found}}
+{{#ifexist:ParserFunctions page|Found|Not found}}
+{{#ifexist:Missing|Found|Not found}}
+!! result
+<p>Found
+Found
+Not found
+</p>
+!! end
+
+!! test
+{{#ifexist:}} media redirect (bug 32031)
+!! input
+{{#ifexist:Media:Redirect_to_Foobar.jpg|Found|Not found}}
+{{#ifexist:Media:Redirect_to_nowhere.jpg|Found|Not found}}
+{{#ifexist:Media:Missing file.jpg|Found|Not found}}
+{{#ifexist:Media:Dionysos-Brunnen am Kölner Dom.jpg|Found|Not found}}
+!!result
+<p>Found
+Not found
+Not found
+Not found
+</p>
+!!end
+
+!! test
+#if
+!! input
+{{#if: | yes | no}}
+{{#if: string | yes | no}}
+{{#if: | yes | no}}
+{{#if:
+
+
+| yes | no}}
+{{#if: 1==2 | yes | no}}
+{{#if: foo | yes }}
+{{#if: | yes }}(empty)
+{{#if: foo | | no}}(empty)
+{{#if: {{{1}}} | yes | no}}
+{{#if: {{{1|}}} | yes | no}}
+!! result
+<p>no
+yes
+no
+no
+yes
+yes
+(empty)
+(empty)
+yes
+no
+</p>
+!! end
+
+!! test
+#ifeq
+!!input
+{{#ifeq: 01 | 1 | yes | no}}
+{{#ifeq: 0 | -0 | yes | no}}
+{{#ifeq: foo | bar | yes | no}}
+{{#ifeq: foo | Foo | yes | no}}
+{{#ifeq: "01" | "1" | yes | no}}
+!! result
+<p>yes
+yes
+no
+no
+no
+</p>
+!! end
+
+!! test
+#ifeq entities
+!!input
+{{#ifeq: {{PAGENAME:*foo&bar}} | *foo&bar | yes | no}}
+{{#ifeq: a'b | a&#39;b | yes | no}}
+{{#ifeq: a'b | a&amp;#39;b | yes | no}}
+{{#ifeq: foo | Foo | *yes | *no}}
+!! result
+<p>yes
+yes
+no
+</p>
+<ul><li>no</li></ul>
+
+!! end
+
+
+!! test
+#iferror
+!!input
+{{#iferror: {{#expr: 1 + 2 }} | error | correct }}
+{{#iferror: {{#expr: 1 + X }} | error | correct }}
+{{#iferror: {{#expr: 1 + 2 }} | error }}
+{{#iferror: {{#expr: 1 + X }} | error }}
+{{#iferror: {{#expr: 1 + 2 }} }}
+{{#iferror: {{#expr: 1 + X }} }}empty
+!! result
+<p>correct
+error
+3
+error
+3
+empty
+</p>
+!! end
+
+
+!! test
+#ifexpr
+!! input
+{{#ifexpr: | yes | no}}
+{{#ifexpr: 1 > 0 | yes }}
+{{#ifexpr: 1 < 0 | yes }}empty
+{{#ifexpr: 1 > 0 | | no}}empty
+{{#ifexpr: 1 < 0 | | no}}
+{{#ifexpr: 1 > 0 }}empty
+!! result
+<p>no
+yes
+empty
+empty
+no
+empty
+</p>
+!! end
+
+!! test
+Bug 22866: #ifexpr should evaluate "-0" as false
+!! input
+{{#ifexpr: (-1)*0 | true | false }}
+!! result
+<p>false
+</p>
+!! end
+
+!! test
+Templates: Parser functions don't strip whitespace from positional parameters
+!! input
+{{#if: {{foo}}
+| no-pre-then
+| no-pre-else
+}}
+!! result
+<p>no-pre-then
+</p>
+!! end
+
+!! test
+#switch
+!! input
+{{#switch:foo&bar|foo&amp;bar=yes|no}}
+{{#switch:foo&bar|fred=1|foo&amp;bar|g=yes|no}}
+{{#switch:foo&bar|fred=1|foo&amp;&#39;bar|g=yes|no}}
+{{#switch:foo|bar|baz=no|*default}}
+{{#switch:none|foo=1|bar=2|#default=no match|baz=3}}
+{{#switch:none|foo=1|bar=2|#default=ignored|baz=3|Second default}}
+{{#switch:|a&amp;#39;b}}
+!! result
+<p>yes
+yes
+no
+</p>
+<ul><li>default</li></ul>
+<p>no match
+Second default
+a&amp;#39;b
+</p>
+!!end
+
+!! test
+#switch #default should match next and not last named parameter
+!! input
+<{{#switch: foo | #default | bar = DEF }}>
+<{{#switch: foo | #default | bar = DEF | baz = GHI }}>
+!! result
+<p>&lt;DEF&gt;
+&lt;DEF&gt;
+</p>
+!! end
+
+!! test
+#switch should not match #default as a prefix
+!! input
+<{{#switch: foo | #defaultWTF? = This is crazy }}>
+<{{#switch: foo | #defaultWTF? | bar = This is crazy }}>
+!! result
+<p>&lt;&gt;
+&lt;&gt;
+</p>
+!! end
+
+!! test
+#switch Test php truthy
+!!input
+{{#switch: 01 | 1 = yes | no}}
+{{#switch: 0 | -0 = yes | no}}
+{{#switch: foo | bar = yes | no}}
+{{#switch: foo | Foo = yes | no}}
+{{#switch: "01" | "1" = yes | no}}
+{{#switch: 1 | 02 | 01 = yes | no}}
+{{#switch: 1 | "01" | "1" = yes | no}}
+!! result
+<p>yes
+yes
+no
+no
+no
+yes
+no
+</p>
+!! end
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ace.json b/www/wiki/extensions/ParserFunctions/i18n/ace.json
new file mode 100644
index 00000000..9cf2bc0e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ace.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Si Gam Acèh"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Reuloh ekspresi: Narit \"$1\" hana geuturi.",
+ "pfunc_expr_missing_operand": "Salah èksprèsi: Operand hana geuteumèë keu $1",
+ "pfunc_expr_unrecognised_punctuation": "Reuloh ekspresi: Karakter tanda beuët \"$1\" hana geuturi."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ady-cyrl.json b/www/wiki/extensions/ParserFunctions/i18n/ady-cyrl.json
new file mode 100644
index 00000000..52988228
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ady-cyrl.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Highlander45temp",
+ "TheRossatron",
+ "Inyzh",
+ "Amire80"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "ӀуакӀэр къуанчэ: ГущаӀэу \"$1\"-р зэхэшӀыкӀыгъэп.",
+ "pfunc_expr_unexpected_operator": "ӀуакӀэр къуанчэ: ОшӀэдэмышIэ $1 оператор.",
+ "pfunc_expr_missing_operand": "КъэӀокӀэ тэрэзэп: $1-м пае операнд икъурэп.",
+ "pfunc_expr_unrecognised_punctuation": "ӀуакӀэр къуанчэ: Пыутхэбзэ символэу \"$1\" зэхэшӀыкӀыгъэп."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/af.json b/www/wiki/extensions/ParserFunctions/i18n/af.json
new file mode 100644
index 00000000..119bc9ff
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/af.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Naudefj",
+ "Arnobarnard"
+ ]
+ },
+ "pfunc_desc": "Verryk die ontleder met logiese funksies",
+ "pfunc_time_error": "Fout: ongeldige tyd",
+ "pfunc_time_too_long": "Fout: #time te veel kere geroep",
+ "pfunc_rel2abs_invalid_depth": "Fout: Ongeldige diepte in pad: \"$1\" (probeer 'n node bo die wortelnode te roep)",
+ "pfunc_expr_stack_exhausted": "Fout in uitdrukking: stack uitgeput",
+ "pfunc_expr_unexpected_number": "Fout in uitdrukking: onverwagte getal",
+ "pfunc_expr_preg_match_failure": "Fout in uitdrukking: onverwagte faling van preg_match",
+ "pfunc_expr_unrecognised_word": "Fout in uitdrukking: woord \"$1\" nie herken",
+ "pfunc_expr_unexpected_operator": "Fout in uitdrukking: onverwagte operator $1.",
+ "pfunc_expr_missing_operand": "Fout in uitdrukking: geen operand vir $1",
+ "pfunc_expr_unexpected_closing_bracket": "Fout in uitdrukking: hakkie onverwags gesluit",
+ "pfunc_expr_unrecognised_punctuation": "Fout in uitdrukking: onbekende leesteken \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Fout in uitdrukking: hakkie nie gesluit nie",
+ "pfunc_expr_division_by_zero": "Deling deur nul",
+ "pfunc_expr_invalid_argument": "Ongeldige argument vir $1: < -1 of > 1",
+ "pfunc_expr_invalid_argument_ln": "Ongeldige argument vir ln: <= 0",
+ "pfunc_expr_unknown_error": "Fout in uitdrukking: onbekende fout ($1)",
+ "pfunc_expr_not_a_number": "In $1: resultaat is nie 'n getal nie",
+ "pfunc_string_too_long": "Fout: String oorskry $1 karakter limiet"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ais.json b/www/wiki/extensions/ParserFunctions/i18n/ais.json
new file mode 100644
index 00000000..c31f0989
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ais.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Benel",
+ "Bunukwiki"
+ ]
+ },
+ "pfunc_desc": "sangaleb papulita-sakaluk, nipabeli loci sapisausi sasahicaan",
+ "pfunc_time_error": "mungangaw: la’cusay a tuki",
+ "pfunc_time_too_long": "mungangaw: mangsiw #time miawaw.",
+ "pfunc_time_too_big": "mungangaw:#time midama pabaw-sahezek ku 9999 a mihca.",
+ "pfunc_time_too_small": "mungangaw: #time midama sainayi'ay ku 0 a mihca.",
+ "pfunc_rel2abs_invalid_depth": "mungangaw: la’cusay a zazan salabuay:\"$1\" (mitanam misuped-miala pabaw nu lamit ciyityin)",
+ "pfunc_expr_stack_exhausted": "sakamu tu nizateng sasakawawen mungangaw: kalud kihkih tuway.",
+ "pfunc_expr_unexpected_number": "sakamu tu nizateng sasakawawen mungangaw: talibahalay asip-bacu.",
+ "pfunc_expr_preg_match_failure": "sakamu tu nizateng sasakawawen mungangaw: talibahalay preg_match mungangaw.",
+ "pfunc_expr_unrecognised_word": "sakamu tu nizateng sasakawawen mungangaw: la’cusay sapulitaan a sulit \"$1\".",
+ "pfunc_expr_unexpected_operator": "Expression error: Unexpected $1 operator.",
+ "pfunc_expr_missing_operand": "sakamu tu nizateng sasakawawen mungangaw:caay kataneng $1 a yunswaniyin.",
+ "pfunc_expr_unexpected_closing_bracket": "sakamu tu nizateng sasakawawen mungangaw: talibahalay a belih kwahaw",
+ "pfunc_expr_unrecognised_punctuation": "sakamu tu nizateng sasakawawen mungangaw: la’cusay sapulitaan a sulit nu hahanhanan nu kamu \"$1\".",
+ "pfunc_expr_unclosed_bracket": "sakamu tu nizateng sasakawawen mungangaw: caay pahezek a kwahaw.",
+ "pfunc_expr_division_by_zero": "sapiwada’ nu piasip u inayi’.",
+ "pfunc_expr_invalid_argument": "$1 a aazihen-sulyang la’cus: < -1 saca > 1.",
+ "pfunc_expr_invalid_argument_ln": "ln a aazihan a sulyang la’cus: <= 0.",
+ "pfunc_expr_unknown_error": "sakamu tu nizateng sasakawawen mungangaw:caay katinengay a mungangaw ($1)",
+ "pfunc_expr_not_a_number": "ilabu $1: kya heci caay ku asip-bacu.",
+ "pfunc_string_too_long": "mungangaw: sulisulitan mangasiw $1 tatebanan-nisulitan kelec."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/aln.json b/www/wiki/extensions/ParserFunctions/i18n/aln.json
new file mode 100644
index 00000000..d3a338f3
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/aln.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mdupont"
+ ]
+ },
+ "pfunc_desc": "Enhance parser me funksione logjike",
+ "pfunc_time_error": "Gabim: koha e pavlefshme",
+ "pfunc_time_too_long": "Gabim: kohë shumë # thirrjet",
+ "pfunc_rel2abs_invalid_depth": "Gabim: thellësia e pavlefshme në rrugën: \"$1\" (u përpoq për të hyrë në një nyjë mbi nyjen e rrënjë)",
+ "pfunc_expr_stack_exhausted": "gabim Shprehja: qipi rraskapitur",
+ "pfunc_expr_unexpected_number": "gabim Shprehja: Numri i papritur"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/an.json b/www/wiki/extensions/ParserFunctions/i18n/an.json
new file mode 100644
index 00000000..4ffb4119
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/an.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Juanpabl"
+ ]
+ },
+ "pfunc_desc": "Amillorar o parseyador con funcions lochicas",
+ "pfunc_time_error": "Error: tiempo incorreuto",
+ "pfunc_time_too_long": "Error: masiadas cridas #time",
+ "pfunc_rel2abs_invalid_depth": "Error: Fondura incorreuta en o camín: \"$1\" (ha prebato d'acceder ta un nodo por dencima d'o nodo radiz)",
+ "pfunc_expr_stack_exhausted": "Error d'expresión: Pila acotolada",
+ "pfunc_expr_unexpected_number": "Error d'expresión: numero no asperato",
+ "pfunc_expr_preg_match_failure": "Error d'expresión: fallo de preg_match no asperato",
+ "pfunc_expr_unrecognised_word": "Error d'expresión: parola \"$1\" no reconoixita",
+ "pfunc_expr_unexpected_operator": "Error d'expresión: operador $1 no asperato",
+ "pfunc_expr_missing_operand": "Error d'expresión: a $1 li falta un operando",
+ "pfunc_expr_unexpected_closing_bracket": "Error d'expresión: zarradura d'o gafet no asperata",
+ "pfunc_expr_unrecognised_punctuation": "Error d'expresión: carácter de puntuación \"$1\" no reconoixito",
+ "pfunc_expr_unclosed_bracket": "Error d'expresión: gafet sin zarrar",
+ "pfunc_expr_division_by_zero": "División por zero",
+ "pfunc_expr_invalid_argument": "Argumento no conforme ta $1: < -1 u > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumento no conforme ta ln: <=0",
+ "pfunc_expr_unknown_error": "Error d'expresión: error esconoixito ($1)",
+ "pfunc_expr_not_a_number": "En $1: o resultau no ye un numero"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/anp.json b/www/wiki/extensions/ParserFunctions/i18n/anp.json
new file mode 100644
index 00000000..abf4157a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/anp.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Angpradesh"
+ ]
+ },
+ "pfunc_time_error": "त्रुटि: अमान्य समय।",
+ "pfunc_expr_unrecognised_word": "एक्स्प्रेशन त्रुटि: अज्ञात शब्द \"$1\"।",
+ "pfunc_expr_unexpected_operator": "एक्स्प्रेशन त्रुटि: अनपेक्षित $1 ऑपरेटर",
+ "pfunc_expr_missing_operand": "एक्स्प्रेशन त्रुटि: $1 केरऽ घटक नै मिललै",
+ "pfunc_expr_unrecognised_punctuation": "एक्स्प्रेशन त्रुटि: अनपेक्षित उद्गार चिन्ह \"$1\"",
+ "pfunc_expr_division_by_zero": "शून्य स॑ भाग।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ar.json b/www/wiki/extensions/ParserFunctions/i18n/ar.json
new file mode 100644
index 00000000..15ea9638
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ar.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aiman titi",
+ "Asaifm",
+ "Meno25",
+ "أحمد"
+ ]
+ },
+ "pfunc_desc": "محلل ممدد بدوال منطقية",
+ "pfunc_time_error": "خطأ: زمن غير صحيح",
+ "pfunc_time_too_long": "خطأ: استدعاءات #time كثيرة جدا",
+ "pfunc_time_too_big": "خطأ : # الوقت يدعم فقط حتى 9999 سنة",
+ "pfunc_time_too_small": "خطأ: #time تدعم الأعوام بدءا من 0.",
+ "pfunc_rel2abs_invalid_depth": "خطأ: عمق غير صحيح في المسار: \"$1\" (حاول دخول عقدة فوق العقدة الجذرية)",
+ "pfunc_expr_stack_exhausted": "خطأ في التعبير: ستاك مجهد",
+ "pfunc_expr_unexpected_number": "خطأ في التعبير: رقم غير متوقع",
+ "pfunc_expr_preg_match_failure": "خطأ في التعبير: فشل preg_match غير متوقع",
+ "pfunc_expr_unrecognised_word": "خطأ في التعبير: كلمة غير متعرف عليها \"$1\"",
+ "pfunc_expr_unexpected_operator": "خطأ في التعبير: عامل $1 غير متوقع",
+ "pfunc_expr_missing_operand": "خطأ في التعبير: معامل مفقود للعامل $1",
+ "pfunc_expr_unexpected_closing_bracket": "خطأ في التعبير: قوس إغلاق غير متوقع",
+ "pfunc_expr_unrecognised_punctuation": "خطأ في التعبير: علامة ترقيم غير متعرف عليها \"$1\"",
+ "pfunc_expr_unclosed_bracket": "خطأ في التعبير: قوس غير مغلق",
+ "pfunc_expr_division_by_zero": "القسمة على صفر",
+ "pfunc_expr_invalid_argument": "مدخلة غير صحيحة ل $1: < -1 أو > 1",
+ "pfunc_expr_invalid_argument_ln": "مدخلة غير صحيحة ل ln: <= 0",
+ "pfunc_expr_unknown_error": "خطأ في التعبير: خطأ غير معروف ($1)",
+ "pfunc_expr_not_a_number": "في $1: النتيجة ليست رقما",
+ "pfunc_string_too_long": "خطأ: السلسلة تتجاوز الحد $1 حرف"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/arc.json b/www/wiki/extensions/ParserFunctions/i18n/arc.json
new file mode 100644
index 00000000..726879d6
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/arc.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Basharh"
+ ]
+ },
+ "pfunc_time_error": "ܦܘܕܐ: ܥܕܢܐ ܠܐ ܬܪܝܨܬܐ"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/arq.json b/www/wiki/extensions/ParserFunctions/i18n/arq.json
new file mode 100644
index 00000000..a8eb5208
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/arq.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bachounda",
+ "Oldstoneage"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "غلط فالتعبير: كلمة غير متعرف عليها \"$1\"",
+ "pfunc_expr_unexpected_operator": "غلطة تاع تعبير : عامل '''$1''' ماشي مقارع.",
+ "pfunc_expr_missing_operand": "غلطة ف`التعبير: معمول مودّر لـ$1",
+ "pfunc_expr_unrecognised_punctuation": "غلطه فالتعبير: علامة تنقيط ماشي متعرف عليها \"$1\""
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/arz.json b/www/wiki/extensions/ParserFunctions/i18n/arz.json
new file mode 100644
index 00000000..68acef86
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/arz.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ghaly",
+ "Meno25",
+ "Ramsis II"
+ ]
+ },
+ "pfunc_desc": "محلل متدعم ب دوال منطقية",
+ "pfunc_time_error": "غلطه:وقت مش صحيح",
+ "pfunc_time_too_long": "غلط: استدعاءات #time كتيرة قوى",
+ "pfunc_rel2abs_invalid_depth": "غلط: عمق مش صحيح فى المسار: \"$1\" (حاول دخول عقدة فوق العقدة الجزرية)",
+ "pfunc_expr_stack_exhausted": "غلط فى التعبير: ستاك مجهد",
+ "pfunc_expr_unexpected_number": "غلط فى التعبير: رقم مش متوقع",
+ "pfunc_expr_preg_match_failure": "غلط تعبيري: فشل مش متوقع فى preg_match",
+ "pfunc_expr_unrecognised_word": "غلط تعبيري: كلمة مش متعرف عليها \"$1\"",
+ "pfunc_expr_unexpected_operator": "غلط تعبيري: عامل $1 مش متوقع",
+ "pfunc_expr_missing_operand": "غلط تعبيري: operand بتاع $1 ضايع",
+ "pfunc_expr_unexpected_closing_bracket": "غلط تعبيري:قوس قفل مش متوقع",
+ "pfunc_expr_unrecognised_punctuation": "غلط تعبيري:علامة الترقيم \"$1\" مش متعرف عليها",
+ "pfunc_expr_unclosed_bracket": "غلط تعبيري:قوس مش مقفول",
+ "pfunc_expr_division_by_zero": "القسمه على صفر",
+ "pfunc_expr_invalid_argument": "مدخلة مش صحيحة لـ $1: < -1 or > 1",
+ "pfunc_expr_invalid_argument_ln": "مدخلة مش صحيحة لـ ln: <= 0",
+ "pfunc_expr_unknown_error": "($1)غلط تعبيري: غلط مش معروف",
+ "pfunc_expr_not_a_number": "فى $1: النتيجه مش رقم"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/as.json b/www/wiki/extensions/ParserFunctions/i18n/as.json
new file mode 100644
index 00000000..8987f121
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/as.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bishnu Saikia",
+ "Gitartha.bordoloi",
+ "Rajuonline"
+ ]
+ },
+ "pfunc_desc": "লজিকেল ফাংছন ব্যৱহাৰ কৰি পাৰ্ছাৰক উন্নত কৰক",
+ "pfunc_time_error": "ভুল: অযোগ্য সময়",
+ "pfunc_time_too_long": "ত্রুটী: অত্যধিক #time কল আছে",
+ "pfunc_time_too_big": "ত্ৰুটী: #time -এ কেৱল ৯৯৯৯ চনলৈকে লৈকেহে সমৰ্থন কৰে",
+ "pfunc_rel2abs_invalid_depth": "ত্ৰুটী: পাথত অবৈধ গভীৰতা: \"$1\" (মূল নোডৰ ওপৰৰ এটা নোড আহৰণ কৰাৰ চেষ্টা কৰিছিল)",
+ "pfunc_expr_stack_exhausted": "এক্সপ্ৰেছন ত্ৰুটী: ষ্টক শেষ হৈছে",
+ "pfunc_expr_unexpected_number": "এক্সপ্ৰেছন ত্ৰুটী: অবাঞ্চিত সংখ্যা",
+ "pfunc_expr_preg_match_failure": "এক্সপ্ৰেছন ত্ৰুটী: অবাঞ্চিত preg_match ব্যৰ্থতা",
+ "pfunc_expr_unrecognised_word": "এক্সপ্ৰেছন ত্ৰুটী: অপৰিচিত শব্দ \"$1\"",
+ "pfunc_expr_unexpected_operator": "এক্সপ্ৰেছন ত্ৰুটী: অবাঞ্চিত $1 অপাৰেটৰ",
+ "pfunc_expr_missing_operand": "এক্সপ্ৰেছন ত্ৰুটী: $1’ৰ বাবে অপাৰেণ্ড নাই।",
+ "pfunc_expr_unexpected_closing_bracket": "এক্সপ্ৰেছন ত্ৰুটী: অবাঞ্চিত সমাপ্তকাৰী বন্ধনী",
+ "pfunc_expr_unrecognised_punctuation": "এক্সপ্ৰেছন ত্ৰুটী: অপৰিচিত বিৰামচিহ্ন কেৰেক্টাৰ \"$1\"",
+ "pfunc_expr_unclosed_bracket": "এক্সপ্ৰেছন ত্ৰুটী: উন্মুক্ত বন্ধনী",
+ "pfunc_expr_division_by_zero": "শূন্যৰে হৰণ কৰা হৈছে।",
+ "pfunc_expr_invalid_argument": "$1 ৰ বাবে ভুল চৰ্ত: < -1 অথবা > 1",
+ "pfunc_expr_invalid_argument_ln": "ln ৰ বাবে অমান্য চৰ্ত: <= 0",
+ "pfunc_expr_unknown_error": "এক্সপ্ৰেছন ত্ৰুটী: : অজ্ঞাত ত্ৰুটী ($1)",
+ "pfunc_expr_not_a_number": "$1: ৰ ফলাফল একো সংখ্যা নহয়"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ast.json b/www/wiki/extensions/ParserFunctions/i18n/ast.json
new file mode 100644
index 00000000..9e2d5bb9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ast.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Esbardu",
+ "Xuacu"
+ ]
+ },
+ "pfunc_desc": "Ameyora l'análisis sintáuticu con funciones llóxiques",
+ "pfunc_time_error": "Error: tiempu non válidu",
+ "pfunc_time_too_long": "Error: demasiaes llamaes #time",
+ "pfunc_time_too_big": "Error: #time sólo almite años fasta 9999.",
+ "pfunc_time_too_small": "Error: #time sólo almite años dende 0.",
+ "pfunc_rel2abs_invalid_depth": "Error: Nivel de subdireutoriu non válidu: \"$1\" (intentu d'accesu penriba del direutoriu raíz)",
+ "pfunc_expr_stack_exhausted": "Error d'espresión: Pila escosada",
+ "pfunc_expr_unexpected_number": "Error d'espresión: Númberu inesperáu",
+ "pfunc_expr_preg_match_failure": "Error d'espresión: Fallu inesperáu de preg_match",
+ "pfunc_expr_unrecognised_word": "Error d'espresión: Pallabra \"$1\" non reconocida.",
+ "pfunc_expr_unexpected_operator": "Error d'espresión: Operador $1 inesperáu",
+ "pfunc_expr_missing_operand": "Error na espresión: Falta l'operando pa $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Error d'espresión: Paréntesis final inesperáu",
+ "pfunc_expr_unrecognised_punctuation": "Error d'espresión: Caráuter de puntuación \"$1\" non reconocíu.",
+ "pfunc_expr_unclosed_bracket": "Error d'espresión: Paréntesis non zarráu",
+ "pfunc_expr_division_by_zero": "División por cero",
+ "pfunc_expr_invalid_argument": "Argumentu non válidu pa $1: < -1 o > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumentu non válidu pa ln: <= 0",
+ "pfunc_expr_unknown_error": "Error d'espresión: Error desconocíu ($1)",
+ "pfunc_expr_not_a_number": "En $1: el resultáu nun ye un númberu",
+ "pfunc_string_too_long": "Error: la cadena pasa la llende de $1 caráuteres"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/atj.json b/www/wiki/extensions/ParserFunctions/i18n/atj.json
new file mode 100644
index 00000000..1afcb50a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/atj.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jeannette Coocoo",
+ "Ninmeka"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Onamowin : itewin« $1 » nama miskam.",
+ "pfunc_expr_unexpected_operator": "onimonaniwon:ispitamowin$1 aka ka petakaniwok",
+ "pfunc_expr_missing_operand": "arotc icinikatcikatew : ka notepirik icinikatamowin '''$1'''.",
+ "pfunc_expr_unrecognised_punctuation": "Onimowin : nakwe tcikasinahikanicica « $1 » nama miskam ."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/av.json b/www/wiki/extensions/ParserFunctions/i18n/av.json
new file mode 100644
index 00000000..4d6e161b
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/av.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazimagomedov"
+ ]
+ },
+ "pfunc_expr_unexpected_operator": "Хъвай-хъвагӀиялъул гъалатӀ: данде кколареб оператор $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/awa.json b/www/wiki/extensions/ParserFunctions/i18n/awa.json
new file mode 100644
index 00000000..272c3ada
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/awa.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "1AnuraagPandey"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "एक्स्प्रेशन त्रुटि: अज्ञात शब्द \"$1\"।",
+ "pfunc_expr_unexpected_operator": "एक्स्प्रेशन त्रुटि: अनपेक्षित $1 ऑपरेटर।",
+ "pfunc_expr_missing_operand": "एक्स्प्रेशन त्रुटि: $1 का घटक नहीं मिला",
+ "pfunc_expr_unrecognised_punctuation": "एक्स्प्रेशन त्रुटि: अनपेक्षित उद्गार चिन्ह \"$1\"।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/az.json b/www/wiki/extensions/ParserFunctions/i18n/az.json
new file mode 100644
index 00000000..fa04d6a7
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/az.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cekli829",
+ "Dağlı95"
+ ]
+ },
+ "pfunc_time_error": "Xəta: yanlış zaman",
+ "pfunc_expr_stack_exhausted": "İfadə xətası: Stek doludur.",
+ "pfunc_expr_unexpected_number": "İfadə xətası: gözlənilməz ədəd",
+ "pfunc_expr_preg_match_failure": "İfadə xətası: Gözlənilməz preg_match nasazlığı",
+ "pfunc_expr_unrecognised_word": "İfadə xətası: tanınmayan ifadə söz \"$1\".",
+ "pfunc_expr_unexpected_operator": "İfadə xətası: gözlənilməz \"$1\" operatoru.",
+ "pfunc_expr_missing_operand": "İfadə xətası: $1 operantı çatışmır.",
+ "pfunc_expr_unexpected_closing_bracket": "İfadə xətası: Gözlənilməz bağlanmış mötərizə",
+ "pfunc_expr_unrecognised_punctuation": "İfadə xətası: \"$1\" punktuasiyasının tanınmayan simvolu.",
+ "pfunc_expr_unclosed_bracket": "İfadə xətası: Mötərizə bağlanılmamışdır.",
+ "pfunc_expr_division_by_zero": "Sıfıra bölmə",
+ "pfunc_expr_invalid_argument_ln": "ln üçün xətalı arqument: <= 0",
+ "pfunc_expr_unknown_error": "İfadə xətası: naməlum xəta ($1)",
+ "pfunc_expr_not_a_number": "$1-də: nəticə ədəd deyildir."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/azb.json b/www/wiki/extensions/ParserFunctions/i18n/azb.json
new file mode 100644
index 00000000..c1c93a69
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/azb.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amir a57",
+ "Sadiqr"
+ ]
+ },
+ "pfunc_time_error": "ختا: یانلیش زامان",
+ "pfunc_expr_unrecognised_word": "عیبارت خطاسی: تانینمایان سوز «$1»",
+ "pfunc_expr_unexpected_operator": "عیبارت خطاسی: عمل ائدن $1 اینتظار دان اوزاق",
+ "pfunc_expr_missing_operand": "عیبارت خطاسی: ایتمیش عمل ائدن $1 اوچون",
+ "pfunc_expr_unrecognised_punctuation": "عیبارت خطاسی: تانیمایان نوقطالنمیش یازی «$1»",
+ "pfunc_expr_division_by_zero": "صفره‌ بؤلوم"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ba.json b/www/wiki/extensions/ParserFunctions/i18n/ba.json
new file mode 100644
index 00000000..d3b30791
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ba.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Assele",
+ "Янмурза Баки"
+ ]
+ },
+ "pfunc_desc": "Логик функциялар менән яҡшыртылған уҡыу ҡоралы",
+ "pfunc_time_error": "Хата: ваҡыт дөрөҫ түгел",
+ "pfunc_time_too_long": "Хата: #time функцияһы бигерәк күп саҡырылған",
+ "pfunc_time_too_big": "Хата. #time параметры 9999-ҙан артырға тейеш түгел.",
+ "pfunc_time_too_small": "Хата: 0-дан, #time тик йылдарҙы ғына тота.",
+ "pfunc_rel2abs_invalid_depth": "Хата: \"$1\" юлының тәрәнлеге дөрөҫ түгел (тәүге төйөндән өҫтәрәк торған төйөндө асырға тырышыу)",
+ "pfunc_expr_stack_exhausted": "Аңлатма хатаһы: Стек тулған",
+ "pfunc_expr_unexpected_number": "Аңлатма хатаһы: Көтөлмәгән һан",
+ "pfunc_expr_preg_match_failure": "Аңлатма хатаһы: Көтөлмәгән preg_match хатаһы",
+ "pfunc_expr_unrecognised_word": "Аңлатма хатаһы: Танылмаған \"$1\" һүҙе",
+ "pfunc_expr_unexpected_operator": "Аңлатма хатаһы: Көтөлмәгән $1 операторы",
+ "pfunc_expr_missing_operand": "Аңлатма хатаһы: $1 аңлатмаһы өсөн операнд етмәй",
+ "pfunc_expr_unexpected_closing_bracket": "Аңлатма хатаһы: Көтөлмәгән ябыу йәйәһе",
+ "pfunc_expr_unrecognised_punctuation": "Аңлатма хатаһы: Танылмаған \"$1\" тыныш билдәһе",
+ "pfunc_expr_unclosed_bracket": "Аңлатма хатаһы: Ябылмаған йәйә",
+ "pfunc_expr_division_by_zero": "Нулгә бүлеү хатаһы",
+ "pfunc_expr_invalid_argument": "$1 өсөн аргумент дөрөҫ түгел: < -1 йәки > 1",
+ "pfunc_expr_invalid_argument_ln": "ln өсөн аргумент дөрөҫ түгел: <= 0",
+ "pfunc_expr_unknown_error": "Аңлатма хатаһы: Билдәһеҙ хата ($1)",
+ "pfunc_expr_not_a_number": "$1: һөҙөмтә — һан түгел",
+ "pfunc_string_too_long": "Хата: Юл оҙонлоғо билдәләнгән сиктән — $1 хәрефтән — ашҡан"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/bcc.json b/www/wiki/extensions/ParserFunctions/i18n/bcc.json
new file mode 100644
index 00000000..05b0e2be
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/bcc.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mostafadaneshvar"
+ ]
+ },
+ "pfunc_desc": "تجزیه کنوکء بهتر کن گون عملگر آن منطقی",
+ "pfunc_time_error": "حطا: نامعتبر وهد",
+ "pfunc_time_too_long": "حطا: بازگین #زمان سوج",
+ "pfunc_rel2abs_invalid_depth": "حطا: نامعتبر عمق ته مسیر: \"$1\"(سعی کتن په یک بالادی گرهنی چه ریشگی گرهنانا برسیت)",
+ "pfunc_expr_stack_exhausted": "حطا اصطلاح: توده حالیک",
+ "pfunc_expr_unexpected_number": "حطا اصطلاح: غیر منظرین شماره",
+ "pfunc_expr_preg_match_failure": "حطا اصطلاح: غیرمنتظره این preg_ همسانی پروش وارت",
+ "pfunc_expr_unrecognised_word": "حطا اصطلاح: نا شناسین کلمه \"$1\"",
+ "pfunc_expr_unexpected_operator": "حطا اصطلاح:نه لوٹتین $1 اپراتور",
+ "pfunc_expr_missing_operand": "حطا اصطلاح: گارین عملوند په $1",
+ "pfunc_expr_unexpected_closing_bracket": "حطا اصطلاح: نه لوٹتگین براکت بندگ",
+ "pfunc_expr_unrecognised_punctuation": "حطا اصطلاح: ناشناسین کاراکتر نشانه هلگی \"$1\"",
+ "pfunc_expr_unclosed_bracket": "حطا اصطلاح: نه بسته گین براکت",
+ "pfunc_expr_division_by_zero": "تقسیم بر صفر",
+ "pfunc_expr_invalid_argument": "نامعتبر آرگومان په $1: < -1 یا > 1",
+ "pfunc_expr_invalid_argument_ln": "نامعتبر آرگومان ته شی : <= 0",
+ "pfunc_expr_unknown_error": "حطا اصطلاح :ناشناسین حطا ($1)",
+ "pfunc_expr_not_a_number": "ته $1: نتیجه یک عددی نهنت"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/bcl.json b/www/wiki/extensions/ParserFunctions/i18n/bcl.json
new file mode 100644
index 00000000..c54b4574
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/bcl.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Geopoet"
+ ]
+ },
+ "pfunc_desc": "Minapabuswang kan parabangay na igwang lohikal na mga punksyon",
+ "pfunc_time_error": "Kasalaan: Imbalidong oras.",
+ "pfunc_time_too_long": "Kasalaan:Grabe kadakol na #time na mga apod.",
+ "pfunc_time_too_big": "Kasalaan: #time minasuporta sana nin mga taon sagkod sa 9999.",
+ "pfunc_time_too_small": "Kasalaan: #time minasuporta sana nin mga taon magpoon 0.",
+ "pfunc_rel2abs_invalid_depth": "Kasalaan:Imbalidong rarom nin agihan: \"$1\" (nagprubar na makalaog sa sarong boko-boko sa ibabaw kan ugat nin boko-boko).",
+ "pfunc_expr_stack_exhausted": "Kasalaan sa pagpapasabot:An bangay ubos na.",
+ "pfunc_expr_unexpected_number": "Kasalaan sa pagpapasabot: Dae pinag-asahang numero.",
+ "pfunc_expr_preg_match_failure": "Kasalaan nin pagpapasabot: Dae pinag-aasahang pagpalya kan preg_match.",
+ "pfunc_expr_unrecognised_word": "Kasalaan nin pagpapasabot: Dae rekonosidong tataramon an \"$1\".",
+ "pfunc_expr_unexpected_operator": "Kasalaan nin pagpapasabot: Dae pinag-asahan an $1 na operador.",
+ "pfunc_expr_missing_operand": "Kasalaan nin pagpapasabot: Nawawara an halaga para sa $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Kasalaan nin pagpapasabot: Dae pinag-asahang pagseserado kan pangudal.",
+ "pfunc_expr_unrecognised_punctuation": "Kasalaan nin pagpapasabot: Dae rekonosidong panbalangkay na karakter an \"$1\".",
+ "pfunc_expr_unclosed_bracket": "Kasalaan nin pagpapasabot: Dae nakaseradong pangudal.",
+ "pfunc_expr_division_by_zero": "Barangaan sa paagi ni sero.",
+ "pfunc_expr_invalid_argument": "Imbalidong argumento para sa $1: < -1 or > 1.",
+ "pfunc_expr_invalid_argument_ln": "Imbalidong argumento para sa ln: <= 0.",
+ "pfunc_expr_unknown_error": "Kasalaan nin pagpapasabot:Dae aram na kasalaan ($1).",
+ "pfunc_expr_not_a_number": "Sa $1:An resulta bako sarong numero.",
+ "pfunc_string_too_long": "Kasalaan:An panunod nagsobra sa $1 na limit nin karakter."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/be-tarask.json b/www/wiki/extensions/ParserFunctions/i18n/be-tarask.json
new file mode 100644
index 00000000..cb362d14
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/be-tarask.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "EugeneZelenko",
+ "Jim-by",
+ "Red Winged Duck",
+ "Wizardist"
+ ]
+ },
+ "pfunc_desc": "Палепшаны парсэр зь лягічнымі функцыямі",
+ "pfunc_time_error": "Памылка: няслушны час.",
+ "pfunc_time_too_long": "Памылка: зашмат выклікаў функцыі #time",
+ "pfunc_time_too_big": "Памылка: #time падтрымлівае гады толькі ў дыяпазоне да 9999",
+ "pfunc_time_too_small": "Памылка: #time падтрымлівае толькі гады ад 0.",
+ "pfunc_rel2abs_invalid_depth": "Памылка: няслушная глыбіня шляху: «$1» (спроба доступу да вузла, які знаходзіцца вышэй карэннага)",
+ "pfunc_expr_stack_exhausted": "Памылка выразу: стэк перапоўнены",
+ "pfunc_expr_unexpected_number": "Памылка выразу: нечаканая лічба",
+ "pfunc_expr_preg_match_failure": "Памылка выразу: нечаканая памылка preg_match",
+ "pfunc_expr_unrecognised_word": "Памылка выразу: нераспазнанае слова «$1»",
+ "pfunc_expr_unexpected_operator": "Памылка выразу: нечаканы апэратар $1",
+ "pfunc_expr_missing_operand": "Памылка выразу: няма апэранду $1",
+ "pfunc_expr_unexpected_closing_bracket": "Памылка выразу: нечаканая закрываючая дужка",
+ "pfunc_expr_unrecognised_punctuation": "Памылка выразу: нераспазнаны сымбаль пунктуацыі «$1»",
+ "pfunc_expr_unclosed_bracket": "Памылка выразу: незакрытая дужка",
+ "pfunc_expr_division_by_zero": "Дзяленьне на нуль.",
+ "pfunc_expr_invalid_argument": "Памылковы аргумэнт для $1: < -1 ці > 1",
+ "pfunc_expr_invalid_argument_ln": "Памылковы аргумэнт для ln: <= 0",
+ "pfunc_expr_unknown_error": "Памылка выразу: невядомая памылка ($1)",
+ "pfunc_expr_not_a_number": "У $1: вынік не зьяўляецца лічбай",
+ "pfunc_string_too_long": "Памылка: у радку перавышаны ліміт $1 {{PLURAL:$1|сымбаль|сымбалі|сымбаляў}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/be.json b/www/wiki/extensions/ParserFunctions/i18n/be.json
new file mode 100644
index 00000000..4712276d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/be.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Чаховіч Уладзіслаў",
+ "Mikalai Udodau"
+ ]
+ },
+ "pfunc_time_error": "Памылка: Недапушчальны час.",
+ "pfunc_expr_unrecognised_word": "Памылка выраза: неапазнанае слова «$1»",
+ "pfunc_expr_unexpected_operator": "Памылка выраза: нечаканы аператар $1",
+ "pfunc_expr_missing_operand": "Памылка выраза: няма аперанда $1",
+ "pfunc_expr_unrecognised_punctuation": "Памылка выраза: неапазнаны сімвал пунктуацыі «$1»",
+ "pfunc_expr_division_by_zero": "Дзяленне на нуль."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/bg.json b/www/wiki/extensions/ParserFunctions/i18n/bg.json
new file mode 100644
index 00000000..4c24ee99
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/bg.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "DCLXVI",
+ "Spiritia",
+ "StanProg"
+ ]
+ },
+ "pfunc_desc": "Подобряване на парсера с логически функции",
+ "pfunc_time_error": "Грешка: невалидно време",
+ "pfunc_time_too_long": "Грешка: Твърде много извиквания на #time",
+ "pfunc_rel2abs_invalid_depth": "Грешка: Невалидна дълбочина в път: „$1“ (опит за достъп на възел над корена)",
+ "pfunc_expr_stack_exhausted": "Грешка в израза: Стекът е изчерпан.",
+ "pfunc_expr_unexpected_number": "Грешка в записа: Неочаквано число",
+ "pfunc_expr_preg_match_failure": "Грешка в израза: Неочакван проблем с preg_match.",
+ "pfunc_expr_unrecognised_word": "Грешка в записа: Неразпозната дума „$1“.",
+ "pfunc_expr_unexpected_operator": "Грешка в израза: Неочакван оператор $1.",
+ "pfunc_expr_missing_operand": "Грешка в записа: Липсващ операнд в $1",
+ "pfunc_expr_unexpected_closing_bracket": "Грешка в израза: Една затваряща скоба в повече.",
+ "pfunc_expr_unrecognised_punctuation": "Грешка в израза: Неразпознат пунктуационен знак „$1“.",
+ "pfunc_expr_unclosed_bracket": "Грешка в записа: Незатворена скоба",
+ "pfunc_expr_division_by_zero": "Деление на нула",
+ "pfunc_expr_invalid_argument": "Невалиден аргумент за $1: < -1 или > 1",
+ "pfunc_expr_invalid_argument_ln": "Невалиден аргумент за ln: <= 0",
+ "pfunc_expr_unknown_error": "Грешка в израза: Неразпозната грешка ($1).",
+ "pfunc_expr_not_a_number": "В $1: резултатът не е число",
+ "pfunc_string_too_long": "Грешка: Низът превишава ограничението от $1 знака"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/bgn.json b/www/wiki/extensions/ParserFunctions/i18n/bgn.json
new file mode 100644
index 00000000..1a317e80
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/bgn.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Baloch Afghanistan",
+ "Ibrahim khashrowdi"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "ئبارت ئی ختا: نازانتین کلمه «$1»",
+ "pfunc_expr_unexpected_operator": "ئبارت ئی ختا: $1 ئی ئمل کورت دور شه انتظارا",
+ "pfunc_expr_missing_operand": "ئبارت ئی ختا: زیان بودین ئمل په $1 ئا",
+ "pfunc_expr_unrecognised_punctuation": "عبارت‌ئی خطا: نقطه‌گذاری نویسگ دروست نه بوت «$1»"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/bho.json b/www/wiki/extensions/ParserFunctions/i18n/bho.json
new file mode 100644
index 00000000..408d03f7
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/bho.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "SatyamMishra"
+ ]
+ },
+ "pfunc_time_error": "खराबी: अबैध समय।",
+ "pfunc_expr_unrecognised_word": "एक्सप्रेशन खराबी: नामालूम शब्द \"$1\"।",
+ "pfunc_expr_unexpected_operator": "एक्सप्रेशन खराबी: $1 आपरेटर जेकर उमेद ना रहल।",
+ "pfunc_expr_missing_operand": "एक्सप्रेशन खराबी: $1 खातिर गायब क्रिया-चीन्हा (Operand)!",
+ "pfunc_expr_unrecognised_punctuation": "एक्सप्रेशन खराबी: नामालूम चीन्हा \"$1\"।",
+ "pfunc_expr_division_by_zero": "जीरो से भाग."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/bn.json b/www/wiki/extensions/ParserFunctions/i18n/bn.json
new file mode 100644
index 00000000..4db5a5d9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/bn.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bellayet",
+ "Zaheen",
+ "Aftabuzzaman"
+ ]
+ },
+ "pfunc_desc": "লজিকাল ফাংশন দিয়ে পার্সারকে উন্নত করুন",
+ "pfunc_time_error": "ত্রুটি: অবৈধ সময়",
+ "pfunc_time_too_long": "ত্রুটি: অত্যধিক সংখ্যক #time কল",
+ "pfunc_time_too_big": "ত্রুটি: #time শুধুমাত্র ৯৯৯৯ পর্যন্ত বছর সমর্থন করে।",
+ "pfunc_time_too_small": "ত্রুটি: #time শুধুমাত্র ০ থেকে বছর সমর্থন করে।",
+ "pfunc_rel2abs_invalid_depth": "ত্রুটি: পাথে অবৈধ গভীরতা: \"$1\" (মূল নোডের উপরের একটি নোড অ্যাক্সেস করতে চেষ্টা করেছিল)",
+ "pfunc_expr_stack_exhausted": "এক্সপ্রেশন ত্রুটি: স্ট্যাক শেষ হয়ে গেছে।",
+ "pfunc_expr_unexpected_number": "এক্সপ্রেশন ত্রুটি: অযাচিত সংখ্যা।",
+ "pfunc_expr_preg_match_failure": "এক্সপ্রেশন ত্রুটি: অযাচিত preg_match ব্যর্থতা।",
+ "pfunc_expr_unrecognised_word": "এক্সপ্রেশন ত্রুটি: অপরিচিত শব্দ \"$1\"।",
+ "pfunc_expr_unexpected_operator": "এক্সপ্রেশন ত্রুটি: অযাচিত $1 অপারেটর।",
+ "pfunc_expr_missing_operand": "এক্সপ্রেশন ত্রুটি: $1-এর জন্য অপারেন্ড নেই।",
+ "pfunc_expr_unexpected_closing_bracket": "এক্সপ্রেশন ত্রুটি: অযাচিত সমাপ্তকারী বন্ধনী।",
+ "pfunc_expr_unrecognised_punctuation": "এক্সপ্রেশন ত্রুটি: অপরিচিত বিরামচিহ্ন অক্ষর \"$1\"।",
+ "pfunc_expr_unclosed_bracket": "এক্সপ্রেশন ত্রুটি: উন্মুক্ত বন্ধনী।",
+ "pfunc_expr_division_by_zero": "শূন্য দ্বারা ভাগ করা হয়েছে।",
+ "pfunc_expr_invalid_argument": "$1 এর জন্য ভুল শর্ত: < -1 অথবা > 1",
+ "pfunc_expr_invalid_argument_ln": "ln এর জন্য অসিদ্ধ শর্ত: <= 0",
+ "pfunc_expr_unknown_error": "এক্সপ্রেশন ত্রুটি: অজানা ত্রুটি ($1)।",
+ "pfunc_expr_not_a_number": "$1 এ: ফলাফল কোন সংখ্যা নয়।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/bqi.json b/www/wiki/extensions/ParserFunctions/i18n/bqi.json
new file mode 100644
index 00000000..df6c7ca4
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/bqi.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mogoeilor"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "خطا جوملإیي: ڤاجإ دسدإ بندي نڤابيڌإ\"$1\".",
+ "pfunc_expr_unexpected_operator": "خطا جمله: عملدیارکن ناخاسدني $1",
+ "pfunc_expr_missing_operand": "خطا جمله ای:عملیار گوم ڤابيڌإ سي $1",
+ "pfunc_expr_unrecognised_punctuation": "خطا جوملإیي: کاراکتر نوقتإ نإهاڌن دأسدإ بندي نڤابيڌإ \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/br.json b/www/wiki/extensions/ParserFunctions/i18n/br.json
new file mode 100644
index 00000000..ca5bab8e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/br.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fulup"
+ ]
+ },
+ "pfunc_desc": "Gwellaat a ra ar parser gant arc'hwelioù poellek",
+ "pfunc_time_error": "Fazi : pad direizh",
+ "pfunc_time_too_long": "Fazi : betek re eo bet galvet #time",
+ "pfunc_time_too_big": "Fazi: #time ne skor nemet bloazioù betek 9999",
+ "pfunc_rel2abs_invalid_depth": "Fazi : Donder direizh evit an hent : \"$1\" (klasket ez eus bet mont d'ul live a-us d'ar c'havlec'h-mamm)",
+ "pfunc_expr_stack_exhausted": "Kemennad faziek : pil riñset",
+ "pfunc_expr_unexpected_number": "Kemennad faziek : niver dic'hortoz",
+ "pfunc_expr_preg_match_failure": "Kemennad faziek : c'hwitadenn dic'hortoz evit preg_match",
+ "pfunc_expr_unrecognised_word": "Kemennad faziek : Ger dianav \"$1\"",
+ "pfunc_expr_unexpected_operator": "Kemennad faziek : Oberier $1 dianav",
+ "pfunc_expr_missing_operand": "Kemennad faziek : Dianav eo operand $1",
+ "pfunc_expr_unexpected_closing_bracket": "Kemennad faziek : Krommell zehoù dic'hortoz",
+ "pfunc_expr_unrecognised_punctuation": "Kemennad faziek : arouezenn boentadouiñ dianav \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Kemennad faziek : Krommell zigor",
+ "pfunc_expr_division_by_zero": "Rannañ dre mann",
+ "pfunc_expr_invalid_argument": "Talvoudenn direizh evit $1: < -1 pe > 1",
+ "pfunc_expr_invalid_argument_ln": "Talvoudenn direizh evit ln: <= 0",
+ "pfunc_expr_unknown_error": "Kemennad faziek : Fazi dianav ($1)",
+ "pfunc_expr_not_a_number": "E $1: An disoc'h n'eo ket un niver",
+ "pfunc_string_too_long": "Fazi : Dreist d'ar vevenn uhelañ a $1 arouezenn eo an neudennad"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/bs.json b/www/wiki/extensions/ParserFunctions/i18n/bs.json
new file mode 100644
index 00000000..96c1a8b7
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/bs.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "CERminator",
+ "Seha",
+ "Srdjan m"
+ ]
+ },
+ "pfunc_desc": "Povisi parser sa logičnim funkcijama",
+ "pfunc_time_error": "Greška: vrijeme nije valjano",
+ "pfunc_time_too_long": "Greška: previše poziva funkcije #time",
+ "pfunc_time_too_big": "Greška: #time samo podržava godine do 9999",
+ "pfunc_time_too_small": "Greška: #time samo podržava godine od 0.",
+ "pfunc_rel2abs_invalid_depth": "Graška: Nevrijedeća dubina u putu: \"$1\" (pokušaj dolaska na nula tačku iza korijenske nula tačke)",
+ "pfunc_expr_stack_exhausted": "Greška izraza: Stok potrošen",
+ "pfunc_expr_unexpected_number": "Greška izraza: Neočekivani broj",
+ "pfunc_expr_preg_match_failure": "Razvojna greška: Neočekivana greška preg-pogotka",
+ "pfunc_expr_unrecognised_word": "Greška izraza: Nepoznata riječ \"$1\"",
+ "pfunc_expr_unexpected_operator": "Greška izraza: Neočekivani $1 operator",
+ "pfunc_expr_missing_operand": "Greška izraza: Nedostaje operator za $1",
+ "pfunc_expr_unexpected_closing_bracket": "Greška izraza: Neočekivana zagrada zatvaranja",
+ "pfunc_expr_unrecognised_punctuation": "Razvojna greška: Nije prepoznat karakter punktacije \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Greška izraza: Nezatvorena zagrada",
+ "pfunc_expr_division_by_zero": "Dijeljenje s nulom",
+ "pfunc_expr_invalid_argument": "Nevažeći argument za $1: : < -1 ili > 1",
+ "pfunc_expr_invalid_argument_ln": "Nevažeći argument za ln: <= 0",
+ "pfunc_expr_unknown_error": "Razvojna greška: Nepoznata greška ($1)",
+ "pfunc_expr_not_a_number": "u $1: rezultat nije broj",
+ "pfunc_string_too_long": "Greška: Niz prelazi limit od $1 znakova"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ca.json b/www/wiki/extensions/ParserFunctions/i18n/ca.json
new file mode 100644
index 00000000..9f14268a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ca.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jordi Roqué",
+ "Qllach",
+ "SMP",
+ "Vriullop"
+ ]
+ },
+ "pfunc_desc": "Millora el processat amb funcions lògiques",
+ "pfunc_time_error": "Error: temps invàlid",
+ "pfunc_time_too_long": "Error: massa crides #time",
+ "pfunc_time_too_big": "Error: #time només admet anys fins al 9999.",
+ "pfunc_time_too_small": "Error: #time només admet anys des de 0.",
+ "pfunc_rel2abs_invalid_depth": "Error: Adreça invàlida al directori: «$1» (s'intentava accedir a un node superior de l'arrel)",
+ "pfunc_expr_stack_exhausted": "Error de l'expressió: Pila exhaurida",
+ "pfunc_expr_unexpected_number": "Error de l'expressió: Nombre inesperat",
+ "pfunc_expr_preg_match_failure": "Error de l'expressió: Error de funció no compresa i inesperada",
+ "pfunc_expr_unrecognised_word": "Error de l'expressió: Paraula no reconeguda \"$1\".",
+ "pfunc_expr_unexpected_operator": "Error de l'expressió: Operador $1 inesperat",
+ "pfunc_expr_missing_operand": "Error de l'expressió: Falta l'operand de $1",
+ "pfunc_expr_unexpected_closing_bracket": "Error de l'expressió: Parèntesi inesperat",
+ "pfunc_expr_unrecognised_punctuation": "Error de l'expressió: Signe de puntuació no reconegut \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Error de l'expressió: Parèntesi no tancat",
+ "pfunc_expr_division_by_zero": "Divisió entre zero",
+ "pfunc_expr_invalid_argument": "Valor no vàlid per a $1: < -1 ó > 1",
+ "pfunc_expr_invalid_argument_ln": "Valor no vàlid per a ln: <= 0",
+ "pfunc_expr_unknown_error": "Error de l'expressió: Desconegut ($1)",
+ "pfunc_expr_not_a_number": "A $1: el resultat no és un nombre",
+ "pfunc_string_too_long": "Error: La cadena és $1 caràcters massa llarga"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ce.json b/www/wiki/extensions/ParserFunctions/i18n/ce.json
new file mode 100644
index 00000000..96c73451
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ce.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sasan700",
+ "Умар"
+ ]
+ },
+ "pfunc_desc": "Дика тайина маьӀнийн функцешца анализатор",
+ "pfunc_time_error": "Гlалато: хан нийса яц",
+ "pfunc_expr_stack_exhausted": "Яздарехь гӀалат ду: хьаладуьззина татол",
+ "pfunc_expr_unrecognised_word": "Яздарехь гӀалат ду: дойзуш доцу дош «$1»",
+ "pfunc_expr_unexpected_operator": "Дешнийн гӀалат: ца хаа оператор $1",
+ "pfunc_expr_unrecognised_punctuation": "Дешнийн гӀалат: евзина йоцу пунктуацин символ «$1»",
+ "pfunc_expr_division_by_zero": "Нолан декъадалар",
+ "pfunc_expr_unknown_error": "Дешнийн гӀалат: ца хаа гӀалат ($1)"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ceb.json b/www/wiki/extensions/ParserFunctions/i18n/ceb.json
new file mode 100644
index 00000000..7c984cab
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ceb.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bentong Isles"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Problema sa ekspresyon: Wa mailhi nga pulong \"$1\".",
+ "pfunc_expr_missing_operand": "Sayop sa ekspresyon: Nawala nga operand sa $1.",
+ "pfunc_expr_unrecognised_punctuation": "Problema sa ekspresyon: Wa mailhi nga karakter \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ckb.json b/www/wiki/extensions/ParserFunctions/i18n/ckb.json
new file mode 100644
index 00000000..2f5a4006
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ckb.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Asoxor",
+ "Lost Whispers",
+ "Muhammed taha",
+ "Épine"
+ ]
+ },
+ "pfunc_time_error": "ھەڵە: کات نادروستە.",
+ "pfunc_expr_unrecognised_word": "ھەڵەی Expression: وشەی نەناسراو \"$1\".",
+ "pfunc_expr_unexpected_operator": "ھەڵەی دەربڕین: کرداری $1 پێشبینی نەکراوە.",
+ "pfunc_expr_missing_operand": "ھەڵەى دەربڕین: کارلەسەکراوی $1 ونبووە.",
+ "pfunc_expr_unrecognised_punctuation": "ھەڵەی دەربڕین: پیتێکی نەناسراو ھەیە \"$1\"",
+ "pfunc_expr_division_by_zero": "دابەشکردن بەسەر سفردا."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/cs.json b/www/wiki/extensions/ParserFunctions/i18n/cs.json
new file mode 100644
index 00000000..fe32aa58
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/cs.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "Danny B.",
+ "Li-sung",
+ "Matěj Grabovský",
+ "Mormegil",
+ "Sp5uhe",
+ "LordMsz"
+ ]
+ },
+ "pfunc_desc": "Rozšíření syntaktického analyzátoru o logické funkce",
+ "pfunc_time_error": "Chyba: neplatný čas",
+ "pfunc_time_too_long": "Chyba: příliš mnoho volání #time",
+ "pfunc_time_too_big": "Chyba: #time nepodporuje roky nad 9999",
+ "pfunc_time_too_small": "Chyba: #time nepodporuje roky menší než 0.",
+ "pfunc_rel2abs_invalid_depth": "Chyba: Neplatná hloubka v cestě: \"$1\" (pokus o přístup do uzlu vyššího než kořen)",
+ "pfunc_expr_stack_exhausted": "Chyba ve výrazu: Zásobník plně obsazen",
+ "pfunc_expr_unexpected_number": "Chyba ve výrazu: Očekáváno číslo",
+ "pfunc_expr_preg_match_failure": "Chyba ve výrazu: Neočekávaná chyba funkce preg_match",
+ "pfunc_expr_unrecognised_word": "Chyba ve výrazu: Nerozpoznané slovo ˆ„$1“.",
+ "pfunc_expr_unexpected_operator": "Chyba ve výrazu: Neočekávaný operátor $1",
+ "pfunc_expr_missing_operand": "Chyba ve výrazu: Chybí operand pro $1",
+ "pfunc_expr_unexpected_closing_bracket": "Chyba ve výrazu: Neočekávaná uzavírací závorka",
+ "pfunc_expr_unrecognised_punctuation": "Chyba ve výrazu: Nerozpoznaný interpunkční znak ˆ„$1“.",
+ "pfunc_expr_unclosed_bracket": "Chyba ve výrazu: Neuzavřené závorky",
+ "pfunc_expr_division_by_zero": "Dělení nulou",
+ "pfunc_expr_invalid_argument": "Neplatný argument pro $1: < -1 nebo > 1",
+ "pfunc_expr_invalid_argument_ln": "Neplatný argument pro ln: <= 0",
+ "pfunc_expr_unknown_error": "Chyba ve výrazu: Neznámá chyba ($1)",
+ "pfunc_expr_not_a_number": "V $1: výsledkem není číslo",
+ "pfunc_string_too_long": "Chyba: Řetězec je delší než $1 {{PLURAL:$1|znak|znaky|znaků}}, což je limit"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/csb.json b/www/wiki/extensions/ParserFunctions/i18n/csb.json
new file mode 100644
index 00000000..c0279ba9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/csb.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kaszeba"
+ ]
+ },
+ "pfunc_time_error": "Fela: lëchi czas",
+ "pfunc_expr_unrecognised_word": "Fela w wësłowieniu – nieznóné słowò „$1”",
+ "pfunc_expr_unexpected_operator": "Fela w wësłowieniu – nieakceptowólny òperatora $1",
+ "pfunc_expr_missing_operand": "Fela wësłowienia – felënk argùmentu fùnkcëji $1",
+ "pfunc_expr_unrecognised_punctuation": "Fela w wësłowieniu – nieznóny interpùnkcjowi mërk \"$1\".",
+ "pfunc_expr_division_by_zero": "Dzélenié przez zero"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/cv.json b/www/wiki/extensions/ParserFunctions/i18n/cv.json
new file mode 100644
index 00000000..ed5e4147
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/cv.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chavash"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Ҫырнинчи йӑнӑш: Палласа илеймен сӑмах: \"$1\"",
+ "pfunc_expr_unrecognised_punctuation": "Ҫырнинчи йӑнӑш: Палласа илеймен паллӑ: $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/cy.json b/www/wiki/extensions/ParserFunctions/i18n/cy.json
new file mode 100644
index 00000000..1563525d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/cy.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lloffiwr",
+ "Diafol"
+ ]
+ },
+ "pfunc_time_error": "Gwall: Amser annilys",
+ "pfunc_time_too_long": "Gwall: Gormod o alwadau #time.",
+ "pfunc_time_too_big": "Gwall: nid yw #time yn cynnal blynyddoedd wedi 9999.",
+ "pfunc_time_too_small": "Gwall: nid yw #time yn cynnal blynyddoedd cyn 0.",
+ "pfunc_expr_unexpected_number": "Gwall yn y mynegiad: Rhif annisgwyl.",
+ "pfunc_expr_unrecognised_word": "Gwall mynegiad: Heb adnabod y gair \"$1\".",
+ "pfunc_expr_unexpected_operator": "Gweithredydd $1 annisgwyl",
+ "pfunc_expr_missing_operand": "Gwall mynegiad: Operand ar gyfer $1 ar goll.",
+ "pfunc_expr_unrecognised_punctuation": "Gwall mynegiad: Heb adnabod y nod atalnodi \"$1\".",
+ "pfunc_expr_unclosed_bracket": "Gwall yn y mynegiad: Cromfach heb ei gau.",
+ "pfunc_expr_division_by_zero": "Yn rhannu gyda sero.",
+ "pfunc_expr_unknown_error": "Gwall yn y mynegiad: Gwall anhysbys ($1).",
+ "pfunc_expr_not_a_number": "Yn $1: Nid yw'r canlyniad yn rhif."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/da.json b/www/wiki/extensions/ParserFunctions/i18n/da.json
new file mode 100644
index 00000000..c31125f1
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/da.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Byrial",
+ "HenrikKbh",
+ "Morten LJ",
+ "Peter Alberti",
+ "Christian List"
+ ]
+ },
+ "pfunc_desc": "Udvider parser med logiske funktioner",
+ "pfunc_time_error": "Fejl: Ugyldig tid",
+ "pfunc_time_too_long": "Fejl: for mange kald af #time",
+ "pfunc_time_too_big": "Fejl: #time understøtter kun årstal frem til 9999",
+ "pfunc_time_too_small": "Fejl: #tid understøtter kun år fra 0.",
+ "pfunc_rel2abs_invalid_depth": "Fejl: Ugyldig dybde i sti: \"$1\" (prøvede at tilgå en knude over rodknuden)",
+ "pfunc_expr_stack_exhausted": "Udtryksfejl: Stak tømt",
+ "pfunc_expr_unexpected_number": "Fejl: Uventet tal",
+ "pfunc_expr_preg_match_failure": "Udtryksfejl: Uventet fejl i preg_match",
+ "pfunc_expr_unrecognised_word": "Udtryksfejl: Ukendt ord \"$1\".",
+ "pfunc_expr_unexpected_operator": "Fejl i udtrykket: Uventet $1-operator.",
+ "pfunc_expr_missing_operand": "Fejl i udtrykket: Operand for $1 mangler",
+ "pfunc_expr_unexpected_closing_bracket": "Udtryksfejl: Uventet lukkende parentes",
+ "pfunc_expr_unrecognised_punctuation": "Udtryksfejl: Uventet tegnsætning-tegn: \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Udtryksfejl: Uafsluttet kantet parantes",
+ "pfunc_expr_division_by_zero": "Division med nul",
+ "pfunc_expr_invalid_argument": "Ugyldigt argument for $1: < -1 eller > 1",
+ "pfunc_expr_invalid_argument_ln": "Ugyldigt argument for ln: <= 0",
+ "pfunc_expr_unknown_error": "Udtryksfejl: Ukendt fejl ($1)",
+ "pfunc_expr_not_a_number": "I $1: Resultatet er ikke et tal",
+ "pfunc_string_too_long": "Fejl: Strengen overskrider grænsen på $1 tegn"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/de-ch.json b/www/wiki/extensions/ParserFunctions/i18n/de-ch.json
new file mode 100644
index 00000000..2f388daf
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/de-ch.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "MichaelFrey"
+ ]
+ },
+ "pfunc_expr_unexpected_closing_bracket": "Expression-Fehler: Unerwartete schliessende eckige Klammer"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/de.json b/www/wiki/extensions/ParserFunctions/i18n/de.json
new file mode 100644
index 00000000..70de3373
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/de.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kghbln",
+ "LWChris",
+ "Metalhead64",
+ "Purodha",
+ "Raimond Spekking",
+ "Rentenirer",
+ "Rillke"
+ ]
+ },
+ "pfunc_desc": "Erweitert den Parser um logische Funktionen",
+ "pfunc_time_error": "Fehler: Ungültige Zeitangabe",
+ "pfunc_time_too_long": "Fehler: Zu viele #time-Aufrufe",
+ "pfunc_time_too_big": "Fehler: #time unterstützt nur Jahre bis 9999",
+ "pfunc_time_too_small": "Fehler: #time unterstützt nur Jahre ab 0.",
+ "pfunc_rel2abs_invalid_depth": "Fehler: Ungültige Pfadtiefe: „$1“ (Zugriff auf einen Knotenpunkt oberhalb des Hauptknotenpunktes ist empfohlen)",
+ "pfunc_expr_stack_exhausted": "Expression-Fehler: Stacküberlauf",
+ "pfunc_expr_unexpected_number": "Expression-Fehler: Unerwartete Zahl",
+ "pfunc_expr_preg_match_failure": "Expression-Fehler: Unerwartete „preg_match“-Fehlfunktion",
+ "pfunc_expr_unrecognised_word": "Fehler im Ausdruck: Unerkanntes Wort „$1“",
+ "pfunc_expr_unexpected_operator": "Fehler im Ausdruck: Unerwarteter Operator $1",
+ "pfunc_expr_missing_operand": "Fehler im Ausdruck: Fehlender Operand für $1",
+ "pfunc_expr_unexpected_closing_bracket": "Expression-Fehler: Unerwartete schließende eckige Klammer",
+ "pfunc_expr_unrecognised_punctuation": "Fehler im Ausdruck: Nicht erkanntes Satzzeichen „$1“",
+ "pfunc_expr_unclosed_bracket": "Expression-Fehler: Nicht geschlossene eckige Klammer",
+ "pfunc_expr_division_by_zero": "Division durch Null",
+ "pfunc_expr_invalid_argument": "Ungültiges Argument für $1: < -1 oder > 1",
+ "pfunc_expr_invalid_argument_ln": "Ungültiges Argument für ln: <= 0",
+ "pfunc_expr_unknown_error": "Expression-Fehler: Unbekannter Fehler ($1)",
+ "pfunc_expr_not_a_number": "In $1: Ergebnis ist keine Zahl",
+ "pfunc_string_too_long": "Fehler: Zeichenkette überschreitet Zeichenlimit von $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/din.json b/www/wiki/extensions/ParserFunctions/i18n/din.json
new file mode 100644
index 00000000..d850c13a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/din.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dinkawiki",
+ "Amire80"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Awöc ë gɔ̈tic: Wët këcrɔtŋic \"$1\".",
+ "pfunc_expr_unexpected_operator": "Awöc ë gɔ̈tic: Këloikëdaŋ $1 ee kuc lɔn ben̈ rɔtlooi.",
+ "pfunc_expr_missing_operand": "Awöc ë gɔ̈tic: $1 acïn kë cath ke ye lëu bï makuën luui thïn.",
+ "pfunc_expr_unrecognised_punctuation": "Awäc cïlooi: Kitëjamtekic këcrɔtŋic \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/diq.json b/www/wiki/extensions/ParserFunctions/i18n/diq.json
new file mode 100644
index 00000000..394bcc64
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/diq.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aspar",
+ "Erdemaslancan",
+ "Gorizon",
+ "Gırd",
+ "1917 Ekim Devrimi"
+ ]
+ },
+ "pfunc_desc": "Peserkerden fonksiyanane mantıxin weş kere",
+ "pfunc_time_error": "xeta: zemano nemeqbul",
+ "pfunc_time_too_long": "xeta:zaf zêd mesajê #timeyi",
+ "pfunc_time_too_big": "Xırabin: #time honke qebuliya cı hetana 9999.",
+ "pfunc_time_too_small": "Xırab: #time ancağ 0 serra beno qebul.",
+ "pfunc_rel2abs_invalid_depth": "Hata: Yolda geçersiz derinlik: \"$1\" (kök düğümünün üstünde bir düğüme erişmeye çalıştı)",
+ "pfunc_expr_stack_exhausted": "İfade yo xırab: stack qedi ya",
+ "pfunc_expr_unexpected_number": "xetay ifadey: amaro bêtexmin",
+ "pfunc_expr_preg_match_failure": "xetay ifadey: arızay preg_matchiyo bêtexmin",
+ "pfunc_expr_unrecognised_word": "Ğeletê ifadekerdışi: Vatekê \"$1\"iyo ke nêşınasiyeno.",
+ "pfunc_expr_unexpected_operator": "xetay ifadey: operatorê $1i yo bêtexmin",
+ "pfunc_expr_missing_operand": "Ğeletê ifadey: Qandë $1'i terimo kemi.",
+ "pfunc_expr_unexpected_closing_bracket": "İfade yo xırab: parantez racnayışo bêtexmin",
+ "pfunc_expr_unrecognised_punctuation": "Ğeletê ifadekerdışi: Karakterê noxtakerdışê \"$1\"iyo ke nêşınasiyeno.",
+ "pfunc_expr_unclosed_bracket": "xetay ifadey: parantezo nêqefelnaye",
+ "pfunc_expr_division_by_zero": "pê sıfır teqsim ker",
+ "pfunc_expr_invalid_argument": "Qande $1 vurnayeno xoser: : < -1 or > 1.",
+ "pfunc_expr_invalid_argument_ln": "Qande Ln vurnayeno xoser: < = 0.",
+ "pfunc_expr_unknown_error": "xetay ifadey: neticeyo ke nêzaniyeno ($1)",
+ "pfunc_expr_not_a_number": "$1 de: netice yew amar niyo",
+ "pfunc_string_too_long": "xeta: rêze heddê karakteri yo $1i veciyaya"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/dsb.json b/www/wiki/extensions/ParserFunctions/i18n/dsb.json
new file mode 100644
index 00000000..b14d29f2
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/dsb.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michawiki"
+ ]
+ },
+ "pfunc_desc": "Rozšyrja parser wó logiske funkcije",
+ "pfunc_time_error": "Zmólka: njepłaśiwy cas",
+ "pfunc_time_too_long": "Zmólka: pśewjele zawołanjow #time",
+ "pfunc_time_too_big": "Zmólka: #time pódpěra jano lěta až do 9999.",
+ "pfunc_time_too_small": "Zmólka: #time pódpěra jano lěta wót 0.",
+ "pfunc_rel2abs_invalid_depth": "Zmólka: Njepłaśiwy dłym w sćažce: \"$1\" (wopyt na suk pśistup měś, kótaryž jo wušej kórjenjowego suka)",
+ "pfunc_expr_stack_exhausted": "Wurazowa zmólka: Stack wupócerany",
+ "pfunc_expr_unexpected_number": "Wurazowa zmólka: Njewócakana licba",
+ "pfunc_expr_preg_match_failure": "Wurazowa zmólka: Njewócakana zmólkata funkcija preg_match",
+ "pfunc_expr_unrecognised_word": "Wurazowa zmólka: Njespóznane słowo \"$1\"",
+ "pfunc_expr_unexpected_operator": "Wurazowa zmólka: Njewócakany opeator $1",
+ "pfunc_expr_missing_operand": "Wurazowa zmólka: Felujucy operand za $1",
+ "pfunc_expr_unexpected_closing_bracket": "Wurazowa zmólka: Njewócakana kóńcajuca rožkata spinka",
+ "pfunc_expr_unrecognised_punctuation": "Wurazowa zmólka: Njespóznane interpunkciske znamuško \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Wurazowa zmólka: Žedna kóńcajuca spinka",
+ "pfunc_expr_division_by_zero": "Diwizija pśez nul",
+ "pfunc_expr_invalid_argument": "Njepłaśiwy argument $1: < -1 abo > 1",
+ "pfunc_expr_invalid_argument_ln": "Njepłaśiwy argument za ln: <= 0",
+ "pfunc_expr_unknown_error": "Wurazowa zmólka: Njeznata zmólka ($1)",
+ "pfunc_expr_not_a_number": "W $1: wuslědk njejo licba",
+ "pfunc_string_too_long": "Zmólka: Znamješkowy rěd pśekčaca limit $1 znamješkow"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/dty.json b/www/wiki/extensions/ParserFunctions/i18n/dty.json
new file mode 100644
index 00000000..f782aab7
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/dty.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "रमेश सिंह बोहरा",
+ "जनक राज भट्ट",
+ "Nirajan pant"
+ ]
+ },
+ "pfunc_time_error": "त्रुटी: अमान्य समय।",
+ "pfunc_expr_unrecognised_word": "अभिव्यक्ति त्रुटि: अज्ञात शब्द \"$1\"।",
+ "pfunc_expr_unexpected_operator": "अभिव्यक्ति त्रुटि र आकस्मिक संचालन $1",
+ "pfunc_expr_missing_operand": "अभिव्यक्ति त्रुटि:संचालन भुलका लागि $1",
+ "pfunc_expr_unrecognised_punctuation": "अभिव्यक्ति त्रुटि: नपछड्याको विराम चिन्ह चरित्र \"$1\"।",
+ "pfunc_expr_division_by_zero": "सुन्ना ले भाग।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ee.json b/www/wiki/extensions/ParserFunctions/i18n/ee.json
new file mode 100644
index 00000000..3765f37e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ee.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aguve"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Nuŋɔŋlɔ ƒe kuxi: Medze si nya \"$1\" o."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/el.json b/www/wiki/extensions/ParserFunctions/i18n/el.json
new file mode 100644
index 00000000..de3ae5d0
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/el.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Consta",
+ "Dead3y3",
+ "Lou",
+ "Omnipaedista",
+ "Protnet",
+ "Απεργός"
+ ]
+ },
+ "pfunc_desc": "Βελτιώνει το συντακτικό αναλυτή με λογικές συναρτήσεις",
+ "pfunc_time_error": "Σφάλμα: Μη έγκυρος χρόνος",
+ "pfunc_time_too_long": "Σφάλμα: πάρα πολλές κλήσεις της #time",
+ "pfunc_time_too_big": "Σφάλμα: το #time υποστηρίζει έτη μέχρι το 9999.",
+ "pfunc_rel2abs_invalid_depth": "Σφάλμα: Άκυρο βάθος στη διαδρομή: «$1» (έγινε προσπάθεια για πρόσβαση σε έναν κόμβο πάνω από τον ριζικό κόμβο)",
+ "pfunc_expr_stack_exhausted": "Σφάλμα έκφρασης: Η στοίβα εξαντλήθηκε",
+ "pfunc_expr_unexpected_number": "Σφάλμα έκφρασης: Μη αναμενόμενος αριθμός",
+ "pfunc_expr_preg_match_failure": "Σφάλμα έκφρασης: Μη αναμενόμενη αποτυχία preg_match",
+ "pfunc_expr_unrecognised_word": "Σφάλμα έκφρασης: Μη αναγνωρίσιμη λέξη \"$1\"",
+ "pfunc_expr_unexpected_operator": "Σφάλμα έκφρασης: Μη αναμενόμενος τελεστής $1",
+ "pfunc_expr_missing_operand": "Σφάλμα έκφρασης: Λείπει ο τελεστέος για την έκφραση $1",
+ "pfunc_expr_unexpected_closing_bracket": "Σφάλμα έκφρασης: Μη αναμενόμενη αγκύλη κλεισίματος",
+ "pfunc_expr_unrecognised_punctuation": "Σφάλμα έκφρασης: Μη αναγνωρίσμος χαρακτήρας στίξης \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Σφάλμα έκφρασης: Αγκύλη χωρίς κλείσιμο",
+ "pfunc_expr_division_by_zero": "Διαίρεση με το μηδέν",
+ "pfunc_expr_invalid_argument": "Άκυρη παράμετρος για το $1: < -1 ή > 1",
+ "pfunc_expr_invalid_argument_ln": "Άκυρη παράμετρος για το ln: <= 0",
+ "pfunc_expr_unknown_error": "Σφάλμα έκφρασης: Άγνωστο σφάλμα ($1)",
+ "pfunc_expr_not_a_number": "Στο $1: το αποτέλεσμα δεν είναι αριθμός",
+ "pfunc_string_too_long": "Σφάλμα: Η συμβολοσειρά υπερβαίνει το όριο {{PLURAL:$1|του 1 χαρακτήρα|των $1 χαρακτήρων}}."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/en-gb.json b/www/wiki/extensions/ParserFunctions/i18n/en-gb.json
new file mode 100644
index 00000000..6c7d8b8e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/en-gb.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shirayuki"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Expression error: Unrecognised word \"$1\".",
+ "pfunc_expr_unrecognised_punctuation": "Expression error: Unrecognised punctuation character \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/en.json b/www/wiki/extensions/ParserFunctions/i18n/en.json
new file mode 100644
index 00000000..aac50eab
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/en.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": []
+ },
+ "pfunc_desc": "Enhance parser with logical functions",
+ "pfunc_time_error": "Error: Invalid time.",
+ "pfunc_time_too_long": "Error: Too many #time calls.",
+ "pfunc_time_too_big": "Error: #time only supports years up to 9999.",
+ "pfunc_time_too_small": "Error: #time only supports years from 0.",
+ "pfunc_rel2abs_invalid_depth": "Error: Invalid depth in path: \"$1\" (tried to access a node above the root node).",
+ "pfunc_expr_stack_exhausted": "Expression error: Stack exhausted.",
+ "pfunc_expr_unexpected_number": "Expression error: Unexpected number.",
+ "pfunc_expr_preg_match_failure": "Expression error: Unexpected preg_match failure.",
+ "pfunc_expr_unrecognised_word": "Expression error: Unrecognized word \"$1\".",
+ "pfunc_expr_unexpected_operator": "Expression error: Unexpected $1 operator.",
+ "pfunc_expr_missing_operand": "Expression error: Missing operand for $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Expression error: Unexpected closing bracket.",
+ "pfunc_expr_unrecognised_punctuation": "Expression error: Unrecognized punctuation character \"$1\".",
+ "pfunc_expr_unclosed_bracket": "Expression error: Unclosed bracket.",
+ "pfunc_expr_division_by_zero": "Division by zero.",
+ "pfunc_expr_invalid_argument": "Invalid argument for $1: < -1 or > 1.",
+ "pfunc_expr_invalid_argument_ln": "Invalid argument for ln: <= 0.",
+ "pfunc_expr_unknown_error": "Expression error: Unknown error ($1).",
+ "pfunc_expr_not_a_number": "In $1: Result is not a number.",
+ "pfunc_string_too_long": "Error: String exceeds $1 character limit."
+} \ No newline at end of file
diff --git a/www/wiki/extensions/ParserFunctions/i18n/eo.json b/www/wiki/extensions/ParserFunctions/i18n/eo.json
new file mode 100644
index 00000000..87445ac7
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/eo.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Yekrats",
+ "Lucas"
+ ]
+ },
+ "pfunc_desc": "Etendi sintaksan analizilon kun logikaj funkcioj",
+ "pfunc_time_error": "Eraro: malvalida tempo",
+ "pfunc_time_too_long": "Eraro: tro da vokoj ''#time''",
+ "pfunc_time_too_big": "Eraro: #time nur subtenas jaroj ĝis 9999.",
+ "pfunc_rel2abs_invalid_depth": "Eraro: Malvalida profundo en vojo: \"$1\" (provis atingi nodon super la radika nodo)",
+ "pfunc_expr_stack_exhausted": "Esprima eraro: Stako estis malplenigita",
+ "pfunc_expr_unexpected_number": "Esprima eraro: Neatendita numeralo",
+ "pfunc_expr_preg_match_failure": "Esprima eraro: Neatendita preg_match malsukceso",
+ "pfunc_expr_unrecognised_word": "Esprima eraro: Nekonata vorto “$1”.",
+ "pfunc_expr_unexpected_operator": "Esprima eraro: Neatendita operacisimbolo $1",
+ "pfunc_expr_missing_operand": "Esprima eraro: Mankas operando por $1",
+ "pfunc_expr_unexpected_closing_bracket": "Esprima eraro: Neatendita ferma krampo",
+ "pfunc_expr_unrecognised_punctuation": "Esprima eraro: Nekonata interpunkcia simbolo “$1”.",
+ "pfunc_expr_unclosed_bracket": "Esprima eraro: Malferma krampo",
+ "pfunc_expr_division_by_zero": "Divido per nulo",
+ "pfunc_expr_invalid_argument": "Malvalida argumento por $1: < -1 or > 1",
+ "pfunc_expr_invalid_argument_ln": "Malvalida argumento por ln: <= 0",
+ "pfunc_expr_unknown_error": "Esprima eraro: Nekonata eraro ($1)",
+ "pfunc_expr_not_a_number": "En $1: rezulto ne estas nombro",
+ "pfunc_string_too_long": "Eraro: Ĉeno preterpasas signo-limon $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/es.json b/www/wiki/extensions/ParserFunctions/i18n/es.json
new file mode 100644
index 00000000..68650967
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/es.json
@@ -0,0 +1,35 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bernardom",
+ "Crazymadlover",
+ "Fitoschido",
+ "Muro de Aguas",
+ "Remember the dot",
+ "Sanbec",
+ "Macofe",
+ "Ryo567"
+ ]
+ },
+ "pfunc_desc": "Mejora el analizador con funciones lógicas.",
+ "pfunc_time_error": "Error: fecha y hora no válidos.",
+ "pfunc_time_too_long": "Error: demasiados \"#time\".",
+ "pfunc_time_too_big": "Error: #time solo admite años hasta 9999.",
+ "pfunc_time_too_small": "Error: #time solo admite años desde 0.",
+ "pfunc_rel2abs_invalid_depth": "Error: profundidad no válida en la ruta «$1» (trataste de acceder a un nodo por encima de la raíz).",
+ "pfunc_expr_stack_exhausted": "Error en la expresión: pila agotada.",
+ "pfunc_expr_unexpected_number": "Error en la expresión: número no esperado.",
+ "pfunc_expr_preg_match_failure": "Error en la expresión: fallo no esperado de \"preg_match\".",
+ "pfunc_expr_unrecognised_word": "Error en la expresión: no se reconoce la palabra «$1».",
+ "pfunc_expr_unexpected_operator": "Error en la expresión: operador $1 no esperado.",
+ "pfunc_expr_missing_operand": "Error en la expresión: falta un operando para $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Error en la expresión: paréntesis de cierre no esperado.",
+ "pfunc_expr_unrecognised_punctuation": "Error en la expresión: no se reconoce el carácter de puntuación «$1».",
+ "pfunc_expr_unclosed_bracket": "Error en la expresión: paréntesis sin cerrar.",
+ "pfunc_expr_division_by_zero": "División por cero.",
+ "pfunc_expr_invalid_argument": "Argumento no válido para $1: < -1 o > 1.",
+ "pfunc_expr_invalid_argument_ln": "Argumento incorrecto para ln: <= 0.",
+ "pfunc_expr_unknown_error": "Error en la expresión: error desconocido ($1).",
+ "pfunc_expr_not_a_number": "En $1: el resultado no es un número.",
+ "pfunc_string_too_long": "Error: la cadena excede el límite de $1 caracteres."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/et.json b/www/wiki/extensions/ParserFunctions/i18n/et.json
new file mode 100644
index 00000000..ba832d29
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/et.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pikne"
+ ]
+ },
+ "pfunc_desc": "Laiendab parserit loogiliste funktsioonidega.",
+ "pfunc_time_error": "Tõrge: Vigane aeg",
+ "pfunc_time_too_long": "Tõrge: Liiga palju #time-kutseid.",
+ "pfunc_time_too_big": "Tõrge: #time toetab vaid aastaid kuni väärtuseni 9999.",
+ "pfunc_time_too_small": "Tõrge: #time toetab aastaid alates 0-st.",
+ "pfunc_rel2abs_invalid_depth": "Tõrge: Vigane tee pikkus: \"$1\" (üritati pöörduda juursõlmest kõrgema sõlme poole).",
+ "pfunc_expr_unexpected_number": "Avaldistõrge: Ootamatu number",
+ "pfunc_expr_preg_match_failure": "Avaldistõrge: preg_match nurjus ootamatult.",
+ "pfunc_expr_unrecognised_word": "Avaldistõrge: Tundmatu sõna \"$1\"",
+ "pfunc_expr_unexpected_operator": "Avaldistõrge: Ootamatu $1-tehtemärk",
+ "pfunc_expr_missing_operand": "Avaldistõrge: Puudub $1-tehte operand",
+ "pfunc_expr_unexpected_closing_bracket": "Avaldistõrge: Ootamatu lõpusulg",
+ "pfunc_expr_unrecognised_punctuation": "Avaldistõrge: Tundmatu kirjavahemärk \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Avaldistõrge: sulgemata sulud",
+ "pfunc_expr_division_by_zero": "Nulliga jagamine",
+ "pfunc_expr_invalid_argument": "Vigane $1-tehte argument: < -1 või > 1",
+ "pfunc_expr_invalid_argument_ln": "Vigane ln-tehte argument: <= 0",
+ "pfunc_expr_unknown_error": "Avaldistõrge: Tundmatu tõrge ($1).",
+ "pfunc_expr_not_a_number": "$1-tehtes: Vastus pole number",
+ "pfunc_string_too_long": "Tõrge: Sõne ületab $1 märgi piirangu."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/eu.json b/www/wiki/extensions/ParserFunctions/i18n/eu.json
new file mode 100644
index 00000000..eb631a43
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/eu.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "An13sa",
+ "Kobazulo",
+ "Theklan",
+ "Xabier Armendaritz"
+ ]
+ },
+ "pfunc_time_error": "Errorea: baliogabeko ordua",
+ "pfunc_time_too_long": "Errorea: #time dei gehiegi",
+ "pfunc_time_too_big": "Errorea: #time funtzioak 9999 urtera arte funtzionatzen du bakarrik",
+ "pfunc_rel2abs_invalid_depth": "Errorea: «$1» bide-izenean, sakonera baliogabea da (errotik gora dagoen nodo batera sartzen saiatu zara)",
+ "pfunc_expr_unexpected_number": "Adierazpen errorea: Ustekabeko zenbakia",
+ "pfunc_expr_unrecognised_word": "Adierazpen errorea: Hitz ezezaguna \"$1\"",
+ "pfunc_expr_unexpected_operator": "Adierazpen errorea: Ustekabeko $1 eragilea",
+ "pfunc_expr_missing_operand": "Espresio akatsa: Ez dago operadorerik $1(r)entzat",
+ "pfunc_expr_unexpected_closing_bracket": "Adierazpen errorea: Ustekabeko kortxete itxiera",
+ "pfunc_expr_unrecognised_punctuation": "Adierazpen errorea: puntuazio karaktere ezezaguna \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Adierazpen errorea: Itxi gabeko kortxetea",
+ "pfunc_expr_division_by_zero": "Zeroz zatitu",
+ "pfunc_expr_invalid_argument": "Argumentu okerra ondorengoarentzat: $1: < -1 edo > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumentu okerra ondorengoarentzat: ln: <= 0",
+ "pfunc_expr_unknown_error": "Adierazpen errorea: errore ezezaguna ($1)",
+ "pfunc_expr_not_a_number": "$1-(e)n: emaitza ez da zenbaki bat",
+ "pfunc_string_too_long": "Errorea: hitzak $1 karaktereko muga gainditzen du"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/fa.json b/www/wiki/extensions/ParserFunctions/i18n/fa.json
new file mode 100644
index 00000000..81a39762
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/fa.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Ebraminio",
+ "Huji",
+ "Reza1615",
+ "Wayiran"
+ ]
+ },
+ "pfunc_desc": "به تجزیه‌گر، دستورهای منطقی می‌افزاید",
+ "pfunc_time_error": "خطا: زمان نامجاز",
+ "pfunc_time_too_long": "خطا: فراخوانی بیش از حد #time",
+ "pfunc_time_too_big": "خطا: #زمان تا سال ۹۹۹۹ را فقط حمایت می‌کند.",
+ "pfunc_time_too_small": "خطا: #time تنها از سال 0 به بعد را پشتیبانی می‌کند.",
+ "pfunc_rel2abs_invalid_depth": "خطا: عمق نامجاز در نشانی «$1» (تلاش برای دسترسی به یک نشانی فراتر از نشانی ریشه)",
+ "pfunc_expr_stack_exhausted": "خطای عبارت: پشته از دست رفته",
+ "pfunc_expr_unexpected_number": "خطای عبارت: عدد دور از انتظار",
+ "pfunc_expr_preg_match_failure": "خطای عبارت: خطای preg_match دور از انتظار",
+ "pfunc_expr_unrecognised_word": "خطای عبارت: کلمه ناشناخته «$1»",
+ "pfunc_expr_unexpected_operator": "خطای عبارت: عملگر $1 دور از انتظار",
+ "pfunc_expr_missing_operand": "خطای عبارت: عملگر گمشده برای $1",
+ "pfunc_expr_unexpected_closing_bracket": "خطای عبارت: پرانتز بسته اضافی",
+ "pfunc_expr_unrecognised_punctuation": "خطای عبارت: نویسه نقطه‌گذاری شناخته نشده «$1»",
+ "pfunc_expr_unclosed_bracket": "خطای عبارت: پرانتز بسته‌نشده",
+ "pfunc_expr_division_by_zero": "تقسیم بر صفر",
+ "pfunc_expr_invalid_argument": "پارامتر نامجاز برای $1: < -۱ یا > ۱",
+ "pfunc_expr_invalid_argument_ln": "پارامتر نامجاز برای لگاریتم طبیعی: <= صفر",
+ "pfunc_expr_unknown_error": "خطای عبارت: خطای ناشناخته ($1)",
+ "pfunc_expr_not_a_number": "در $1: نتیجه عدد نیست",
+ "pfunc_string_too_long": "خطا: رشته از محدودیت نویسه‌ای $1 تجاوز می‌کند"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/fi.json b/www/wiki/extensions/ParserFunctions/i18n/fi.json
new file mode 100644
index 00000000..ed4511ab
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/fi.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Agony",
+ "Cimon Avaro",
+ "Linnea",
+ "Nike",
+ "VezonThunder"
+ ]
+ },
+ "pfunc_desc": "Laajentaa jäsennintä loogisilla funktiolla.",
+ "pfunc_time_error": "Virhe: kelvoton aika",
+ "pfunc_time_too_long": "Virhe: liian monta #time-kutsua",
+ "pfunc_time_too_big": "Virhe: #time tukee vuosilukuja vain vuoteen 9999 asti.",
+ "pfunc_time_too_small": "Virhe: #time tukee vain vuosia 0:sta eteenpäin.",
+ "pfunc_rel2abs_invalid_depth": "Virhe: Virheellinen syvyys polussa: $1 (ei juurisolmun sisällä)",
+ "pfunc_expr_stack_exhausted": "Virhe lausekkeessa: pino loppui",
+ "pfunc_expr_unexpected_number": "Virhe lausekkeessa: odottamaton numero",
+ "pfunc_expr_preg_match_failure": "Virhe lausekkeessa: preg_match palautti virheen",
+ "pfunc_expr_unrecognised_word": "Virhe lausekkeessa: tunnistamaton sana ”$1”",
+ "pfunc_expr_unexpected_operator": "Virhe lausekkeessa: odottamaton $1-operaattori",
+ "pfunc_expr_missing_operand": "Virhe lausekkeessa: operaattorin $1 edellyttämä operandi puuttuu",
+ "pfunc_expr_unexpected_closing_bracket": "Virhe lausekkeessa: odottamaton sulkeva sulkumerkki",
+ "pfunc_expr_unrecognised_punctuation": "Virhe lausekkeessa: tunnistamaton välimerkki ”$1”",
+ "pfunc_expr_unclosed_bracket": "Virhe ilmauksessa: sulkeva sulkumerkki puuttuu",
+ "pfunc_expr_division_by_zero": "Virhe: Jako nollalla",
+ "pfunc_expr_invalid_argument": "Virheellinen arvo $1: < -1 tai > 1",
+ "pfunc_expr_invalid_argument_ln": "Virheellinen arvo funktiolle ln: <= 0",
+ "pfunc_expr_unknown_error": "Virhe lausekkeessa: tuntematon virhe ($1)",
+ "pfunc_expr_not_a_number": "Lausekkeessa $1: tulos ei ole luku",
+ "pfunc_string_too_long": "Virhe: Merkkijono ylittää $1 merkin ylärajan"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/fo.json b/www/wiki/extensions/ParserFunctions/i18n/fo.json
new file mode 100644
index 00000000..7a15c860
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/fo.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "EileenSanda"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Feilur í frágreiðing: Ókent orð \"$1\".",
+ "pfunc_expr_unexpected_operator": "Feilur í málbering: Óvæntaður $1 operatorur.",
+ "pfunc_expr_missing_operand": "Feilur í málburði: Manglandi operandur fyri $1.",
+ "pfunc_expr_unrecognised_punctuation": "Feilur í frágreiðing: Ókend teknseting \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/fr.json b/www/wiki/extensions/ParserFunctions/i18n/fr.json
new file mode 100644
index 00000000..9c2489a8
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/fr.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Crochet.david",
+ "Gomoko",
+ "Grondin",
+ "Hashar",
+ "IAlex",
+ "Od1n",
+ "Sherbrooke",
+ "Urhixidur",
+ "Verdy p"
+ ]
+ },
+ "pfunc_desc": "Améliore l’analyseur syntaxique avec des fonctions logiques",
+ "pfunc_time_error": "Erreur : durée invalide.",
+ "pfunc_time_too_long": "Erreur : appels trop nombreux à #time.",
+ "pfunc_time_too_big": "Erreur : #time prend uniquement en charge des années jusqu’à 9999.",
+ "pfunc_time_too_small": "Erreur : #time prend uniquement en charge les années à partir de 0.",
+ "pfunc_rel2abs_invalid_depth": "Erreur : profondeur invalide dans le chemin « $1 » (a essayé d’accéder à un niveau au-dessus du nœud racine).",
+ "pfunc_expr_stack_exhausted": "Erreur d’expression : pile épuisée.",
+ "pfunc_expr_unexpected_number": "Erreur d’expression : nombre inattendu.",
+ "pfunc_expr_preg_match_failure": "Erreur d’expression : échec inattendu de preg_match.",
+ "pfunc_expr_unrecognised_word": "Erreur d’expression : mot « $1 » non reconnu.",
+ "pfunc_expr_unexpected_operator": "Erreur d’expression : opérateur '''$1''' inattendu.",
+ "pfunc_expr_missing_operand": "Erreur d’expression : opérande manquant pour '''$1'''.",
+ "pfunc_expr_unexpected_closing_bracket": "Erreur d’expression : parenthèse fermante inattendue.",
+ "pfunc_expr_unrecognised_punctuation": "Erreur d’expression : caractère de ponctuation « $1 » non reconnu.",
+ "pfunc_expr_unclosed_bracket": "Erreur d’expression : parenthèse non fermée.",
+ "pfunc_expr_division_by_zero": "Division par zéro.",
+ "pfunc_expr_invalid_argument": "Paramètre incorrect pour '''$1''' : < -1 ou > 1.",
+ "pfunc_expr_invalid_argument_ln": "Paramètre incorrect pour '''ln''' : ≤ 0.",
+ "pfunc_expr_unknown_error": "Erreur d’expression : erreur inconnue ($1).",
+ "pfunc_expr_not_a_number": "Dans $1 : le résultat n’est pas un nombre.",
+ "pfunc_string_too_long": "Erreur : La chaîne dépasse la limite maximale de $1 caractère{{PLURAL:$1||s}}."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/frp.json b/www/wiki/extensions/ParserFunctions/i18n/frp.json
new file mode 100644
index 00000000..77f08cdc
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/frp.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "ChrisPtDe"
+ ]
+ },
+ "pfunc_desc": "Mèlyore lo parsor avouéc des fonccions logiques.",
+ "pfunc_time_error": "Fôta : temps pas justo",
+ "pfunc_time_too_long": "Èrror : trop grant nombro d’apèls a #time",
+ "pfunc_rel2abs_invalid_depth": "Èrror : provondior envalida dens lo chemin « $1 » (at tâchiê d’arrevar a un nivél en-dessus du nuod racena)",
+ "pfunc_expr_stack_exhausted": "Èrror d’èxprèssion : pila èpouesiê",
+ "pfunc_expr_unexpected_number": "Èrror d’èxprèssion : nombro emprèvu",
+ "pfunc_expr_preg_match_failure": "Èrror d’èxprèssion : falyita emprèvua de preg_match",
+ "pfunc_expr_unrecognised_word": "Fôta d’èxprèssion : mot « $1 » pas recognu.",
+ "pfunc_expr_unexpected_operator": "Fôta d’èxprèssion : opèrator « $1 » emprèviu",
+ "pfunc_expr_missing_operand": "Fôta d’èxprèssion : opèrando manquent por « $1 ».",
+ "pfunc_expr_unexpected_closing_bracket": "Èrror d’èxprèssion : parentèsa cllosenta emprèvua",
+ "pfunc_expr_unrecognised_punctuation": "Fôta d’èxprèssion : caractèro de ponctuacion « $1 » pas recognu.",
+ "pfunc_expr_unclosed_bracket": "Èrror d’èxprèssion : parentèsa pas cllôsa",
+ "pfunc_expr_division_by_zero": "Division per zérô.",
+ "pfunc_expr_invalid_argument": "Argument fôx por « $1 » : < -1 ou ben > 1",
+ "pfunc_expr_invalid_argument_ln": "Argument fôx por « ln » : ≤ 0",
+ "pfunc_expr_unknown_error": "Èrror d’èxprèssion : èrror encognua ($1)",
+ "pfunc_expr_not_a_number": "Dens $1 : lo rèsultat est pas un nombro",
+ "pfunc_string_too_long": "Èrror : la chêna dèpâsse la limita d’amont de $1 caractèro{{PLURAL:$1||s}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/frr.json b/www/wiki/extensions/ParserFunctions/i18n/frr.json
new file mode 100644
index 00000000..842ab93f
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/frr.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Murma174"
+ ]
+ },
+ "pfunc_time_error": "Feeler: Ferkiard tidj",
+ "pfunc_expr_unrecognised_word": "Tiaken-feeler: Ünbekäänd wurd \"$1\"",
+ "pfunc_expr_unexpected_operator": "Tiaken-feeler: Ünbekäänd operaator $1",
+ "pfunc_expr_missing_operand": "Tiaken-feeler: Operand för $1 ei diar",
+ "pfunc_expr_unrecognised_punctuation": "Tiaken-feeler: Ünbekäänd tiaken \"$1\"",
+ "pfunc_expr_division_by_zero": "Dialen troch nul."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/fur.json b/www/wiki/extensions/ParserFunctions/i18n/fur.json
new file mode 100644
index 00000000..534886d9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/fur.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Tocaibon"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Erôr inte espression: peraule \"$1\" no ricognossude.",
+ "pfunc_expr_unexpected_operator": "Erôr inte espression: operatôr $1 no spietât.",
+ "pfunc_expr_missing_operand": "Erôr inte espression: la mancje un operandôr par $1.",
+ "pfunc_expr_unrecognised_punctuation": "Erôt inte espression: segn di puntegjature \"$1\" no ricognossût."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/gcr.json b/www/wiki/extensions/ParserFunctions/i18n/gcr.json
new file mode 100644
index 00000000..e8c845a0
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/gcr.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "LeGuyanaisPure"
+ ]
+ },
+ "pfunc_time_error": "Éròr : douré envalid.",
+ "pfunc_expr_unrecognised_word": "Éròr d’èksprésyon : mo « $1 » pa roukonèt.",
+ "pfunc_expr_unexpected_operator": "Éròr d’èksprésyon : opératò '''$1''' inatandou.",
+ "pfunc_expr_missing_operand": "Éròr d’èksprésyon : opérand mankan pou '''$1'''.",
+ "pfunc_expr_unrecognised_punctuation": "Éròr d’èksprésyon : karaktèr di ponktchwasyon « $1 » pa roukonèt.",
+ "pfunc_expr_division_by_zero": "Divizyon pa zéro."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/gd.json b/www/wiki/extensions/ParserFunctions/i18n/gd.json
new file mode 100644
index 00000000..e6e9b2e0
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/gd.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "GunChleoc",
+ "Akerbeltz"
+ ]
+ },
+ "pfunc_time_error": "Mearachd: Àm mì-dhligheach.",
+ "pfunc_expr_unrecognised_word": "Marachd eas-preisein: Chan aithne dhuinn am facal \"$1\".",
+ "pfunc_expr_unexpected_operator": "Mearachd eas-preisein: Gnìomharaiche $1 ris nach robh dùil.",
+ "pfunc_expr_missing_operand": "Mearachd eas-preisein: Tha oparand a dhìth airson $1.",
+ "pfunc_expr_unrecognised_punctuation": "Mearachd eas-preisein: Chan aithne dhuinn an caractar puingeachaidh \"$1\".",
+ "pfunc_expr_division_by_zero": "Roinneadh le neoini."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/gl.json b/www/wiki/extensions/ParserFunctions/i18n/gl.json
new file mode 100644
index 00000000..386c15cb
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/gl.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alma",
+ "Elisardojm",
+ "Toliño",
+ "Xosé"
+ ]
+ },
+ "pfunc_desc": "Mellora o analizador con funcións lóxicas",
+ "pfunc_time_error": "Erro: Hora non válida.",
+ "pfunc_time_too_long": "Erro: Demasiadas chamadas #time.",
+ "pfunc_time_too_big": "Erro: #time só permite anos ata o 9999.",
+ "pfunc_time_too_small": "Erro: #time só permite anos desde o 0.",
+ "pfunc_rel2abs_invalid_depth": "Erro: Profundidade da ruta non válida: \"$1\" (intentouse acceder a un nodo por riba do nodo raíz).",
+ "pfunc_expr_stack_exhausted": "Erro de expresión: Pila esgotada.",
+ "pfunc_expr_unexpected_number": "Erro de expresión: Número inesperado.",
+ "pfunc_expr_preg_match_failure": "Erro de expresión: Fallo de preg_match inesperado.",
+ "pfunc_expr_unrecognised_word": "Erro de expresión: Descoñécese a palabra \"$1\".",
+ "pfunc_expr_unexpected_operator": "Erro de expresión: Operador \"$1\" inesperado.",
+ "pfunc_expr_missing_operand": "Erro de expresión: Falta un operador para $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Erro de expresión: Corchete de peche inesperado.",
+ "pfunc_expr_unrecognised_punctuation": "Erro de expresión: Descoñécese o signo de puntuación \"$1\".",
+ "pfunc_expr_unclosed_bracket": "Erro de expresión: Paréntese sen pechar.",
+ "pfunc_expr_division_by_zero": "División por cero.",
+ "pfunc_expr_invalid_argument": "Argumento inválido para $1: < -1 ou > 1.",
+ "pfunc_expr_invalid_argument_ln": "Argumento inválido para ln: <= 0.",
+ "pfunc_expr_unknown_error": "Erro de expresión: Erro descoñecido ($1).",
+ "pfunc_expr_not_a_number": "En $1: O resultado non é un número.",
+ "pfunc_string_too_long": "Erro: A cadea excede o límite de $1 caracteres."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/glk.json b/www/wiki/extensions/ParserFunctions/i18n/glk.json
new file mode 100644
index 00000000..dd58b646
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/glk.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "شیخ"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "عبارتˇ سأب: ناشناخته کلمه «$1»",
+ "pfunc_expr_unrecognised_punctuation": "عبارتˇ سأب: نۊقطه نأني وؤت بشناخته نۊبؤ «$1»"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/gom-deva.json b/www/wiki/extensions/ParserFunctions/i18n/gom-deva.json
new file mode 100644
index 00000000..88aabea1
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/gom-deva.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Konknni mogi 24",
+ "Supriya kankumbikar"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "अभिव्यक्तींत त्रुटीः अनवळखी उतर \"$1\".",
+ "pfunc_expr_unexpected_operator": "अभिव्यक्ती त्रुटी: अनवळखी $1 कार्यवाहक",
+ "pfunc_expr_missing_operand": "अभिव्यक्ती त्रुटि: $1 चो घटक मेळूंक ना",
+ "pfunc_expr_unrecognised_punctuation": "अभिव्यक्तींत त्रुटीः अनपेक्षीत उदगार चिन्ह \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/gom-latn.json b/www/wiki/extensions/ParserFunctions/i18n/gom-latn.json
new file mode 100644
index 00000000..0810281a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/gom-latn.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "The Discoverer"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Abhivyaktint chuk: Onolkhi utor: $1",
+ "pfunc_expr_unexpected_operator": "Abhivyaktint chuk: Onolkhi karyavahak: $1",
+ "pfunc_expr_missing_operand": "Abhivyaktint chuk: $1 cho ghotok mellunk na.",
+ "pfunc_expr_unrecognised_punctuation": "Abhivyaktint chuk: Onolkhi udgar chinh \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/gor.json b/www/wiki/extensions/ParserFunctions/i18n/gor.json
new file mode 100644
index 00000000..b6e8c971
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/gor.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Marwan Mohamad"
+ ]
+ },
+ "pfunc_time_error": "Tilala:wakutu diila banari",
+ "pfunc_expr_unrecognised_word": "Tilala ekspresi: Tahe \"$1\" diila iloonuhe.",
+ "pfunc_expr_unexpected_operator": "Ekspresi tilala: Operator $1 ja ilotaawa",
+ "pfunc_expr_missing_operand": "Ekspresi tilala: Operasi diila yilotapu $1",
+ "pfunc_expr_unrecognised_punctuation": "Tilala ekspresi:Watade lo tanda baca \"$1\" diila oonuhe.",
+ "pfunc_expr_division_by_zero": "Tilayadu noolo"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/grc.json b/www/wiki/extensions/ParserFunctions/i18n/grc.json
new file mode 100644
index 00000000..42b1df78
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/grc.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Omnipaedista",
+ "Gts-tg"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Σφάλμα ἐκφράσεως: Μῆ άναγνωρισμένη λέξις \"$1\".",
+ "pfunc_expr_unexpected_operator": "Σφάλμα ἐκφράσεως: Μῆ ἀναμενόμενος τελεστής $1.",
+ "pfunc_expr_missing_operand": "Σφάλμα ἐκφράσεως: Ἐλλειπών τελεστής διά τό $1.",
+ "pfunc_expr_unrecognised_punctuation": "Σφάλμα ἐκφράσεως: Μή ἀναγνωρισμένος χαρακτήρας στίξεως \"$1\".",
+ "pfunc_expr_division_by_zero": "Διαίρεσις διὰ τοῦ μηδενός"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/gsw.json b/www/wiki/extensions/ParserFunctions/i18n/gsw.json
new file mode 100644
index 00000000..529e29fd
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/gsw.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Als-Holder"
+ ]
+ },
+ "pfunc_desc": "Erwyteret dr Parser um logischi Funktione",
+ "pfunc_time_error": "Fähler: uugiltigi Zytaagab",
+ "pfunc_time_too_long": "Fähler: z vyyl #time-Ufruef",
+ "pfunc_time_too_big": "Fähler: #time unterstitzt nume Johr bis 9999",
+ "pfunc_rel2abs_invalid_depth": "Fähler: uugültigi Tiefi im Pfad: „$1“ (Versuech, uf e Chnotepunkt oberhalb vum Hauptchnotepunkt zuezgryfe)",
+ "pfunc_expr_stack_exhausted": "Expression-Fähler: Stackiberlauf",
+ "pfunc_expr_unexpected_number": "Expression-Fähler: Nit erwarteti Zahl",
+ "pfunc_expr_preg_match_failure": "Expression-Fähler: Nit erwarteti „preg_match“-Fählfunktion",
+ "pfunc_expr_unrecognised_word": "Expression-Fähler: Nit erkannt Wort „$1“",
+ "pfunc_expr_unexpected_operator": "Expression-Fähler: Nit erwartete Operator: $1",
+ "pfunc_expr_missing_operand": "Expression-Fähler: Operand fir $1 fählt",
+ "pfunc_expr_unexpected_closing_bracket": "Expression-Fähler: Nit erwarteti schließendi eckigi Chlammere",
+ "pfunc_expr_unrecognised_punctuation": "Expression-Fähler: Nit erkannt Satzzeiche „$1“",
+ "pfunc_expr_unclosed_bracket": "Expression-Fähler: Nit gschlosseni eckige Chlammere",
+ "pfunc_expr_division_by_zero": "Expression-Fähler: Division dur Null",
+ "pfunc_expr_invalid_argument": "Nit giltig Argument fir $1: < -1 oder > 1",
+ "pfunc_expr_invalid_argument_ln": "Nit giltig Argument fir ln: <= 0",
+ "pfunc_expr_unknown_error": "Expression-Fähler: Nit bekannte Fehler ($1)",
+ "pfunc_expr_not_a_number": "Expression-Fähler: In $1: Ergebnis isch kei Zahl",
+ "pfunc_string_too_long": "Fähler: d Zeichechette het meh wie di zuelässig Zahl vu $1 Zeiche"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/gu.json b/www/wiki/extensions/ParserFunctions/i18n/gu.json
new file mode 100644
index 00000000..034caf91
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/gu.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arbhatt",
+ "KartikMistry"
+ ]
+ },
+ "pfunc_time_error": "ક્ષતિ: અયોગ્ય સમય.",
+ "pfunc_expr_unrecognised_word": "સમીકરણ ક્ષતિ: અજ્ઞાત શબ્દ \"$1\".",
+ "pfunc_expr_unexpected_operator": "સમીકરણ ક્ષતિ : અણધારી સમીકરણ નિશાની $1",
+ "pfunc_expr_missing_operand": "સમિકરણ ક્ષતિ: $1 ની માટે સમીકરણ-નિશાની ખુટે છે",
+ "pfunc_expr_unrecognised_punctuation": "સમીકરણ ક્ષતિ: અજ્ઞાત વિરામચિહ્ન \"$1\" નો ઉપયોગ.",
+ "pfunc_expr_division_by_zero": "શૂન્ય વડે ભાગાકાર."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/hak.json b/www/wiki/extensions/ParserFunctions/i18n/hak.json
new file mode 100644
index 00000000..1bcc505b
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/hak.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hakka"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Péu-tha̍t-sṳt chho-ngu: mò-fap ngin-sṳt ke sṳ \"$1\".",
+ "pfunc_expr_unexpected_operator": "Péu-tha̍t-sṳt chhâ-chho: Yi-khì chṳ̂-ngoi ke $1 yun-son-chṳ́.",
+ "pfunc_expr_missing_operand": "Péu-tha̍t-sṳt chhâ-chho: Khiet-séu $1 ke yun-son-ngièn.",
+ "pfunc_expr_unrecognised_punctuation": "Péu-tha̍t-sṳt chho-ngu: mò-fap ngin-sṳt ke phiêu-tiám fù-ho \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/he.json b/www/wiki/extensions/ParserFunctions/i18n/he.json
new file mode 100644
index 00000000..98c1e26f
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/he.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80"
+ ]
+ },
+ "pfunc_desc": "הוספת פונקציות לוגיות למפענח",
+ "pfunc_time_error": "שגיאה: זמן שגוי",
+ "pfunc_time_too_long": "שגיאה: יותר מדי קריאות ל#זמן.",
+ "pfunc_time_too_big": "שגיאה: #זמן תומכת רק בשנים עד 9999",
+ "pfunc_time_too_small": "שגיאה: הפונקציה #time תומכת רק בשנים מ־0.",
+ "pfunc_rel2abs_invalid_depth": "שגיאה: עומק שגוי בנתיב: \"$1\" (ניסיון כניסה לצומת מעל צומת השורש)",
+ "pfunc_expr_stack_exhausted": "שגיאה בביטוי: המחסנית מלאה",
+ "pfunc_expr_unexpected_number": "שגיאה בביטוי: מספר בלתי צפוי",
+ "pfunc_expr_preg_match_failure": "שגיאה בביטוי: כישלון בלתי צפוי של התאמת ביטוי רגולרי",
+ "pfunc_expr_unrecognised_word": "שגיאה בביטוי: מילה בלתי מזוהה, \"$1\"",
+ "pfunc_expr_unexpected_operator": "שגיאה בביטוי: אופרנד $1 בלתי צפוי",
+ "pfunc_expr_missing_operand": "שגיאה בביטוי: חסר אופרנד ל־$1",
+ "pfunc_expr_unexpected_closing_bracket": "שגיאה בביטוי: סוגריים סוגרים בלתי צפויים",
+ "pfunc_expr_unrecognised_punctuation": "שגיאה בביטוי: תו פיסוק בלתי מזוהה, \"$1\"",
+ "pfunc_expr_unclosed_bracket": "שגיאה בביטוי: סוגריים בלתי סגורים",
+ "pfunc_expr_division_by_zero": "חלוקה באפס",
+ "pfunc_expr_invalid_argument": "ארגומנט בלתי תקין לפונקציה $1: < -1 או > 1",
+ "pfunc_expr_invalid_argument_ln": "ארגומנט בלתי תקין לפונקציה ln: <= 0",
+ "pfunc_expr_unknown_error": "שגיאה בביטוי: שגיאה בלתי ידועה ($1)",
+ "pfunc_expr_not_a_number": "התוצאה של $1 אינה מספר",
+ "pfunc_string_too_long": "שגיאה: המחרוזת עוברת את גבול התווים המותר, $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/hi.json b/www/wiki/extensions/ParserFunctions/i18n/hi.json
new file mode 100644
index 00000000..783ae6c9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/hi.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kaustubh",
+ "Shyam",
+ "Siddhartha Ghai"
+ ]
+ },
+ "pfunc_desc": "लॉजिकल फ़ंक्शनों द्वारा पार्सर का विस्तार करें",
+ "pfunc_time_error": "त्रुटि: अमान्य समय।",
+ "pfunc_time_too_long": "त्रुटि: बहुत सारे #time कॉल।",
+ "pfunc_time_too_big": "त्रुटि: #time केवल 9999 तक वर्ष स्वीकार करता है।",
+ "pfunc_time_too_small": "त्रुटि: #time केवल 0 से आगे वर्ष स्वीकार करता है।",
+ "pfunc_rel2abs_invalid_depth": "त्रुटि: पाथ में अमान्य गहराई: \"$1\" (रूट नोड के ऊपर नोड खोजने की कोशिश की)",
+ "pfunc_expr_stack_exhausted": "एक्स्प्रेशन त्रुटि: स्टैक खतम हो गया।",
+ "pfunc_expr_unexpected_number": "एक्स्प्रेशन त्रुटि: अनपेक्षित संख्या।",
+ "pfunc_expr_preg_match_failure": "एक्स्प्रेशन त्रुटि: अनपेक्षित preg_match विफलता।",
+ "pfunc_expr_unrecognised_word": "एक्स्प्रेशन त्रुटि: अज्ञात शब्द \"$1\"।",
+ "pfunc_expr_unexpected_operator": "एक्स्प्रेशन त्रुटि: अनपेक्षित $1 ऑपरेटर।",
+ "pfunc_expr_missing_operand": "एक्स्प्रेशन त्रुटि: $1 का घटक नहीं मिला",
+ "pfunc_expr_unexpected_closing_bracket": "एक्स्प्रेशन त्रुटि: अनपेक्षित समाप्ति ब्रैकेट।",
+ "pfunc_expr_unrecognised_punctuation": "एक्स्प्रेशन त्रुटि: अनपेक्षित उद्गार चिन्ह \"$1\"।",
+ "pfunc_expr_unclosed_bracket": "एक्स्प्रेशन त्रुटि: ब्रैकेट बंद नहीं किया।",
+ "pfunc_expr_division_by_zero": "शून्य से भाग।",
+ "pfunc_expr_invalid_argument": "$1 के लिए अमान्य कथन: < -1 या > 1।",
+ "pfunc_expr_invalid_argument_ln": "ln के लिए अमान्य कथन: <= 0",
+ "pfunc_expr_unknown_error": "एक्स्प्रेशन त्रुटि: अज्ञात त्रुटि ($1)।",
+ "pfunc_expr_not_a_number": "$1 में: रिज़ल्ट संख्या नहीं है।",
+ "pfunc_string_too_long": "त्रुटि: स्ट्रिंग $1 कैरेक्टर सीमा से अधिक लम्बा है।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/hif-latn.json b/www/wiki/extensions/ParserFunctions/i18n/hif-latn.json
new file mode 100644
index 00000000..98bef84c
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/hif-latn.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Girmitya",
+ "Abdul Kadir"
+ ]
+ },
+ "pfunc_time_error": "Error: Time invalid hai.",
+ "pfunc_expr_unrecognised_word": "Expression error: Unrecognized word \"$1\".",
+ "pfunc_expr_unexpected_operator": "Expression error: Unexpected $1 operator.",
+ "pfunc_expr_missing_operand": "Expression error: Missing operand for $1.",
+ "pfunc_expr_unrecognised_punctuation": "Expression error: Unrecognized punctuation character \"$1\".",
+ "pfunc_expr_division_by_zero": "Zero se divide karaa gais."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/hr.json b/www/wiki/extensions/ParserFunctions/i18n/hr.json
new file mode 100644
index 00000000..ade11080
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/hr.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dalibor Bosits",
+ "Dnik",
+ "Ex13",
+ "Roberta F.",
+ "SpeedyGonsales",
+ "Bugoslav"
+ ]
+ },
+ "pfunc_desc": "Mogućnost proširivanja parsera logičkim funkcijama",
+ "pfunc_time_error": "Pogrješka: oblik vremena nije valjan",
+ "pfunc_time_too_long": "Pogrješka: prevelik broj #time (vremenskih) poziva",
+ "pfunc_time_too_small": "Pogrješka: #time podržava godine samo od 0.",
+ "pfunc_rel2abs_invalid_depth": "Pogrješka: Nevaljana dubina putanje: \"$1\" (pokušaj pristupanja čvoru iznad korijenskog)",
+ "pfunc_expr_stack_exhausted": "Pogrješka u predlošku: prepunjen stog",
+ "pfunc_expr_unexpected_number": "Pogrješka u predlošku: Neočekivan broj",
+ "pfunc_expr_preg_match_failure": "Pogrješka u predlošku: Neočekivana preg_match pogrješka",
+ "pfunc_expr_unrecognised_word": "Pogrješka u predlošku: Nepoznata riječ \"$1\"",
+ "pfunc_expr_unexpected_operator": "Pogrješka u predlošku: Neočekivani operator $1",
+ "pfunc_expr_missing_operand": "Pogrješka u predlošku: Operator $1 nedostaje",
+ "pfunc_expr_unexpected_closing_bracket": "Pogrješka u predlošku: Neočekivana zatvorena zagrada",
+ "pfunc_expr_unrecognised_punctuation": "Pogrješka u predlošku: Nepoznat interpunkcijski znak \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Pogrješka u predlošku: Nezatvorene zagrade",
+ "pfunc_expr_division_by_zero": "Dijeljenje s nulom",
+ "pfunc_expr_invalid_argument": "Nevaljani argumenti za $1: < -1 ili > 1",
+ "pfunc_expr_invalid_argument_ln": "Nevaljani argument za ln: <= 0",
+ "pfunc_expr_unknown_error": "Pogrješka u predlošku: Nepoznata pogrješka ($1)",
+ "pfunc_expr_not_a_number": "U $1: rezultat nije broj",
+ "pfunc_string_too_long": "Pogrješka: Niz prelazi ograničenje od $1 znakova"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/hsb.json b/www/wiki/extensions/ParserFunctions/i18n/hsb.json
new file mode 100644
index 00000000..7a353a0f
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/hsb.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michawiki"
+ ]
+ },
+ "pfunc_desc": "Parser wo logiske funkcije rozšěrić",
+ "pfunc_time_error": "Zmylk: njepłaćiwe časowe podaće",
+ "pfunc_time_too_long": "Zmylk: přewjele zawołanjow #time",
+ "pfunc_time_too_big": "Zmylk: #time jenož lěta hač do 9999 podpěruje.",
+ "pfunc_time_too_small": "Zmylk: #time jenož lěta wot 0 podpěruje.",
+ "pfunc_rel2abs_invalid_depth": "Zmylk: Njepłaćiwa hłubokosć w pućiku: \"$1\" (Pospyt, zo by na suk wyše hłowneho suka dohrabnyło)",
+ "pfunc_expr_stack_exhausted": "Wurazowy zmylk: Staplowy skład wučerpany",
+ "pfunc_expr_unexpected_number": "Wurazowy zmylk: Njewočakowana ličba",
+ "pfunc_expr_preg_match_failure": "Wurazowy zmylk: Njewočakowana zmylna funkcija \"preg_match\"",
+ "pfunc_expr_unrecognised_word": "Wurazowy zmylk: Njespóznate słowo \"$1\"",
+ "pfunc_expr_unexpected_operator": "Wurazowy zmylk: Njewočakowany operator $1",
+ "pfunc_expr_missing_operand": "Wurazowy zmylk: Falowacy operand za $1",
+ "pfunc_expr_unexpected_closing_bracket": "Wurazowy zmylk: Njewočakowana kónčna róžkata spinka",
+ "pfunc_expr_unrecognised_punctuation": "Wurazowy zmylk: Njespóznate interpunkciske znamješko \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Wurazowy zmylk: Njewotzamknjena róžkata spinka",
+ "pfunc_expr_division_by_zero": "Diwizija přez nulu",
+ "pfunc_expr_invalid_argument": "Njepłaćiwy argument za $1: < -1 abo > 1",
+ "pfunc_expr_invalid_argument_ln": "Njepłaćiwy argument za ln: <= 0",
+ "pfunc_expr_unknown_error": "Wurazowy zmylk: Njeznaty zmylk ($1)",
+ "pfunc_expr_not_a_number": "W $1: Wuslědk ličba njeje",
+ "pfunc_string_too_long": "Zmylk: Znamješkowy slěd překročuje limit $1 znamješkow"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ht.json b/www/wiki/extensions/ParserFunctions/i18n/ht.json
new file mode 100644
index 00000000..8db4441e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ht.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Tisave",
+ "Lucas"
+ ]
+ },
+ "pfunc_expr_unrecognised_punctuation": "Pwoblèm ekspresyon : ponktiyasyon « $1 » a pa valid."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/hu.json b/www/wiki/extensions/ParserFunctions/i18n/hu.json
new file mode 100644
index 00000000..4fc320e3
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/hu.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dani",
+ "Tacsipacsi"
+ ]
+ },
+ "pfunc_desc": "Az értelmező kiegészítése logikai funkciókkal",
+ "pfunc_time_error": "Hiba: Érvénytelen idő.",
+ "pfunc_time_too_long": "Hiba: a #time túl sokszor lett meghívva",
+ "pfunc_time_too_big": "Hiba: a #time csak 9999-ig támogatja az éveket",
+ "pfunc_time_too_small": "Hiba: A #time csak 0-tól támogatja az éveket.",
+ "pfunc_rel2abs_invalid_depth": "Hiba: nem megfelelő a mélység az elérési útban: „$1” (egy olyan csomópontot akartál elérni, amely a gyökércsomópont felett van)",
+ "pfunc_expr_stack_exhausted": "Hiba a kifejezésben: a verem kiürült",
+ "pfunc_expr_unexpected_number": "Hiba a kifejezésben: nem várt szám",
+ "pfunc_expr_preg_match_failure": "Hiba a kifejezésben: a preg_match váratlanul hibát jelzett",
+ "pfunc_expr_unrecognised_word": "Hiba a kifejezésben: ismeretlen „$1” szó.",
+ "pfunc_expr_unexpected_operator": "Hiba a kifejezésben: nem várt $1 operátor",
+ "pfunc_expr_missing_operand": "Hiba a kifejezésben: $1 egyik operandusa hiányzik",
+ "pfunc_expr_unexpected_closing_bracket": "Hiba a kifejezésben: nem várt zárójel",
+ "pfunc_expr_unrecognised_punctuation": "Hiba a kifejezésben: ismeretlen „$1” központozó karakter.",
+ "pfunc_expr_unclosed_bracket": "Hiba a kifejezésben: lezáratlan zárójel",
+ "pfunc_expr_division_by_zero": "Nullával való osztás",
+ "pfunc_expr_invalid_argument": "$1 érvénytelen paramétert kapott: < -1 vagy > 1",
+ "pfunc_expr_invalid_argument_ln": "Az ln érvénytelen paramétert kapott: <= 0",
+ "pfunc_expr_unknown_error": "Hiba a kifejezésben: ismeretlen hiba ($1)",
+ "pfunc_expr_not_a_number": "$1: az eredmény nem szám",
+ "pfunc_string_too_long": "Hiba: a sztring túllépte a(z) $1 karakteres határt"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/hy.json b/www/wiki/extensions/ParserFunctions/i18n/hy.json
new file mode 100644
index 00000000..5c0a2406
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/hy.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Դավիթ Սարոյան"
+ ]
+ },
+ "pfunc_time_error": "Սխալ՝ անվավեր ժամանակ",
+ "pfunc_expr_unrecognised_word": "Արտահայտության սխալ․ չճանաչված բառ՝ «$1»։",
+ "pfunc_expr_unexpected_operator": "Արտահայտության սխալ․ $1 անսպասելի օպերատոր։",
+ "pfunc_expr_missing_operand": "Արտահայտության սխալ․ $1-ը չունի օպերանդ։",
+ "pfunc_expr_unrecognised_punctuation": "Արտահայտության սխալ․ չճանաչված կետադրական նշան՝ «$1»։",
+ "pfunc_expr_division_by_zero": "Զրոյի վրա բաժանում"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/hyw.json b/www/wiki/extensions/ParserFunctions/i18n/hyw.json
new file mode 100644
index 00000000..b8812ab2
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/hyw.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "ArmenBakkalian"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Արտայայտութեան սխալ․ չճանչցուած բառ՝ «$1»։",
+ "pfunc_expr_unrecognised_punctuation": "Արտայայտութեան սխալ․ չճանչցուած կէտադրական նշան՝ «$1»։"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ia.json b/www/wiki/extensions/ParserFunctions/i18n/ia.json
new file mode 100644
index 00000000..5765025c
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ia.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "McDutchie"
+ ]
+ },
+ "pfunc_desc": "Meliorar le analysator syntactic con functiones logic",
+ "pfunc_time_error": "Error: tempore invalide",
+ "pfunc_time_too_long": "Error: troppo de appellos a #time",
+ "pfunc_time_too_big": "Error: #time supporta solmente annos usque a 9999",
+ "pfunc_time_too_small": "Error: #time supporta solmente annos desde 0.",
+ "pfunc_rel2abs_invalid_depth": "Error: Profunditate invalide in cammino: \"$1\" (essayava acceder a un nodo superior al radice)",
+ "pfunc_expr_stack_exhausted": "Error in expression: Pila exhaurite",
+ "pfunc_expr_unexpected_number": "Error in expression: Numero non expectate",
+ "pfunc_expr_preg_match_failure": "Error in expression: Fallimento non expectate in preg_match",
+ "pfunc_expr_unrecognised_word": "Error in expression: Parola \"$1\" non recognoscite",
+ "pfunc_expr_unexpected_operator": "Error in expression: Operator $1 non expectate",
+ "pfunc_expr_missing_operand": "Error in expression: Manca un operando pro $1",
+ "pfunc_expr_unexpected_closing_bracket": "Error in expression: Accollada clause non expectate",
+ "pfunc_expr_unrecognised_punctuation": "Error in expression: Character de punctuation \"$1\" non recognoscite",
+ "pfunc_expr_unclosed_bracket": "Error in expression: Accollada non claudite",
+ "pfunc_expr_division_by_zero": "Division per zero",
+ "pfunc_expr_invalid_argument": "Argumento invalide pro $1: < -1 o > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumento invalide pro ln: ≤ 0",
+ "pfunc_expr_unknown_error": "Error de expression: Error incognite ($1)",
+ "pfunc_expr_not_a_number": "In $1: le resultato non es un numero",
+ "pfunc_string_too_long": "Error: Le catena excede le limite de $1 {{PLURAL:$1|character|characteres}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/id.json b/www/wiki/extensions/ParserFunctions/i18n/id.json
new file mode 100644
index 00000000..5f549f39
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/id.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "IvanLanin",
+ "Meursault2004",
+ "Rex",
+ "Iwan Novirion"
+ ]
+ },
+ "pfunc_desc": "Mengembangkan parser dengan fungsi logis",
+ "pfunc_time_error": "Kesalahan: waktu tidak valid",
+ "pfunc_time_too_long": "Kesalahan: Pemanggilan #time terlalu banyak",
+ "pfunc_time_too_big": "Galat: #time hanya mendukung tahun hingga 9999",
+ "pfunc_rel2abs_invalid_depth": "Kesalahan: Kedalaman path tidak valid: \"$1\" (mencoba mengakses simpul di atas simpul akar)",
+ "pfunc_expr_stack_exhausted": "Kesalahan ekspresi: Stack habis",
+ "pfunc_expr_unexpected_number": "Kesalahan ekspresi: Angka yang tak terduga",
+ "pfunc_expr_preg_match_failure": "Kesalahan ekspresi: Kegagalan preg_match tak terduga",
+ "pfunc_expr_unrecognised_word": "Kesalahan ekspresi: Kata \"$1\" tak dikenal.",
+ "pfunc_expr_unexpected_operator": "Kesalahan ekspresi: Operator $1 tak terduga",
+ "pfunc_expr_missing_operand": "Kesalahan ekspresi: Operand tak ditemukan untuk $1",
+ "pfunc_expr_unexpected_closing_bracket": "Kesalahan ekspresi: Kurung tutup tak terduga",
+ "pfunc_expr_unrecognised_punctuation": "Kesalahan ekspresi: Karakter tanda baca \"$1\" tak dikenali.",
+ "pfunc_expr_unclosed_bracket": "Kesalahan ekspresi: Kurung tanpa tutup",
+ "pfunc_expr_division_by_zero": "Pembagian oleh nol",
+ "pfunc_expr_invalid_argument": "Argumen tidak berlaku untuk $1: < -1 or > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumen tidak berlaku untuk ln: <= 0",
+ "pfunc_expr_unknown_error": "Kesalahan ekspresi: Kesalahan tak dikenal ($1)",
+ "pfunc_expr_not_a_number": "Pada $1: hasilnya bukan angka",
+ "pfunc_string_too_long": "Kesalahan: String melebihi limit $1 karakter"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ie.json b/www/wiki/extensions/ParserFunctions/i18n/ie.json
new file mode 100644
index 00000000..75282d42
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ie.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Stavanger7"
+ ]
+ },
+ "pfunc_expr_missing_operand": "Errore de expression: operande mancant por $1."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ilo.json b/www/wiki/extensions/ParserFunctions/i18n/ilo.json
new file mode 100644
index 00000000..156e5617
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ilo.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lam-ang"
+ ]
+ },
+ "pfunc_desc": "Napasayaat a parser nga adda kadagiti lohikal nga annong",
+ "pfunc_time_error": "Biddut: Imbalido nga oras.",
+ "pfunc_time_too_long": "Biddut: Adu unay dagiti panagtawag ti #time.",
+ "pfunc_time_too_big": "Biddut: Ti #time ket suportaranna laeng dagiti tawen aginggana iti 9999.",
+ "pfunc_time_too_small": "Biddut: ti #time ket suportaranna laeng dagiti tawen manipud iti 0.",
+ "pfunc_rel2abs_invalid_depth": "Biddut: Imbalido a kauneg iti dalan: \"$1\" (nagpadas a nangserrek ti nodo iti ngato ti ramut a nodo).",
+ "pfunc_expr_stack_exhausted": "Biddut a panangiyebkas: Naibusen ti tuon.",
+ "pfunc_expr_unexpected_number": "Biddut a panangiyebkas:Di nanamnama a bilang.",
+ "pfunc_expr_preg_match_failure": "Biddut a panangiyebkas: Di nanamnama a pannakapaay ti preg_match.",
+ "pfunc_expr_unrecognised_word": "Biddut a panangiyebkas: Di mabigbigan a balikas ti \"$1\".",
+ "pfunc_expr_unexpected_operator": "Biddut a panangiyebkas: Di nanamnama nga operator ti $1.",
+ "pfunc_expr_missing_operand": "Biddut a panangiyebkas: Napukaw nga operand para iti $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Biddut a panangiyebkas: Di nanamnama a pangrikep a braket.",
+ "pfunc_expr_unrecognised_punctuation": "Biddut a panangiyebkas: Di nanamnama a karakter ti tuldek ti \"$1\".",
+ "pfunc_expr_unclosed_bracket": "Biddut a panangiyebkas: Di narikpan a braket.",
+ "pfunc_expr_division_by_zero": "Panagbingbingay babaen ti sero.",
+ "pfunc_expr_invalid_argument": "Imbalido nga argumento para iti $1: < -1 wenno > 1.",
+ "pfunc_expr_invalid_argument_ln": "Imbalido nga argumento para iti ln: <= 0.",
+ "pfunc_expr_unknown_error": "Biddut a panangiyebkas: Di ammo a biddut ($1).",
+ "pfunc_expr_not_a_number": "Iti $1: Ti resulta ket saan a bilang.",
+ "pfunc_string_too_long": "Biddut: Ti kuerdas ket nasurokanna ti limitado ti karakter iti $1."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/inh.json b/www/wiki/extensions/ParserFunctions/i18n/inh.json
new file mode 100644
index 00000000..982c851a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/inh.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Adam-Yourist"
+ ]
+ },
+ "pfunc_time_error": "ГIалат: ха нийса яц",
+ "pfunc_expr_unrecognised_word": "Дешáш белгалдаккхара гӀалат: довзанза дола дош «$1»",
+ "pfunc_expr_unexpected_operator": "Дешаш белгалдаккхара гIалат: цIаьхха хинна оператор $1",
+ "pfunc_expr_missing_operand": "Дешáш белгалдаккхара гӀалат: «$1» операнд тоъаш яц",
+ "pfunc_expr_unrecognised_punctuation": "Дешáш белгалдаккхара гӀалат: йовзанза йола пунктуацен хьарак «$1»",
+ "pfunc_expr_division_by_zero": "КIолханна декъар"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/io.json b/www/wiki/extensions/ParserFunctions/i18n/io.json
new file mode 100644
index 00000000..ca163ea2
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/io.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya",
+ "Joao Xavier"
+ ]
+ },
+ "pfunc_time_error": "Eroro: ne-valida tempo",
+ "pfunc_expr_unrecognised_word": "Skriptal eroro: vorto \"$1\" nekonocita.",
+ "pfunc_expr_unexpected_operator": "Eroro en la frazo: Neexpektata $1 operacero.",
+ "pfunc_expr_missing_operand": "Eroro en la frazo: Mankas operando por $1.",
+ "pfunc_expr_unrecognised_punctuation": "Frazala eroro: Nekonocita puntizosigno “$1”.",
+ "pfunc_expr_division_by_zero": "Divido per zero"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/is.json b/www/wiki/extensions/ParserFunctions/i18n/is.json
new file mode 100644
index 00000000..b277961b
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/is.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Snævar"
+ ]
+ },
+ "pfunc_time_error": "Villa: Ógildur tími.",
+ "pfunc_time_too_long": "Villa: Of mörg köll til #time.",
+ "pfunc_time_too_big": "Villa: #time styður aðeins ár upp til 9999.",
+ "pfunc_time_too_small": "Villa: #time styður aðeins ár frá 0.",
+ "pfunc_expr_unexpected_number": "Villa í segð: Óvænt tala.",
+ "pfunc_expr_preg_match_failure": "Villa í segð: Óvænt villa í preg_match",
+ "pfunc_expr_unrecognised_word": "Villa í segð: Óþekkt orð „$1”.",
+ "pfunc_expr_unexpected_operator": "Villa í segð: Óvæntur $1 virki.",
+ "pfunc_expr_missing_operand": "Villa í segð: Vantar þolanda fyrir $1.",
+ "pfunc_expr_unrecognised_punctuation": "Villa í segð: Óþekkt greinarmerki „$1”.",
+ "pfunc_expr_unclosed_bracket": "Villa í segð: Ólokaður svigi.",
+ "pfunc_expr_division_by_zero": "Deiling með núlli.",
+ "pfunc_expr_invalid_argument": "Ógilt frumgildi fyrir $1: < -1 eða > 1.",
+ "pfunc_expr_invalid_argument_ln": "Ógilt frumgildi fyrir ln: <= 0.",
+ "pfunc_expr_unknown_error": "Villa í segð: Óþekkt villa ($1).",
+ "pfunc_expr_not_a_number": "Niðurstaðan úr $1 er ekki tala.",
+ "pfunc_string_too_long": "Villa: Strengurinn er lengri en hámarkslengdin $1 segir til um."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/it.json b/www/wiki/extensions/ParserFunctions/i18n/it.json
new file mode 100644
index 00000000..e0105c9f
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/it.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beta16",
+ "BrokenArrow",
+ "Darth Kule",
+ "Pietrodn",
+ "FRacco"
+ ]
+ },
+ "pfunc_desc": "Aggiunge al parser una serie di funzioni logiche",
+ "pfunc_time_error": "Errore: orario non valido.",
+ "pfunc_time_too_long": "Errore: troppe chiamate a #time.",
+ "pfunc_time_too_big": "Errore: #time supporta solo fino all'anno 9999.",
+ "pfunc_time_too_small": "Errore: #time supporta solo dall'anno 0.",
+ "pfunc_rel2abs_invalid_depth": "Errore: profondità non valida nel percorso \"$1\" (si è tentato di accedere a un nodo superiore alla radice).",
+ "pfunc_expr_stack_exhausted": "Errore nell'espressione: stack esaurito.",
+ "pfunc_expr_unexpected_number": "Errore nell'espressione: numero inatteso.",
+ "pfunc_expr_preg_match_failure": "Errore nell'espressione: errore inatteso in preg_match.",
+ "pfunc_expr_unrecognised_word": "Errore nell'espressione: parola \"$1\" non riconosciuta.",
+ "pfunc_expr_unexpected_operator": "Errore nell'espressione: operatore $1 inatteso.",
+ "pfunc_expr_missing_operand": "Errore nell'espressione: operando mancante per $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Errore nell'espressione: parentesi chiusa inattesa.",
+ "pfunc_expr_unrecognised_punctuation": "Errore nell'espressione: carattere di punteggiatura \"$1\" non riconosciuto.",
+ "pfunc_expr_unclosed_bracket": "Errore nell'espressione: parentesi non chiusa.",
+ "pfunc_expr_division_by_zero": "Divisione per zero.",
+ "pfunc_expr_invalid_argument": "Argomento non valido per $1: < -1 o > 1.",
+ "pfunc_expr_invalid_argument_ln": "Argomento non valido per ln: <= 0.",
+ "pfunc_expr_unknown_error": "Errore nell'espressione: errore sconosciuto ($1).",
+ "pfunc_expr_not_a_number": "In $1: il risultato non è un numero.",
+ "pfunc_string_too_long": "Errore: la stringa supera il limite di $1 {{PLURAL:$1|carattere|caratteri}}."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ja.json b/www/wiki/extensions/ParserFunctions/i18n/ja.json
new file mode 100644
index 00000000..84f53378
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ja.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aotake",
+ "Fryed-peach",
+ "JtFuruhata",
+ "Ohgi",
+ "Shirayuki",
+ "青子守歌"
+ ]
+ },
+ "pfunc_desc": "パーサーに論理関数を追加して拡張する",
+ "pfunc_time_error": "エラー: 日時が無効です。",
+ "pfunc_time_too_long": "エラー: #time の呼び出しが多すぎます。",
+ "pfunc_time_too_big": "エラー: #time が対応しているのは 9999 年までです。",
+ "pfunc_time_too_small": "エラー: #time が対応しているのは 0 年以降です。",
+ "pfunc_rel2abs_invalid_depth": "エラー: パス「$1」の階層が無効です (ルート階層からのアクセスをお試しください)。",
+ "pfunc_expr_stack_exhausted": "構文エラー: スタックを使い果たしました。",
+ "pfunc_expr_unexpected_number": "構文エラー: 予期しない数字です。",
+ "pfunc_expr_preg_match_failure": "構文エラー: preg_match で予期しない失敗をしました。",
+ "pfunc_expr_unrecognised_word": "構文エラー:「$1」を認識できません。",
+ "pfunc_expr_unexpected_operator": "構文エラー: 予期しない演算子 $1 です。",
+ "pfunc_expr_missing_operand": "構文エラー: $1 の演算対象がありません。",
+ "pfunc_expr_unexpected_closing_bracket": "構文エラー: 予期しない閉じ括弧です。",
+ "pfunc_expr_unrecognised_punctuation": "構文エラー: 認識できない区切り文字「$1」です。",
+ "pfunc_expr_unclosed_bracket": "構文エラー: 括弧が閉じられていません。",
+ "pfunc_expr_division_by_zero": "0 で除算しました。",
+ "pfunc_expr_invalid_argument": "$1 の引数が無効です: < -1 または > 1",
+ "pfunc_expr_invalid_argument_ln": "ln の引数が無効です: <= 0",
+ "pfunc_expr_unknown_error": "構文エラー: 不明なエラー ($1) です。",
+ "pfunc_expr_not_a_number": "$1: 結果が数値ではありません。",
+ "pfunc_string_too_long": "エラー: 文字列の長さが上限の $1 文字を超えています。"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/jam.json b/www/wiki/extensions/ParserFunctions/i18n/jam.json
new file mode 100644
index 00000000..fe057bdf
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/jam.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Katxis"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Expreshan era: Anrekanaiz wod \"$1\".",
+ "pfunc_expr_unexpected_operator": "Expreshan era: Anexpectid $1 aparieta.",
+ "pfunc_expr_missing_operand": "Expreshan era: Misn aparand fi $1.‎",
+ "pfunc_expr_unrecognised_punctuation": "Expreshan era: Anrekanaiz pongchieshan kiarakta \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/jut.json b/www/wiki/extensions/ParserFunctions/i18n/jut.json
new file mode 100644
index 00000000..b2189e3d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/jut.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jyllanj"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Uttrøkksfejl: Utjenntj uerd \"$1\".",
+ "pfunc_expr_unexpected_operator": "Uttrøkksfejl: Uwentjen \"$1\"-operator",
+ "pfunc_expr_missing_operand": "Uttrøkksfejl: Månglenje operand til $1",
+ "pfunc_expr_unrecognised_punctuation": "Uttrøkksfejl: Uwentjen tejnsättneng-tejn: \"$1\""
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/jv.json b/www/wiki/extensions/ParserFunctions/i18n/jv.json
new file mode 100644
index 00000000..e3079030
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/jv.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Meursault2004",
+ "NoiX180"
+ ]
+ },
+ "pfunc_desc": "Kembangna parser mawa fungsi logis",
+ "pfunc_time_error": "Masalah: wektu ora absah",
+ "pfunc_time_too_long": "Kaluputan: Olèhé nyeluk #time kakèhan",
+ "pfunc_rel2abs_invalid_depth": "Kaluputan: Kajeroané path ora absah: \"$1\" (nyoba ngakses simpul sadhuwuring simpul oyot)",
+ "pfunc_expr_stack_exhausted": "Kaluputan èksprèsi: Stack entèk",
+ "pfunc_expr_unexpected_number": "Kaluputan èksprèsi: Angka ora kaduga",
+ "pfunc_expr_preg_match_failure": "Kaluputan èksprèsi: Kaluputan preg_match sing ora kaduga",
+ "pfunc_expr_unrecognised_word": "Masalah pitembungan: Tembung \"$1\" ora dingertèni.",
+ "pfunc_expr_unexpected_operator": "Masalah pitembungan: Operator $1 ora kinira.",
+ "pfunc_expr_missing_operand": "Masalah pitembungan: Operand kanggo $1 ora ana.",
+ "pfunc_expr_unexpected_closing_bracket": "Kaluputan èksprèsi: Kurung tutup ora kaduga",
+ "pfunc_expr_unrecognised_punctuation": "Masalah pitembungan: Karakter tandha waca \"$1\" ora dingertèni.",
+ "pfunc_expr_unclosed_bracket": "Kaluputan èksprèsi: Kurung tanpa tutup",
+ "pfunc_expr_division_by_zero": "Dipara nul.",
+ "pfunc_expr_invalid_argument": "Argumèn ora absah kanggo $1: < -1 utawa > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumèn ora absah kanggo ln: <= 0",
+ "pfunc_expr_unknown_error": "Kaluputan èksprèsi: Kaluputan ora ditepungi ($1)",
+ "pfunc_expr_not_a_number": "Ing $1: pituwasé dudu angka"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ka.json b/www/wiki/extensions/ParserFunctions/i18n/ka.json
new file mode 100644
index 00000000..49de1c6b
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ka.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "BRUTE",
+ "David1010",
+ "Dawid Deutschland"
+ ]
+ },
+ "pfunc_desc": "გაუმჯებესებული სინტაქსური ანალიზატორი ლოგიკური ფუნქციებით",
+ "pfunc_time_error": "შეცდომა: არასწორი დრო",
+ "pfunc_time_too_long": "შეცდომა: #time ფუნქციის ძალიან ბევრი გამოძახება.",
+ "pfunc_time_too_big": "შეცდომა: პარამეტრი #time არ უნდა აჭარბებდეს 9999.",
+ "pfunc_rel2abs_invalid_depth": "შეცდომა: გზის არასწორი სიღრმე: „$1“ (კვანძთან წვდომის ცდა, რომელიც მდებარეობს უფრო მაღლა, ვიდრე ძირეული)",
+ "pfunc_expr_stack_exhausted": "ექსპრესიის შეცდომა: დასტა გადავსებულია.",
+ "pfunc_expr_unexpected_number": "ექსპრესიის შეცდომა: მოულოდნელი რიცხვი.",
+ "pfunc_expr_preg_match_failure": "ექსპრესიის შეცდომა: მოულოდნელი preg_match წარუმატებლობა.",
+ "pfunc_expr_unrecognised_word": "ექსპესიის შეცდომა: ამოუცნობი სიტყვა „$1“.",
+ "pfunc_expr_unexpected_operator": "ექსპრესიის შეცდომა: მოულოდნელი $1 ოპერატორი.",
+ "pfunc_expr_missing_operand": "ექსპრესიის შეცდომა: დაიკარგა ოპერანდი $1-თვის.",
+ "pfunc_expr_unexpected_closing_bracket": "ექსპრესიის შეცდომა: მოულოდნელი დახურვის ფრჩხილი.",
+ "pfunc_expr_unrecognised_punctuation": "ექსპრესიის შეცდომა: ამოუცნობი პუნქტუაციის ნიშანი „$1“.",
+ "pfunc_expr_unclosed_bracket": "ექსპესიის შეცდომა: დაუხურავი ფრჩხილი.",
+ "pfunc_expr_division_by_zero": "გაყოფა ნულით",
+ "pfunc_expr_invalid_argument": "მცდარი არგუმენტი $1: < -1 ან > 1",
+ "pfunc_expr_invalid_argument_ln": "მცდარი არგუმენტი ln: <= 0",
+ "pfunc_expr_unknown_error": "ექსპრესიის შეცდომა: უცნობი შეცდომა ($1).",
+ "pfunc_expr_not_a_number": "$1: შედეგში ციფრი არაა",
+ "pfunc_string_too_long": "შეცდომა: სტრიქონის ზომა აღემატება $1 სიმბოლოს ლიმიტს"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/kab.json b/www/wiki/extensions/ParserFunctions/i18n/kab.json
new file mode 100644
index 00000000..52d7fddc
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/kab.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Belkacem77"
+ ]
+ },
+ "pfunc_time_error": "Tuccḍa: Yir tanzagt.",
+ "pfunc_expr_unrecognised_word": "Tuccḍa n tenfalit: Awal \"$1\" ur yettwassen ara",
+ "pfunc_expr_unexpected_operator": "Tuccḍa di tenfalit : amahal '''$1''' ur yettwaṛǧa ara.",
+ "pfunc_expr_missing_operand": "Tuccḍa di tenfalit: Ixuṣ umḍan i $1.",
+ "pfunc_expr_unrecognised_punctuation": "Tuccḍa n tenfalit: asekkil n usenqeḍ \"$1\" ur yettwassen ara.",
+ "pfunc_expr_division_by_zero": "Beṭṭu ɣe yilem."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/kbp.json b/www/wiki/extensions/ParserFunctions/i18n/kbp.json
new file mode 100644
index 00000000..2f23407f
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/kbp.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gnangbade"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Maʋ yiɣduu : tɔm piye \\\"$1\\\" kɩtɩtɩlɩyɛ",
+ "pfunc_expr_unexpected_operator": "Maʋ yiɣduu : mantasʋʋna labɩyʋ $1",
+ "pfunc_expr_missing_operand": "Maʋ yiɣduu : mayaɣ kilebaɣ nɛ $1",
+ "pfunc_expr_unrecognised_punctuation": "Maʋ yiɣduu : piye kɩñɩɣyɛ \\\"$1\\\" kɩtɩtɩlɩyɛ"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/khw.json b/www/wiki/extensions/ParserFunctions/i18n/khw.json
new file mode 100644
index 00000000..60c01da6
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/khw.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rachitrali"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "ظاہریت خطاْْْْ: نامعلوم لفظ \"$1\"",
+ "pfunc_expr_unexpected_operator": "Expression error: Unexpected $1 operator.",
+ "pfunc_expr_missing_operand": "ایکسپریس ایرر: Missing operand for $1.",
+ "pfunc_expr_unrecognised_punctuation": "خطائے تعبیری: نامعلوم تلفظ برائے \"$1\""
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/kk-arab.json b/www/wiki/extensions/ParserFunctions/i18n/kk-arab.json
new file mode 100644
index 00000000..c39911fc
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/kk-arab.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": [],
+ "pfunc_time_error": "قاتە: جارامسىز ۋاقىت",
+ "pfunc_time_too_long": "قاتە: #time شاقىرۋى تىم كوپ",
+ "pfunc_rel2abs_invalid_depth": "قاتە: مىنا جولدىڭ جارامسىز تەرەندىگى «$1» (تامىر ٴتۇيىننىڭ ۇستىندەگى تۇيىنگە قاتىناۋ تالابى)",
+ "pfunc_expr_stack_exhausted": "ايتىلىم قاتەسى: ستەك سارقىلدى",
+ "pfunc_expr_unexpected_number": "ايتىلىم قاتەسى: كۇتىلمەگەن سان",
+ "pfunc_expr_preg_match_failure": "ايتىلىم قاتەسى: كۇتىلمەگەن preg_match ساتسىزدىگى",
+ "pfunc_expr_unrecognised_word": "ايتىلىم قاتەسى: تانىلماعان ٴسوز «$1»",
+ "pfunc_expr_unexpected_operator": "ايتىلىم قاتەسى: كۇتىلمەگەن وپەراتور $1",
+ "pfunc_expr_missing_operand": "ايتىلىم قاتەسى: $1 ٴۇشىن جوعالعان وپەراند",
+ "pfunc_expr_unexpected_closing_bracket": "ايتىلىم قاتەسى: كۇتىلمەگەن جاباتىن جاقشا",
+ "pfunc_expr_unrecognised_punctuation": "ايتىلىم قاتەسى: تانىلماعان تىنىس بەلگىسى «$1»",
+ "pfunc_expr_unclosed_bracket": "ايتىلىم قاتەسى: جابىلماعان جاقشا",
+ "pfunc_expr_division_by_zero": "نولگە ٴبولىنۋى",
+ "pfunc_expr_unknown_error": "ايتىلىم قاتەسى: بەلگىسىز قاتە ($1)",
+ "pfunc_expr_not_a_number": "$1 دەگەندە: ناتىيجە سان ەمەس"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/kk-cyrl.json b/www/wiki/extensions/ParserFunctions/i18n/kk-cyrl.json
new file mode 100644
index 00000000..3afdf3a3
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/kk-cyrl.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arystanbek"
+ ]
+ },
+ "pfunc_time_error": "Қате: жарамсыз уақыт",
+ "pfunc_time_too_long": "Қате: #time шақыруы тым көп",
+ "pfunc_time_too_big": "Қате: #time 9999 дейінгі жылды қолдайды.",
+ "pfunc_time_too_small": "Қате: #time 0 кейінгі жылды қолдайды.",
+ "pfunc_rel2abs_invalid_depth": "Қате: Мына жолдың жарамсыз терендігі «$1» (тамыр түйіннің үстіндегі түйінге қатынау талабы)",
+ "pfunc_expr_stack_exhausted": "Айтылым қатесі: Стек сарқылды",
+ "pfunc_expr_unexpected_number": "Айтылым қатесі: Күтілмеген сан",
+ "pfunc_expr_preg_match_failure": "Айтылым қатесі: Күтілмеген preg_match сәтсіздігі",
+ "pfunc_expr_unrecognised_word": "Айтылым қатесі: Танылмаған сөз «$1»",
+ "pfunc_expr_unexpected_operator": "Айтылым қатесі: Күтілмеген оператор $1",
+ "pfunc_expr_missing_operand": "Айтылым қатесі: $1 үшін жоғалған операнд",
+ "pfunc_expr_unexpected_closing_bracket": "Айтылым қатесі: Күтілмеген жабатын жақша",
+ "pfunc_expr_unrecognised_punctuation": "Айтылым қатесі: Танылмаған тыныс белгісі «$1»",
+ "pfunc_expr_unclosed_bracket": "Айтылым қатесі: Жабылмаған жақша",
+ "pfunc_expr_division_by_zero": "Нөлге бөлінуі",
+ "pfunc_expr_invalid_argument": "$1 үшін жарамсыз аргумент: < -1 немесе > 1.",
+ "pfunc_expr_invalid_argument_ln": "ln үшін жарамсыз аргумент: <= 0.",
+ "pfunc_expr_unknown_error": "Айтылым қатесі: Белгісіз қате ($1)",
+ "pfunc_expr_not_a_number": "$1 дегенде: нәтиже сан емес"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/kk-latn.json b/www/wiki/extensions/ParserFunctions/i18n/kk-latn.json
new file mode 100644
index 00000000..74bfd3da
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/kk-latn.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": [],
+ "pfunc_time_error": "Qate: jaramsız waqıt",
+ "pfunc_time_too_long": "Qate: #time şaqırwı tım köp",
+ "pfunc_rel2abs_invalid_depth": "Qate: Mına joldıñ jaramsız terendigi «$1» (tamır tüýinniñ üstindegi tüýinge qatınaw talabı)",
+ "pfunc_expr_stack_exhausted": "Aýtılım qatesi: Stek sarqıldı",
+ "pfunc_expr_unexpected_number": "Aýtılım qatesi: Kütilmegen san",
+ "pfunc_expr_preg_match_failure": "Aýtılım qatesi: Kütilmegen preg_match sätsizdigi",
+ "pfunc_expr_unrecognised_word": "Aýtılım qatesi: Tanılmağan söz «$1»",
+ "pfunc_expr_unexpected_operator": "Aýtılım qatesi: Kütilmegen operator $1",
+ "pfunc_expr_missing_operand": "Aýtılım qatesi: $1 üşin joğalğan operand",
+ "pfunc_expr_unexpected_closing_bracket": "Aýtılım qatesi: Kütilmegen jabatın jaqşa",
+ "pfunc_expr_unrecognised_punctuation": "Aýtılım qatesi: Tanılmağan tınıs belgisi «$1»",
+ "pfunc_expr_unclosed_bracket": "Aýtılım qatesi: Jabılmağan jaqşa",
+ "pfunc_expr_division_by_zero": "Nölge bölinwi",
+ "pfunc_expr_unknown_error": "Aýtılım qatesi: Belgisiz qate ($1)",
+ "pfunc_expr_not_a_number": "$1 degende: nätïje san emes"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/km.json b/www/wiki/extensions/ParserFunctions/i18n/km.json
new file mode 100644
index 00000000..789be6c9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/km.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lovekhmer",
+ "Thearith",
+ "គីមស៊្រុន"
+ ]
+ },
+ "pfunc_time_error": "កំហុស៖ ពេលវេលាមិនត្រឹមត្រូវ",
+ "pfunc_expr_division_by_zero": "ចែកនឹងសូន្យ។",
+ "pfunc_expr_not_a_number": "ក្នុង $1: លទ្ធផល​មិន​មែន​ជា​លេខ​ទេ"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/kn.json b/www/wiki/extensions/ParserFunctions/i18n/kn.json
new file mode 100644
index 00000000..4f858fa6
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/kn.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "ಶಿವಕುಮಾರ್ ನಾಯಕ್"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "ಪದವಿನ್ಯಾಸ ದೋಷ: ಗುರುತಿಸಲಾಗದ ಪದ\"$1\".",
+ "pfunc_expr_unrecognised_punctuation": "ಪದವಿನ್ಯಾಸ ದೋಷ: ಗುರುತಿಸಲಾಗದ ವಿರಾಮ ಚಿಹ್ನೆ\"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ko.json b/www/wiki/extensions/ParserFunctions/i18n/ko.json
new file mode 100644
index 00000000..7c33fc64
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ko.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "Klutzy",
+ "Kwj2772",
+ "ToePeu",
+ "Yknok29",
+ "아라",
+ "IRTC1015"
+ ]
+ },
+ "pfunc_desc": "파서에 논리 함수를 추가합니다",
+ "pfunc_time_error": "오류: 시간이 잘못되었습니다.",
+ "pfunc_time_too_long": "오류: #time을 너무 많이 호출했습니다.",
+ "pfunc_time_too_big": "오류: #time 함수는 9999년까지만을 지원합니다.",
+ "pfunc_time_too_small": "오류: #time은 0년부터만을 지원합니다.",
+ "pfunc_rel2abs_invalid_depth": "오류: 경로 구조가 잘못되었습니다: \"$1\" (루트 노드 위의 노드에 접속을 시도했습니다)",
+ "pfunc_expr_stack_exhausted": "수식 오류: 스택이 비어 있습니다.",
+ "pfunc_expr_unexpected_number": "표현식 오류: 예상치 못한 숫자입니다.",
+ "pfunc_expr_preg_match_failure": "표현식 오류: 예상치 못한 preg_match 실패입니다.",
+ "pfunc_expr_unrecognised_word": "표현식 오류: \"$1\" 낱말을 알 수 없습니다.",
+ "pfunc_expr_unexpected_operator": "수식 오류: 예상치 못한 $1 연산자입니다.",
+ "pfunc_expr_missing_operand": "수식 오류: $1의 피연산자가 없습니다.",
+ "pfunc_expr_unexpected_closing_bracket": "수식 오류: 예상치 못한 괄호 닫기입니다.",
+ "pfunc_expr_unrecognised_punctuation": "수식 오류: 알 수 없는 \"$1\" 구두점 문자입니다.",
+ "pfunc_expr_unclosed_bracket": "수식 오류: 괄호를 닫지 않았습니다.",
+ "pfunc_expr_division_by_zero": "0으로 나눴습니다.",
+ "pfunc_expr_invalid_argument": "$1 함수의 변수가 잘못되었습니다: < -1 또는 > 1",
+ "pfunc_expr_invalid_argument_ln": "자연로그의 진수가 잘못되었습니다: <= 0",
+ "pfunc_expr_unknown_error": "수식 오류: 알 수 없는 오류입니다($1).",
+ "pfunc_expr_not_a_number": "$1: 결과가 숫자가 아닙니다.",
+ "pfunc_string_too_long": "오류: 문자열이 $1 글자 제한을 초과하였습니다."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/krc.json b/www/wiki/extensions/ParserFunctions/i18n/krc.json
new file mode 100644
index 00000000..7efe2ecb
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/krc.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Iltever",
+ "Ernác"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Ангылатыуну халаты: танылмагъан «$1» сёз",
+ "pfunc_expr_unexpected_operator": "Ангылатыуну халаты: сакъланмагъан $1 оператор.",
+ "pfunc_expr_missing_operand": "Ангылатыуну халаты: $1 ючюн операнд джетмейди.",
+ "pfunc_expr_unrecognised_punctuation": "Ангылатыуну халаты: пунктуацияны танылмагъан «$1» символы"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/krl.json b/www/wiki/extensions/ParserFunctions/i18n/krl.json
new file mode 100644
index 00000000..8f1679f5
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/krl.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Varvana",
+ "Ilja.mos"
+ ]
+ },
+ "pfunc_time_error": "Hirhe: viärä aika.",
+ "pfunc_expr_unrecognised_word": "Hairahuš: tuntomatoin šana \"$1\"",
+ "pfunc_expr_unexpected_operator": "Hairahuš: Vuottamatoin operattori $1.",
+ "pfunc_expr_missing_operand": "Hairahuš: operattorilla $1 ei ole operandie.",
+ "pfunc_expr_unrecognised_punctuation": "Hairahuš: tuntomatoin välimerkki \"$1\".",
+ "pfunc_expr_division_by_zero": "Virhe: jako nollalla"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ksh.json b/www/wiki/extensions/ParserFunctions/i18n/ksh.json
new file mode 100644
index 00000000..6a1a5ad4
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ksh.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Purodha",
+ "Rentenirer"
+ ]
+ },
+ "pfunc_desc": "Deit em Wiki Funxione för Entscheidunge un esu jät dobei.",
+ "pfunc_time_error": "Fähler: En onjöltejje Zigg.",
+ "pfunc_time_too_long": "Fähler: <code lang=\"en\" xml:lang=\"en\">#time</code> weed zo öff jebruch.",
+ "pfunc_time_too_big": "Ene Fähler es opjefalle: <code lang=\"en\" xml:lang=\"en\">#time</code> kann blohß bes nohm Johr 9999 jonn.",
+ "pfunc_time_too_small": "Ene Fähler es opjefalle: <code lang=\"en\" xml:lang=\"en\">#time</code> kann blohß Johre övver Noll.",
+ "pfunc_rel2abs_invalid_depth": "Fähler: Zo fill „retuur“ em Pahdt „$1“ — mer wöre wigger wi för der Aanfang zeröck jejange.",
+ "pfunc_expr_stack_exhausted": "Fähler en enem Ußdrock: Dä löht der stack övverloufe.",
+ "pfunc_expr_unexpected_number": "Fähler en enem Ußdrock: En Zahl dom_mer nit äwaade.",
+ "pfunc_expr_preg_match_failure": "Fähler en enem Ußdrock: Esu ene Fähler en „preg_match“ dum_mer nit äwade.",
+ "pfunc_expr_unrecognised_word": "Fähler en enem Ußdrock: Dat Woot „$1“ es unbikannt.",
+ "pfunc_expr_unexpected_operator": "Fähler en enem Ußdrock: Dat Räschezeiche „$1“ dom_mer hee nit äwaade.",
+ "pfunc_expr_missing_operand": "Fähler en enem Ußdrock: För dat Räschezeiche „$1“ dom_mer ävver ene Operand äwaade.",
+ "pfunc_expr_unexpected_closing_bracket": "Fähler en enem Ußdrock: En eckijje Klammer-Zoh dom_mer esu nit äwaade.",
+ "pfunc_expr_unrecognised_punctuation": "Fähler en enem Ußdrock: Dat Satzzeiche „$1“ dom_mer esu nit äwaade.",
+ "pfunc_expr_unclosed_bracket": "Fähler en enem Ußdrock: Do fählt en eckijje Klammer-Zoh.",
+ "pfunc_expr_division_by_zero": "Fähler en enem Ußdrock: Dorsch Noll jedeilt.",
+ "pfunc_expr_invalid_argument": "Fähler: Dä Parrameeter för $1 moß -1 udder 1 sin, udder dozwesche lijje.",
+ "pfunc_expr_invalid_argument_ln": "Fähler: Dä Parrameeter för ln moß 0 udder kleiner wi 0 sin.",
+ "pfunc_expr_unknown_error": "Fähler en enem Ußdrock: Unbikannt ($1)",
+ "pfunc_expr_not_a_number": "Fähler en enem Ußdrock: En $1 es dat wat erus kütt kein Zahl.",
+ "pfunc_string_too_long": "Fähler en enem Ußdrock: En Zeijshereih es länger wi $1 Zeijshe."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/kum.json b/www/wiki/extensions/ParserFunctions/i18n/kum.json
new file mode 100644
index 00000000..ba884d0a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/kum.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arsenekoumyk",
+ "ArslanX"
+ ]
+ },
+ "pfunc_time_error": "Хата: терс заман",
+ "pfunc_expr_unrecognised_word": "Жумла хата: белгисиз сёз \"$1\".‎",
+ "pfunc_expr_unexpected_operator": "Жумла янгылыш:гёзленмейген оператор $1.",
+ "pfunc_expr_missing_operand": "Жумла янгылышы: $1 операнд етишмей",
+ "pfunc_expr_unrecognised_punctuation": "Жумла хата: белгисиз бюртюклев ишара \"$1\".‎",
+ "pfunc_expr_division_by_zero": "Сыфыргъа бёлюв"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/la.json b/www/wiki/extensions/ParserFunctions/i18n/la.json
new file mode 100644
index 00000000..1737045b
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/la.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amahoney",
+ "UV"
+ ]
+ },
+ "pfunc_expr_unrecognised_punctuation": "Punctum ignotum: \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/lb.json b/www/wiki/extensions/ParserFunctions/i18n/lb.json
new file mode 100644
index 00000000..4b6f2824
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/lb.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robby",
+ "Soued031",
+ "Les Meloures"
+ ]
+ },
+ "pfunc_desc": "Erweidert Parser mat logesche Funktiounen",
+ "pfunc_time_error": "Feeler: ongëlteg Zäit",
+ "pfunc_time_too_long": "Feeler: ze dacks #time opgeruff",
+ "pfunc_time_too_big": "Feeler: #time ënnerstëtzt nëmme Jore bis 9999",
+ "pfunc_time_too_small": "Feeler: #time ënnerstëtzt nëmme Jore vun 0 un.",
+ "pfunc_expr_stack_exhausted": "Expressiouns-Feeler: Stack iwwergelaf",
+ "pfunc_expr_unexpected_number": "Expressiouns-Feeler: Onerwarten Zuel",
+ "pfunc_expr_unrecognised_word": "Expressiouns-Feeler: Onerkantent Wuert \"$1\"",
+ "pfunc_expr_unexpected_operator": "Expressiounsfeeler: Onerwarten Operateur: $1",
+ "pfunc_expr_missing_operand": "Expressiounsfeeler: Et feelt en Operand fir $1",
+ "pfunc_expr_unexpected_closing_bracket": "Expressiouns-Feeler: Onerwarte Klammer déi zougemaach gëtt",
+ "pfunc_expr_unrecognised_punctuation": "Expressiouns-Feeler: D'Sazzeechen \"$1\" gouf net erkannt",
+ "pfunc_expr_unclosed_bracket": "Expressiouns-Feeler: Eckeg Klammer net zougemaach",
+ "pfunc_expr_division_by_zero": "Divisioun duerch Null",
+ "pfunc_expr_invalid_argument": "Ongültege Wäert fir $1: < -1 oder > 1",
+ "pfunc_expr_invalid_argument_ln": "Ongültege Wäert fir ln: <= 0",
+ "pfunc_expr_unknown_error": "Expression-Feeler: Onbekannte Feeler ($1)",
+ "pfunc_expr_not_a_number": "An $1: D'Resultat ass keng Zuel",
+ "pfunc_string_too_long": "Feeler: D'Zeecheketten ass méi laang wéi d'Limit vu(n) $1 Zeechen"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/lfn.json b/www/wiki/extensions/ParserFunctions/i18n/lfn.json
new file mode 100644
index 00000000..a36e1296
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/lfn.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cgboeree",
+ "Chabi",
+ "Katxis"
+ ]
+ },
+ "pfunc_time_error": "Era: Tempo nonvalida.",
+ "pfunc_expr_unrecognised_word": "Era de espresa: Parola nonreconoseda $1",
+ "pfunc_expr_unexpected_operator": "Era de espresa: Operador $1 nonespetada",
+ "pfunc_expr_missing_operand": "Era de espresa: Operada manca per $1.",
+ "pfunc_expr_unrecognised_punctuation": "Era de espresa: Puntua nonreconoseda \"$1\".",
+ "pfunc_expr_division_by_zero": "Divide par zero."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/li.json b/www/wiki/extensions/ParserFunctions/i18n/li.json
new file mode 100644
index 00000000..db642aed
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/li.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Matthias",
+ "Ooswesthoesbes"
+ ]
+ },
+ "pfunc_desc": "Verrijkt de parser met logische functies",
+ "pfunc_time_error": "Fout: ongeldige tied",
+ "pfunc_time_too_long": "Fout: #time te vaok aangerope",
+ "pfunc_time_too_big": "Fout: #time óngersteunt jaore tot maximaal 9999",
+ "pfunc_time_too_small": "Fout: #time óngersteunt allein jaore vanaaf 0.",
+ "pfunc_rel2abs_invalid_depth": "Fout: ongeldige diepte in pad: \"$1\" (probeerde 'n node bove de stamnode aan te rope)",
+ "pfunc_expr_stack_exhausted": "Fout in oetdrukking: stack oetgeput",
+ "pfunc_expr_unexpected_number": "Fout in oetdrukking: onverwacht getal",
+ "pfunc_expr_preg_match_failure": "Fout in oetdrukking: onverwacht fale van preg_match",
+ "pfunc_expr_unrecognised_word": "Fout in oetdrukking: woord \"$1\" neet herkend",
+ "pfunc_expr_unexpected_operator": "Fout in oetdrukking: neet verwachte operator $1",
+ "pfunc_expr_missing_operand": "Fout in oetdrukking: operand veur $1 mist",
+ "pfunc_expr_unexpected_closing_bracket": "Fout in oetdrukking: haakje sloete op onverwachte plaats",
+ "pfunc_expr_unrecognised_punctuation": "Fout in oetdrukking: neet herkend leesteke \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Fout in oetdrukking: neet geslote haakje opene",
+ "pfunc_expr_division_by_zero": "Deiling door nul",
+ "pfunc_expr_invalid_argument": "Ongeldige paramaeter veur $1: < -1 of > 1",
+ "pfunc_expr_invalid_argument_ln": "Ongeldige paramaeter veur ln: <= 0",
+ "pfunc_expr_unknown_error": "Fout in oetdrukking: ónbekindje fout ($1)",
+ "pfunc_expr_not_a_number": "In $1: rezultaot is gein getal",
+ "pfunc_string_too_long": "Fout: De teks is lenger es de limiet van $1 {{PLURAL:$1|teike|teikes}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/lij.json b/www/wiki/extensions/ParserFunctions/i18n/lij.json
new file mode 100644
index 00000000..16a2355e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/lij.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Giromin Cangiaxo"
+ ]
+ },
+ "pfunc_time_error": "Errô: oa non vallida.",
+ "pfunc_expr_unrecognised_word": "Errô inte l'esprescion: parolla \"$1\" non riconosciua.",
+ "pfunc_expr_unexpected_operator": "Errô inte l'esprescion: operatô $1 inatteiso.",
+ "pfunc_expr_missing_operand": "Errô inte l'esprescion: operando mancante pe $1.",
+ "pfunc_expr_unrecognised_punctuation": "Errô inte l'esprescion: carattere de puntezzatua \"$1\" non riconosciuo.",
+ "pfunc_expr_division_by_zero": "Divixon pe zero."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/lki.json b/www/wiki/extensions/ParserFunctions/i18n/lki.json
new file mode 100644
index 00000000..6aa4a50d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/lki.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hosseinblue"
+ ]
+ },
+ "pfunc_desc": "به تجزیه‌گر، دستورهای منطقی می‌افزاید",
+ "pfunc_time_error": "خطا: زمان نامجاز",
+ "pfunc_time_too_long": "خطا: فراخوانی بیش از حد #time",
+ "pfunc_time_too_big": "خطا: #زمان تا سال ۹۹۹۹ را فقط حمایت می‌کند.",
+ "pfunc_time_too_small": "خطا: #time تنها از سال 0 به بعد را پشتیبانی می‌کند.",
+ "pfunc_rel2abs_invalid_depth": "خطا: عمق نامجاز در نشانی «$1» (تلاش برای دسترسی به یک نشانی فراتر از نشانی ریشه)",
+ "pfunc_expr_stack_exhausted": "خطای عبارت: پشته از دست رفته",
+ "pfunc_expr_unexpected_number": "خطای عبارت: عدد دور از انتظار",
+ "pfunc_expr_preg_match_failure": "خطای عبارت: خطای preg_match دور از انتظار",
+ "pfunc_expr_unrecognised_word": "خطای عبارت: کلمه ناشنائۀ $1",
+ "pfunc_expr_unexpected_operator": "خطای عبارت: عملگر $1 دور از انتظار",
+ "pfunc_expr_missing_operand": "خطای عبارت: عملگر گمشده برای$1",
+ "pfunc_expr_unexpected_closing_bracket": "خطای عبارت: پرانتز بسته اضافی",
+ "pfunc_expr_unrecognised_punctuation": "$1خطای عبارت: نویسه نقطه‌گذاری شناخته نؤی",
+ "pfunc_expr_unclosed_bracket": "خطای عبارت: پرانتز بسته‌نشده",
+ "pfunc_expr_division_by_zero": "تقسیم بر صفر",
+ "pfunc_expr_invalid_argument": "پارامتر نامجاز برای $1: < -۱ یا > ۱",
+ "pfunc_expr_invalid_argument_ln": "پارامتر نامجاز برای لگاریتم طبیعی: <= صفر",
+ "pfunc_expr_unknown_error": "خطای عبارت: خطای ناشناخته ($1)",
+ "pfunc_expr_not_a_number": "در $1: نتیجه عدد نیست",
+ "pfunc_string_too_long": "خطا: رشته از محدودیت نویسه‌ای $1 تجاوز می‌کند"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/lrc.json b/www/wiki/extensions/ParserFunctions/i18n/lrc.json
new file mode 100644
index 00000000..de161b96
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/lrc.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bonevarluri",
+ "Mogoeilor"
+ ]
+ },
+ "pfunc_time_error": "خطا:وخت نامعتور.",
+ "pfunc_expr_unrecognised_word": "خطا جمله ای: کلیمه دسه بنی نبیه \"$1\".",
+ "pfunc_expr_unexpected_operator": "خطا جمله: عملدیارکن ناحاستنی $1",
+ "pfunc_expr_missing_operand": "خطا جمله ای:عملیار گم بیه سی $1",
+ "pfunc_expr_unrecognised_punctuation": "خطا جمله ای: کاراکتر نقطه نیائن دسه بنی نبیه\"$1\".",
+ "pfunc_expr_division_by_zero": "بهرکنون وا صفر",
+ "pfunc_expr_invalid_argument_ln": "چک چنه گن سی درینده:<=0."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/lt.json b/www/wiki/extensions/ParserFunctions/i18n/lt.json
new file mode 100644
index 00000000..72e15566
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/lt.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hugo.arg",
+ "Albertas"
+ ]
+ },
+ "pfunc_desc": "Papildyti analizatorių loginėmis funkcijomis",
+ "pfunc_time_error": "Klaida: neteisingas laikas",
+ "pfunc_time_too_long": "Klaida: Per daug #time kreipimųsi.",
+ "pfunc_time_too_big": "Klaida: #time palaiko metus tik iki 9999.",
+ "pfunc_time_too_small": "Klaida: #time palaiko metus tik nuo 0.",
+ "pfunc_rel2abs_invalid_depth": "Klaida: Netinkamas kelio gylis: \"$1\" (bandoma pasiekti mazgą, esantį virš šakninio mazgo).",
+ "pfunc_expr_stack_exhausted": "Išraiškos klaida: Išnaudotas atminties dėklas.",
+ "pfunc_expr_unexpected_number": "Išraiškos klaida: Netikėtas skaičius.",
+ "pfunc_expr_preg_match_failure": "Išraiškos klaida: Netikėta preg_match klaida.",
+ "pfunc_expr_unrecognised_word": "Išraiškos klaida: nežinomas žodis „$1“.",
+ "pfunc_expr_unexpected_operator": "Išraiškos klaida: netikėtas operatorius „$1“.",
+ "pfunc_expr_missing_operand": "Išraiškos klaida: trūksta operando „$1“.",
+ "pfunc_expr_unexpected_closing_bracket": "Išraiškos klaida: Netikėtas uždaromasis skliaustelis.",
+ "pfunc_expr_unrecognised_punctuation": "Išraiškos klaida: neatpažintas punktuacijos ženklas „$1“.",
+ "pfunc_expr_unclosed_bracket": "Išraiškos klaida: Neuždarytas skliaustelis.",
+ "pfunc_expr_division_by_zero": "Dalyba iš nulio.",
+ "pfunc_expr_invalid_argument": "Netinkamas $1 argumentas: < -1 arba > 1.",
+ "pfunc_expr_invalid_argument_ln": "Netinkamas ln argumentas: <= 0.",
+ "pfunc_expr_unknown_error": "Išraiškos klaida: Nežinoma klaida ($1).",
+ "pfunc_expr_not_a_number": "$1: Rezultatas nėra skaičius.",
+ "pfunc_string_too_long": "Klaida: Eilutė viršija $1 simbolių limitą."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/luz.json b/www/wiki/extensions/ParserFunctions/i18n/luz.json
new file mode 100644
index 00000000..dd70599a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/luz.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "علی ساکی لرستانی"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "خطای عبارت:کألمە نوٙم دیارنی ھ \"$1\"",
+ "pfunc_expr_unexpected_operator": "خأطا عیبارأت:ئۉپیراتۉر$1 غیر مۉنتأظیرھ.",
+ "pfunc_expr_missing_operand": "خأطای عیبارت: عأمألڤأند أز دأس رأتە سی $1.",
+ "pfunc_expr_unrecognised_punctuation": "خطای عبارت: نیڤیسه نۉقطە گذاری \"$1\" نوٙم دیار نیسس."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/lv.json b/www/wiki/extensions/ParserFunctions/i18n/lv.json
new file mode 100644
index 00000000..0fa2240a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/lv.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Papuass"
+ ]
+ },
+ "pfunc_time_error": "Kļūda: nederīgs laiks",
+ "pfunc_time_too_long": "Kļūda: pārāk daudz #time izsaukumu",
+ "pfunc_expr_unrecognised_word": "Izteiksmes kļūda: Neatpazīts vārds \"$1\".",
+ "pfunc_expr_unexpected_operator": "Izteiksmes kļūda: Negaidīts $1 operators.",
+ "pfunc_expr_missing_operand": "Izteiksmes kļūda: trūkst $1 operands.",
+ "pfunc_expr_unrecognised_punctuation": "Izteiksmes kļūda: Neatpazīta pieturzīme \"$1\".",
+ "pfunc_expr_division_by_zero": "Dalīšana ar nulli"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mai.json b/www/wiki/extensions/ParserFunctions/i18n/mai.json
new file mode 100644
index 00000000..e419df34
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mai.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Tulsi Bhagat",
+ "बिप्लब आनन्द"
+ ]
+ },
+ "pfunc_desc": "लजिकल फङ्क्सनद्वारा पार्सरक विस्तार करी",
+ "pfunc_time_too_long": "त्रुटी: बहुत बेसी #time कल।",
+ "pfunc_expr_unrecognised_word": "एक्स्प्रेशन गल्ती: अनपेक्षित शब्द \"$1\"।",
+ "pfunc_expr_unexpected_operator": "एक्स्प्रेशन गल्ती: अनपेक्षित $1 अपरेटर।",
+ "pfunc_expr_missing_operand": "एक्स्प्रेशन त्रुटि: $1क घटक नै भेटल।",
+ "pfunc_expr_unrecognised_punctuation": "एक्स्प्रेशन गल्ती: अनपेक्षित उद्गार चिन्ह \"$1\"।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mg.json b/www/wiki/extensions/ParserFunctions/i18n/mg.json
new file mode 100644
index 00000000..7c57a80c
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mg.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jagwar"
+ ]
+ },
+ "pfunc_time_error": "Hadisoana: fotoana tsy azo raisina.",
+ "pfunc_expr_unrecognised_word": "Hadisoam-pilazana: Teny \"$1\" tsy fantatra",
+ "pfunc_expr_unexpected_operator": "Hadisoam-panehoan-kevitra: mpamaritra \"$1\" tsy fantatra.",
+ "pfunc_expr_missing_operand": "Hadisoam-pitenenana: ôperandy tsy ampy ho an'i $1.",
+ "pfunc_expr_unrecognised_punctuation": "Hadisoam-pilazana: Soratra mari-piatoana \"$1\" tsy fantatra",
+ "pfunc_expr_division_by_zero": "Fizarana amin'ny isa aotra."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mhr.json b/www/wiki/extensions/ParserFunctions/i18n/mhr.json
new file mode 100644
index 00000000..ff28d61a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mhr.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Санюн Вадик"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Йоҥылыш: «$1» мутым кучылташ ок лий.",
+ "pfunc_expr_unrecognised_punctuation": "Йоҥылыш: \"$1\" пунктуационный символым кучылташ ок лий."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/min.json b/www/wiki/extensions/ParserFunctions/i18n/min.json
new file mode 100644
index 00000000..a2c1c926
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/min.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Iwan Novirion"
+ ]
+ },
+ "pfunc_time_error": "Kasalahan: wakatu indak tapek"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mk.json b/www/wiki/extensions/ParserFunctions/i18n/mk.json
new file mode 100644
index 00000000..24cbef08
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mk.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06",
+ "Brest"
+ ]
+ },
+ "pfunc_desc": "Проширување на можностите на расчленувачот со логички функции",
+ "pfunc_time_error": "Грешка: погрешен формат за време",
+ "pfunc_time_too_long": "Грешка: премногу повикувања на функцијата #time",
+ "pfunc_time_too_big": "Грешка: #time поддржува само години до 9999",
+ "pfunc_time_too_small": "Грешка: #time поддржува само години од 0 натаму.",
+ "pfunc_rel2abs_invalid_depth": "Грешка: Неважечка продорност во патеката: „$1“ (обид за пристап до јазол кој се наоѓа повисоко од коренитиот)",
+ "pfunc_expr_stack_exhausted": "Грешка во изразот: Складот е преполн",
+ "pfunc_expr_unexpected_number": "Грешка во изразот: Неочекуван број",
+ "pfunc_expr_preg_match_failure": "Грешка во изразот: Неочекуван проблем со preg_match",
+ "pfunc_expr_unrecognised_word": "Грешка во изразот: Непрепознаен збор „$1“",
+ "pfunc_expr_unexpected_operator": "Грешка во изразот: Неочекуван оператор $1",
+ "pfunc_expr_missing_operand": "Грешка во изразот: Недостасува операнд за $1",
+ "pfunc_expr_unexpected_closing_bracket": "Грешка во изразот: Неочекувано затворање на заграда",
+ "pfunc_expr_unrecognised_punctuation": "Грешка во изразот: Непрепознаен интерпункциски знак „$1“",
+ "pfunc_expr_unclosed_bracket": "Грешка во изразот: Незатворена заграда",
+ "pfunc_expr_division_by_zero": "Делење со нула",
+ "pfunc_expr_invalid_argument": "Неважечки аргумент за $1: < -1 или > 1",
+ "pfunc_expr_invalid_argument_ln": "Неважечки аргумент за ln: <= 0",
+ "pfunc_expr_unknown_error": "Грешка во изразот: Непозната грешка ($1)",
+ "pfunc_expr_not_a_number": "Во $1: Исходот не е број",
+ "pfunc_string_too_long": "Грешка: низата го надминува ограничувањето од $1 знаци"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ml.json b/www/wiki/extensions/ParserFunctions/i18n/ml.json
new file mode 100644
index 00000000..1c0b37e6
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ml.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Praveenp",
+ "Shijualex"
+ ]
+ },
+ "pfunc_desc": "ലോജിക്കൽ ഫങ്ഷൻസ് ഉപയോഗിച്ച് പാർസർ വിപുലപ്പെടുത്തുക",
+ "pfunc_time_error": "പിഴവ്:അസാധുവായ സമയം",
+ "pfunc_time_too_long": "പിഴവ്: വളരെയധികം #സമയ കാളുകൾ",
+ "pfunc_time_too_big": "പിഴവ്: 9999 വരെയുള്ള വർഷങ്ങൾ മാത്രമേ #time പിന്തുണയ്ക്കുന്നുള്ളു",
+ "pfunc_time_too_small": "പിഴവ്: 0 മുതലുള്ള വർഷങ്ങൾ മാത്രമേ #time പിന്തുണയ്ക്കുന്നുള്ളു.",
+ "pfunc_rel2abs_invalid_depth": "പിഴവ്: പഥത്തിൽ അസാധുവായ ആഴം: \"$1\" (റൂട്ട് തലത്തിനും മുകളിലുള്ള തലം എടുക്കാനുള്ള ശ്രമം)",
+ "pfunc_expr_stack_exhausted": "എക്സ്‌പ്രെഷൻ പിഴവ്: സ്റ്റാക്ക് പുറന്തള്ളിയിരിക്കുന്നു",
+ "pfunc_expr_unexpected_number": "പ്രയോഗരീതിയിൽ പിഴവ്: പ്രതീക്ഷിക്കാത്ത സംഖ്യ",
+ "pfunc_expr_preg_match_failure": "പ്രയോഗരീതിയിൽ പിഴവ്: അപ്രതീക്ഷിതമായ preg_match പരാജയം",
+ "pfunc_expr_unrecognised_word": "പ്രയോഗരീതിയിൽ പിഴവ്: \"$1\" എന്ന തിരിച്ചറിയാൻ സാധിക്കാഞ്ഞ വാക്ക്",
+ "pfunc_expr_unexpected_operator": "പ്രയോഗരീതിയിൽ പിഴവ്: അപ്രതീക്ഷിതമായ $1 ഓപ്പറേറ്റർ",
+ "pfunc_expr_missing_operand": "എക്സ്പ്രെഷൻ പിഴവ്: $1 എന്നതിനുള്ള പ്രവർത്തനഘടകം നൽകിയിട്ടില്ല",
+ "pfunc_expr_unexpected_closing_bracket": "പ്രയോഗരീതിയിൽ പിഴവ്: അപ്രതീക്ഷിതമായി കോഷ്ഠകം അടച്ചിരിക്കുന്നു",
+ "pfunc_expr_unrecognised_punctuation": "പ്രയോഗരീതിയിൽ പിഴവ്: തിരിച്ചറിയാൻ കഴിയാത്ത വിരാമചിഹ്നം \"$1\"",
+ "pfunc_expr_unclosed_bracket": "പ്രയോഗരീതിയിൽ പിഴവ്: അടയ്ക്കാത്ത കോഷ്ഠകം",
+ "pfunc_expr_division_by_zero": "പൂജ്യം കൊണ്ടുള്ള ഹരണം",
+ "pfunc_expr_invalid_argument": "$1:< -1 അല്ലെങ്കിൽ > 1 എന്നതിനു നൽകിയ അസാധുവായ ആർഗ്യുമെന്റ്",
+ "pfunc_expr_invalid_argument_ln": "ln: <= 0 എന്നതിനു നൽകിയ അസാധുവായ ആർഗ്യുമെന്റ്",
+ "pfunc_expr_unknown_error": "പ്രയോഗരീതിയിൽ പിഴവ്: കാരണം അജ്ഞാതമായ പിഴവ് ($1)",
+ "pfunc_expr_not_a_number": "$1-ൽ: ഫലം ഒരു സംഖ്യയല്ല",
+ "pfunc_string_too_long": "പിഴവ്: പദം ലിപികളുടെ പരിധിയായ $1 അതിലംഘിക്കുന്നു"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mr.json b/www/wiki/extensions/ParserFunctions/i18n/mr.json
new file mode 100644
index 00000000..c473897b
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mr.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Htt",
+ "Kaustubh",
+ "V.narsikar"
+ ]
+ },
+ "pfunc_desc": "तार्किक कार्ये वापरून पार्सर वाढवा",
+ "pfunc_time_error": "त्रुटी: चुकीचा वेळ",
+ "pfunc_time_too_long": "त्रुटी: खूप जास्त #time कॉल्स",
+ "pfunc_time_too_big": "चूक: #वेळ फक्त ९९९९ सालापर्यंतच्या वर्षांना समर्थन देते",
+ "pfunc_rel2abs_invalid_depth": "त्रुटी: मार्गामध्ये चुकीची गहनता: \"$1\" (रूट नोडच्या वरील नोड शोधायचा प्रयत्न केला)",
+ "pfunc_expr_stack_exhausted": "एक्स्प्रेशन त्रुटी: स्टॅक संपला",
+ "pfunc_expr_unexpected_number": "एक्स्प्रेशन त्रुटी: अनपेक्षित क्रमांक",
+ "pfunc_expr_preg_match_failure": "एक्स्प्रेशन त्रुटी: अनपेक्षित preg_match रद्दीकरण",
+ "pfunc_expr_unrecognised_word": "अभिव्यक्ती त्रुटी: अनोळखी शब्द \"$1\"",
+ "pfunc_expr_unexpected_operator": "एक्स्प्रेशन त्रुटी: अनोळखी $1 कार्यवाहक",
+ "pfunc_expr_missing_operand": "एक्स्प्रेशन त्रुटी: $1 चा घटक सापडला नाही",
+ "pfunc_expr_unexpected_closing_bracket": "एक्स्प्रेशन त्रुटी: अनपेक्षित समाप्ती कंस",
+ "pfunc_expr_unrecognised_punctuation": "अभिव्यक्ती त्रुटी: अनोळखी उद्गारवाचक चिन्ह \"$1\"",
+ "pfunc_expr_unclosed_bracket": "एक्स्प्रेशन त्रुटी: कंस समाप्त केलेला नाही",
+ "pfunc_expr_division_by_zero": "शून्य ने भागाकार",
+ "pfunc_expr_invalid_argument": "$1 साठी अवैध अर्ग्युमेंट: < -1 किंवा > 1",
+ "pfunc_expr_invalid_argument_ln": "ln करिता अवैध अर्ग्युमेंट: <= 0",
+ "pfunc_expr_unknown_error": "एक्स्प्रेशन त्रुटी: अनोळखी त्रुटी ($1)",
+ "pfunc_expr_not_a_number": "$1 मध्ये: निकाल संख्येत नाही"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ms.json b/www/wiki/extensions/ParserFunctions/i18n/ms.json
new file mode 100644
index 00000000..bbaf36b6
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ms.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia",
+ "Aurora",
+ "Aviator",
+ "Kurniasan"
+ ]
+ },
+ "pfunc_desc": "Meningkatkan penghurai dengan fungsi-fungsi logik",
+ "pfunc_time_error": "Ralat: waktu tidak sah",
+ "pfunc_time_too_long": "Ralat: terlalu banyak panggilan #time",
+ "pfunc_time_too_big": "Ralat: #time hanya menyokong tahun sehingga 9999",
+ "pfunc_time_too_small": "Ralat: #time hanya menyokong tahun-tahun mulai 0.",
+ "pfunc_rel2abs_invalid_depth": "Ralat: Kedalaman tidak sah dalam laluan: \"$1\" (cubaan mencapai nod di atas nod induk)",
+ "pfunc_expr_stack_exhausted": "Ralat ungkapan: Tindanan tuntas",
+ "pfunc_expr_unexpected_number": "Ralat ungkapan: Nombor tidak dijangka",
+ "pfunc_expr_preg_match_failure": "Ralat ungkapan: Kegagalan preg_match tidak dijangka",
+ "pfunc_expr_unrecognised_word": "Ralat ungkapan: Perkataan \"$1\" tidak dikenali",
+ "pfunc_expr_unexpected_operator": "Ralat ungkapan: Pengendali $1 tidak dijangka",
+ "pfunc_expr_missing_operand": "Ralat ungkapan: Kendalian bagi $1 tiada",
+ "pfunc_expr_unexpected_closing_bracket": "Ralat ungkapan: Penutup kurungan tidak dijangka",
+ "pfunc_expr_unrecognised_punctuation": "Ralat ungkapan: Aksara tanda baca \"$1\" tidak dikenali",
+ "pfunc_expr_unclosed_bracket": "Ralat ungkapan: Tanda kurung tidak ditutup",
+ "pfunc_expr_division_by_zero": "Pembahagian dengan sifar",
+ "pfunc_expr_invalid_argument": "Argumen bagi $1 tidak sah: < -1 atau > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumen bagi ln tidak sah: <= 0",
+ "pfunc_expr_unknown_error": "Ralat ungkapan: Ralat tidak diketahui ($1)",
+ "pfunc_expr_not_a_number": "Dalam $1: hasil bukan nombor",
+ "pfunc_string_too_long": "Ralat: Rentetan melampaui batas aksara $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mt.json b/www/wiki/extensions/ParserFunctions/i18n/mt.json
new file mode 100644
index 00000000..f2d57172
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mt.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Leli Forte"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Żball fl-espressjoni: Il-kelma \"$1\" mhux magħrufa.",
+ "pfunc_expr_unexpected_operator": "Żball fl-espressjoni: Operatur $1 mhux mistenni.",
+ "pfunc_expr_missing_operand": "Żball fl-espressjoni: Operand nieqes għal $1.",
+ "pfunc_expr_unrecognised_punctuation": "Żball fl-espressjoni: Il-karattru tal-punteġġjatura \"$1\" mhux magħruf."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mui.json b/www/wiki/extensions/ParserFunctions/i18n/mui.json
new file mode 100644
index 00000000..0503a3ff
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mui.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jawadywn"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Salah jingok: Kato \"$1\" dak ketemu.",
+ "pfunc_expr_unrecognised_punctuation": "Salah jingok: Karakter tando baco \"$1\" dak ketemu."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mwl.json b/www/wiki/extensions/ParserFunctions/i18n/mwl.json
new file mode 100644
index 00000000..ddb6acb4
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mwl.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "MokaAkashiyaPT",
+ "Athena in Wonderland"
+ ]
+ },
+ "pfunc_time_error": "Erro: Tiempo ambálido.",
+ "pfunc_expr_unrecognised_word": "Erro de spresson: Palabra \"$1\" nun recoincida.",
+ "pfunc_expr_unexpected_operator": "Erro de spresson: Ouparador $1 inasperado",
+ "pfunc_expr_missing_operand": "Erro de spresson: Falta un ouparador pa $1.",
+ "pfunc_expr_unrecognised_punctuation": "Erro de spresson: Carátele de pontuaçon \"$1\" nun recoincido.",
+ "pfunc_expr_division_by_zero": "Debison por zero."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/my.json b/www/wiki/extensions/ParserFunctions/i18n/my.json
new file mode 100644
index 00000000..297763f6
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/my.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ninjastrikers",
+ "9.sinistra"
+ ]
+ },
+ "pfunc_time_error": "အမှား။ မရေရာသော အချိန်။",
+ "pfunc_expr_unrecognised_word": "ဖော်ပြချက် အမှား - နားမလည်သော စကားလုံး \"$1\"။",
+ "pfunc_expr_unexpected_operator": "ဖော်ပြချက် အမှား - Unexpected $1 operator.",
+ "pfunc_expr_missing_operand": "ဖော်ပြချက်အမှား: Missing operand for $1.",
+ "pfunc_expr_unrecognised_punctuation": "ဖော်ပြချက် အမှား - နားမလည်သော ပုဒ်ဖြတ် စာလုံး \"$1\"။",
+ "pfunc_expr_division_by_zero": "သုညဖြင့် စားသည်။"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/myv.json b/www/wiki/extensions/ParserFunctions/i18n/myv.json
new file mode 100644
index 00000000..f1bc77c2
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/myv.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Botuzhaleny-sodamo",
+ "Rueter"
+ ]
+ },
+ "pfunc_time_error": "Ильведевксэсь: амаштовикс шкась",
+ "pfunc_expr_stack_exhausted": "Ёвтавкссонть ильведевкс: стекесь тыц пешксе",
+ "pfunc_expr_unrecognised_word": "Ёвтамонь ильведевкс:«$1» — асодавикс вал.",
+ "pfunc_expr_division_by_zero": "Нольсэ йавома"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/mzn.json b/www/wiki/extensions/ParserFunctions/i18n/mzn.json
new file mode 100644
index 00000000..5eec52ff
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/mzn.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "محک"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "عبارتی خطا: این کلمه ره نشناسمبی «$1»",
+ "pfunc_expr_unexpected_operator": "عبارتون خطا: $1 ِعملگر اَمه وسّه آشنا نی‌یه",
+ "pfunc_expr_missing_operand": "عبارتی خطا: گوم‌بیی عملگر $1 وسّه",
+ "pfunc_expr_unrecognised_punctuation": "عبارتی خطا: اینتی نقطه‌گذاری ره نشناسمبی «$1»"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nah.json b/www/wiki/extensions/ParserFunctions/i18n/nah.json
new file mode 100644
index 00000000..49868280
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nah.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fluence"
+ ]
+ },
+ "pfunc_time_error": "Ahcuallōtl: ahcualli cāhuitl"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nan.json b/www/wiki/extensions/ParserFunctions/i18n/nan.json
new file mode 100644
index 00000000..a661a8ec
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nan.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ianbu",
+ "Luuva",
+ "Yoxem"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Piáu-ta̍t chhò-ngō͘: Jīn-bô \"$1\" chit ê jī.",
+ "pfunc_expr_missing_operand": "Piáu-tat chha-chhok: Phàng-kiàn $1 ê pī-sǹg-sò͘.",
+ "pfunc_expr_unrecognised_punctuation": "Piáu-ta̍t chhò-ngō͘: jīn-bô piau-tiám hû-hō \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nap.json b/www/wiki/extensions/ParserFunctions/i18n/nap.json
new file mode 100644
index 00000000..d658151d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nap.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "C.R."
+ ]
+ },
+ "pfunc_desc": "Migliora 'o parser ch' 'e funziune logiche",
+ "pfunc_time_error": "Errore: Orario invalido.",
+ "pfunc_time_too_long": "Errore: Tropp'assaje chiammate a #time .",
+ "pfunc_time_too_big": "Errore: 'o #time suppuorta anne sulamente nfin'a 9999.",
+ "pfunc_time_too_small": "Errore: 'o #time suppuorta anne sulamente nfin'a 0.",
+ "pfunc_rel2abs_invalid_depth": "Errore: Profondità infalida int'a lu percorso: \"$1\" (pruvaje 'e trasì dint'a nu nodo superiore d' 'a rareca).",
+ "pfunc_expr_stack_exhausted": "Espressione 'n errore: Stack muscio e fernuto.",
+ "pfunc_expr_unexpected_number": "Espressione 'n errore Nummero inaspettato.",
+ "pfunc_expr_preg_match_failure": "Espressione in errore: preg_match inaspettato e fallito",
+ "pfunc_expr_unrecognised_word": "Espressione 'n errore: Parola scanusciuta \"$1\"",
+ "pfunc_expr_unexpected_operator": "Espressione 'n errore: Operatore $1 inaspettato",
+ "pfunc_expr_missing_operand": "Espressione 'n errore: Operatore zumpato pe' $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Espressione in errore: parentesi nchiusa inaspettata",
+ "pfunc_expr_unrecognised_punctuation": "Espressione 'n errore: Carattere 'e punteggiatura \"$1\" scanusciuto",
+ "pfunc_expr_unclosed_bracket": "Espressione in errore: Parentesi nun chiusa.",
+ "pfunc_expr_division_by_zero": "Divisione pe zero",
+ "pfunc_expr_invalid_argument": "Argomento invalido pe $1: < -1 o > 1",
+ "pfunc_expr_invalid_argument_ln": "Argomento invalido pe' ln: <= 0",
+ "pfunc_expr_unknown_error": "Espressione in errore: Errore scanusciuto ($1)",
+ "pfunc_expr_not_a_number": "Int'a $1: 'O risultato nun è nu nummero.",
+ "pfunc_string_too_long": "Errore: 'A stringa appassa 'o lemmeto $1 'e carattere"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nb.json b/www/wiki/extensions/ParserFunctions/i18n/nb.json
new file mode 100644
index 00000000..70639ca2
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nb.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Event",
+ "Laaknor",
+ "Jon Harald Søby"
+ ]
+ },
+ "pfunc_desc": "Utvid parser med logiske funksjoner",
+ "pfunc_time_error": "Feil: ugyldig tid",
+ "pfunc_time_too_long": "Feil: #time brukt for mange ganger",
+ "pfunc_time_too_big": "Feil: #time støtter kun år opp til 9999",
+ "pfunc_time_too_small": "Feil: #time støtter bare år fra 0.",
+ "pfunc_rel2abs_invalid_depth": "Feil: Ugyldig dybde i sti: «$1» (prøvde å få tilgang til en node over rotnoden)",
+ "pfunc_expr_stack_exhausted": "Uttrykksfeil: Stakk utbrukt",
+ "pfunc_expr_unexpected_number": "Uttrykksfeil: Uventet nummer",
+ "pfunc_expr_preg_match_failure": "Uttrykksfeil: Uventet preg_match-feil",
+ "pfunc_expr_unrecognised_word": "Uttrykksfeil: Ugjenkjennelig ord «$1»",
+ "pfunc_expr_unexpected_operator": "Uttrykksfeil: Uventet $1-operator",
+ "pfunc_expr_missing_operand": "Uttrykksfeil: Mangler operand for $1",
+ "pfunc_expr_unexpected_closing_bracket": "Uttrykksfeil: Uventet lukkende parentes",
+ "pfunc_expr_unrecognised_punctuation": "Uttrykksfeil: Ugjenkjennelig skilletegn «$1»",
+ "pfunc_expr_unclosed_bracket": "Uttrykksfeil: Åpen parentes",
+ "pfunc_expr_division_by_zero": "Deling på null",
+ "pfunc_expr_invalid_argument": "Ugyldig argument for $1: < -1 eller > 1",
+ "pfunc_expr_invalid_argument_ln": "Ugyldig argument for ln: <= 0",
+ "pfunc_expr_unknown_error": "Uttrykksfeil: Ukjent feil ($1)",
+ "pfunc_expr_not_a_number": "I $1: resultat er ikke et tall",
+ "pfunc_string_too_long": "Feil: Strengen går over grensen på $1 tegn"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nds-nl.json b/www/wiki/extensions/ParserFunctions/i18n/nds-nl.json
new file mode 100644
index 00000000..f5be8f84
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nds-nl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Servien"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Fout in uutdrokkige: woord \"$1\" niet herkend.",
+ "pfunc_expr_unexpected_operator": "Fout in uutdrokkige: niet verwachten operator $1.",
+ "pfunc_expr_missing_operand": "Fout in uutdrokkige: operand veur $1 ontbrik.",
+ "pfunc_expr_unrecognised_punctuation": "Fout in uutdrokkige: niet herkend leesteken \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nds.json b/www/wiki/extensions/ParserFunctions/i18n/nds.json
new file mode 100644
index 00000000..43594cc3
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nds.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Slomox"
+ ]
+ },
+ "pfunc_desc": "Beriekert den Parser mit logische Funkschonen",
+ "pfunc_time_error": "Fehler: mit de Tiet stimmt wat nich",
+ "pfunc_time_too_long": "Fehler: #time warrt to faken opropen",
+ "pfunc_rel2abs_invalid_depth": "Fehler: Mit den Padd „$1“ stimmt wat nich, liggt nich ünner den Wuddelorner",
+ "pfunc_expr_stack_exhausted": "Fehler in’n Utdruck: Stack överlopen",
+ "pfunc_expr_unexpected_number": "Fehler in’n Utdruck: Unverwacht Tall",
+ "pfunc_expr_preg_match_failure": "Fehler in’n Utdruck: Unverwacht Fehler bi „preg_match“",
+ "pfunc_expr_unrecognised_word": "Fehler in’n Utdruck: Woort „$1“ nich kennt",
+ "pfunc_expr_unexpected_operator": "Fehler in’n Utdruck: Unverwacht Operator $1",
+ "pfunc_expr_missing_operand": "Fehler in’n Utdruck: Operand för $1 fehlt",
+ "pfunc_expr_unexpected_closing_bracket": "Fehler in’n Utdruck: Unverwacht Klammer to",
+ "pfunc_expr_unrecognised_punctuation": "Fehler in’n Utdruck: Satzteken „$1“ nich kennt",
+ "pfunc_expr_unclosed_bracket": "Fehler in’n Utdruck: Nich slatene Klammer",
+ "pfunc_expr_division_by_zero": "Delen dör Null",
+ "pfunc_expr_invalid_argument": "Ungüllig Argument för $1: < -1 oder > 1",
+ "pfunc_expr_invalid_argument_ln": "Ungüllig Argument för ln: <= 0",
+ "pfunc_expr_unknown_error": "Fehler in’n Utdruck: Unbekannten Fehler ($1)",
+ "pfunc_expr_not_a_number": "In $1: wat rutkamen is, is kene Tall"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ne.json b/www/wiki/extensions/ParserFunctions/i18n/ne.json
new file mode 100644
index 00000000..103ac313
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ne.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": {
+ "authors": [
+ "RajeshPandey",
+ "बिप्लब आनन्द",
+ "राम प्रसाद जोशी",
+ "Nirajan pant"
+ ]
+ },
+ "pfunc_time_error": "त्रुटी: गलत/वा हुदैनहुने समय",
+ "pfunc_time_too_long": "त्रुटी: एकदम धेरै #time callहरु",
+ "pfunc_rel2abs_invalid_depth": "त्रुटी: पाथमा (इनभ्यालिड)गलत गहिराइ(डेप्थ) भयो: \"$1\" (ले रुट नोड भन्दापनि माथिको नोडलाइ चलाउन(एकसेस गर्न) खोज्यो)",
+ "pfunc_expr_unrecognised_word": "अभिव्यक्ति त्रुटि: अज्ञात शब्द \"$1\"।",
+ "pfunc_expr_unexpected_operator": "एक्स्प्रेशन त्रुटि: अनपेक्षित $1 अपरेटर।",
+ "pfunc_expr_missing_operand": "अज्ञात त्रुटी:$1 को लागि ओपरन्ड छुटेको",
+ "pfunc_expr_unrecognised_punctuation": "अभिव्यक्ति त्रुटि: अज्ञात विराम चिन्ह चरित्र \"$1\"।",
+ "pfunc_expr_division_by_zero": "शून्यद्वारा भाग।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nl.json b/www/wiki/extensions/ParserFunctions/i18n/nl.json
new file mode 100644
index 00000000..212443f8
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nl.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "SPQRobin",
+ "Siebrand"
+ ]
+ },
+ "pfunc_desc": "Verrijkt de parser met logische functies",
+ "pfunc_time_error": "Fout: ongeldige tijd.",
+ "pfunc_time_too_long": "Fout: #time te vaak aangeroepen.",
+ "pfunc_time_too_big": "Fout: #time ondersteunt jaren tot maximaal 9999",
+ "pfunc_time_too_small": "Fout: #time ondersteunt alleen jaren vanaf 0.",
+ "pfunc_rel2abs_invalid_depth": "Fout: ongeldige diepte in pad: \"$1\" (probeerde een node boven de stamnode aan te roepen).",
+ "pfunc_expr_stack_exhausted": "Fout in uitdrukking: stack uitgeput.",
+ "pfunc_expr_unexpected_number": "Fout in uitdrukking: onverwacht getal.",
+ "pfunc_expr_preg_match_failure": "Fout in uitdrukking: onverwacht falen van preg_match.",
+ "pfunc_expr_unrecognised_word": "Fout in uitdrukking: woord \"$1\" niet herkend.",
+ "pfunc_expr_unexpected_operator": "Fout in uitdrukking: niet verwachte operator $1.",
+ "pfunc_expr_missing_operand": "Fout in uitdrukking: operand voor $1 ontbreekt.",
+ "pfunc_expr_unexpected_closing_bracket": "Fout in uitdrukking: haakje sluiten op onverwachte plaats.",
+ "pfunc_expr_unrecognised_punctuation": "Fout in uitdrukking: niet herkend leesteken \"$1\".",
+ "pfunc_expr_unclosed_bracket": "Fout in uitdrukking: niet gesloten haakje openen.",
+ "pfunc_expr_division_by_zero": "Deling door nul",
+ "pfunc_expr_invalid_argument": "Ongeldige parameter voor $1: < -1 of > 1",
+ "pfunc_expr_invalid_argument_ln": "Ongeldige parameter voor ln: <= 0",
+ "pfunc_expr_unknown_error": "Fout in uitdrukking: onbekende fout ($1).",
+ "pfunc_expr_not_a_number": "In $1: resultaat is geen getal",
+ "pfunc_string_too_long": "Fout: De tekst is langer dan de limiet van $1 {{PLURAL:$1|teken|tekens}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nn.json b/www/wiki/extensions/ParserFunctions/i18n/nn.json
new file mode 100644
index 00000000..e810cf99
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nn.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Eirik",
+ "Frokor",
+ "Gunnernett",
+ "Harald Khan",
+ "Njardarlogar"
+ ]
+ },
+ "pfunc_desc": "Legg til logiske funksjonar i parseren.",
+ "pfunc_time_error": "Feil: Ugyldig tid",
+ "pfunc_time_too_long": "Feil: #time er kalla for mange gonger",
+ "pfunc_rel2abs_invalid_depth": "Feil: Ugyldig djupn i stien: «$1» (prøvde å nå ein node ovanfor rotnoden)",
+ "pfunc_expr_stack_exhausted": "Feil i uttrykket: Stacken er tømd",
+ "pfunc_expr_unexpected_number": "Feil i uttrykket: Uventa tal",
+ "pfunc_expr_preg_match_failure": "Feil i uttrykket: Uventa feil i preg_match",
+ "pfunc_expr_unrecognised_word": "Feil i uttrykket: Ukjent ord, «$1»",
+ "pfunc_expr_unexpected_operator": "Feil i uttrykket: Uventa operatør, $1",
+ "pfunc_expr_missing_operand": "Feil i uttrykket: Operand for $1 manglar",
+ "pfunc_expr_unexpected_closing_bracket": "Feil i uttrykket: Uventa avsluttande parentes",
+ "pfunc_expr_unrecognised_punctuation": "Feil i uttrykket: Ukjent punktumsteikn, «$1»",
+ "pfunc_expr_unclosed_bracket": "Feil i uttrykket: Ein parentes er ikkje avslutta",
+ "pfunc_expr_division_by_zero": "Divisjon med null",
+ "pfunc_expr_invalid_argument": "Ugyldig argument for $1: < -1 eller > 1",
+ "pfunc_expr_invalid_argument_ln": "Ugyldig argument for ln: <= 0",
+ "pfunc_expr_unknown_error": "Feil i uttrykket: Ukjend feil ($1)",
+ "pfunc_expr_not_a_number": "Resultatet i $1 er ikkje eit tal",
+ "pfunc_string_too_long": "Feil: Strengen går over grensa på $1 teikn"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/nys.json b/www/wiki/extensions/ParserFunctions/i18n/nys.json
new file mode 100644
index 00000000..06b61bb2
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/nys.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gnangarra"
+ ]
+ },
+ "pfunc_time_error": "Error: Yuwart time.",
+ "pfunc_expr_unrecognised_word": "Expression error: Unrecognized word \"$1\".",
+ "pfunc_expr_unexpected_operator": "Expression error: Unexpected $1 operator.",
+ "pfunc_expr_missing_operand": "Expression error: Missing operand for $1.",
+ "pfunc_expr_unrecognised_punctuation": "Expression error: Baliak natj punctuation character \"$1\".",
+ "pfunc_expr_division_by_zero": "Division by zero."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/oc.json b/www/wiki/extensions/ParserFunctions/i18n/oc.json
new file mode 100644
index 00000000..6283a504
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/oc.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31",
+ "Jfblanc"
+ ]
+ },
+ "pfunc_desc": "Aumenta lo parser amb de foncions logicas",
+ "pfunc_time_error": "Error: durada invalida",
+ "pfunc_time_too_long": "Error: parser #time apelat tròp de còps",
+ "pfunc_rel2abs_invalid_depth": "Error: nivèl de repertòri invalid dins lo camin : \"$1\" (a ensajat d’accedir a un nivèl al-dessús del repertòri raiç)",
+ "pfunc_expr_stack_exhausted": "Expression erronèa : pila agotada",
+ "pfunc_expr_unexpected_number": "Expression erronèa : nombre pas esperat",
+ "pfunc_expr_preg_match_failure": "Expression erronèa : una expression pas compresa a pas capitat",
+ "pfunc_expr_unrecognised_word": "Error d'expression : lo mot '''$1''' es pas reconegut",
+ "pfunc_expr_unexpected_operator": "Error d'expression : l'operador '''$1''' es pas reconegut",
+ "pfunc_expr_missing_operand": "Error d'expression : l'operand '''$1''' es pas reconegut",
+ "pfunc_expr_unexpected_closing_bracket": "Error d'expression : parentèsi tampanta pas prevista",
+ "pfunc_expr_unrecognised_punctuation": "Error d'expression : caractèr de ponctuacion « $1 » pas reconegut",
+ "pfunc_expr_unclosed_bracket": "Error d’expression : parentèsi pas tampada",
+ "pfunc_expr_division_by_zero": "Division per zèro",
+ "pfunc_expr_invalid_argument": "Valor incorrècta per $1 : < -1 o > 1",
+ "pfunc_expr_invalid_argument_ln": "Valor incorrècta per ln : ≤ 0",
+ "pfunc_expr_unknown_error": "Error d'expression : error desconeguda ($1)",
+ "pfunc_expr_not_a_number": "Dins $1 : lo resultat es pas un nombre",
+ "pfunc_string_too_long": "Error : La cadena depassa lo limit maximal de $1 caractèr{{PLURAL:$1||s}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/olo.json b/www/wiki/extensions/ParserFunctions/i18n/olo.json
new file mode 100644
index 00000000..525ee866
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/olo.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ilja.mos",
+ "Mashoi7"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Haireh: tundematoi sana \"$1\"",
+ "pfunc_expr_unexpected_operator": "Ilmaisuhaireh: Vuottamatoi $1 operuattoru.",
+ "pfunc_expr_missing_operand": "Kuvavushaireh: Ei ole operandua operatorale $1.",
+ "pfunc_expr_unrecognised_punctuation": "Haireh: tundematoi välimerki \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/or.json b/www/wiki/extensions/ParserFunctions/i18n/or.json
new file mode 100644
index 00000000..88f41f2e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/or.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jnanaranjan Sahu"
+ ]
+ },
+ "pfunc_desc": "ପାର୍ସରକୁ ଯୁକ୍ତିମୂଳକ ବ୍ୟବହାରିତା ଦେଇ ଉନ୍ନତ କରନ୍ତୁ",
+ "pfunc_time_error": "ଅସୁବିଧା: ଅବୈଧ ସମୟ ।",
+ "pfunc_time_too_long": "ଅସୁବିଧା: ଅତ୍ୟଧିକ #time ଡକରା ।",
+ "pfunc_time_too_big": "ଅସୁବିଧା: #time କେବଳ 9999ବର୍ଷ ପର୍ଯ୍ୟନ୍ତ ଭିତରେ ରହିପାରିବ ।",
+ "pfunc_rel2abs_invalid_depth": "ଅସୁବିଧା: \"$1\" ପଥରେ ଅଜଣା ଦୂରତା (ମୂଳ ନୋଡ ଠାରୁ ଆହୁରି ଭିତରକୁ ଯିବାକୁ ଚେଷ୍ଟା କରୁଛି) ।",
+ "pfunc_expr_stack_exhausted": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ଷ୍ଟାକ ପୂର୍ଣ ହୋଇଗଲା ।",
+ "pfunc_expr_unexpected_number": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ଅଜଣା ସଂଖ୍ୟା ।",
+ "pfunc_expr_preg_match_failure": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ଅଜଣା ପ୍ରେଗ_ମିଳନରେ ଅସୁବିଧା ।",
+ "pfunc_expr_unrecognised_word": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ଅଜଣା ଶବ୍ଦ \"$1\"",
+ "pfunc_expr_unexpected_operator": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ଅଜଣା $1 ଯୁକ୍ତାକ୍ଷର ।",
+ "pfunc_expr_missing_operand": "ପ୍ରକାଶନରେ ଅସୁବିଧା: $1 ପାଇଁ ଅକ୍ଷର ନାହିଁ ।",
+ "pfunc_expr_unexpected_closing_bracket": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ଅଜଣା ବନ୍ଧନୀ ।",
+ "pfunc_expr_unrecognised_punctuation": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ଅଜଣା ଚିହ୍ନ \"$1\" ।",
+ "pfunc_expr_unclosed_bracket": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ବନ୍ଧନୀ ଶେଷ ହୋଇନାହିଁ ।",
+ "pfunc_expr_division_by_zero": "ଶୁନ ଦ୍ଵାରା ଭାଗ ।",
+ "pfunc_expr_invalid_argument": "$1 ପାଇଁ ଅବୈଧ ଯୁକ୍ତି:< -୧ କିମ୍ବା > ୧ ।",
+ "pfunc_expr_invalid_argument_ln": "ln ପାଇଁ ଅବୈଧ ଲେଖା: <= 0 ।",
+ "pfunc_expr_unknown_error": "ପ୍ରକାଶନରେ ଅସୁବିଧା: ଅଜଣା ଅସୁବିଧା ($1) ।",
+ "pfunc_expr_not_a_number": "$1ରେ: ଫଳାଫଳଟି ସଂଖ୍ୟା ନୁହେଁ ।",
+ "pfunc_string_too_long": "ଅସୁବିଧା: ଧାଡିଟି $1 ଅକ୍ଷର ସୀମାଠୁ ଅଧିକ ହେଲାଣି ।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/pa.json b/www/wiki/extensions/ParserFunctions/i18n/pa.json
new file mode 100644
index 00000000..ce8f1805
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/pa.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Satdeep gill",
+ "Tow"
+ ]
+ },
+ "pfunc_time_error": "ਗਲਤੀ: ਗਲਤ ਸਮਾਂ",
+ "pfunc_expr_unrecognised_word": "ਗ਼ਲਤੀ:ਅਣਪਛਾਤਾ ਸ਼ਬਦ \"$1\"।",
+ "pfunc_expr_unexpected_operator": "ਗ਼ਲਤੀ: ਅਕਲਪਿਤ $1 ਚਾਲਕ।",
+ "pfunc_expr_missing_operand": "ਗ਼ਲਤੀ: $1 ਲਈ ਕਾਰਜ ਸੰਖਿਆ ਮੌਜੂਦ ਨਹੀਂ।",
+ "pfunc_expr_unrecognised_punctuation": "ਗ਼ਲਤੀ:ਅਣਪਛਾਤਾ ਚਿੰਨ੍ਹ \"$1\"।",
+ "pfunc_expr_division_by_zero": "ਸਿਫਰ ਨਾਲ ਵਿਭਾਜਨ।"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/pfl.json b/www/wiki/extensions/ParserFunctions/i18n/pfl.json
new file mode 100644
index 00000000..909f0bf3
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/pfl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Manuae"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Fehla im Ausdrugg: Uubekondes Woad „$1“",
+ "pfunc_expr_unexpected_operator": "Fehla im Ausdrugg: Uueawadedi Greeß $1",
+ "pfunc_expr_missing_operand": "Ausdrugg-Fehla: Fehldä Greeß fa $1",
+ "pfunc_expr_unrecognised_punctuation": "Fehla im Ausdrugg: Uubekondes Sadzzaische „$1“"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/pl.json b/www/wiki/extensions/ParserFunctions/i18n/pl.json
new file mode 100644
index 00000000..d5ff6995
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/pl.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chrumps",
+ "Derbeth",
+ "Grzechooo",
+ "Sp5uhe",
+ "WTM",
+ "Woytecr"
+ ]
+ },
+ "pfunc_desc": "Rozszerza analizator składni o funkcje logiczne",
+ "pfunc_time_error": "Błąd – niepoprawny czas",
+ "pfunc_time_too_long": "Błąd – zbyt wiele wywołań funkcji #time",
+ "pfunc_time_too_big": "Błąd – rok w #time nie może być większy niż 9999",
+ "pfunc_time_too_small": "Błąd: #time obsługuje tylko lata od 0.",
+ "pfunc_rel2abs_invalid_depth": "Błąd – nieprawidłowa głębokość w ścieżce „$1” (próba dostępu do węzła powyżej korzenia)",
+ "pfunc_expr_stack_exhausted": "Błąd w wyrażeniu – stos wyczerpany",
+ "pfunc_expr_unexpected_number": "Błąd w wyrażeniu – nieoczekiwana liczba",
+ "pfunc_expr_preg_match_failure": "Błąd w wyrażeniu – nieoczekiwany błąd preg_match",
+ "pfunc_expr_unrecognised_word": "Błąd w wyrażeniu – nierozpoznane słowo „$1”",
+ "pfunc_expr_unexpected_operator": "Błąd w wyrażeniu – nieoczekiwany operator $1",
+ "pfunc_expr_missing_operand": "Błąd w wyrażeniu – brak argumentu funkcji $1",
+ "pfunc_expr_unexpected_closing_bracket": "Błąd w wyrażeniu – nieoczekiwany nawias zamykający",
+ "pfunc_expr_unrecognised_punctuation": "Błąd w wyrażeniu – nierozpoznany znak interpunkcyjny „$1”",
+ "pfunc_expr_unclosed_bracket": "Błąd w wyrażeniu – niedomknięty nawias",
+ "pfunc_expr_division_by_zero": "Dzielenie przez zero",
+ "pfunc_expr_invalid_argument": "Nieprawidłowy argument funkcji $1 – mniejszy od -1 lub większy od 1",
+ "pfunc_expr_invalid_argument_ln": "Nieprawidłowy argument funkcji ln – mniejszy lub równy 0",
+ "pfunc_expr_unknown_error": "Błąd w wyrażeniu – nieznany błąd ($1)",
+ "pfunc_expr_not_a_number": "W $1 – wynik nie jest liczbą",
+ "pfunc_string_too_long": "Błąd – długość ciągu znaków przekracza dopuszczalne $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/pms.json b/www/wiki/extensions/ParserFunctions/i18n/pms.json
new file mode 100644
index 00000000..24e2b863
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/pms.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Borichèt",
+ "Bèrto 'd Sèra",
+ "Dragonòt"
+ ]
+ },
+ "pfunc_desc": "Mijora ël parse con funsion lògiche",
+ "pfunc_time_error": "Eror: temp nen bon",
+ "pfunc_time_too_long": "Eror: #time a ven ciamà tròpe vire",
+ "pfunc_time_too_big": "Eror: #time a përmët mach j'agn fin al 9999.",
+ "pfunc_time_too_small": "Eror: #time a përmet j'agn mach da 0.",
+ "pfunc_rel2abs_invalid_depth": "Eror: profondità nen bon-a ant ël përcors: \"$1\" (a l'é provasse a ciamé un grop dzora a la rèis)",
+ "pfunc_expr_stack_exhausted": "Eror ëd l'espression: stach esaurìa",
+ "pfunc_expr_unexpected_number": "Eror ëd l'espression: nùmer pa spetà",
+ "pfunc_expr_preg_match_failure": "Eror ëd l'espression: eror pa spetà an preg_match",
+ "pfunc_expr_unrecognised_word": "Eror ëd l'espression: paròla \"$1\" pa arconossùa",
+ "pfunc_expr_unexpected_operator": "Eror ëd l'espression: operator $1 pa spetà",
+ "pfunc_expr_missing_operand": "Eror ëd l'espression: Operand për $1 mancant",
+ "pfunc_expr_unexpected_closing_bracket": "Eror ëd l'espression: paréntesi pa sarà",
+ "pfunc_expr_unrecognised_punctuation": "Eror ëd l'espression: caràter ëd puntegiadura \"$1\" pa arconossù",
+ "pfunc_expr_unclosed_bracket": "Eror ëd l'espression: paréntesi pa sarà",
+ "pfunc_expr_division_by_zero": "Division për zero",
+ "pfunc_expr_invalid_argument": "Argoment pa bon për $1: < -1 o > 1",
+ "pfunc_expr_invalid_argument_ln": "Argoment pa bon për ln: <= 0",
+ "pfunc_expr_unknown_error": "Eror ëd l'espression: Eror pa conossù ($1)",
+ "pfunc_expr_not_a_number": "An $1: l'arzultà a l'é pa un nùmer",
+ "pfunc_string_too_long": "Eror: la stringa a passa ël lìmit ëd $1 caràter"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/pnb.json b/www/wiki/extensions/ParserFunctions/i18n/pnb.json
new file mode 100644
index 00000000..006cab5c
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/pnb.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Khalid Mahmood",
+ "Abbas dhothar"
+ ]
+ },
+ "pfunc_time_error": "غلطی: ویلہ ٹھیک نئیں۔",
+ "pfunc_time_too_long": "غلطی: بعوت ساریاں # کالاں",
+ "pfunc_expr_unrecognised_word": "لکھن غلطی: \"$1\" شبد پچھانیا نہیں جاریا",
+ "pfunc_expr_unexpected_operator": "لکھت غلطی:اچانک $1 اوپریٹر",
+ "pfunc_expr_missing_operand": "لکھن غلطی: $1 لئی مسنگ اوپرینڈ.",
+ "pfunc_expr_unrecognised_punctuation": "لکھن غلطی: \"$1\" نشان پچھانیا نہیں جارہیا"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ps.json b/www/wiki/extensions/ParserFunctions/i18n/ps.json
new file mode 100644
index 00000000..c0323cac
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ps.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ahmed-Najib-Biabani-Ibrahimkhel",
+ "عثمان خان شاہ",
+ "Baloch Khan"
+ ]
+ },
+ "pfunc_time_error": "ستونزه: ناسم وخت",
+ "pfunc_expr_unrecognised_word": "اصطلاحي تېروتنه: ناپېژندل شوې ټکي \"$1\".",
+ "pfunc_expr_unexpected_operator": "اصطلاحي تېروتنه: نااټکله $1 چارنگر.",
+ "pfunc_expr_missing_operand": "اصطلاحي تېروتنه: د $1 ورک شوی چارنگر.",
+ "pfunc_expr_unrecognised_punctuation": "اصطلاحي تېروتنه: د ناپېژندلې ليکنښې لوښه \"$1\".",
+ "pfunc_expr_division_by_zero": "وېش په صفر"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/pt-br.json b/www/wiki/extensions/ParserFunctions/i18n/pt-br.json
new file mode 100644
index 00000000..30738dd9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/pt-br.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cainamarques",
+ "Eduardo.mps",
+ "Giro720",
+ "Felipe L. Ewald"
+ ]
+ },
+ "pfunc_desc": "Melhora o analisador (parser) com funções lógicas",
+ "pfunc_time_error": "Erro: tempo inválido.",
+ "pfunc_time_too_long": "Erro: muitas chamadas a #time.",
+ "pfunc_time_too_big": "Erro: #time só lida com anos até 9999.",
+ "pfunc_time_too_small": "Erro: #time suporta apenas anos superiores a 0.",
+ "pfunc_rel2abs_invalid_depth": "Erro: Profundidade inválida no caminho: \"$1\" (foi tentado o acesso a um nó acima do nó raiz).",
+ "pfunc_expr_stack_exhausted": "Erro de expressão: Pilha esgotada.",
+ "pfunc_expr_unexpected_number": "Erro de expressão: Número inesperado.",
+ "pfunc_expr_preg_match_failure": "Erro de expressão: Falha em preg_match inesperada.",
+ "pfunc_expr_unrecognised_word": "Erro de expressão: Palavra \"$1\" não reconhecida.",
+ "pfunc_expr_unexpected_operator": "Erro de expressão: Operador $1 inesperado.",
+ "pfunc_expr_missing_operand": "Erro de expressão: Falta operando para $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Erro de expressão: Parêntese de fechamento inesperado.",
+ "pfunc_expr_unrecognised_punctuation": "Erro de expressão: Caractere de pontuação \"$1\" não reconhecido.",
+ "pfunc_expr_unclosed_bracket": "Erro de expressão: Parêntese não fechado.",
+ "pfunc_expr_division_by_zero": "Divisão por zero.",
+ "pfunc_expr_invalid_argument": "Argumento inválido para $1: < -1 ou > 1.",
+ "pfunc_expr_invalid_argument_ln": "Argumento inválido para ln: <= 0.",
+ "pfunc_expr_unknown_error": "Erro de expressão: Erro desconhecido ($1).",
+ "pfunc_expr_not_a_number": "Em $1: resultado não é um número.",
+ "pfunc_string_too_long": "Erro: cadeia de caracteres excede o limite de $1 caracteres."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/pt.json b/www/wiki/extensions/ParserFunctions/i18n/pt.json
new file mode 100644
index 00000000..9f48ef5d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/pt.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hamilton Abreu",
+ "Luckas",
+ "Malafaya"
+ ]
+ },
+ "pfunc_desc": "Melhora o analisador sintático com funções lógicas",
+ "pfunc_time_error": "Erro: tempo inválido",
+ "pfunc_time_too_long": "Erro: demasiadas chamadas a #time",
+ "pfunc_time_too_big": "Erro: #time só permite anos até 9999",
+ "pfunc_time_too_small": "Erro: #time só permite anos a partir de 0.",
+ "pfunc_rel2abs_invalid_depth": "Erro: Profundidade inválida no caminho: \"$1\" (foi tentado o acesso a um nó acima do nó raiz)",
+ "pfunc_expr_stack_exhausted": "Erro de expressão: Pilha esgotada",
+ "pfunc_expr_unexpected_number": "Erro de expressão: Número inesperado",
+ "pfunc_expr_preg_match_failure": "Erro de expressão: Falha em preg_match inesperada",
+ "pfunc_expr_unrecognised_word": "Erro de expressão: Palavra \"$1\" não reconhecida",
+ "pfunc_expr_unexpected_operator": "Erro de expressão: Operador $1 inesperado",
+ "pfunc_expr_missing_operand": "Erro de expressão: Falta operando para $1",
+ "pfunc_expr_unexpected_closing_bracket": "Erro de expressão: Parêntese de fecho inesperado",
+ "pfunc_expr_unrecognised_punctuation": "Erro de expressão: Carácter de pontuação \"$1\" não reconhecido",
+ "pfunc_expr_unclosed_bracket": "Erro de expressão: Parêntese não fechado",
+ "pfunc_expr_division_by_zero": "Divisão por zero",
+ "pfunc_expr_invalid_argument": "Argumento inválido para $1: < -1 or > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumento inválido para ln: <= 0",
+ "pfunc_expr_unknown_error": "Erro de expressão: Erro desconhecido ($1)",
+ "pfunc_expr_not_a_number": "Em $1: resultado não é um número",
+ "pfunc_string_too_long": "Erro: Texto excede o limite de $1 caracteres"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/qqq.json b/www/wiki/extensions/ParserFunctions/i18n/qqq.json
new file mode 100644
index 00000000..67ff5e66
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/qqq.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jon Harald Søby",
+ "Kghbln",
+ "Meno25",
+ "Shirayuki",
+ "Siebrand",
+ "The Evil IP address",
+ "Umherirrender"
+ ]
+ },
+ "pfunc_desc": "{{desc|name=Parser Functions|url=https://www.mediawiki.org/wiki/Extension:ParserFunctions}}",
+ "pfunc_time_error": "Used as error message about DateTime object, so this \"time\" means \"date and time\".\n\nSee also:\n* {{msg-mw|Pfunc time too long}}\n* {{msg-mw|Pfunc time too big}}\n* {{msg-mw|Pfunc time too small}}",
+ "pfunc_time_too_long": "Used as error message.\n\nSee also:\n* {{msg-mw|Pfunc time error}}\n* {{msg-mw|Pfunc time too big}}\n* {{msg-mw|Pfunc time too small}}",
+ "pfunc_time_too_big": "Used as error message.\n\nSee also:\n* {{msg-mw|Pfunc time error}}\n* {{msg-mw|Pfunc time too long}}\n* {{msg-mw|Pfunc time too small}}",
+ "pfunc_time_too_small": "Used as error message.\n\nSee also:\n* {{msg-mw|Pfunc time error}}\n* {{msg-mw|Pfunc time too long}}\n* {{msg-mw|Pfunc time too big}}",
+ "pfunc_rel2abs_invalid_depth": "Used as error message. Parameters:\n* $1 - full path",
+ "pfunc_expr_stack_exhausted": "Used as error message.\n{{Related|Pfunc expr}}",
+ "pfunc_expr_unexpected_number": "Used as error message.\n{{Related|Pfunc expr}}",
+ "pfunc_expr_preg_match_failure": "{{doc-important|Do not translate <code>preg_match</code>. It is a PHP function name.}}\nUsed as error message.\n{{Related|Pfunc expr}}",
+ "pfunc_expr_unrecognised_word": "Used as error message. Parameters:\n* $1 - word\n{{Related|Pfunc expr}}",
+ "pfunc_expr_unexpected_operator": "Used as error message. Parameters:\n* $1 - operator\n{{Related|Pfunc expr}}",
+ "pfunc_expr_missing_operand": "Used as error message. Parameters:\n* $1 - operator name. e.g. +, -, not, mod, sin, cos, sqrt\n{{Related|Pfunc expr}}",
+ "pfunc_expr_unexpected_closing_bracket": "Used as error message.\n{{Related|Pfunc expr}}",
+ "pfunc_expr_unrecognised_punctuation": "Used as error message. Parameters:\n* $1 - invalid character\n{{Related|Pfunc expr}}",
+ "pfunc_expr_unclosed_bracket": "Used as error message.\n{{Related|Pfunc expr}}",
+ "pfunc_expr_division_by_zero": "Used as error message.\n{{Related|Pfunc expr}}",
+ "pfunc_expr_invalid_argument": "Used as error message when the operand is invalid. Parameters:\n* $1 - operator name. Any one of the following: asin, acos\n{{Related|Pfunc expr}}",
+ "pfunc_expr_invalid_argument_ln": "{{doc-important|Do not translate <code>ln</code>. It is an operator.}}\nUsed as error message when the operand for the operator \"ln\" is invalid.\n{{Related|Pfunc expr}}",
+ "pfunc_expr_unknown_error": "Used as error message.\n\nIn the source code, there is a comment \"// Should be impossible to reach here.\".\n\nParameters:\n* $1 - (Undefined in the source code)\n{{Related|Pfunc expr}}",
+ "pfunc_expr_not_a_number": "Used as error message when the result of \"sqrt\" (square root) is not a number.\n\nParameters:\n* $1 - operator name: sqrt\n{{Related|Pfunc expr}}",
+ "pfunc_string_too_long": "PLURAL is supported for $1."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/qu.json b/www/wiki/extensions/ParserFunctions/i18n/qu.json
new file mode 100644
index 00000000..62f5e8a3
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/qu.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "AlimanRuna"
+ ]
+ },
+ "pfunc_desc": "Parser nisqata sullwa ruranakunawan allinchay",
+ "pfunc_time_error": "Pantasqa: Pachaqa manam allinchu",
+ "pfunc_time_too_long": "Pantasqa: nisyu \"#time\" (pacha)",
+ "pfunc_time_too_big": "Pantasqa: #time nisqaqa 9999 watallakamam watakunata q'imin",
+ "pfunc_rel2abs_invalid_depth": "Pantasqa: ñanpa ukhu kayninqa manam allinchu: \"$1\" (saphi khipu hawanpi kaq khiputam aypayta munaspa)",
+ "pfunc_expr_stack_exhausted": "Rikuchikuypi pantasqa: Nisyu tawqa",
+ "pfunc_expr_unexpected_number": "Rikuchikuypi pantasqa: Mana suyakusqa yupay",
+ "pfunc_expr_preg_match_failure": "Rikuchikuypi pantasqa: Mana suyakusqa preg_match alqa",
+ "pfunc_expr_unrecognised_word": "Rikuchikuypi pantasqa: Mana riqsisqa rima \"$1\"",
+ "pfunc_expr_unexpected_operator": "Rikuchikuypi pantasqa: Mana suyakusqa ruraq \"$1\"",
+ "pfunc_expr_missing_operand": "Rikuchikuypi pantasqa: Manam kanchu $1-paq ruraq",
+ "pfunc_expr_unexpected_closing_bracket": "Rikuchikuypi pantasqa: Nisyu wichq'aq qinchaq",
+ "pfunc_expr_unrecognised_punctuation": "Rikuchikuypi pantasqa: Mana riqsisqa qillqa unancha \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Rikuchikuypi pantasqa: Manam kanchu wichq'aq qinchaq",
+ "pfunc_expr_division_by_zero": "Ch'usaqwan rakisqa",
+ "pfunc_expr_invalid_argument": "$1-paq mana allin ninakuy: : < -1 icha > 1",
+ "pfunc_expr_invalid_argument_ln": "ln-paq mana allin ninakuy: <= 0",
+ "pfunc_expr_unknown_error": "Rikuchikuypi pantasqa: Mana riqsisqa pantasqa ($1)",
+ "pfunc_expr_not_a_number": "$1-pi: lluqsiyninqa manam yupaychu",
+ "pfunc_string_too_long": "Pantasqa: Qillqa tiwlliqa $1 sanampa saywatam llallin"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ro.json b/www/wiki/extensions/ParserFunctions/i18n/ro.json
new file mode 100644
index 00000000..9b1670ed
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ro.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "KlaudiuMihaila",
+ "Minisarm",
+ "Stelistcristi",
+ "ImGelu",
+ "Strainu"
+ ]
+ },
+ "pfunc_desc": "Îmbunătățește parserul cu funcții logice",
+ "pfunc_time_error": "Eroare: timp incorect",
+ "pfunc_time_too_long": "Eroare: prea multe apeluri #time",
+ "pfunc_time_too_big": "Eroare: #time acceptă doar ani până la 9999",
+ "pfunc_time_too_small": "Eroare: #time acceptă doar ani de la 0.",
+ "pfunc_rel2abs_invalid_depth": "Eroare: adâncime incorectă în cale: „$1” (încercat accesarea unui nod deasupra nodului rădăcină)",
+ "pfunc_expr_stack_exhausted": "Eroare de expresie: stivă epuizată",
+ "pfunc_expr_unexpected_number": "Eroare de expresie: număr neașteptat",
+ "pfunc_expr_preg_match_failure": "Eroare de expresie: eșuare preg_match neașteptată",
+ "pfunc_expr_unrecognised_word": "Eroare de expresie: „$1” este un cuvânt nerecunoscut.",
+ "pfunc_expr_unexpected_operator": "Eroare de expresie: operator $1 neașteptat",
+ "pfunc_expr_missing_operand": "Eroare de expresie: operand lipsă pentru $1",
+ "pfunc_expr_unexpected_closing_bracket": "Eroare de expresie: paranteză închisă neașteptată",
+ "pfunc_expr_unrecognised_punctuation": "Eroare de expresie: caracter de punctuație „$1” necunoscut",
+ "pfunc_expr_unclosed_bracket": "Eroare de expresie: paranteză neînchisă",
+ "pfunc_expr_division_by_zero": "Împărțire la zero",
+ "pfunc_expr_invalid_argument": "Argument incorect pentru $1: < -1 sau > 1",
+ "pfunc_expr_invalid_argument_ln": "Argument incorect pentru ln: <= 0",
+ "pfunc_expr_unknown_error": "Eroare de expresie: eroare necunoscută ($1)",
+ "pfunc_expr_not_a_number": "În $1: rezultatul nu este un număr",
+ "pfunc_string_too_long": "Eroare: șirul depășește limita de caractere de $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/roa-tara.json b/www/wiki/extensions/ParserFunctions/i18n/roa-tara.json
new file mode 100644
index 00000000..565e7c71
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/roa-tara.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joetaras"
+ ]
+ },
+ "pfunc_desc": "L'analizzatore avanzate cu le funziune loggeche",
+ "pfunc_time_error": "Errore: Orarie invalide",
+ "pfunc_time_too_long": "Errore: stonne troppe #time chiamate",
+ "pfunc_time_too_big": "Errore: #time vole sulamende valore de anne 'mbonde a 9999",
+ "pfunc_time_too_small": "Errore: #time pigghie anne sulamende da 'u 0.",
+ "pfunc_rel2abs_invalid_depth": "Errore: Profondità invalide jndr'à 'u percorse: \"$1\" (s'à pruvate a pigghià 'nu node sus a 'u node radice)",
+ "pfunc_expr_stack_exhausted": "Espressione in errore: Stack anghiute",
+ "pfunc_expr_unexpected_number": "Espressione in errore: Numere inaspettate",
+ "pfunc_expr_preg_match_failure": "Espressione in errore: preg_match inaspettate e fallite",
+ "pfunc_expr_unrecognised_word": "Espressione in errore: Parola scanusciute \"$1\"",
+ "pfunc_expr_unexpected_operator": "Espressione in errore: Operatore $1 inaspettate",
+ "pfunc_expr_missing_operand": "Espressione in errore: Operande zumbate pe $1",
+ "pfunc_expr_unexpected_closing_bracket": "Espressione in errore: Non g'onne state achiuse le parendesi",
+ "pfunc_expr_unrecognised_punctuation": "Espressione in errore: Carattere de punde \"$1\" scanusciute",
+ "pfunc_expr_unclosed_bracket": "Espressione in errore: Parendesi non achiuse",
+ "pfunc_expr_division_by_zero": "Divisione pe zero",
+ "pfunc_expr_invalid_argument": "Argomende invalide pe $1: < -1 o > 1",
+ "pfunc_expr_invalid_argument_ln": "Argomende invalide pe ln: <= 0",
+ "pfunc_expr_unknown_error": "Espressione in errore: Errore scanusciute ($1)",
+ "pfunc_expr_not_a_number": "In $1: 'u resultate non g'è 'nu numere",
+ "pfunc_string_too_long": "Errore: 'A stringhe supranesce 'u limite de $1 carattere"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ru.json b/www/wiki/extensions/ParserFunctions/i18n/ru.json
new file mode 100644
index 00000000..22fa5900
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ru.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "G0rn",
+ "Putnik",
+ "Александр Сигачёв",
+ "Jack who built the house"
+ ]
+ },
+ "pfunc_desc": "Улучшенный синтаксический анализатор с логическими функциями",
+ "pfunc_time_error": "Ошибка: неправильное время",
+ "pfunc_time_too_long": "Ошибка: слишком много вызовов функции #time",
+ "pfunc_time_too_big": "Ошибка. Параметр #time не может превышать 9999",
+ "pfunc_time_too_small": "Ошибка: #time поддерживает только года от 0.",
+ "pfunc_rel2abs_invalid_depth": "Ошибка: ошибочная глубина пути: «$1» (попытка доступа к узлу, находящемуся выше, чем корневой)",
+ "pfunc_expr_stack_exhausted": "Ошибка выражения: переполнение стека",
+ "pfunc_expr_unexpected_number": "Ошибка выражения: неожидаемое число",
+ "pfunc_expr_preg_match_failure": "Ошибка выражения: сбой preg_match",
+ "pfunc_expr_unrecognised_word": "Ошибка выражения: неопознанное слово «$1»",
+ "pfunc_expr_unexpected_operator": "Ошибка выражения: не ожидаемый оператор $1",
+ "pfunc_expr_missing_operand": "Ошибка выражения: $1 не хватает операнда",
+ "pfunc_expr_unexpected_closing_bracket": "Ошибка выражения: неожидаемая закрывающая скобка",
+ "pfunc_expr_unrecognised_punctuation": "Ошибка выражения: неопознанный символ пунктуации «$1»",
+ "pfunc_expr_unclosed_bracket": "Ошибка выражения: незакрытая скобка",
+ "pfunc_expr_division_by_zero": "Деление на ноль",
+ "pfunc_expr_invalid_argument": "Ошибочный аргумент $1: < -1 или > 1",
+ "pfunc_expr_invalid_argument_ln": "Ошибочный аргумент ln: <= 0",
+ "pfunc_expr_unknown_error": "Ошибка выражения: неизвестная ошибка ($1)",
+ "pfunc_expr_not_a_number": "В $1: результат не является числом",
+ "pfunc_string_too_long": "Ошибка: строка превышает ограничение в $1 символов"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/rue.json b/www/wiki/extensions/ParserFunctions/i18n/rue.json
new file mode 100644
index 00000000..b381e7d0
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/rue.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazeb",
+ "Tkalyn"
+ ]
+ },
+ "pfunc_desc": "Росшырїня парсера о лоґічны функції",
+ "pfunc_time_error": "Хыба: неплатный час",
+ "pfunc_time_too_long": "Хыба: дуже много кликаня #time",
+ "pfunc_rel2abs_invalid_depth": "Хыба: Неплатна глубка в стежцї: \"$1\" (проба о приступ до узла высшого як корїнь)",
+ "pfunc_expr_stack_exhausted": "Хыба выразу: Засобник переповненый",
+ "pfunc_expr_unexpected_number": "Хыба выразу: Чекане чісло",
+ "pfunc_expr_preg_match_failure": "Хыба выразу: Нечекана хыба функції preg_match",
+ "pfunc_expr_unrecognised_word": "Хыба выразу: Нерозпознане слово „$1“",
+ "pfunc_expr_unexpected_operator": "Хыба выразу: Нечеканый оператор: $1",
+ "pfunc_expr_missing_operand": "Хыба выразу: Хыбить операнд про $1",
+ "pfunc_expr_unexpected_closing_bracket": "Хыба выразу: Нечекана заперача заперка",
+ "pfunc_expr_unrecognised_punctuation": "Хыба выразу: Нерозпознаный роздїловый знак „$1“",
+ "pfunc_expr_unclosed_bracket": "Хыба ыразу: Незаперты заперкы",
+ "pfunc_expr_division_by_zero": "Дїлїня нулов",
+ "pfunc_expr_invalid_argument": "Неправилный арґумент про $1: < -1 або > 1",
+ "pfunc_expr_invalid_argument_ln": "Неправилный арґумент про ln: <= 0",
+ "pfunc_expr_unknown_error": "Хыба выразу: Незнама хыба ($1)",
+ "pfunc_expr_not_a_number": "У $1: резултат не є чісло",
+ "pfunc_string_too_long": "Хыба: Ланц є довшый як $1 {{PLURAL:$1|знак|знакы|знаків}}, што є ліміт"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sa.json b/www/wiki/extensions/ParserFunctions/i18n/sa.json
new file mode 100644
index 00000000..bff88cab
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sa.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "NehalDaveND"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "वाचनिकदोषः : अज्ञातशब्दः $1",
+ "pfunc_expr_unexpected_operator": "वाचनिकदोषः : $1 इत्येतत् अनपेक्षितं चिह्नम् ।",
+ "pfunc_expr_missing_operand": "वाचनिकदोषः : $1 इत्यस्य कृते समीकरणचिह्नं न प्राप्तम् ।",
+ "pfunc_expr_unrecognised_punctuation": "वाचनिकदोषः : अनपेक्षितम् उद्गारचिह्नम $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sah.json b/www/wiki/extensions/ParserFunctions/i18n/sah.json
new file mode 100644
index 00000000..a5a9fb7a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sah.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "HalanTul"
+ ]
+ },
+ "pfunc_desc": "Логическай функциялаах тупсарыллыбыт синтаксическай анализатор",
+ "pfunc_time_error": "Алҕас: сыыһа кэм",
+ "pfunc_time_too_long": "Алҕас: #time функция наһаа элбэхтик хатыламмыт",
+ "pfunc_time_too_big": "Алҕас: #time 9999-у ааһыа суохтаах",
+ "pfunc_rel2abs_invalid_depth": "Алҕас: ошибочная глубина пути: «$1» (попытка доступа к узлу, находящемуся выше, чем корневой)",
+ "pfunc_expr_stack_exhausted": "Ошибка выражения: переполнение стека",
+ "pfunc_expr_unexpected_number": "Алҕас: кэтэһиллибэтэх чыыһыла",
+ "pfunc_expr_preg_match_failure": "Алҕас: preg_match моһуоктанна",
+ "pfunc_expr_unrecognised_word": "Алҕас: биллибэт тыл «$1»",
+ "pfunc_expr_unexpected_operator": "Алҕас: кэтэһиллибэтэх оператор $1",
+ "pfunc_expr_missing_operand": "Алҕас: $1 операнда тиийбэт",
+ "pfunc_expr_unexpected_closing_bracket": "Алҕас: кэтэһиллибэтэх сабар ускуопка",
+ "pfunc_expr_unrecognised_punctuation": "Алҕас: биллибэт пунктуация бэлиэтэ «$1»",
+ "pfunc_expr_unclosed_bracket": "Алҕас: сабыллыбатах ускуопка",
+ "pfunc_expr_division_by_zero": "Нуулга түҥэттии",
+ "pfunc_expr_invalid_argument": "$1 алҕас аргуменнаах: < -1 or > 1",
+ "pfunc_expr_invalid_argument_ln": "ln аргумена сыыһалаах: <= 0",
+ "pfunc_expr_unknown_error": "Expression error (ошибка выражения): Биллибэт алҕас ($1)",
+ "pfunc_expr_not_a_number": "$1 иһигэр: эппиэтэ чыыһыла буолбатах",
+ "pfunc_string_too_long": "Алҕас: Устуруока уһуна $1 бэлиэннэн хааччахха баппат"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sat.json b/www/wiki/extensions/ParserFunctions/i18n/sat.json
new file mode 100644
index 00000000..9c3f1646
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sat.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Manik Soren",
+ "Ramjit Tudu"
+ ]
+ },
+ "pfunc_time_error": "ᱦᱩᱲᱟᱹᱜ : ᱚᱢᱟᱱᱚᱛ ᱚᱠᱛᱚ ᱾",
+ "pfunc_expr_unrecognised_word": "Expression error: ᱵᱟᱝ ᱧᱮᱞ ᱴᱷᱤᱠᱚᱜᱠᱟᱱ ᱟᱹᱲᱟᱹ \"$1\".",
+ "pfunc_expr_unexpected_operator": "ᱞᱟᱹᱭᱟᱜ ᱦᱩᱲᱟᱹᱜ : ᱵᱟᱝᱩᱭᱦᱟᱹᱨ $1 ᱠᱟᱹᱢᱤᱭᱟᱹ ᱾",
+ "pfunc_expr_missing_operand": "ᱞᱟᱹᱭᱟᱜ ᱦᱩᱲᱟᱹᱜ: $1 ᱞᱟᱹᱜᱤᱫ ᱠᱟᱹᱢᱤ ᱦᱚᱨᱟ ᱯᱩᱪᱩᱡ ᱟᱠᱟᱱᱟ ᱾",
+ "pfunc_expr_unrecognised_punctuation": "Expression error: ᱵᱟᱝ ᱧᱮᱞ ᱴᱷᱤᱠᱚᱜᱠᱟᱱ ᱪᱤᱱᱦᱟᱹ ᱠᱚ \"$1\".",
+ "pfunc_expr_division_by_zero": "ᱥᱩᱱ ᱛᱮ ᱵᱷᱮᱜᱮᱫ"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/scn.json b/www/wiki/extensions/ParserFunctions/i18n/scn.json
new file mode 100644
index 00000000..6690212b
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/scn.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Melos",
+ "Santu"
+ ]
+ },
+ "pfunc_desc": "Ci junci ô parser na sèrii di funzioni lòggichi",
+ "pfunc_time_error": "Sbàgghiu: uràriu nun vàlidu",
+ "pfunc_time_too_long": "Sbàgghiu: troppi chiamati a #time",
+ "pfunc_rel2abs_invalid_depth": "Sbàgghiu: prufunnità non vàlida ntô pircorsu \"$1\" (si tintau di tràsiri a nu nodu cchiù supra di la ràdica)",
+ "pfunc_expr_stack_exhausted": "Sbàgghiu nti la sprissioni: lu stack finìu",
+ "pfunc_expr_unexpected_number": "Sbàgghiu nti la sprissioni: nùmmiru non privistu",
+ "pfunc_expr_preg_match_failure": "Sbàgghiu nti la sprissioni: sbàgghiu non privistu 'n preg_match",
+ "pfunc_expr_unrecognised_word": "Sbàgghiu nti la sprissioni: palora \"$1\" non canusciuta",
+ "pfunc_expr_unexpected_operator": "Sbàgghiu nti la sprissioni: upiraturi $1 non privistu",
+ "pfunc_expr_missing_operand": "Sbàgghiu nti la sprissioni: upirandu mancanti pi $1",
+ "pfunc_expr_unexpected_closing_bracket": "Sbàgghiu nti la sprissioni: parèntisi chiusa non aspittata",
+ "pfunc_expr_unrecognised_punctuation": "Sbàgghiu nti la sprissioni: caràttiri di puntiggiatura \"$1\" non canusciutu",
+ "pfunc_expr_unclosed_bracket": "Sbàgghiu nti la sprissioni: parèntisi non chiuruta",
+ "pfunc_expr_division_by_zero": "Divisioni pi zeru",
+ "pfunc_expr_invalid_argument": "Argumentu non vàlidu pi $1: < -1 o > 1",
+ "pfunc_expr_invalid_argument_ln": "Argumentu non vàlidu pi ln: <= 0",
+ "pfunc_expr_unknown_error": "Sbàgghiu nti la sprissioni: sbàgghiu scanusciutu ($1)",
+ "pfunc_expr_not_a_number": "Nti $1: lu risurtatu nun è nu nùmmiru",
+ "pfunc_string_too_long": "Erruri: la stringa supira lu limiti di $1 carattiri"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sco.json b/www/wiki/extensions/ParserFunctions/i18n/sco.json
new file mode 100644
index 00000000..6d6c203e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sco.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "AmaryllisGardener"
+ ]
+ },
+ "pfunc_time_error": "Error: Invalid time.",
+ "pfunc_expr_unrecognised_word": "Expression error: Unrecognised wird \"$1\".",
+ "pfunc_expr_unexpected_operator": "Expression error: Unexpectit $1 operator.",
+ "pfunc_expr_missing_operand": "Expression error: Missin operand for $1.",
+ "pfunc_expr_unrecognised_punctuation": "Expression error: Unrecognised punctuation character \"$1\".",
+ "pfunc_expr_division_by_zero": "Diveesion bi zero."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sd.json b/www/wiki/extensions/ParserFunctions/i18n/sd.json
new file mode 100644
index 00000000..0c0ce227
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sd.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aursani",
+ "Mehtab ahmed"
+ ]
+ },
+ "pfunc_time_error": "چُڪَ:ناقابلِڪار وقت.",
+ "pfunc_expr_unrecognised_word": "اظھاري چُڪَ: اڻڄاتل لفظ $1.",
+ "pfunc_expr_unexpected_operator": "اظھاري چُڪَ: غير متوقع $1 عامل.",
+ "pfunc_expr_missing_operand": "اظھاري چُڪَ: $1 لاءِ معامل انگ کٽل.",
+ "pfunc_expr_unrecognised_punctuation": "اظھاري چُڪَ: اڻڄاتل وقفي نشاني \"$1\".",
+ "pfunc_expr_division_by_zero": "ٻريءَ سان ونڊ."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sdh.json b/www/wiki/extensions/ParserFunctions/i18n/sdh.json
new file mode 100644
index 00000000..2b1e288a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sdh.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Paraw2"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "ھەڵەێ ڕستە: وشەێ نەناسیاێ \"$1\".",
+ "pfunc_expr_unrecognised_punctuation": "ھەڵەێ دەربڕین: پێتێگ نەناسیاێ دێرێد \"$1\""
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sgs.json b/www/wiki/extensions/ParserFunctions/i18n/sgs.json
new file mode 100644
index 00000000..977c660d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sgs.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hugo.arg"
+ ]
+ },
+ "pfunc_time_error": "Soklīdėmsː natinkams čiesos.",
+ "pfunc_expr_unrecognised_word": "Rašīma soklīdėms: nažėnuoms žuodis „$1“.",
+ "pfunc_expr_unexpected_operator": "Ėšsirēškėma soklīdėms: nelaukts $1 operatuorios.",
+ "pfunc_expr_missing_operand": "Ėšsirēškėma soklīkėms: trūkst $1 vēkėma.",
+ "pfunc_expr_unrecognised_punctuation": "Rašīma soklīdėms: nažėnuoms skīrības znuoks „$1“.",
+ "pfunc_expr_division_by_zero": "Dalėnėms ėš nolė."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sh.json b/www/wiki/extensions/ParserFunctions/i18n/sh.json
new file mode 100644
index 00000000..c0862961
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sh.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kolega2357",
+ "OC Ripper"
+ ]
+ },
+ "pfunc_time_error": "Greška: pogrešno vreme",
+ "pfunc_time_too_long": "Greška: previše pozivanja funkcije #time",
+ "pfunc_rel2abs_invalid_depth": "Greška: Nepravilna dubina u putanji: \"$1\"",
+ "pfunc_expr_unrecognised_word": "Greška izraza: Nepoznata riječ \"$1\"",
+ "pfunc_expr_unexpected_operator": "Greška izraza: Neočekivani $1 operator",
+ "pfunc_expr_missing_operand": "Greška izraza: Nedostaje operator za $1",
+ "pfunc_expr_unrecognised_punctuation": "Razvojna greška: Nije prepoznat karakter punktacije \"$1\""
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/shn.json b/www/wiki/extensions/ParserFunctions/i18n/shn.json
new file mode 100644
index 00000000..0e820d1d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/shn.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saimawnkham"
+ ]
+ },
+ "pfunc_time_error": "ၽိတ်းပိူင်ႈ : ၶၢဝ်းယၢမ်း ဢမ်ႇၶဝ်ႈပိူင်",
+ "pfunc_expr_unrecognised_word": "လွင်ႈၽိတ်းပိူင်ႈ : ဢမ်ႇၼႄႉၼွၼ်းလႆႈ တူဝ်လိၵ်ႈ \"$1\"",
+ "pfunc_expr_unexpected_operator": "လွင်ႈၽိတ်းပိူင်ႈ တူဝ်ၼႄ: $1 ၼႆ့ ပဵၼ်တူဝ်ဢမ်ႇ မုင်ႈမွင်းဝႆႉ။",
+ "pfunc_expr_missing_operand": "လွင်ႈၽိတ်းပိူင်ႈ တူဝ်ၼႄ : တူဝ်ႁဵတ်းသၢင်ႈ တွၼ်ႈတႃႇ $1 ႁၢႆဝႆႉ။",
+ "pfunc_expr_unrecognised_punctuation": "လွင်ႈၽိတ်းပိူင်ႈ: တူဝ်လိၵ်ႈ လၢၵ်ႇလၢႆး \"$1\" ဢၼ်ၼႆႉ ဢမ်ႇလႆႈမၵ်းမၼ်ႈဝႆႉ",
+ "pfunc_expr_division_by_zero": "ဢဝ်သုၼ်သေၵိၼ်ၸႅၵ်ႇ"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/si.json b/www/wiki/extensions/ParserFunctions/i18n/si.json
new file mode 100644
index 00000000..6643e66e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/si.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Budhajeewa",
+ "නන්දිමිතුරු",
+ "Singhalawap"
+ ]
+ },
+ "pfunc_desc": "තාර්කීක ශ්‍රිතයන් උපයෝගී කරගනිමින් ව්‍යාකරණ විග්‍රහකය වර්ධනය කරන්න",
+ "pfunc_time_error": "දෝෂය: අනීතික වේලාව",
+ "pfunc_time_too_long": "දෝෂය: වේලා ඇමතුම් # පමණට වැඩිය",
+ "pfunc_rel2abs_invalid_depth": "දෝෂය: පෙතෙහි ගැඹුර අනීතිකයි: \"$1\" (මූල මංසලට ඉහළ මංසලක් ප්‍රවේශනයට උත්සාහ දැරිණි)",
+ "pfunc_expr_stack_exhausted": "ප්‍රකාශන දෝෂය: ඇසිරුම හිස්ව පැවතිණි",
+ "pfunc_expr_unexpected_number": "ප්‍රකාශන දෝෂය: අනපේක්‍ෂිත සංඛ්‍යාව",
+ "pfunc_expr_preg_match_failure": "ප්‍රකාශන දෝෂය: බලාපොරොත්තු නොවූ preg_match ඇණහිටුම",
+ "pfunc_expr_unrecognised_word": "ප්‍රකාශන දෝෂය: හඳුනානොගත් වදන \"$1\"",
+ "pfunc_expr_unexpected_operator": "ප්‍රකාශන දෝෂය: අනපේක්‍ෂිත $1 මෙහෙයුම්කාරකය",
+ "pfunc_expr_missing_operand": "ප්‍රකාශන දෝෂය: $1 සඳහා අස්ථානගත ප්‍රවර්ත්‍යය",
+ "pfunc_expr_unexpected_closing_bracket": "ප්‍රකාශන දෝෂය: අනපේක්‍ෂිත වැසීම් වරහන",
+ "pfunc_expr_unrecognised_punctuation": "ප්‍රකාශන දෝෂය: හඳුනානොගත් විරාම සංකේතය \"$1\"",
+ "pfunc_expr_unclosed_bracket": "ප්‍රකාශන දෝෂය: නොවැසූ වරහන",
+ "pfunc_expr_division_by_zero": "ශුන්‍යයෙන් බෙදීම",
+ "pfunc_expr_invalid_argument": "$1: < -1 හෝ > 1 සඳහා අනීතික විස්තාරකය",
+ "pfunc_expr_invalid_argument_ln": "ln: <= 0 සඳහා අනීතික විස්තාරකය",
+ "pfunc_expr_unknown_error": "ප්‍රකාශන දෝෂය: අඥාත දෝෂය ($1)",
+ "pfunc_expr_not_a_number": "$1: හි ප්‍රතිඵලය සංඛ්‍යාවක් නොවේ",
+ "pfunc_string_too_long": "Error: වදන් පෙළ අකුරු $1 සීමාව ඉක්මවයි"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sk.json b/www/wiki/extensions/ParserFunctions/i18n/sk.json
new file mode 100644
index 00000000..e8285b51
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sk.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Helix84"
+ ]
+ },
+ "pfunc_desc": "Rozšírenie syntaktického analyzátora o logické funkcie",
+ "pfunc_time_error": "Chyba: Neplatný čas",
+ "pfunc_time_too_long": "Chyba: príliš veľa volaní #time",
+ "pfunc_rel2abs_invalid_depth": "Chyba: Neplatná hĺbka v ceste: „$1“ (pokus o prístup k uzlu nad koreňovým uzlom)",
+ "pfunc_expr_stack_exhausted": "Chyba výrazu: Zásobník vyčerpaný",
+ "pfunc_expr_unexpected_number": "Chyba výrazu: Neočakávané číslo",
+ "pfunc_expr_preg_match_failure": "Chyba výrazu: Neočakávané zlyhanie funkcie preg_match",
+ "pfunc_expr_unrecognised_word": "Chyba výrazu: Nerozpoznané slovo „$1“",
+ "pfunc_expr_unexpected_operator": "Chyba výrazu: Neočakávaný operátor $1",
+ "pfunc_expr_missing_operand": "Chyba výrazu: Chýbajúci operand pre $1",
+ "pfunc_expr_unexpected_closing_bracket": "Chyba výrazu: Neočakávaná zatvárajúca hranatá zátvorka",
+ "pfunc_expr_unrecognised_punctuation": "Chyba výrazu: Nerozpoznané diakritické znamienko „$1“",
+ "pfunc_expr_unclosed_bracket": "Chyba výrazu: Neuzavretá hranatá zátvorka",
+ "pfunc_expr_division_by_zero": "Chyba výrazu: Delenie nulou",
+ "pfunc_expr_invalid_argument": "Neplatný argument pre $1: < -1 alebo > 1",
+ "pfunc_expr_invalid_argument_ln": "Neplatný argument pre ln: <= 0",
+ "pfunc_expr_unknown_error": "Chyba výrazu: Neznáma chyba ($1)",
+ "pfunc_expr_not_a_number": "V $1: výsledok nie je číslo",
+ "pfunc_string_too_long": "Chyba: Reťazec prekračuje limit $1 znakov"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/skr-arab.json b/www/wiki/extensions/ParserFunctions/i18n/skr-arab.json
new file mode 100644
index 00000000..f4292392
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/skr-arab.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saraiki"
+ ]
+ },
+ "pfunc_time_error": "غلطی: ویلہ ٹھیک کائنی ۔",
+ "pfunc_expr_unrecognised_word": "لکھݨ غلطی: \"$1\" ان سون٘ہاں لفظ",
+ "pfunc_expr_unexpected_operator": "لکھت غلطی:اچانک $1 اوپریٹر",
+ "pfunc_expr_missing_operand": "لکھن غلطی: $1 کیتے اوپرینڈ کائنی۔",
+ "pfunc_expr_unrecognised_punctuation": "لکھݨ غلطی: \"$1\" نشان دی سنڄاݨ نی تھیدی پئی",
+ "pfunc_expr_division_by_zero": "صفر نال تقسیم۔"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sl.json b/www/wiki/extensions/ParserFunctions/i18n/sl.json
new file mode 100644
index 00000000..4be7beb5
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sl.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dbc334"
+ ]
+ },
+ "pfunc_desc": "Izboljša razčlenjevalnik z logičnimi funkcijami",
+ "pfunc_time_error": "Napaka: neveljaven čas",
+ "pfunc_time_too_long": "Napaka: preveč klicev #time",
+ "pfunc_time_too_big": "Napaka: #time podpira samo leta do 9999",
+ "pfunc_time_too_small": "Napaka: #time podpira samo leta od 0.",
+ "pfunc_rel2abs_invalid_depth": "Napaka: Neveljavna globina poti: »$1« (poskus dostopanja do vozlišča višjega od korenskega vozlišča)",
+ "pfunc_expr_stack_exhausted": "Napaka v izrazu: Sklad je izčrpan",
+ "pfunc_expr_unexpected_number": "Napaka v izrazu: Nepričakovani število",
+ "pfunc_expr_preg_match_failure": "Napaka v izrazu: Nepričakovan neuspeh preg_match",
+ "pfunc_expr_unrecognised_word": "Napaka v izrazu: Neprepoznana beseda »$1«",
+ "pfunc_expr_unexpected_operator": "Napaka v izrazu: Nepričakovan operator $1",
+ "pfunc_expr_missing_operand": "Napaka v izrazu: Manjkajoč operand za $1",
+ "pfunc_expr_unexpected_closing_bracket": "Napaka v izrazu: Nepričakovan zaključni oklepaj",
+ "pfunc_expr_unrecognised_punctuation": "Napaka v izrazu: Nepričakovan znak za ločilo »$1«",
+ "pfunc_expr_unclosed_bracket": "Napaka v izrazu: Nezaprti oklepaj",
+ "pfunc_expr_division_by_zero": "Deljenje z ničlo",
+ "pfunc_expr_invalid_argument": "Napačen argument za $1: < -1 ali > 1",
+ "pfunc_expr_invalid_argument_ln": "Napačen argument za ln: <= 0",
+ "pfunc_expr_unknown_error": "Napaka v izrazu: Neznana napaka ($1)",
+ "pfunc_expr_not_a_number": "V $1: rezultat ni število",
+ "pfunc_string_too_long": "Napaka: Niz presega omejitev $1 {{PLURAL:$1|znaka|znakov}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sq.json b/www/wiki/extensions/ParserFunctions/i18n/sq.json
new file mode 100644
index 00000000..42434b0d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sq.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Olsi",
+ "Vinie007"
+ ]
+ },
+ "pfunc_desc": "Enhance parser me funksione logjike",
+ "pfunc_time_error": "Gabim: kohë e pavlefshme",
+ "pfunc_time_too_long": "Gabim: shumë #thirrje kohe",
+ "pfunc_time_too_big": "Gabim: # kohë mbështet vetëm vjet deri në 9999",
+ "pfunc_rel2abs_invalid_depth": "Gabim: thellësi e pavlefshme në rrugë: \"$1\" (u përpoq për të hyrë në një nyje mbi nyjen e rrënjës)",
+ "pfunc_expr_stack_exhausted": "Gabim shprehjeje: Stack exhausted",
+ "pfunc_expr_unexpected_number": "Gabim shprehjeje: Numër i papritur",
+ "pfunc_expr_preg_match_failure": "Gabim shprehjeje: Dështim i papritur i preg_match",
+ "pfunc_expr_unrecognised_word": "Gabim shprehjeje: Fjalë e panjohur: $1",
+ "pfunc_expr_unexpected_operator": "Gabim shprehjeje: Operator i papritur $1",
+ "pfunc_expr_missing_operand": "Gabim shprehjej: Operim i munfuar për $1",
+ "pfunc_expr_unexpected_closing_bracket": "Gabim shprehjeje: Mbyllje e papritur kllapash",
+ "pfunc_expr_unrecognised_punctuation": "Gabim shprehjeje: Karakater pikësimi i panjohur \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Gabim shprehjeje: Mosmbyllje kllapash",
+ "pfunc_expr_division_by_zero": "Pjesëtim me zero",
+ "pfunc_expr_invalid_argument": "Argument i pavlefshëm për $1: < -1 ose > 1",
+ "pfunc_expr_invalid_argument_ln": "Argument i pavlefshëm për ln: <= 0",
+ "pfunc_expr_unknown_error": "Gabim shprehjeje: Gabim i panjohur ($1)",
+ "pfunc_expr_not_a_number": "Në $1: rezultati nuk është një numër",
+ "pfunc_string_too_long": "Gabim: string kalon limit $1 karakter"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sr-ec.json b/www/wiki/extensions/ParserFunctions/i18n/sr-ec.json
new file mode 100644
index 00000000..05e62e8c
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sr-ec.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Millosh",
+ "Rancher",
+ "Verlor",
+ "Milicevic01",
+ "Сербијана"
+ ]
+ },
+ "pfunc_desc": "Проширује рашчлањивач с логичким функцијама",
+ "pfunc_time_error": "Грешка: Погрешно време.",
+ "pfunc_time_too_long": "Грешка: превише #time позива",
+ "pfunc_rel2abs_invalid_depth": "Грешка: неправилна дубина у путањи: „$1“ (покушај приступа чвору изнад коренског (root)).",
+ "pfunc_expr_stack_exhausted": "Грешка у изразу: стек напуњен",
+ "pfunc_expr_unexpected_number": "Грешка у изразу: неочекивани број",
+ "pfunc_expr_preg_match_failure": "Грешка у изразу: Неочекивана preg_match грешка",
+ "pfunc_expr_unrecognised_word": "Грешка у изразу: непозната реч „$1“",
+ "pfunc_expr_unexpected_operator": "Грешка у изразу: неочекивани оператор „$1“",
+ "pfunc_expr_missing_operand": "Грешка у изразу: недостаје операнд за $1",
+ "pfunc_expr_unexpected_closing_bracket": "Грешка у изразу: неочекивано затварање средње заграде.",
+ "pfunc_expr_unrecognised_punctuation": "Грешка у изразу: непознати интерпункцијски карактер „$1“.",
+ "pfunc_expr_unclosed_bracket": "Грешка у изразу: незатворена средња заграда.",
+ "pfunc_expr_division_by_zero": "Дељење са нулом.",
+ "pfunc_expr_invalid_argument": "Лош аргумент: $1 је < -1 или > 1",
+ "pfunc_expr_invalid_argument_ln": "Лош аргумент: ln <= 0",
+ "pfunc_expr_unknown_error": "Грешка у изразу: Непозната грешка ($1)",
+ "pfunc_expr_not_a_number": "Резултат у $1 није број.",
+ "pfunc_string_too_long": "Грешка: реч прекорачује $1 слова, што је постављено ограничење"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sr-el.json b/www/wiki/extensions/ParserFunctions/i18n/sr-el.json
new file mode 100644
index 00000000..7aa8af22
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sr-el.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michaello",
+ "Milicevic01",
+ "Сербијана"
+ ]
+ },
+ "pfunc_desc": "obogati parser logičkim funkcijama",
+ "pfunc_time_error": "Greška: Pogrešno vreme.",
+ "pfunc_time_too_long": "Greška: previše #time poziva",
+ "pfunc_rel2abs_invalid_depth": "Greška: nepravilna dubina u putanji: „$1“ (pokušaj pristupa čvoru iznad korenskog (root)).",
+ "pfunc_expr_stack_exhausted": "Greška u izrazu: stek napunjen",
+ "pfunc_expr_unexpected_number": "Greška u izrazu: neočekivani broj",
+ "pfunc_expr_preg_match_failure": "Greška u izrazu: Neočekivana preg_match greška",
+ "pfunc_expr_unrecognised_word": "Greška u izrazu: nepoznata reč „$1“",
+ "pfunc_expr_unexpected_operator": "Greška u izrazu: neočekivani operator „$1“",
+ "pfunc_expr_missing_operand": "Greška u izrazu: nedostaje operand za $1",
+ "pfunc_expr_unexpected_closing_bracket": "Greška u izrazu: neočekivano zatvaranje srednje zagrade.",
+ "pfunc_expr_unrecognised_punctuation": "Greška u izrazu: nepoznati interpunkcijski karakter „$1“.",
+ "pfunc_expr_unclosed_bracket": "Greška u izrazu: nezatvorena srednja zagrada.",
+ "pfunc_expr_division_by_zero": "Deljenje sa nulom.",
+ "pfunc_expr_invalid_argument": "Loš argument: $1 je < -1 ili > 1",
+ "pfunc_expr_invalid_argument_ln": "Loš argument: ln <= 0",
+ "pfunc_expr_unknown_error": "Greška u izrazu: Nepoznata greška ($1)",
+ "pfunc_expr_not_a_number": "Rezultat u $1 nije broj.",
+ "pfunc_string_too_long": "Greška: reč prekoračuje $1 slova, što je postavljeno ograničenje"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/stq.json b/www/wiki/extensions/ParserFunctions/i18n/stq.json
new file mode 100644
index 00000000..87407d28
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/stq.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pyt"
+ ]
+ },
+ "pfunc_desc": "Ärwiedert dän Parser uum logiske Funktione",
+ "pfunc_time_error": "Failer: uungultige Tiedangoawe",
+ "pfunc_time_too_long": "Failer: tou fuul #time-Aproupe",
+ "pfunc_rel2abs_invalid_depth": "Failer: uungultige Djüpte in Paad: „$1“ (Fersäik, ap n Knättepunkt buppe dän Haudknättepunkt toutougriepen)",
+ "pfunc_expr_stack_exhausted": "Expression-Failer: Stack-Uurloop",
+ "pfunc_expr_unexpected_number": "Expression-Failer: Nit ferwachtede Taal",
+ "pfunc_expr_preg_match_failure": "Expression-Failer: Uunferwachtede „preg_match“-Failfunktion",
+ "pfunc_expr_unrecognised_word": "Expression-Failer: Nit wierkoand Woud „$1“",
+ "pfunc_expr_unexpected_operator": "Expression-Failer: Uunferwachteden Operator: $1",
+ "pfunc_expr_missing_operand": "Expression-Failer: Failenden Operand foar $1",
+ "pfunc_expr_unexpected_closing_bracket": "Expression-Failer: Uunferwachte sluutende kaantige Klammere",
+ "pfunc_expr_unrecognised_punctuation": "Expression-Failer: Nit wierkoand Satsteeken „$1“",
+ "pfunc_expr_unclosed_bracket": "Expression-Failer: Nit sleetene kaantige Klammer",
+ "pfunc_expr_division_by_zero": "Expression-Failer: Division truch Null",
+ "pfunc_expr_invalid_argument": "Uungultich Argument foar $1: < -1 of > 1",
+ "pfunc_expr_invalid_argument_ln": "Uungultich Argument foar ln: <= 0",
+ "pfunc_expr_unknown_error": "Expression-Failer: Uunbekoanden Failer ($1)",
+ "pfunc_expr_not_a_number": "Expression-Failer: In $1: Resultoat is neen Taal",
+ "pfunc_string_too_long": "Failer: Teekenkätte is laanger as dät Teekenlimit fon $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sty.json b/www/wiki/extensions/ParserFunctions/i18n/sty.json
new file mode 100644
index 00000000..264cc3f8
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sty.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Khanmarat"
+ ]
+ },
+ "pfunc_time_error": "Ҡата: уаҡыт төрөс түгел.",
+ "pfunc_expr_unrecognised_word": "Аңнатма ҡата: танылмаған \"$1\" сүс",
+ "pfunc_expr_unexpected_operator": "Аңнатма ҡата: Көтөлмәгән $1 операторы",
+ "pfunc_expr_missing_operand": "Аңнатма ҡата: $1 операнд йетмәйте.",
+ "pfunc_expr_unrecognised_punctuation": "Аңнатма ҡата: танылмаған \"$1\" пунктуация тамғасы",
+ "pfunc_expr_division_by_zero": "Нольға пүлеү"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/su.json b/www/wiki/extensions/ParserFunctions/i18n/su.json
new file mode 100644
index 00000000..f55f0198
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/su.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Irwangatot",
+ "Kandar"
+ ]
+ },
+ "pfunc_desc": "Ngembangkeun parser kalawan fungsi logis",
+ "pfunc_time_error": "Éror: titimangsa teu valid",
+ "pfunc_expr_unrecognised_word": "Salah éksprési: Kecap \"$1\" teu dipikawanoh.",
+ "pfunc_expr_unexpected_operator": "Salah éksprési: operator $1 teu dipiharep.",
+ "pfunc_expr_missing_operand": "Salah éksprési: operan $1 leungit.",
+ "pfunc_expr_unrecognised_punctuation": "Salah éksprési: Tanda baca \"$1\" teu dipikawanoh.",
+ "pfunc_expr_division_by_zero": "Pambagi ku nol"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/sv.json b/www/wiki/extensions/ParserFunctions/i18n/sv.json
new file mode 100644
index 00000000..b9d32d55
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/sv.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ainali",
+ "Lejonel",
+ "Lokal Profil",
+ "M.M.S.",
+ "Najami",
+ "WikiPhoenix",
+ "Skalman"
+ ]
+ },
+ "pfunc_desc": "Lägger till logiska funktioner i parsern",
+ "pfunc_time_error": "Fel: ogiltig tid",
+ "pfunc_time_too_long": "Fel: för många anrop av #time",
+ "pfunc_time_too_big": "Fel: # tid stöder endast år fram till 9999",
+ "pfunc_time_too_small": "Fel: #tid stödjer enbart år från 0.",
+ "pfunc_rel2abs_invalid_depth": "Fel: felaktig djup i sökväg: \"$1\" (försöker nå en nod ovanför rotnoden)",
+ "pfunc_expr_stack_exhausted": "Fel i uttryck: Stackutrymmet tog slut",
+ "pfunc_expr_unexpected_number": "Fel i uttryck: Oväntat tal",
+ "pfunc_expr_preg_match_failure": "Fel i uttryck: Oväntad fel i preg_match",
+ "pfunc_expr_unrecognised_word": "Fel i uttryck: Okänt ord \"$1\".",
+ "pfunc_expr_unexpected_operator": "Fel i uttryck: Oväntad operator $1.",
+ "pfunc_expr_missing_operand": "Fel i uttryck: Operand saknas för $1.",
+ "pfunc_expr_unexpected_closing_bracket": "Fel i uttryck: Oväntad avslutande parentes",
+ "pfunc_expr_unrecognised_punctuation": "Fel i uttryck: Okänt skiljetecken \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Fel i uttryck: Oavslutad parentes",
+ "pfunc_expr_division_by_zero": "Division med noll",
+ "pfunc_expr_invalid_argument": "Ogiltigt argument för $1: < -1 eller > 1",
+ "pfunc_expr_invalid_argument_ln": "Ogiltigt argument för ln: <= 0",
+ "pfunc_expr_unknown_error": "Fel i uttryck: Okänt fel ($1)",
+ "pfunc_expr_not_a_number": "I $1: resultatet är inte ett tal",
+ "pfunc_string_too_long": "Fel: Strängen överskrider gränsen på $1 tecken"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/szl.json b/www/wiki/extensions/ParserFunctions/i18n/szl.json
new file mode 100644
index 00000000..038f8afc
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/szl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Krol111"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Błąd we wyrażyńu – felerne słowo „$1”",
+ "pfunc_expr_unexpected_operator": "Feler we wyrażyńu: Felerny uoperator.",
+ "pfunc_expr_missing_operand": "Feler we wyrażyńu – brak argumyntu funkcyji $1",
+ "pfunc_expr_unrecognised_punctuation": "Feler we wyrażyńu – felerny znok „$1”"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ta.json b/www/wiki/extensions/ParserFunctions/i18n/ta.json
new file mode 100644
index 00000000..7b5b0507
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ta.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shanmugamp7"
+ ]
+ },
+ "pfunc_time_error": "பிழை: செல்லாத நேரம்"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tay.json b/www/wiki/extensions/ParserFunctions/i18n/tay.json
new file mode 100644
index 00000000..21dab9e0
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tay.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hitaypayan",
+ "Temu19900728",
+ "Translatealcd"
+ ]
+ },
+ "pfunc_time_error": "Min’uqu’: ungat zyuwaw zikang.",
+ "pfunc_expr_unrecognised_word": "min’uqu’ bniru’ su’: ungat qqbaq mita’ biru’ tay \"$1\"",
+ "pfunc_expr_unexpected_operator": "Min’uqu’ pinkaykita’ su’:Iyat sinpngan sa sawn naha Yuswanc’ $1",
+ "pfunc_expr_missing_operand": "Min’uqu’ quw sinbbaq kay’ su’:wal su’ zhuqan biru’ sa bbiru’ na pplpgan tay $1",
+ "pfunc_expr_unrecognised_punctuation": "Min’uqu’ quw bniru’ su’: ini’ baqiy mita’ quw bniru’ na sinbbaq su’ \"$1\".",
+ "pfunc_expr_division_by_zero": "Ungat quw pinqsugan na pinqsugan."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tcy.json b/www/wiki/extensions/ParserFunctions/i18n/tcy.json
new file mode 100644
index 00000000..fdfa6ab5
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tcy.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Vishwanatha Badikana",
+ "BHARATHESHA ALASANDEMAJALU",
+ "Kiranpoojary"
+ ]
+ },
+ "pfunc_time_error": "ದೋಷ: ಸಮಯ ತಪ್ಪಾತ್ಂಡ್.",
+ "pfunc_expr_unrecognised_word": "ಸಾಲ್‍ದ ದೋಸೊ: ಪತ್ತೆದಾಂತಿನ ಪದೊ \"$1\".",
+ "pfunc_expr_unexpected_operator": "ಅಬಿವ್ಯಕ್ತಿ ದೋಸೊ: ಅನಿರೀಕ್ಷಿತೊ ಒಪರೇಟರ್ $1.",
+ "pfunc_expr_missing_operand": "ಸಾಲ್‍ದ ದೋಸೊ: $1 ಕ್ರಿಯಾಚಿನ್ನೆ ತಿಕ್ಕಿಜಿ.",
+ "pfunc_expr_unrecognised_punctuation": "ವಿವರೊ ದೋಸೊ: ಗೊತ್ತಾವಂದಿನ ಚಿನ್ನೆಲು \"$1\".",
+ "pfunc_expr_division_by_zero": "ಸೊನ್ನೆಡ್ದ್ ಭಾಗಕಾರೊ"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/te.json b/www/wiki/extensions/ParserFunctions/i18n/te.json
new file mode 100644
index 00000000..8485ccaf
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/te.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mpradeep",
+ "Veeven"
+ ]
+ },
+ "pfunc_time_error": "లోపం: సమయం సరిగ్గా లేదు",
+ "pfunc_time_too_long": "లోపం: #timeను చాలా సార్లు ఉపయోగించారు",
+ "pfunc_rel2abs_invalid_depth": "లోపం: పాత్ యొక్క డెప్తు సరిగ్గాలేదు: \"$1\" (రూట్ నోడు కంటే పైన ఉన్న నోడు ఉపయోగించటానికి ప్రయత్నం జరిగింది)",
+ "pfunc_expr_stack_exhausted": "సమాసంలో(Expression) లోపం: స్టాకు మొత్తం అయిపోయింది",
+ "pfunc_expr_unexpected_number": "సమాసంలో(Expression) లోపం: ఊహించని సంఖ్య వచ్చింది",
+ "pfunc_expr_preg_match_failure": "సమాసంలో(Expression) లోపం: preg_matchలో ఊహించని విఫలం",
+ "pfunc_expr_unrecognised_word": "సమాసంలో(Expression) లోపం: \"$1\" అనే పదాన్ని గుర్తుపట్టలేకపోతున్నాను",
+ "pfunc_expr_unexpected_operator": "సమాసంలో(Expression) లోపం: $1 పరికర్తను(operator) ఊహించలేదు",
+ "pfunc_expr_missing_operand": "సమాసంలో(Expression) లోపం: $1కు ఒక ఆపరాండును ఇవ్వలేదు",
+ "pfunc_expr_unexpected_closing_bracket": "సమాసంలో(Expression) లోపం: ఊహించని బ్రాకెట్టు ముగింపు",
+ "pfunc_expr_unrecognised_punctuation": "సమాసంలో(Expression) లోపం: \"$1\" అనే విరామ చిహ్నాన్ని గుర్తించలేకపోతున్నాను",
+ "pfunc_expr_unclosed_bracket": "సమాసంలో(Expression) లోపం: బ్రాకెట్టును మూయలేదు",
+ "pfunc_expr_division_by_zero": "సున్నాతో భాగించారు",
+ "pfunc_expr_unknown_error": "సమాసంలో(Expression) లోపం: తెలియని లోపం ($1)",
+ "pfunc_expr_not_a_number": "$1లో: వచ్చిన ఫలితం సంఖ్య కాదు"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tg-cyrl.json b/www/wiki/extensions/ParserFunctions/i18n/tg-cyrl.json
new file mode 100644
index 00000000..ca776e10
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tg-cyrl.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ibrahim"
+ ]
+ },
+ "pfunc_desc": "Ба таҷзеҳкунанда, дастурҳои мантиқӣ меафзояд",
+ "pfunc_time_error": "Хато: замони ғайримиҷоз",
+ "pfunc_time_too_long": "Хато: #time фарохонии беш аз ҳад",
+ "pfunc_rel2abs_invalid_depth": "Хато: Чуқурии ғайримиҷоз дар нишонӣ: \"$1\" (талош барои дастраси ба як нишонӣ болотар аз нишонии реша)",
+ "pfunc_expr_stack_exhausted": "Хатои ибора: Пушта аз даст рафтааст",
+ "pfunc_expr_unexpected_number": "Хатои ибора: Адади ғайримунтазир",
+ "pfunc_expr_preg_match_failure": "Хатои ибора: Хатои ғайримунтазири preg_match",
+ "pfunc_expr_unrecognised_word": "Хатои ибора: Калимаи ношинохта \"$1\"",
+ "pfunc_expr_unexpected_operator": "Хатои ибора: Амалгари ғайримунтазири $1",
+ "pfunc_expr_missing_operand": "Хатои ибора: Амалгари гумшуда барои $1",
+ "pfunc_expr_unexpected_closing_bracket": "Хатои ибора: Қафси бастаи номунтазир",
+ "pfunc_expr_unrecognised_punctuation": "Хатои ибора: Аломати нуқтагузории шинохтанашуда \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Хатои ибора: Қафси бастанашуда",
+ "pfunc_expr_division_by_zero": "Тақсим бар сифр",
+ "pfunc_expr_unknown_error": "Хатои ибора: Хатои ношинос ($1)",
+ "pfunc_expr_not_a_number": "Дар $1: натиҷа адад нест"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tg-latn.json b/www/wiki/extensions/ParserFunctions/i18n/tg-latn.json
new file mode 100644
index 00000000..3747c2e5
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tg-latn.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Liangent"
+ ]
+ },
+ "pfunc_desc": "Ba taçzehkunanda, dasturhoi mantiqī meafzojad",
+ "pfunc_time_error": "Xato: zamoni ƣajrimiçoz",
+ "pfunc_time_too_long": "Xato: #time faroxoniji beş az had",
+ "pfunc_rel2abs_invalid_depth": "Xato: Cuquriji ƣajrimiçoz dar nişonī: \"$1\" (taloş baroi dastrasi ba jak nişonī bolotar az nişoniji reşa)",
+ "pfunc_expr_stack_exhausted": "Xatoi ibora: Puşta az dast raftaast",
+ "pfunc_expr_unexpected_number": "Xatoi ibora: Adadi ƣajrimuntazir",
+ "pfunc_expr_preg_match_failure": "Xatoi ibora: Xatoi ƣajrimuntaziri preg_match",
+ "pfunc_expr_unrecognised_word": "Xatoi ibora: Kalimai noşinoxta \"$1\"",
+ "pfunc_expr_unexpected_operator": "Xatoi ibora: Amalgari ƣajrimuntaziri $1",
+ "pfunc_expr_missing_operand": "Xatoi ibora: Amalgari gumşuda baroi $1",
+ "pfunc_expr_unexpected_closing_bracket": "Xatoi ibora: Qafsi bastai nomuntazir",
+ "pfunc_expr_unrecognised_punctuation": "Xatoi ibora: Alomati nuqtaguzoriji şinoxtanaşuda \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Xatoi ibora: Qafsi bastanaşuda",
+ "pfunc_expr_division_by_zero": "Taqsim bar sifr",
+ "pfunc_expr_unknown_error": "Xatoi ibora: Xatoi noşinos ($1)",
+ "pfunc_expr_not_a_number": "Dar $1: natiça adad nest"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/th.json b/www/wiki/extensions/ParserFunctions/i18n/th.json
new file mode 100644
index 00000000..54862fb1
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/th.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ans",
+ "Horus"
+ ]
+ },
+ "pfunc_time_error": "เกิดข้อผิดพลาด: ค่าเวลาไม่ถูกต้อง",
+ "pfunc_time_too_long": "เกิดข้อผิดพลาด: มีการเรียกใช้ #time มากเกินไป",
+ "pfunc_rel2abs_invalid_depth": "เกิดข้อผิดพลาด: path depth ไม่ถูกต้อง: \"$1\" (เป็นการพยายามที่จะเข้าถึงตำแหน่งที่อยู่เหนือตำแหน่งราก)",
+ "pfunc_expr_stack_exhausted": "สูตรเกิดข้อผิดพลาด: มี stack ไม่พอในการคำนวณสูตร",
+ "pfunc_expr_unexpected_number": "สูตรไม่ถูกต้อง: ค่าตัวเลขอยู่ผิดที่",
+ "pfunc_expr_preg_match_failure": "สูตรเกิดข้อผิดพลาด: เกิดความล้มเหลวในการสั่ง preg_match โดยไม่ทราบสาเหตุ",
+ "pfunc_expr_unrecognised_word": "ข้อผิดพลาดนิพจน์: \"$1\" เป็นคำที่ไม่รู้จัก",
+ "pfunc_expr_unexpected_operator": "สูตรไม่ถูกต้อง: $1 อยู่ผิดที่",
+ "pfunc_expr_missing_operand": "ข้อผิดพลาดนิพจน์: ขาดตัวถูกดำเนินการสำหรับ $1",
+ "pfunc_expr_unexpected_closing_bracket": "สูตรไม่ถูกต้อง: ปิดวงเล็บเกิน หรือ ปิดวงเล็บผิดที่",
+ "pfunc_expr_unrecognised_punctuation": "ข้อผิดพลาดนิพจน์: \"$1\" เป็นอักขระที่ไม่รู้จัก",
+ "pfunc_expr_unclosed_bracket": "สูตรไม่ถูกต้อง: ไม่ได้ปิดวงเล็บ",
+ "pfunc_expr_division_by_zero": "ตัวหารเป็นศูนย์",
+ "pfunc_expr_invalid_argument": "ค่าตัวแปรไม่ถูกต้อง: $1 ไม่สามารถรับค่าที่น้อยกว่า -1 หรือ มากกว่า 1",
+ "pfunc_expr_invalid_argument_ln": "ค่าตัวแปรไม่ถูกต้อง: ln ไม่สามารถรับค่าที่น้อยกว่าหรือเท่ากับศูนย์",
+ "pfunc_expr_unknown_error": "สูตรไม่ถูกต้อง: เกิดความผิดพลาดในสูตรโดยไม่ทราบสาเหตุ ($1)",
+ "pfunc_expr_not_a_number": "$1: ผลลัพธ์ไม่สามารถแทนด้วยจำนวน (NAN or not a number)"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tk.json b/www/wiki/extensions/ParserFunctions/i18n/tk.json
new file mode 100644
index 00000000..2aff7139
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tk.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hanberke"
+ ]
+ },
+ "pfunc_desc": "Parseri logiki funksiýalar bilen güýçlendir",
+ "pfunc_time_error": "Säwlik: nädogry wagt",
+ "pfunc_time_too_long": "Säwlik: aşa köp #time çagyryşlary",
+ "pfunc_rel2abs_invalid_depth": "Säwlik: Ýolda nädogry çuňluk: \"$1\" (kök düwüniň üstündäki bir düwüne barjak boldy)",
+ "pfunc_expr_stack_exhausted": "Aňlatma säwligi: Stek gutardy",
+ "pfunc_expr_unexpected_number": "Aňlatma säwligi: Garaşylmaýan san",
+ "pfunc_expr_preg_match_failure": "Aňlatma säwligi: Garaşylmaýan preg_match näsazlygy",
+ "pfunc_expr_unrecognised_word": "Aňlatma säwligi: Bilinmeýän \"$1\" sözi",
+ "pfunc_expr_unexpected_operator": "Aňlatma säwligi: Garaşylmaýan $1 operatory",
+ "pfunc_expr_missing_operand": "Aňlatma säwligi: $1 üçin kem operand",
+ "pfunc_expr_unexpected_closing_bracket": "Aňlatma säwligi: Garaşylmaýan ýapyjy ýaý",
+ "pfunc_expr_unrecognised_punctuation": "Aňlatma säwligi: Bilinmeýän punktuasiýa simwoly \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Aňlatma säwligi: Ýapylmadyk ýaý",
+ "pfunc_expr_division_by_zero": "Nola bölmek",
+ "pfunc_expr_invalid_argument": "$1: < -1 ýa-da > 1 üçin nädogry argument",
+ "pfunc_expr_invalid_argument_ln": "ln: <= 0 üçin nädogry argument",
+ "pfunc_expr_unknown_error": "Aňlatma säwligi: Näbelli säwlik ($1)",
+ "pfunc_expr_not_a_number": "$1-de: netije san däl",
+ "pfunc_string_too_long": "Säwlik: Setir $1 simwol çäginden geçýär"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tl.json b/www/wiki/extensions/ParserFunctions/i18n/tl.json
new file mode 100644
index 00000000..5e0a2852
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tl.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "AnakngAraw"
+ ]
+ },
+ "pfunc_desc": "Pagibayuhin ang katangian ng banghay na may mga tungkuling makatwiran (may lohika)",
+ "pfunc_time_error": "Kamalian: hindi tanggap na oras",
+ "pfunc_time_too_long": "Kamalian: napakaraming mga pagtawag sa #oras",
+ "pfunc_rel2abs_invalid_depth": "Kamalian: Hindi tanggap na sukat ng lalim sa daanan: \"$1\" (sinubok na puntahan ang isang alimpusong nasa itaas ng bugkol ng ugat)",
+ "pfunc_expr_stack_exhausted": "Kamalian sa pagpapahayag: Naubos na ang salansan",
+ "pfunc_expr_unexpected_number": "Kamalian sa pagpapahayag: Hindi inaasahang bilang",
+ "pfunc_expr_preg_match_failure": "Kamalian sa pagpapahayag: Hindi inaasahang pagkabigo ng \"pagtutugma_ng_hibla\" (''preg_match'')",
+ "pfunc_expr_unrecognised_word": "Kamalian sa pagpapahayag: Hindi nakikilalang salitang \"$1\"",
+ "pfunc_expr_unexpected_operator": "Kamalian sa pagpapahayag: Hindi inaasahang bantas na tagapagsagawa (''operator'') ng $1",
+ "pfunc_expr_missing_operand": "Kamalian sa pagpapahayag: Nawawalang halaga (''operand'') para sa $1",
+ "pfunc_expr_unexpected_closing_bracket": "Kamalian sa pagpapahayag: Hindi inaasahang pangpagtatapos na panaklong na kasingay (braket)",
+ "pfunc_expr_unrecognised_punctuation": "Kamalian sa pagpapahayag: Hindi nakikilalang panitik na pangpalabantasang \"$1\"",
+ "pfunc_expr_unclosed_bracket": "Kamalian sa pagpapahayag: Hindi naisarang panaklong na kasingay (braket)",
+ "pfunc_expr_division_by_zero": "Paghahati sa pamamagitan ng wala (sero)",
+ "pfunc_expr_invalid_argument": "Hindi tanggap na pangangatwiran (argumento) para sa $1: < -1 o > 1",
+ "pfunc_expr_invalid_argument_ln": "Hindi tanggap na pangangatwiran (argumento) para sa ln: <= 0",
+ "pfunc_expr_unknown_error": "Kamalian sa pagpapahayag: Hindi nalalamang kamalian ($1)",
+ "pfunc_expr_not_a_number": "Sa $1: ang kinalabasan ay hindi isang bilang",
+ "pfunc_string_too_long": "Kamalian: Lumampas ang bagting sa $1 hangganang panitik"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tr.json b/www/wiki/extensions/ParserFunctions/i18n/tr.json
new file mode 100644
index 00000000..c6dc3f50
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tr.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joseph",
+ "Vito Genovese"
+ ]
+ },
+ "pfunc_desc": "Derleyiciyi mantıksal fonksiyonlarla geliştir",
+ "pfunc_time_error": "Hata: Geçersiz saat.",
+ "pfunc_time_too_long": "Hata: çok fazla #time çağrısı",
+ "pfunc_rel2abs_invalid_depth": "Hata: Yolda geçersiz derinlik: \"$1\" (kök düğümünün üstünde bir düğüme erişmeye çalıştı)",
+ "pfunc_expr_stack_exhausted": "İfade hatası: Stack bitti",
+ "pfunc_expr_unexpected_number": "İfade hatası: Beklenmeyen sayı",
+ "pfunc_expr_preg_match_failure": "İfade hatası: Beklenmedik preg_match arızası",
+ "pfunc_expr_unrecognised_word": "İfade hatası: Tanınmayan \"$1\" kelimesi",
+ "pfunc_expr_unexpected_operator": "İfade hatası: Beklenmedik $1 operatörü",
+ "pfunc_expr_missing_operand": "İfade hatası: $1 için eksik terim",
+ "pfunc_expr_unexpected_closing_bracket": "İfade hatası: Beklenmedik kapa parantez",
+ "pfunc_expr_unrecognised_punctuation": "İfade hatası: Tanınmayan noktalama karakteri \"$1\"",
+ "pfunc_expr_unclosed_bracket": "İfade hatası: Kapanmamış parantez",
+ "pfunc_expr_division_by_zero": "Sıfır ile bölme",
+ "pfunc_expr_invalid_argument": "$1 için geçersiz değişken: < -1 ya da > 1",
+ "pfunc_expr_invalid_argument_ln": "ln için geçersiz değişken: <= 0",
+ "pfunc_expr_unknown_error": "İfade hatası: Bilinmeyen hata ($1)",
+ "pfunc_expr_not_a_number": "$1'de: sonuç bir sayı değil",
+ "pfunc_string_too_long": "Hata: Dize $1 karakter sınırını geçiyor"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tt-cyrl.json b/www/wiki/extensions/ParserFunctions/i18n/tt-cyrl.json
new file mode 100644
index 00000000..9c70c9e8
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tt-cyrl.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ильнар"
+ ]
+ },
+ "pfunc_time_error": "Хата: ялган вакыт",
+ "pfunc_expr_unrecognised_word": "Төзмә хата: билгесез сүз «$1»",
+ "pfunc_expr_unexpected_operator": "Төзмә хата: күзәтелмәгән оператор $1",
+ "pfunc_expr_missing_operand": "Төзмә хата: $1 операнда җитми",
+ "pfunc_expr_unrecognised_punctuation": "Төзмә хата: билгесез символ «$1»",
+ "pfunc_expr_division_by_zero": "Нулгә бүлү."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tt-latn.json b/www/wiki/extensions/ParserFunctions/i18n/tt-latn.json
new file mode 100644
index 00000000..bd717b65
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tt-latn.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Frhdkazan"
+ ]
+ },
+ "pfunc_expr_unexpected_operator": "Тäğbir xatası: Kötelmägän $1 operatorı."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/tyv.json b/www/wiki/extensions/ParserFunctions/i18n/tyv.json
new file mode 100644
index 00000000..272513b5
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/tyv.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Монгуш Салим"
+ ]
+ },
+ "pfunc_expr_unrecognised_punctuation": "Частырыг: бижик дүрүмүнде \"$1\" демдек чок."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/udm.json b/www/wiki/extensions/ParserFunctions/i18n/udm.json
new file mode 100644
index 00000000..fb0ecc28
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/udm.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Wadorgurt",
+ "Patrick Star"
+ ]
+ },
+ "pfunc_time_error": "Янгышъёс: недопустимый дыр.",
+ "pfunc_expr_unrecognised_word": "Выражениын янгыш: тодмамтэ кыл «$1».",
+ "pfunc_expr_unexpected_operator": "Выражениын янгыш: возьмамтэ $1 оператор.",
+ "pfunc_expr_missing_operand": "Выражениын янгыш: $1 операнд уг тырмы.",
+ "pfunc_expr_unrecognised_punctuation": "Выражениын янгыш: тодмамтэ пунктуаци пус «$1»."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ug-arab.json b/www/wiki/extensions/ParserFunctions/i18n/ug-arab.json
new file mode 100644
index 00000000..767d0834
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ug-arab.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sahran",
+ "Uzdil"
+ ]
+ },
+ "pfunc_time_error": "خاتالىق: ئىناۋەتسىز ۋاقىت.",
+ "pfunc_expr_division_by_zero": "نۆلگە بۆلۈنگەن."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/uk.json b/www/wiki/extensions/ParserFunctions/i18n/uk.json
new file mode 100644
index 00000000..73da3792
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/uk.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "AS",
+ "Ahonc",
+ "Base",
+ "Piramidion"
+ ]
+ },
+ "pfunc_desc": "Покращений синтаксичний аналізатор з логічними функціями",
+ "pfunc_time_error": "Помилка: неправильний час",
+ "pfunc_time_too_long": "Помилка: забагато викликів функції #time",
+ "pfunc_time_too_big": "Помилка: Параметр #time підтримує роки лише до 9999.",
+ "pfunc_time_too_small": "Помилка: #time підтримує роки лише після 0.",
+ "pfunc_rel2abs_invalid_depth": "Помилка: неправильна глибина шляху: «$1» (спроба доступу до вузла, що знаходиться вище, ніж кореневий)",
+ "pfunc_expr_stack_exhausted": "Помилка виразу: стек переповнений",
+ "pfunc_expr_unexpected_number": "Помилка виразу: неочікуване число",
+ "pfunc_expr_preg_match_failure": "Помилка виразу: збій preg_match",
+ "pfunc_expr_unrecognised_word": "Помилка виразу: незрозуміле слово «$1»",
+ "pfunc_expr_unexpected_operator": "Помилка виразу: неочікуваний оператор $1",
+ "pfunc_expr_missing_operand": "Помилка виразу: бракує операнда для $1",
+ "pfunc_expr_unexpected_closing_bracket": "Помилка виразу: неочікувана закривальна дужка",
+ "pfunc_expr_unrecognised_punctuation": "Помилка виразу: незрозумілий розділовий знак «$1»",
+ "pfunc_expr_unclosed_bracket": "Помилка виразу: незакрита дужка",
+ "pfunc_expr_division_by_zero": "Ділення на нуль",
+ "pfunc_expr_invalid_argument": "Неправильний аргумент для $1: < -1 або > 1",
+ "pfunc_expr_invalid_argument_ln": "Помилковий аргумент логарифма (має бути більший від нуля)",
+ "pfunc_expr_unknown_error": "Помилка виразу: невідома помилка ($1)",
+ "pfunc_expr_not_a_number": "У $1: результат не є числом",
+ "pfunc_string_too_long": "Помилка: довжина рядка перевищує межу в {{PLURAL:$1|$1 символ|$1 символи|$1 символів}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/ur.json b/www/wiki/extensions/ParserFunctions/i18n/ur.json
new file mode 100644
index 00000000..ff1d8680
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/ur.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "عثمان خان شاہ",
+ "Muhammad Shuaib"
+ ]
+ },
+ "pfunc_time_error": "نقص: نادرست وقت۔",
+ "pfunc_time_too_long": "نقص: #وقت کے بے حد زیادہ مطالبات",
+ "pfunc_time_too_big": "نقص: #وقت محض ‌‌9999 برسوں تک معاونت فراہم کرتا ہے۔",
+ "pfunc_time_too_small": "نقص: #وقت کی معاونت محض 0 سے آگے برسوں کے لیے ہے۔",
+ "pfunc_expr_stack_exhausted": "نقص اظہار: اسٹیک نڈھال۔",
+ "pfunc_expr_unexpected_number": "نقص اظہار: غیر متوقع عدد۔",
+ "pfunc_expr_preg_match_failure": "نقص اظہار: preg_match کی غیر متوقع ناکامی۔",
+ "pfunc_expr_unrecognised_word": "نقص اظہار: غیر معروف لفظ «$1»",
+ "pfunc_expr_unexpected_operator": "نقص اظہار: غیر متوقع $1 آپریٹر۔",
+ "pfunc_expr_missing_operand": "نقص اظہار: $1 سے operand مفقود ہے۔",
+ "pfunc_expr_unexpected_closing_bracket": "نقص اظہار: غیر موقع طور پر قوسین کو بند کیا گیا ہے۔",
+ "pfunc_expr_unrecognised_punctuation": "نقص اظہار: «$1» کا غیر معروف تلفظ۔",
+ "pfunc_expr_unclosed_bracket": "نقص اظہار: قوسین بند نہیں ہیں۔",
+ "pfunc_expr_division_by_zero": "صفر کے ذریعہ تقسیم۔",
+ "pfunc_expr_invalid_argument": "$1 کی نادرست دلیل: < -1 یا > 1۔",
+ "pfunc_expr_invalid_argument_ln": "In کی نادرست دلیل: <= 0۔",
+ "pfunc_expr_unknown_error": "نقص اظہار: نامعلوم نقص ($1)۔",
+ "pfunc_expr_not_a_number": "$1 میں: نتیجہ میں کوئی عدد نہیں۔",
+ "pfunc_string_too_long": "نقص: اسٹرنگ میں $1 لفظوں کی حد متعین ہے۔"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/vec.json b/www/wiki/extensions/ParserFunctions/i18n/vec.json
new file mode 100644
index 00000000..f77e2037
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/vec.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Candalua",
+ "GatoSelvadego"
+ ]
+ },
+ "pfunc_desc": "Zonta al parser na serie de funsion logiche",
+ "pfunc_time_error": "Eror: orario mìa valido",
+ "pfunc_time_too_long": "Eror: massa chiamate a #time",
+ "pfunc_time_too_big": "Eror: #time suporta soło che fin al ano 9999",
+ "pfunc_time_too_small": "Eror: #time suporta soło che da l'ano 0.",
+ "pfunc_rel2abs_invalid_depth": "Eror: profondità mìa valida nel percorso \"$1\" (se gà proà a accédar a un nodo piassè sora de la raìsa)",
+ "pfunc_expr_stack_exhausted": "Eror ne l'espression: stack esaurìo",
+ "pfunc_expr_unexpected_number": "Eror ne l'espression: xe vegnù fora un nùmaro che no se se spetava",
+ "pfunc_expr_preg_match_failure": "Eror ne l'espression: eror inateso in preg_match",
+ "pfunc_expr_unrecognised_word": "Eror ne l'espression: parola \"$1\" mìa riconossiùa",
+ "pfunc_expr_unexpected_operator": "Eror ne l'espression: operator $1 inateso",
+ "pfunc_expr_missing_operand": "Eror ne l'espression: operando mancante par $1",
+ "pfunc_expr_unexpected_closing_bracket": "Eror ne l'espression: parentesi chiusa inatesa",
+ "pfunc_expr_unrecognised_punctuation": "Eror ne l'espression: caràtere de puntegiatura \"$1\" mìa riconossiùo",
+ "pfunc_expr_unclosed_bracket": "Eror ne l'espression: parentesi verta e mìa sarà",
+ "pfunc_expr_division_by_zero": "Division par zero",
+ "pfunc_expr_invalid_argument": "Argomento mìa valido par $1: < -1 or > 1",
+ "pfunc_expr_invalid_argument_ln": "Argomento mìa valido par ln: <= 0",
+ "pfunc_expr_unknown_error": "Eror ne l'espression: eror sconossiùo ($1)",
+ "pfunc_expr_not_a_number": "In $1: el risultato no'l xe mìa un nùmaro",
+ "pfunc_string_too_long": "Eròr: la stringa la va fora dal limite de {{PLURAL:$1|1 caràtere|$1 caràteri}}"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/vep.json b/www/wiki/extensions/ParserFunctions/i18n/vep.json
new file mode 100644
index 00000000..0661865e
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/vep.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Игорь Бродский"
+ ]
+ },
+ "pfunc_time_error": "Petuz: vär aig",
+ "pfunc_expr_unrecognised_word": "Kuvandan petuz: tundmatoi sana \"$1\".",
+ "pfunc_expr_unrecognised_punctuation": "Kuvandan petuz: tundmatoi punktuacine znam \"$1\"."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/vi.json b/www/wiki/extensions/ParserFunctions/i18n/vi.json
new file mode 100644
index 00000000..2e743311
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/vi.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Minh Nguyen",
+ "Vinhtantran"
+ ]
+ },
+ "pfunc_desc": "Nâng cao bộ xử lý với những hàm cú pháp lôgic",
+ "pfunc_time_error": "Lỗi: thời gian không hợp lệ",
+ "pfunc_time_too_long": "Lỗi: quá nhiều lần gọi #time",
+ "pfunc_time_too_big": "Lỗi: #time chỉ hỗ trợ các năm cho tới 9999.",
+ "pfunc_time_too_small": "Lỗi: #time chỉ hỗ trợ cho các năm 0 trở lên.",
+ "pfunc_rel2abs_invalid_depth": "Lỗi: độ sâu không hợp lệ trong đường dẫn “$1” (do cố gắng truy cập nút phía trên nút gốc)",
+ "pfunc_expr_stack_exhausted": "Lỗi biểu thức: Đã cạn stack",
+ "pfunc_expr_unexpected_number": "Lỗi biểu thức: Dư số",
+ "pfunc_expr_preg_match_failure": "Lỗi biểu thức: Hàm preg_match thất bại",
+ "pfunc_expr_unrecognised_word": "Lỗi biểu thức: Từ “$1” không rõ ràng",
+ "pfunc_expr_unexpected_operator": "Lỗi biểu thức: Dư toán tử $1",
+ "pfunc_expr_missing_operand": "Lỗi biểu thức: Thiếu toán hạng trong $1",
+ "pfunc_expr_unexpected_closing_bracket": "Lỗi biểu thức: Dư dấu đóng ngoặc",
+ "pfunc_expr_unrecognised_punctuation": "Lỗi biểu thức: Dấu phân cách “$1” không rõ ràng",
+ "pfunc_expr_unclosed_bracket": "Lỗi biểu thức: Dấu ngoặc chưa được đóng",
+ "pfunc_expr_division_by_zero": "Chia cho zero",
+ "pfunc_expr_invalid_argument": "Tham số không hợp lệ cho $1: < −1 hay > 1",
+ "pfunc_expr_invalid_argument_ln": "Tham số không hợp lệ cho ln: ≤ 0",
+ "pfunc_expr_unknown_error": "Lỗi biểu thức: Lỗi không rõ nguyên nhân ($1)",
+ "pfunc_expr_not_a_number": "Trong $1: kết quả không phải là kiểu số",
+ "pfunc_string_too_long": "Lỗi: Chuỗi vượt quá giới hạn $1 ký tự"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/vo.json b/www/wiki/extensions/ParserFunctions/i18n/vo.json
new file mode 100644
index 00000000..86db5494
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/vo.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Smeira"
+ ]
+ },
+ "pfunc_time_error": "Pök: tim no lonöföl",
+ "pfunc_expr_division_by_zero": "Müedam dub ser",
+ "pfunc_expr_unknown_error": "Notidotapöl: pöl nesevädik ($1)",
+ "pfunc_expr_not_a_number": "In $1: sek no binon num"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/vro.json b/www/wiki/extensions/ParserFunctions/i18n/vro.json
new file mode 100644
index 00000000..5e4836b7
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/vro.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Võrok"
+ ]
+ },
+ "pfunc_time_error": "Viga: viganõ aig",
+ "pfunc_expr_unrecognised_word": "Avaldusõ viga: tundmalda sõna \"$1\"",
+ "pfunc_expr_unexpected_operator": "Avaldusviga: uutmalda $1 märk",
+ "pfunc_expr_missing_operand": "Avaldusõ viga: Puudus om $1 operand",
+ "pfunc_expr_unrecognised_punctuation": "Avaldusõ viga: tundmalda kirävaihõmärk \"$1\"",
+ "pfunc_expr_division_by_zero": "Nulliga jagaminõ"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/wa.json b/www/wiki/extensions/ParserFunctions/i18n/wa.json
new file mode 100644
index 00000000..966cfe0d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/wa.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Srtxg"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Aroke di ratourneure: mot nén cnoxhou «$1».",
+ "pfunc_expr_unrecognised_punctuation": "Aroke di ratourneure: sene di pont nén cnoxhou «$1»."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/war.json b/www/wiki/extensions/ParserFunctions/i18n/war.json
new file mode 100644
index 00000000..ae8c36b9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/war.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "JinJian",
+ "Harvzsf"
+ ]
+ },
+ "pfunc_time_error": "Sayop: Diri puydi an oras.",
+ "pfunc_expr_unrecognised_word": "Sayop nga expression:Diri nakikilal-an an pulong nga \"$1\".",
+ "pfunc_expr_unexpected_operator": "Sayop nga expression: Unexpected $1 operator.",
+ "pfunc_expr_missing_operand": "Expression error: Nawawara nga operand para han $1.",
+ "pfunc_expr_unrecognised_punctuation": "Sayop nga expression\": Waray nakilal-an nga punctuation character \"$1\".",
+ "pfunc_expr_division_by_zero": "Pagbahinbahin hin zero."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/wo.json b/www/wiki/extensions/ParserFunctions/i18n/wo.json
new file mode 100644
index 00000000..850385d3
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/wo.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ibou"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Njuumteg mbindiin: baat \"$1\" kenn xamu ko.",
+ "pfunc_expr_unrecognised_punctuation": "Njuumteg mbindiin: màndarga \"$1\" ken xamu ko."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/wuu.json b/www/wiki/extensions/ParserFunctions/i18n/wuu.json
new file mode 100644
index 00000000..d9a1bb50
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/wuu.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Poiuyt",
+ "飞舞回堂前"
+ ]
+ },
+ "pfunc_time_error": "出错:无效个辰光。",
+ "pfunc_expr_unrecognised_word": "表达式出错:弗能识别个词“$1”",
+ "pfunc_expr_unexpected_operator": "表达式出错:朆预料着个$1操作符",
+ "pfunc_expr_missing_operand": "表达式出错:缺少$1个操作数",
+ "pfunc_expr_unrecognised_punctuation": "表达式出错:弗能识别个标点“$1”",
+ "pfunc_expr_division_by_zero": "畀零除。"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/xal.json b/www/wiki/extensions/ParserFunctions/i18n/xal.json
new file mode 100644
index 00000000..047023e9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/xal.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Huuchin"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "Өгүллин эндү: \"$1\" медгдго үг",
+ "pfunc_expr_unrecognised_punctuation": "Өгүллин эндү: \"$1\" медгдго түдлһнә темдг."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/xmf.json b/www/wiki/extensions/ParserFunctions/i18n/xmf.json
new file mode 100644
index 00000000..bd5a42eb
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/xmf.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Silovan"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "ექსპრესიაშ ჩილათა: უჩინებუ ზიტყვა „$1“.",
+ "pfunc_expr_unexpected_operator": "ექსპრესიაშ ჩილათა: უგჷნალი $1 ოპერატორი.",
+ "pfunc_expr_missing_operand": "ექსპრესიაშ ჩილათა: მედინჷ ოპერანდი $1-შო.",
+ "pfunc_expr_unrecognised_punctuation": "ექსპრესიაშ ჩილათა: უჩინებუ პუნქტუაციაშ შანი $1"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/yi.json b/www/wiki/extensions/ParserFunctions/i18n/yi.json
new file mode 100644
index 00000000..b614ef3c
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/yi.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "פוילישער"
+ ]
+ },
+ "pfunc_time_error": "גרײַז: אומגילטיגע צײַט",
+ "pfunc_expr_unrecognised_word": "אויסדרוק־גרײַז: אומבעקאנט ווארט \"$1",
+ "pfunc_expr_unexpected_operator": "אויסדריק גרײַז: אומגעריכטער $1 אפעראַטאר",
+ "pfunc_expr_missing_operand": "אויסדרוק פעלער: פעלט אפעראנד פאר $1.",
+ "pfunc_expr_unrecognised_punctuation": "אויסדרוק־גרײַז: אומבעקאנטער צייכן \"$1\".",
+ "pfunc_expr_unclosed_bracket": "אויסדריק גרײַז: אומגעשלאסענער קלאַמער",
+ "pfunc_expr_division_by_zero": "טיילן דורך נול.",
+ "pfunc_expr_not_a_number": "אין $1: רעזולטאַט איז נישט קיין נומער"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/yo.json b/www/wiki/extensions/ParserFunctions/i18n/yo.json
new file mode 100644
index 00000000..7d1474a9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/yo.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Demmy"
+ ]
+ },
+ "pfunc_time_error": "Àsìṣe: àsìkò àìtọ́",
+ "pfunc_expr_unexpected_number": "Àsìṣe ìgbékalẹ̀ọ̀rọ̀: Nọ́mbà àìretí",
+ "pfunc_expr_unrecognised_word": "Àsìṣe ìgbéọ̀rọ̀sílẹ̀: Àìdámọ̀ ọ̀rọ̀ \"$1\".",
+ "pfunc_expr_unexpected_operator": "Àsìṣe ìgbékalẹ̀ọ̀rọ̀: àmì-ìṣírò $1 àìretí",
+ "pfunc_expr_missing_operand": "Àsìṣe ìgbéọ̀rọ̀sílẹ̀: Kò sí àmì-ìsirò fún $1.",
+ "pfunc_expr_unrecognised_punctuation": "Àsìṣe ìgbéọ̀rọ̀sílẹ̀: Àìdámọ̀ àmì ìdádúró-ọ̀rọ̀ sókí \"$1\".",
+ "pfunc_expr_division_by_zero": "Pínpín pẹ̀lú òdo",
+ "pfunc_expr_not_a_number": "Nínú $1: èsì kìí ṣe nọ́mbà"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/yue.json b/www/wiki/extensions/ParserFunctions/i18n/yue.json
new file mode 100644
index 00000000..5738c3e0
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/yue.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shinjiman",
+ "Yueman"
+ ]
+ },
+ "pfunc_desc": "用邏輯功能去加強處理器",
+ "pfunc_time_error": "錯: 唔啱嘅時間",
+ "pfunc_time_too_long": "錯: 太多 #time 呼叫",
+ "pfunc_time_too_big": "出錯:#time 只係支援最多 9999 年。",
+ "pfunc_time_too_small": "出錯:#time 只係支援最少 0 年。",
+ "pfunc_rel2abs_invalid_depth": "錯: 唔啱路徑嘅深度: \"$1\" (已經試過由頭點落個點度)",
+ "pfunc_expr_stack_exhausted": "表達錯: 堆叠耗盡",
+ "pfunc_expr_unexpected_number": "表達錯: 未預料嘅數字",
+ "pfunc_expr_preg_match_failure": "表達錯: 未預料嘅 preg_match失敗",
+ "pfunc_expr_unrecognised_word": "表達錯: 未預料嘅字 \"$1\"",
+ "pfunc_expr_unexpected_operator": "表達錯: 未預料嘅 $1 運算符",
+ "pfunc_expr_missing_operand": "表達錯: 缺少 $1 嘅運算符",
+ "pfunc_expr_unexpected_closing_bracket": "表達錯: 未預料嘅閂括號",
+ "pfunc_expr_unrecognised_punctuation": "表達錯: 未能認得到嘅標點 \"$1\"",
+ "pfunc_expr_unclosed_bracket": "表達錯: 未閂好嘅括號",
+ "pfunc_expr_division_by_zero": "除以零",
+ "pfunc_expr_invalid_argument": "$1嘅無效參數: < -1 or > 1",
+ "pfunc_expr_invalid_argument_ln": "ln嘅無效參數: <= 0",
+ "pfunc_expr_unknown_error": "表達錯: 未知嘅錯 ($1)",
+ "pfunc_expr_not_a_number": "響 $1: 結果唔係數字",
+ "pfunc_string_too_long": "出錯:字串超過 $1 個字元嘅限制。"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/zgh.json b/www/wiki/extensions/ParserFunctions/i18n/zgh.json
new file mode 100644
index 00000000..1f53e789
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/zgh.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mdb897"
+ ]
+ },
+ "pfunc_expr_unrecognised_word": "ⵜⴰⵣⴳⵍⵜ ⴳ ⵜⴰⵡⵏⵏⵉⵜ: ⵜⴰⴳⵓⵔⵢ \"$1\" ⵓⵔ ⵜⵢⴰⴽⴰⵣ.",
+ "pfunc_expr_unrecognised_punctuation": "ⵜⴰⵣⴳⵍⵜ ⴳ ⵜⴰⵡⵏⵏⵉⵜ: ⵜⴰⵎⴰⵜⴰⵔⵜ ⵏ ⵓⵙⵏⵇⴹ \"$1\" ⵓⵔ ⵜⵢⴰⴽⴰⵣ."
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/zh-hans.json b/www/wiki/extensions/ParserFunctions/i18n/zh-hans.json
new file mode 100644
index 00000000..84be7169
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/zh-hans.json
@@ -0,0 +1,35 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hydra",
+ "Hzy980512",
+ "Liangent",
+ "PhiLiP",
+ "Philip",
+ "Shinjiman",
+ "阿pp",
+ "Liuxinyu970226"
+ ]
+ },
+ "pfunc_desc": "用逻辑函数加强解析器",
+ "pfunc_time_error": "错误:无效时间。",
+ "pfunc_time_too_long": "错误:#time调用次数过多",
+ "pfunc_time_too_big": "错误:#time只支持到9999年。",
+ "pfunc_time_too_small": "错误:#time只支持最低0年。",
+ "pfunc_rel2abs_invalid_depth": "错误:无效路径深度:“$1”(尝试访问根节点以上节点)",
+ "pfunc_expr_stack_exhausted": "表达式错误:堆栈耗尽。",
+ "pfunc_expr_unexpected_number": "表达式错误:未预料的数字。",
+ "pfunc_expr_preg_match_failure": "表达式错误:未预料的preg_match失败。",
+ "pfunc_expr_unrecognised_word": "表达式错误:无法识别的词语“$1”。",
+ "pfunc_expr_unexpected_operator": "表达式错误:未预料的$1操作符。",
+ "pfunc_expr_missing_operand": "表达式错误:缺少$1的操作数。",
+ "pfunc_expr_unexpected_closing_bracket": "表达式错误:未预料的反括号。",
+ "pfunc_expr_unrecognised_punctuation": "表达式错误:无法识别的标点“$1”。",
+ "pfunc_expr_unclosed_bracket": "表达式错误:未封闭的括号。",
+ "pfunc_expr_division_by_zero": "零除。",
+ "pfunc_expr_invalid_argument": "$1的无效参数:< -1 或 > 1。",
+ "pfunc_expr_invalid_argument_ln": "ln的无效参数:<= 0。",
+ "pfunc_expr_unknown_error": "表达式错误:未知错误($1)。",
+ "pfunc_expr_not_a_number": "在$1中:结果不是数字。",
+ "pfunc_string_too_long": "错误:字符串超过$1字符限制"
+}
diff --git a/www/wiki/extensions/ParserFunctions/i18n/zh-hant.json b/www/wiki/extensions/ParserFunctions/i18n/zh-hant.json
new file mode 100644
index 00000000..658c1093
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/i18n/zh-hant.json
@@ -0,0 +1,35 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gaoxuewei",
+ "Justincheng12345",
+ "Liangent",
+ "Mark85296341",
+ "Shinjiman",
+ "Simon Shek",
+ "Waihorace",
+ "Cwlin0416"
+ ]
+ },
+ "pfunc_desc": "加強分析器,提供邏輯函數功能",
+ "pfunc_time_error": "錯誤:無效時間。",
+ "pfunc_time_too_long": "錯誤:過多 #time 呼叫。",
+ "pfunc_time_too_big": "錯誤:#time 支援上限為 9999 年。",
+ "pfunc_time_too_small": "錯誤:#time 支援下限為 0 年。",
+ "pfunc_rel2abs_invalid_depth": "錯誤:無效路徑深度:\"$1\" (嘗試存取根節點以上的節點)",
+ "pfunc_expr_stack_exhausted": "表達式錯誤:堆疊用盡。",
+ "pfunc_expr_unexpected_number": "表達式錯誤:預期之外的數字。",
+ "pfunc_expr_preg_match_failure": "表達式錯誤:預期之外的 preg_match 失敗。",
+ "pfunc_expr_unrecognised_word": "表達式錯誤:無法識別的字 \"$1\"。",
+ "pfunc_expr_unexpected_operator": "表達式錯誤:預期之外的 $1 運算子。",
+ "pfunc_expr_missing_operand": "表達式錯誤:缺少 $1 的運算元。",
+ "pfunc_expr_unexpected_closing_bracket": "表達式錯誤:預期之外的反括號。",
+ "pfunc_expr_unrecognised_punctuation": "表達式錯誤:無法識別的標點符號 \"$1\"。",
+ "pfunc_expr_unclosed_bracket": "表達式錯誤:未結束的括號。",
+ "pfunc_expr_division_by_zero": "除數為零。",
+ "pfunc_expr_invalid_argument": "$1 的參數無效:< -1 或 > 1。",
+ "pfunc_expr_invalid_argument_ln": "ln 的參數無效:<= 0。",
+ "pfunc_expr_unknown_error": "表達式錯誤:未知錯誤 ($1)。",
+ "pfunc_expr_not_a_number": "於 $1 中:結果不為數字。",
+ "pfunc_string_too_long": "錯誤:字串超過 $1 字元限制。"
+}
diff --git a/www/wiki/extensions/ParserFunctions/includes/ExprError.php b/www/wiki/extensions/ParserFunctions/includes/ExprError.php
new file mode 100644
index 00000000..bb2032a9
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/includes/ExprError.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+class ExprError extends Exception {
+ /**
+ * @param string $msg
+ * @param string $parameter
+ */
+ public function __construct( $msg, $parameter = '' ) {
+ // Give grep a chance to find the usages:
+ // pfunc_expr_stack_exhausted, pfunc_expr_unexpected_number, pfunc_expr_preg_match_failure,
+ // pfunc_expr_unrecognised_word, pfunc_expr_unexpected_operator, pfunc_expr_missing_operand,
+ // pfunc_expr_unexpected_closing_bracket, pfunc_expr_unrecognised_punctuation,
+ // pfunc_expr_unclosed_bracket, pfunc_expr_division_by_zero, pfunc_expr_invalid_argument,
+ // pfunc_expr_invalid_argument_ln, pfunc_expr_unknown_error, pfunc_expr_not_a_number
+ $this->message = wfMessage( "pfunc_expr_$msg", $parameter )->inContentLanguage()->text();
+ }
+}
diff --git a/www/wiki/extensions/ParserFunctions/includes/ExprParser.php b/www/wiki/extensions/ParserFunctions/includes/ExprParser.php
new file mode 100644
index 00000000..f6a80432
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/includes/ExprParser.php
@@ -0,0 +1,673 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+use UtfNormal\Validator;
+
+// Character classes
+define( 'EXPR_WHITE_CLASS', " \t\r\n" );
+define( 'EXPR_NUMBER_CLASS', '0123456789.' );
+
+// Token types
+define( 'EXPR_WHITE', 1 );
+define( 'EXPR_NUMBER', 2 );
+define( 'EXPR_NEGATIVE', 3 );
+define( 'EXPR_POSITIVE', 4 );
+define( 'EXPR_PLUS', 5 );
+define( 'EXPR_MINUS', 6 );
+define( 'EXPR_TIMES', 7 );
+define( 'EXPR_DIVIDE', 8 );
+define( 'EXPR_MOD', 9 );
+define( 'EXPR_OPEN', 10 );
+define( 'EXPR_CLOSE', 11 );
+define( 'EXPR_AND', 12 );
+define( 'EXPR_OR', 13 );
+define( 'EXPR_NOT', 14 );
+define( 'EXPR_EQUALITY', 15 );
+define( 'EXPR_LESS', 16 );
+define( 'EXPR_GREATER', 17 );
+define( 'EXPR_LESSEQ', 18 );
+define( 'EXPR_GREATEREQ', 19 );
+define( 'EXPR_NOTEQ', 20 );
+define( 'EXPR_ROUND', 21 );
+define( 'EXPR_EXPONENT', 22 );
+define( 'EXPR_SINE', 23 );
+define( 'EXPR_COSINE', 24 );
+define( 'EXPR_TANGENS', 25 );
+define( 'EXPR_ARCSINE', 26 );
+define( 'EXPR_ARCCOS', 27 );
+define( 'EXPR_ARCTAN', 28 );
+define( 'EXPR_EXP', 29 );
+define( 'EXPR_LN', 30 );
+define( 'EXPR_ABS', 31 );
+define( 'EXPR_FLOOR', 32 );
+define( 'EXPR_TRUNC', 33 );
+define( 'EXPR_CEIL', 34 );
+define( 'EXPR_POW', 35 );
+define( 'EXPR_PI', 36 );
+define( 'EXPR_FMOD', 37 );
+define( 'EXPR_SQRT', 38 );
+
+class ExprParser {
+ public $maxStackSize = 100;
+
+ public $precedence = [
+ EXPR_NEGATIVE => 10,
+ EXPR_POSITIVE => 10,
+ EXPR_EXPONENT => 10,
+ EXPR_SINE => 9,
+ EXPR_COSINE => 9,
+ EXPR_TANGENS => 9,
+ EXPR_ARCSINE => 9,
+ EXPR_ARCCOS => 9,
+ EXPR_ARCTAN => 9,
+ EXPR_EXP => 9,
+ EXPR_LN => 9,
+ EXPR_ABS => 9,
+ EXPR_FLOOR => 9,
+ EXPR_TRUNC => 9,
+ EXPR_CEIL => 9,
+ EXPR_NOT => 9,
+ EXPR_SQRT => 9,
+ EXPR_POW => 8,
+ EXPR_TIMES => 7,
+ EXPR_DIVIDE => 7,
+ EXPR_MOD => 7,
+ EXPR_FMOD => 7,
+ EXPR_PLUS => 6,
+ EXPR_MINUS => 6,
+ EXPR_ROUND => 5,
+ EXPR_EQUALITY => 4,
+ EXPR_LESS => 4,
+ EXPR_GREATER => 4,
+ EXPR_LESSEQ => 4,
+ EXPR_GREATEREQ => 4,
+ EXPR_NOTEQ => 4,
+ EXPR_AND => 3,
+ EXPR_OR => 2,
+ EXPR_PI => 0,
+ EXPR_OPEN => -1,
+ EXPR_CLOSE => -1,
+ ];
+
+ public $names = [
+ EXPR_NEGATIVE => '-',
+ EXPR_POSITIVE => '+',
+ EXPR_NOT => 'not',
+ EXPR_TIMES => '*',
+ EXPR_DIVIDE => '/',
+ EXPR_MOD => 'mod',
+ EXPR_FMOD => 'fmod',
+ EXPR_PLUS => '+',
+ EXPR_MINUS => '-',
+ EXPR_ROUND => 'round',
+ EXPR_EQUALITY => '=',
+ EXPR_LESS => '<',
+ EXPR_GREATER => '>',
+ EXPR_LESSEQ => '<=',
+ EXPR_GREATEREQ => '>=',
+ EXPR_NOTEQ => '<>',
+ EXPR_AND => 'and',
+ EXPR_OR => 'or',
+ EXPR_EXPONENT => 'e',
+ EXPR_SINE => 'sin',
+ EXPR_COSINE => 'cos',
+ EXPR_TANGENS => 'tan',
+ EXPR_ARCSINE => 'asin',
+ EXPR_ARCCOS => 'acos',
+ EXPR_ARCTAN => 'atan',
+ EXPR_LN => 'ln',
+ EXPR_EXP => 'exp',
+ EXPR_ABS => 'abs',
+ EXPR_FLOOR => 'floor',
+ EXPR_TRUNC => 'trunc',
+ EXPR_CEIL => 'ceil',
+ EXPR_POW => '^',
+ EXPR_PI => 'pi',
+ EXPR_SQRT => 'sqrt',
+ ];
+
+ public $words = [
+ 'mod' => EXPR_MOD,
+ 'fmod' => EXPR_FMOD,
+ 'and' => EXPR_AND,
+ 'or' => EXPR_OR,
+ 'not' => EXPR_NOT,
+ 'round' => EXPR_ROUND,
+ 'div' => EXPR_DIVIDE,
+ 'e' => EXPR_EXPONENT,
+ 'sin' => EXPR_SINE,
+ 'cos' => EXPR_COSINE,
+ 'tan' => EXPR_TANGENS,
+ 'asin' => EXPR_ARCSINE,
+ 'acos' => EXPR_ARCCOS,
+ 'atan' => EXPR_ARCTAN,
+ 'exp' => EXPR_EXP,
+ 'ln' => EXPR_LN,
+ 'abs' => EXPR_ABS,
+ 'trunc' => EXPR_TRUNC,
+ 'floor' => EXPR_FLOOR,
+ 'ceil' => EXPR_CEIL,
+ 'pi' => EXPR_PI,
+ 'sqrt' => EXPR_SQRT,
+ ];
+
+ /**
+ * Evaluate a mathematical expression
+ *
+ * The algorithm here is based on the infix to RPN algorithm given in
+ * http://montcs.bloomu.edu/~bobmon/Information/RPN/infix2rpn.shtml
+ * It's essentially the same as Dijkstra's shunting yard algorithm.
+ * @param string $expr
+ * @throws ExprError
+ * @return string
+ */
+ public function doExpression( $expr ) {
+ $operands = [];
+ $operators = [];
+
+ # Unescape inequality operators
+ $expr = strtr( $expr, [ '&lt;' => '<', '&gt;' => '>',
+ '&minus;' => '-', '−' => '-' ] );
+
+ $p = 0;
+ $end = strlen( $expr );
+ $expecting = 'expression';
+ $name = '';
+
+ while ( $p < $end ) {
+ if ( count( $operands ) > $this->maxStackSize || count( $operators ) > $this->maxStackSize ) {
+ throw new ExprError( 'stack_exhausted' );
+ }
+ $char = $expr[$p];
+ $char2 = substr( $expr, $p, 2 );
+
+ // Mega if-elseif-else construct
+ // Only binary operators fall through for processing at the bottom, the rest
+ // finish their processing and continue
+
+ // First the unlimited length classes
+
+ if ( false !== strpos( EXPR_WHITE_CLASS, $char ) ) {
+ // Whitespace
+ $p += strspn( $expr, EXPR_WHITE_CLASS, $p );
+ continue;
+ } elseif ( false !== strpos( EXPR_NUMBER_CLASS, $char ) ) {
+ // Number
+ if ( $expecting !== 'expression' ) {
+ throw new ExprError( 'unexpected_number' );
+ }
+
+ // Find the rest of it
+ $length = strspn( $expr, EXPR_NUMBER_CLASS, $p );
+ // Convert it to float, silently removing double decimal points
+ $operands[] = (float)substr( $expr, $p, $length );
+ $p += $length;
+ $expecting = 'operator';
+ continue;
+ } elseif ( ctype_alpha( $char ) ) {
+ // Word
+ // Find the rest of it
+ $remaining = substr( $expr, $p );
+ if ( !preg_match( '/^[A-Za-z]*/', $remaining, $matches ) ) {
+ // This should be unreachable
+ throw new ExprError( 'preg_match_failure' );
+ }
+ $word = strtolower( $matches[0] );
+ $p += strlen( $word );
+
+ // Interpret the word
+ if ( !isset( $this->words[$word] ) ) {
+ throw new ExprError( 'unrecognised_word', $word );
+ }
+ $op = $this->words[$word];
+ switch ( $op ) {
+ // constant
+ case EXPR_EXPONENT:
+ if ( $expecting !== 'expression' ) {
+ break;
+ }
+ $operands[] = exp( 1 );
+ $expecting = 'operator';
+ continue 2;
+ case EXPR_PI:
+ if ( $expecting !== 'expression' ) {
+ throw new ExprError( 'unexpected_number' );
+ }
+ $operands[] = pi();
+ $expecting = 'operator';
+ continue 2;
+ // Unary operator
+ case EXPR_NOT:
+ case EXPR_SINE:
+ case EXPR_COSINE:
+ case EXPR_TANGENS:
+ case EXPR_ARCSINE:
+ case EXPR_ARCCOS:
+ case EXPR_ARCTAN:
+ case EXPR_EXP:
+ case EXPR_LN:
+ case EXPR_ABS:
+ case EXPR_FLOOR:
+ case EXPR_TRUNC:
+ case EXPR_CEIL:
+ case EXPR_SQRT:
+ if ( $expecting !== 'expression' ) {
+ throw new ExprError( 'unexpected_operator', $word );
+ }
+ $operators[] = $op;
+ continue 2;
+ }
+ // Binary operator, fall through
+ $name = $word;
+ } elseif ( $char2 === '<=' ) {
+ $name = $char2;
+ $op = EXPR_LESSEQ;
+ $p += 2;
+ } elseif ( $char2 === '>=' ) {
+ $name = $char2;
+ $op = EXPR_GREATEREQ;
+ $p += 2;
+ } elseif ( $char2 === '<>' || $char2 === '!=' ) {
+ $name = $char2;
+ $op = EXPR_NOTEQ;
+ $p += 2;
+ } elseif ( $char === '+' ) {
+ ++$p;
+ if ( $expecting === 'expression' ) {
+ // Unary plus
+ $operators[] = EXPR_POSITIVE;
+ continue;
+ } else {
+ // Binary plus
+ $op = EXPR_PLUS;
+ }
+ } elseif ( $char === '-' ) {
+ ++$p;
+ if ( $expecting === 'expression' ) {
+ // Unary minus
+ $operators[] = EXPR_NEGATIVE;
+ continue;
+ } else {
+ // Binary minus
+ $op = EXPR_MINUS;
+ }
+ } elseif ( $char === '*' ) {
+ $name = $char;
+ $op = EXPR_TIMES;
+ ++$p;
+ } elseif ( $char === '/' ) {
+ $name = $char;
+ $op = EXPR_DIVIDE;
+ ++$p;
+ } elseif ( $char === '^' ) {
+ $name = $char;
+ $op = EXPR_POW;
+ ++$p;
+ } elseif ( $char === '(' ) {
+ if ( $expecting === 'operator' ) {
+ throw new ExprError( 'unexpected_operator', '(' );
+ }
+ $operators[] = EXPR_OPEN;
+ ++$p;
+ continue;
+ } elseif ( $char === ')' ) {
+ $lastOp = end( $operators );
+ while ( $lastOp && $lastOp != EXPR_OPEN ) {
+ $this->doOperation( $lastOp, $operands );
+ array_pop( $operators );
+ $lastOp = end( $operators );
+ }
+ if ( $lastOp ) {
+ array_pop( $operators );
+ } else {
+ throw new ExprError( 'unexpected_closing_bracket' );
+ }
+ $expecting = 'operator';
+ ++$p;
+ continue;
+ } elseif ( $char === '=' ) {
+ $name = $char;
+ $op = EXPR_EQUALITY;
+ ++$p;
+ } elseif ( $char === '<' ) {
+ $name = $char;
+ $op = EXPR_LESS;
+ ++$p;
+ } elseif ( $char === '>' ) {
+ $name = $char;
+ $op = EXPR_GREATER;
+ ++$p;
+ } else {
+ $utfExpr = Validator::cleanUp( substr( $expr, $p ) );
+ throw new ExprError( 'unrecognised_punctuation', mb_substr( $utfExpr, 0, 1 ) );
+ }
+
+ // Binary operator processing
+ if ( $expecting === 'expression' ) {
+ throw new ExprError( 'unexpected_operator', $name );
+ }
+
+ // Shunting yard magic
+ $lastOp = end( $operators );
+ while ( $lastOp && $this->precedence[$op] <= $this->precedence[$lastOp] ) {
+ $this->doOperation( $lastOp, $operands );
+ array_pop( $operators );
+ $lastOp = end( $operators );
+ }
+ $operators[] = $op;
+ $expecting = 'expression';
+ }
+
+ // Finish off the operator array
+ // @codingStandardsIgnoreStart
+ while ( $op = array_pop( $operators ) ) {
+ // @codingStandardsIgnoreEnd
+ if ( $op == EXPR_OPEN ) {
+ throw new ExprError( 'unclosed_bracket' );
+ }
+ $this->doOperation( $op, $operands );
+ }
+
+ return implode( "<br />\n", $operands );
+ }
+
+ /**
+ * @param int $op
+ * @param array &$stack
+ * @throws ExprError
+ */
+ public function doOperation( $op, &$stack ) {
+ switch ( $op ) {
+ case EXPR_NEGATIVE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = -$arg;
+ break;
+ case EXPR_POSITIVE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ break;
+ case EXPR_TIMES:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = $left * $right;
+ break;
+ case EXPR_DIVIDE:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ if ( !$right ) {
+ throw new ExprError( 'division_by_zero', $this->names[$op] );
+ }
+ $stack[] = $left / $right;
+ break;
+ case EXPR_MOD:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = (int)array_pop( $stack );
+ $left = (int)array_pop( $stack );
+ if ( !$right ) {
+ throw new ExprError( 'division_by_zero', $this->names[$op] );
+ }
+ $stack[] = $left % $right;
+ break;
+ case EXPR_FMOD:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = (double)array_pop( $stack );
+ $left = (double)array_pop( $stack );
+ if ( !$right ) {
+ throw new ExprError( 'division_by_zero', $this->names[$op] );
+ }
+ $stack[] = fmod( $left, $right );
+ break;
+ case EXPR_PLUS:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = $left + $right;
+ break;
+ case EXPR_MINUS:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = $left - $right;
+ break;
+ case EXPR_AND:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left && $right ) ? 1 : 0;
+ break;
+ case EXPR_OR:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left || $right ) ? 1 : 0;
+ break;
+ case EXPR_EQUALITY:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left == $right ) ? 1 : 0;
+ break;
+ case EXPR_NOT:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = ( !$arg ) ? 1 : 0;
+ break;
+ case EXPR_ROUND:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $digits = (int)array_pop( $stack );
+ $value = array_pop( $stack );
+ $stack[] = round( $value, $digits );
+ break;
+ case EXPR_LESS:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left < $right ) ? 1 : 0;
+ break;
+ case EXPR_GREATER:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left > $right ) ? 1 : 0;
+ break;
+ case EXPR_LESSEQ:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left <= $right ) ? 1 : 0;
+ break;
+ case EXPR_GREATEREQ:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left >= $right ) ? 1 : 0;
+ break;
+ case EXPR_NOTEQ:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = ( $left != $right ) ? 1 : 0;
+ break;
+ case EXPR_EXPONENT:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $stack[] = $left * pow( 10, $right );
+ break;
+ case EXPR_SINE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = sin( $arg );
+ break;
+ case EXPR_COSINE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = cos( $arg );
+ break;
+ case EXPR_TANGENS:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = tan( $arg );
+ break;
+ case EXPR_ARCSINE:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ if ( $arg < -1 || $arg > 1 ) {
+ throw new ExprError( 'invalid_argument', $this->names[$op] );
+ }
+ $stack[] = asin( $arg );
+ break;
+ case EXPR_ARCCOS:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ if ( $arg < -1 || $arg > 1 ) {
+ throw new ExprError( 'invalid_argument', $this->names[$op] );
+ }
+ $stack[] = acos( $arg );
+ break;
+ case EXPR_ARCTAN:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = atan( $arg );
+ break;
+ case EXPR_EXP:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = exp( $arg );
+ break;
+ case EXPR_LN:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ if ( $arg <= 0 ) {
+ throw new ExprError( 'invalid_argument_ln', $this->names[$op] );
+ }
+ $stack[] = log( $arg );
+ break;
+ case EXPR_ABS:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = abs( $arg );
+ break;
+ case EXPR_FLOOR:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = floor( $arg );
+ break;
+ case EXPR_TRUNC:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = (int)$arg;
+ break;
+ case EXPR_CEIL:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $stack[] = ceil( $arg );
+ break;
+ case EXPR_POW:
+ if ( count( $stack ) < 2 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $right = array_pop( $stack );
+ $left = array_pop( $stack );
+ $result = pow( $left, $right );
+ if ( $result === false ) {
+ throw new ExprError( 'division_by_zero', $this->names[$op] );
+ }
+ $stack[] = $result;
+ break;
+ case EXPR_SQRT:
+ if ( count( $stack ) < 1 ) {
+ throw new ExprError( 'missing_operand', $this->names[$op] );
+ }
+ $arg = array_pop( $stack );
+ $result = sqrt( $arg );
+ if ( is_nan( $result ) ) {
+ throw new ExprError( 'not_a_number', $this->names[$op] );
+ }
+ $stack[] = $result;
+ break;
+ default:
+ // Should be impossible to reach here.
+ throw new ExprError( 'unknown_error' );
+ }
+ }
+}
diff --git a/www/wiki/extensions/ParserFunctions/includes/ExtParserFunctions.php b/www/wiki/extensions/ParserFunctions/includes/ExtParserFunctions.php
new file mode 100644
index 00000000..aae37bb1
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/includes/ExtParserFunctions.php
@@ -0,0 +1,891 @@
+<?php
+
+class ExtParserFunctions {
+ public static $mExprParser;
+ public static $mTimeCache = [];
+ public static $mTimeChars = 0;
+ public static $mMaxTimeChars = 6000; # ~10 seconds
+
+ /**
+ * @param Parser $parser
+ * @return bool
+ */
+ public static function clearState( $parser ) {
+ self::$mTimeChars = 0;
+ return true;
+ }
+
+ /**
+ * Register ParserClearState hook.
+ * We defer this until needed to avoid the loading of the code of this file
+ * when no parser function is actually called.
+ */
+ public static function registerClearHook() {
+ static $done = false;
+ if ( !$done ) {
+ global $wgHooks;
+ $wgHooks['ParserClearState'][] = __CLASS__ . '::clearState';
+ $done = true;
+ }
+ }
+
+ /**
+ * @return ExprParser
+ */
+ public static function &getExprParser() {
+ if ( !isset( self::$mExprParser ) ) {
+ self::$mExprParser = new ExprParser;
+ }
+ return self::$mExprParser;
+ }
+
+ /**
+ * @param Parser $parser
+ * @param string $expr
+ * @return string
+ */
+ public static function expr( $parser, $expr = '' ) {
+ try {
+ return self::getExprParser()->doExpression( $expr );
+ } catch ( ExprError $e ) {
+ return '<strong class="error">' . htmlspecialchars( $e->getMessage() ) . '</strong>';
+ }
+ }
+
+ /**
+ * @param Parser $parser
+ * @param string $expr
+ * @param string $then
+ * @param string $else
+ * @return string
+ */
+ public static function ifexpr( $parser, $expr = '', $then = '', $else = '' ) {
+ try {
+ $ret = self::getExprParser()->doExpression( $expr );
+ if ( is_numeric( $ret ) ) {
+ $ret = (float)$ret;
+ }
+ if ( $ret ) {
+ return $then;
+ } else {
+ return $else;
+ }
+ } catch ( ExprError $e ) {
+ return '<strong class="error">' . htmlspecialchars( $e->getMessage() ) . '</strong>';
+ }
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @return string
+ */
+ public static function ifexprObj( $parser, $frame, $args ) {
+ $expr = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $then = isset( $args[1] ) ? $args[1] : '';
+ $else = isset( $args[2] ) ? $args[2] : '';
+ $result = self::ifexpr( $parser, $expr, $then, $else );
+ if ( is_object( $result ) ) {
+ $result = trim( $frame->expand( $result ) );
+ }
+ return $result;
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @return string
+ */
+ public static function ifObj( $parser, $frame, $args ) {
+ $test = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ if ( $test !== '' ) {
+ return isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : '';
+ } else {
+ return isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '';
+ }
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @return string
+ */
+ public static function ifeqObj( $parser, $frame, $args ) {
+ $left = isset( $args[0] ) ? self::decodeTrimExpand( $args[0], $frame ) : '';
+ $right = isset( $args[1] ) ? self::decodeTrimExpand( $args[1], $frame ) : '';
+
+ // Strict compare is not possible here. 01 should equal 1 for example.
+ /** @noinspection TypeUnsafeComparisonInspection */
+ if ( $left == $right ) {
+ return isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '';
+ } else {
+ return isset( $args[3] ) ? trim( $frame->expand( $args[3] ) ) : '';
+ }
+ }
+
+ /**
+ * @param Parser $parser
+ * @param string $test
+ * @param string $then
+ * @param bool $else
+ * @return bool|string
+ */
+ public static function iferror( $parser, $test = '', $then = '', $else = false ) {
+ if ( preg_match(
+ '/<(?:strong|span|p|div)\s(?:[^\s>]*\s+)*?class="(?:[^"\s>]*\s+)*?error(?:\s[^">]*)?"/',
+ $test )
+ ) {
+ return $then;
+ } elseif ( $else === false ) {
+ return $test;
+ } else {
+ return $else;
+ }
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @return string
+ */
+ public static function iferrorObj( $parser, $frame, $args ) {
+ $test = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $then = isset( $args[1] ) ? $args[1] : false;
+ $else = isset( $args[2] ) ? $args[2] : false;
+ $result = self::iferror( $parser, $test, $then, $else );
+ if ( $result === false ) {
+ return '';
+ } else {
+ return trim( $frame->expand( $result ) );
+ }
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @return string
+ */
+ public static function switchObj( $parser, $frame, $args ) {
+ if ( count( $args ) === 0 ) {
+ return '';
+ }
+ $primary = self::decodeTrimExpand( array_shift( $args ), $frame );
+ $found = $defaultFound = false;
+ $default = null;
+ $lastItemHadNoEquals = false;
+ $lastItem = '';
+ $mwDefault =& MagicWord::get( 'default' );
+ foreach ( $args as $arg ) {
+ $bits = $arg->splitArg();
+ $nameNode = $bits['name'];
+ $index = $bits['index'];
+ $valueNode = $bits['value'];
+
+ if ( $index === '' ) {
+ # Found "="
+ $lastItemHadNoEquals = false;
+ if ( $found ) {
+ # Multiple input match
+ return trim( $frame->expand( $valueNode ) );
+ } else {
+ $test = self::decodeTrimExpand( $nameNode, $frame );
+ /** @noinspection TypeUnsafeComparisonInspection */
+ if ( $test == $primary ) {
+ # Found a match, return now
+ return trim( $frame->expand( $valueNode ) );
+ } elseif ( $defaultFound || $mwDefault->matchStartToEnd( $test ) ) {
+ $default = $valueNode;
+ $defaultFound = false;
+ } # else wrong case, continue
+ }
+ } else {
+ # Multiple input, single output
+ # If the value matches, set a flag and continue
+ $lastItemHadNoEquals = true;
+ // $lastItem is an "out" variable
+ $decodedTest = self::decodeTrimExpand( $valueNode, $frame, $lastItem );
+ /** @noinspection TypeUnsafeComparisonInspection */
+ if ( $decodedTest == $primary ) {
+ $found = true;
+ } elseif ( $mwDefault->matchStartToEnd( $decodedTest ) ) {
+ $defaultFound = true;
+ }
+ }
+ }
+ # Default case
+ # Check if the last item had no = sign, thus specifying the default case
+ if ( $lastItemHadNoEquals ) {
+ return $lastItem;
+ } elseif ( !is_null( $default ) ) {
+ return trim( $frame->expand( $default ) );
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Returns the absolute path to a subpage, relative to the current article
+ * title. Treats titles as slash-separated paths.
+ *
+ * Following subpage link syntax instead of standard path syntax, an
+ * initial slash is treated as a relative path, and vice versa.
+ *
+ * @param Parser $parser
+ * @param string $to
+ * @param string $from
+ *
+ * @return string
+ */
+ public static function rel2abs( $parser , $to = '' , $from = '' ) {
+ $from = trim( $from );
+ if ( $from === '' ) {
+ $from = $parser->getTitle()->getPrefixedText();
+ }
+
+ $to = rtrim( $to, ' /' );
+
+ // if we have an empty path, or just one containing a dot
+ if ( $to === '' || $to === '.' ) {
+ return $from;
+ }
+
+ // if the path isn't relative
+ if ( substr( $to, 0, 1 ) !== '/' &&
+ substr( $to, 0, 2 ) !== './' &&
+ substr( $to, 0, 3 ) !== '../' &&
+ $to !== '..'
+ ) {
+ $from = '';
+ }
+ // Make a long path, containing both, enclose it in /.../
+ $fullPath = '/' . $from . '/' . $to . '/';
+
+ // remove redundant current path dots
+ $fullPath = preg_replace( '!/(\./)+!', '/', $fullPath );
+
+ // remove double slashes
+ $fullPath = preg_replace( '!/{2,}!', '/', $fullPath );
+
+ // remove the enclosing slashes now
+ $fullPath = trim( $fullPath, '/' );
+ $exploded = explode( '/', $fullPath );
+ $newExploded = [];
+
+ foreach ( $exploded as $current ) {
+ if ( $current === '..' ) { // removing one level
+ if ( !count( $newExploded ) ) {
+ // attempted to access a node above root node
+ $msg = wfMessage( 'pfunc_rel2abs_invalid_depth', $fullPath )
+ ->inContentLanguage()->escaped();
+ return '<strong class="error">' . $msg . '</strong>';
+ }
+ // remove last level from the stack
+ array_pop( $newExploded );
+ } else {
+ // add the current level to the stack
+ $newExploded[] = $current;
+ }
+ }
+
+ // we can now join it again
+ return implode( '/', $newExploded );
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param string $titletext
+ * @param string $then
+ * @param string $else
+ *
+ * @return string
+ */
+ public static function ifexistCommon(
+ $parser, $frame, $titletext = '', $then = '', $else = ''
+ ) {
+ global $wgContLang;
+ $title = Title::newFromText( $titletext );
+ $wgContLang->findVariantLink( $titletext, $title, true );
+ if ( $title ) {
+ if ( $title->getNamespace() === NS_MEDIA ) {
+ /* If namespace is specified as NS_MEDIA, then we want to
+ * check the physical file, not the "description" page.
+ */
+ if ( !$parser->incrementExpensiveFunctionCount() ) {
+ return $else;
+ }
+ $file = wfFindFile( $title );
+ if ( !$file ) {
+ return $else;
+ }
+ $parser->mOutput->addImage(
+ $file->getName(), $file->getTimestamp(), $file->getSha1() );
+ return $file->exists() ? $then : $else;
+ } elseif ( $title->getNamespace() === NS_SPECIAL ) {
+ /* Don't bother with the count for special pages,
+ * since their existence can be checked without
+ * accessing the database.
+ */
+ return SpecialPageFactory::exists( $title->getDBkey() ) ? $then : $else;
+ } elseif ( $title->isExternal() ) {
+ /* Can't check the existence of pages on other sites,
+ * so just return $else. Makes a sort of sense, since
+ * they don't exist _locally_.
+ */
+ return $else;
+ } else {
+ $pdbk = $title->getPrefixedDBkey();
+ $lc = LinkCache::singleton();
+ $id = $lc->getGoodLinkID( $pdbk );
+ if ( $id !== 0 ) {
+ $parser->mOutput->addLink( $title, $id );
+ return $then;
+ } elseif ( $lc->isBadLink( $pdbk ) ) {
+ $parser->mOutput->addLink( $title, 0 );
+ return $else;
+ }
+ if ( !$parser->incrementExpensiveFunctionCount() ) {
+ return $else;
+ }
+ $id = $title->getArticleID();
+ $parser->mOutput->addLink( $title, $id );
+
+ // bug 70495: don't just check whether the ID != 0
+ if ( $title->exists() ) {
+ return $then;
+ }
+ }
+ }
+ return $else;
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @return string
+ */
+ public static function ifexistObj( $parser, $frame, $args ) {
+ $title = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $then = isset( $args[1] ) ? $args[1] : null;
+ $else = isset( $args[2] ) ? $args[2] : null;
+
+ $result = self::ifexistCommon( $parser, $frame, $title, $then, $else );
+ if ( $result === null ) {
+ return '';
+ } else {
+ return trim( $frame->expand( $result ) );
+ }
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param string $format
+ * @param string $date
+ * @param string $language
+ * @param string|bool $local
+ * @return string
+ */
+ public static function timeCommon(
+ $parser, $frame = null, $format = '', $date = '', $language = '', $local = false
+ ) {
+ global $wgLocaltimezone;
+ self::registerClearHook();
+ if ( $date === '' ) {
+ $cacheKey = $parser->getOptions()->getTimestamp();
+ $timestamp = new MWTimestamp( $cacheKey );
+ $date = $timestamp->getTimestamp( TS_ISO_8601 );
+ $useTTL = true;
+ } else {
+ $cacheKey = $date;
+ $useTTL = false;
+ }
+ if ( isset( self::$mTimeCache[$format][$cacheKey][$language][$local] ) ) {
+ $cachedVal = self::$mTimeCache[$format][$cacheKey][$language][$local];
+ if ( $useTTL
+ && $cachedVal[1] !== null && $frame && is_callable( [ $frame, 'setTTL' ] )
+ ) {
+ $frame->setTTL( $cachedVal[1] );
+ }
+ return $cachedVal[0];
+ }
+
+ # compute the timestamp string $ts
+ # PHP >= 5.2 can handle dates before 1970 or after 2038 using the DateTime object
+
+ $invalidTime = false;
+
+ # the DateTime constructor must be used because it throws exceptions
+ # when errors occur, whereas date_create appears to just output a warning
+ # that can't really be detected from within the code
+ try {
+
+ # Default input timezone is UTC.
+ $utc = new DateTimeZone( 'UTC' );
+
+ # Correct for DateTime interpreting 'XXXX' as XX:XX o'clock
+ if ( preg_match( '/^[0-9]{4}$/', $date ) ) {
+ $date = '00:00 '.$date;
+ }
+
+ # Parse date
+ # UTC is a default input timezone.
+ $dateObject = new DateTime( $date, $utc );
+
+ # Set output timezone.
+ if ( $local ) {
+ if ( isset( $wgLocaltimezone ) ) {
+ $tz = new DateTimeZone( $wgLocaltimezone );
+ } else {
+ $tz = new DateTimeZone( date_default_timezone_get() );
+ }
+ } else {
+ $tz = $utc;
+ }
+ $dateObject->setTimezone( $tz );
+ # Generate timestamp
+ $ts = $dateObject->format( 'YmdHis' );
+
+ } catch ( Exception $ex ) {
+ $invalidTime = true;
+ }
+
+ $ttl = null;
+ # format the timestamp and return the result
+ if ( $invalidTime ) {
+ $result = '<strong class="error">' .
+ wfMessage( 'pfunc_time_error' )->inContentLanguage()->escaped() .
+ '</strong>';
+ } else {
+ self::$mTimeChars += strlen( $format );
+ if ( self::$mTimeChars > self::$mMaxTimeChars ) {
+ return '<strong class="error">' .
+ wfMessage( 'pfunc_time_too_long' )->inContentLanguage()->escaped() .
+ '</strong>';
+ } else {
+ if ( $ts < 0 ) { // Language can't deal with BC years
+ return '<strong class="error">' .
+ wfMessage( 'pfunc_time_too_small' )->inContentLanguage()->escaped() .
+ '</strong>';
+ } elseif ( $ts < 100000000000000 ) { // Language can't deal with years after 9999
+ if ( $language !== '' && Language::isValidBuiltInCode( $language ) ) {
+ // use whatever language is passed as a parameter
+ $langObject = Language::factory( $language );
+ } else {
+ // use wiki's content language
+ $langObject = $parser->getFunctionLang();
+ // $ttl is passed by reference, which doesn't work right on stub objects
+ StubObject::unstub( $langObject );
+ }
+ $result = $langObject->sprintfDate( $format, $ts, $tz, $ttl );
+ } else {
+ return '<strong class="error">' .
+ wfMessage( 'pfunc_time_too_big' )->inContentLanguage()->escaped() .
+ '</strong>';
+ }
+ }
+ }
+ self::$mTimeCache[$format][$cacheKey][$language][$local] = [ $result, $ttl ];
+ if ( $useTTL && $ttl !== null && $frame && is_callable( [ $frame, 'setTTL' ] ) ) {
+ $frame->setTTL( $ttl );
+ }
+ return $result;
+ }
+
+ /**
+ * @param Parser $parser
+ * @param string $format
+ * @param string $date
+ * @param string $language
+ * @param string|bool $local
+ * @return string
+ */
+ public static function time(
+ $parser, $format = '', $date = '', $language = '', $local = false
+ ) {
+ return self::timeCommon( $parser, null, $format, $date, $language, $local );
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @return string
+ */
+ public static function timeObj( $parser, $frame, $args ) {
+ $format = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $date = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : '';
+ $language = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '';
+ $local = isset( $args[3] ) && trim( $frame->expand( $args[3] ) );
+ return self::timeCommon( $parser, $frame, $format, $date, $language, $local );
+ }
+
+ /**
+ * @param Parser $parser
+ * @param string $format
+ * @param string $date
+ * @param string $language
+ * @return string
+ */
+ public static function localTime( $parser, $format = '', $date = '', $language = '' ) {
+ return self::timeCommon( $parser, null, $format, $date, $language, true );
+ }
+
+ /**
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @return string
+ */
+ public static function localTimeObj( $parser, $frame, $args ) {
+ $format = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
+ $date = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : '';
+ $language = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '';
+ return self::timeCommon( $parser, $frame, $format, $date, $language, true );
+ }
+
+ /**
+ * Obtain a specified number of slash-separated parts of a title,
+ * e.g. {{#titleparts:Hello/World|1}} => "Hello"
+ *
+ * @param Parser $parser Parent parser
+ * @param string $title Title to split
+ * @param int $parts Number of parts to keep
+ * @param int $offset Offset starting at 1
+ * @return string
+ */
+ public static function titleparts( $parser, $title = '', $parts = 0, $offset = 0 ) {
+ $parts = (int)$parts;
+ $offset = (int)$offset;
+ $ntitle = Title::newFromText( $title );
+ if ( $ntitle instanceof Title ) {
+ $bits = explode( '/', $ntitle->getPrefixedText(), 25 );
+ if ( count( $bits ) <= 0 ) {
+ return $ntitle->getPrefixedText();
+ } else {
+ if ( $offset > 0 ) {
+ --$offset;
+ }
+ if ( $parts === 0 ) {
+ return implode( '/', array_slice( $bits, $offset ) );
+ } else {
+ return implode( '/', array_slice( $bits, $offset, $parts ) );
+ }
+ }
+ } else {
+ return $title;
+ }
+ }
+
+ /**
+ * Verifies parameter is less than max string length.
+ * @param string $text
+ * @return bool
+ */
+ private static function checkLength( $text ) {
+ global $wgPFStringLengthLimit;
+ return ( mb_strlen( $text ) < $wgPFStringLengthLimit );
+ }
+
+ /**
+ * Generates error message. Called when string is too long.
+ * @return string
+ */
+ private static function tooLongError() {
+ global $wgPFStringLengthLimit;
+ $msg = wfMessage( 'pfunc_string_too_long' )->numParams( $wgPFStringLengthLimit );
+ return '<strong class="error">' . $msg->inContentLanguage()->escaped() . '</strong>';
+ }
+
+ /**
+ * {{#len:string}}
+ *
+ * Reports number of characters in string.
+ * @param Parser $parser
+ * @param string $inStr
+ * @return int
+ */
+ public static function runLen( $parser, $inStr = '' ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ return mb_strlen( $inStr );
+ }
+
+ /**
+ * {{#pos: string | needle | offset}}
+ *
+ * Finds first occurrence of "needle" in "string" starting at "offset".
+ *
+ * Note: If the needle is an empty string, single space is used instead.
+ * Note: If the needle is not found, empty string is returned.
+ * @param Parser $parser
+ * @param string $inStr
+ * @param int|string $inNeedle
+ * @param int $inOffset
+ * @return int|string
+ */
+ public static function runPos( $parser, $inStr = '', $inNeedle = '', $inOffset = 0 ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inNeedle = $parser->killMarkers( (string)$inNeedle );
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inNeedle ) ) {
+ return self::tooLongError();
+ }
+
+ if ( $inNeedle === '' ) {
+ $inNeedle = ' ';
+ }
+
+ $pos = mb_strpos( $inStr, $inNeedle, min( (int)$inOffset, mb_strlen( $inStr ) ) );
+ if ( $pos === false ) {
+ $pos = '';
+ }
+
+ return $pos;
+ }
+
+ /**
+ * {{#rpos: string | needle}}
+ *
+ * Finds last occurrence of "needle" in "string".
+ *
+ * Note: If the needle is an empty string, single space is used instead.
+ * Note: If the needle is not found, -1 is returned.
+ * @param Parser $parser
+ * @param string $inStr
+ * @param int|string $inNeedle
+ * @return int|string
+ */
+ public static function runRPos( $parser, $inStr = '', $inNeedle = '' ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inNeedle = $parser->killMarkers( (string)$inNeedle );
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inNeedle ) ) {
+ return self::tooLongError();
+ }
+
+ if ( $inNeedle === '' ) {
+ $inNeedle = ' ';
+ }
+
+ $pos = mb_strrpos( $inStr, $inNeedle );
+ if ( $pos === false ) {
+ $pos = -1;
+ }
+
+ return $pos;
+ }
+
+ /**
+ * {{#sub: string | start | length }}
+ *
+ * Returns substring of "string" starting at "start" and having
+ * "length" characters.
+ *
+ * Note: If length is zero, the rest of the input is returned.
+ * Note: A negative value for "start" operates from the end of the
+ * "string".
+ * Note: A negative value for "length" returns a string reduced in
+ * length by that amount.
+ *
+ * @param Parser $parser
+ * @param string $inStr
+ * @param int $inStart
+ * @param int $inLength
+ * @return string
+ */
+ public static function runSub( $parser, $inStr = '', $inStart = 0, $inLength = 0 ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+
+ if ( !self::checkLength( $inStr ) ) {
+ return self::tooLongError();
+ }
+
+ if ( (int)$inLength === 0 ) {
+ $result = mb_substr( $inStr, (int)$inStart );
+ } else {
+ $result = mb_substr( $inStr, (int)$inStart, (int)$inLength );
+ }
+
+ return $result;
+ }
+
+ /**
+ * {{#count: string | substr }}
+ *
+ * Returns number of occurrences of "substr" in "string".
+ *
+ * Note: If "substr" is empty, a single space is used.
+ * @param Parser $parser
+ * @param string $inStr
+ * @param string $inSubStr
+ * @return int|string
+ */
+ public static function runCount( $parser, $inStr = '', $inSubStr = '' ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inSubStr = $parser->killMarkers( (string)$inSubStr );
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inSubStr ) ) {
+ return self::tooLongError();
+ }
+
+ if ( $inSubStr === '' ) {
+ $inSubStr = ' ';
+ }
+
+ $result = mb_substr_count( $inStr, $inSubStr );
+
+ return $result;
+ }
+
+ /**
+ * {{#replace:string | from | to | limit }}
+ *
+ * Replaces each occurrence of "from" in "string" with "to".
+ * At most "limit" replacements are performed.
+ *
+ * Note: Armored against replacements that would generate huge strings.
+ * Note: If "from" is an empty string, single space is used instead.
+ * @param Parser $parser
+ * @param string $inStr
+ * @param string $inReplaceFrom
+ * @param string $inReplaceTo
+ * @param int $inLimit
+ * @return mixed|string
+ */
+ public static function runReplace( $parser, $inStr = '',
+ $inReplaceFrom = '', $inReplaceTo = '', $inLimit = -1 ) {
+ global $wgPFStringLengthLimit;
+
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inReplaceFrom = $parser->killMarkers( (string)$inReplaceFrom );
+ $inReplaceTo = $parser->killMarkers( (string)$inReplaceTo );
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inReplaceFrom ) ||
+ !self::checkLength( $inReplaceTo ) ) {
+ return self::tooLongError();
+ }
+
+ if ( $inReplaceFrom === '' ) {
+ $inReplaceFrom = ' ';
+ }
+
+ // Precompute limit to avoid generating enormous string:
+ $diff = mb_strlen( $inReplaceTo ) - mb_strlen( $inReplaceFrom );
+ if ( $diff > 0 ) {
+ $limit = ( ( $wgPFStringLengthLimit - mb_strlen( $inStr ) ) / $diff ) + 1;
+ } else {
+ $limit = -1;
+ }
+
+ $inLimit = (int)$inLimit;
+ if ( $inLimit >= 0 ) {
+ if ( $limit > $inLimit || $limit == -1 ) {
+ $limit = $inLimit;
+ }
+ }
+
+ // Use regex to allow limit and handle UTF-8 correctly.
+ $inReplaceFrom = preg_quote( $inReplaceFrom, '/' );
+ $inReplaceTo = StringUtils::escapeRegexReplacement( $inReplaceTo );
+
+ $result = preg_replace( '/' . $inReplaceFrom . '/u',
+ $inReplaceTo, $inStr, $limit );
+
+ if ( !self::checkLength( $result ) ) {
+ return self::tooLongError();
+ }
+
+ return $result;
+ }
+
+ /**
+ * {{#explode:string | delimiter | position | limit}}
+ *
+ * Breaks "string" into chunks separated by "delimiter" and returns the
+ * chunk identified by "position".
+ *
+ * Note: Negative position can be used to specify tokens from the end.
+ * Note: If the divider is an empty string, single space is used instead.
+ * Note: Empty string is returned if there are not enough exploded chunks.
+ * @param Parser $parser
+ * @param string $inStr
+ * @param string $inDiv
+ * @param int $inPos
+ * @param int|null $inLim
+ * @return string
+ */
+ public static function runExplode(
+ $parser, $inStr = '', $inDiv = '', $inPos = 0, $inLim = null
+ ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ $inDiv = $parser->killMarkers( (string)$inDiv );
+
+ if ( $inDiv === '' ) {
+ $inDiv = ' ';
+ }
+
+ if ( !self::checkLength( $inStr ) ||
+ !self::checkLength( $inDiv ) ) {
+ return self::tooLongError();
+ }
+
+ $inDiv = preg_quote( $inDiv, '/' );
+
+ $matches = preg_split( '/' . $inDiv . '/u', $inStr, $inLim );
+
+ if ( $inPos >= 0 && isset( $matches[$inPos] ) ) {
+ $result = $matches[$inPos];
+ } elseif ( $inPos < 0 && isset( $matches[count( $matches ) + $inPos] ) ) {
+ $result = $matches[count( $matches ) + $inPos];
+ } else {
+ $result = '';
+ }
+
+ return $result;
+ }
+
+ /**
+ * {{#urldecode:string}}
+ *
+ * Decodes URL-encoded (like%20that) strings.
+ * @param Parser $parser
+ * @param string $inStr
+ * @return string
+ */
+ public static function runUrlDecode( $parser, $inStr = '' ) {
+ $inStr = $parser->killMarkers( (string)$inStr );
+ if ( !self::checkLength( $inStr ) ) {
+ return self::tooLongError();
+ }
+
+ return urldecode( $inStr );
+ }
+
+ /**
+ * Take a PPNode (-ish thing), expand it, remove entities, and trim.
+ *
+ * For use when doing string comparisions, where user expects entities
+ * to be equal for what they stand for (e.g. comparisions with {{PAGENAME}})
+ *
+ * @param PPNode|string $obj Thing to expand
+ * @param PPFrame $frame
+ * @param string &$trimExpanded Expanded and trimmed version of PPNode,
+ * but with char refs intact
+ * @return string The trimmed, expanded and entity reference decoded version of the PPNode
+ */
+ private static function decodeTrimExpand( $obj, $frame, &$trimExpanded = null ) {
+ $expanded = $frame->expand( $obj );
+ $trimExpanded = trim( $expanded );
+ return trim( Sanitizer::decodeCharReferences( $expanded ) );
+ }
+}
diff --git a/www/wiki/extensions/ParserFunctions/includes/ParserFunctionsHooks.php b/www/wiki/extensions/ParserFunctions/includes/ParserFunctionsHooks.php
new file mode 100644
index 00000000..af1c7522
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/includes/ParserFunctionsHooks.php
@@ -0,0 +1,59 @@
+<?php
+
+class ParserFunctionsHooks {
+
+ /**
+ * Enable string functions, when running Wikimedia Jenkins unit tests.
+ *
+ * Running Jenkins unit tests without setting $wgPFEnableStringFunctions = true;
+ * will cause all the parser tests for string functions to be skipped.
+ */
+ public static function onRegistration() {
+ if ( isset( $GLOBALS['wgWikimediaJenkinsCI'] ) && $GLOBALS['wgWikimediaJenkinsCI'] === true ) {
+ $GLOBALS['wgPFEnableStringFunctions'] = true;
+ }
+ }
+
+ /**
+ * @param Parser $parser
+ * @return bool
+ */
+ public static function onParserFirstCallInit( $parser ) {
+ global $wgPFEnableStringFunctions;
+
+ // These functions accept DOM-style arguments
+ $parser->setFunctionHook( 'if', 'ExtParserFunctions::ifObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'ifeq', 'ExtParserFunctions::ifeqObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'switch', 'ExtParserFunctions::switchObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'ifexist', 'ExtParserFunctions::ifexistObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'ifexpr', 'ExtParserFunctions::ifexprObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'iferror', 'ExtParserFunctions::iferrorObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'time', 'ExtParserFunctions::timeObj', Parser::SFH_OBJECT_ARGS );
+ $parser->setFunctionHook( 'timel', 'ExtParserFunctions::localTimeObj', Parser::SFH_OBJECT_ARGS );
+
+ $parser->setFunctionHook( 'expr', 'ExtParserFunctions::expr' );
+ $parser->setFunctionHook( 'rel2abs', 'ExtParserFunctions::rel2abs' );
+ $parser->setFunctionHook( 'titleparts', 'ExtParserFunctions::titleparts' );
+
+ // String Functions
+ if ( $wgPFEnableStringFunctions ) {
+ $parser->setFunctionHook( 'len', 'ExtParserFunctions::runLen' );
+ $parser->setFunctionHook( 'pos', 'ExtParserFunctions::runPos' );
+ $parser->setFunctionHook( 'rpos', 'ExtParserFunctions::runRPos' );
+ $parser->setFunctionHook( 'sub', 'ExtParserFunctions::runSub' );
+ $parser->setFunctionHook( 'count', 'ExtParserFunctions::runCount' );
+ $parser->setFunctionHook( 'replace', 'ExtParserFunctions::runReplace' );
+ $parser->setFunctionHook( 'explode', 'ExtParserFunctions::runExplode' );
+ $parser->setFunctionHook( 'urldecode', 'ExtParserFunctions::runUrlDecode' );
+ }
+
+ return true;
+ }
+
+ public static function onScribuntoExternalLibraries( $engine, array &$extraLibraries ) {
+ if ( $engine === 'lua' ) {
+ $extraLibraries['mw.ext.ParserFunctions'] = 'Scribunto_LuaParserFunctionsLibrary';
+ }
+ return true;
+ }
+}
diff --git a/www/wiki/extensions/ParserFunctions/includes/Scribunto_LuaParserFunctionsLibrary.php b/www/wiki/extensions/ParserFunctions/includes/Scribunto_LuaParserFunctionsLibrary.php
new file mode 100644
index 00000000..7dc7c598
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/includes/Scribunto_LuaParserFunctionsLibrary.php
@@ -0,0 +1,23 @@
+<?php
+
+class Scribunto_LuaParserFunctionsLibrary extends Scribunto_LuaLibraryBase {
+ public function register() {
+ $lib = [
+ 'expr' => [ $this, 'expr' ],
+ ];
+
+ return $this->getEngine()->registerInterface(
+ __DIR__ . '/mw.ext.ParserFunctions.lua', $lib, []
+ );
+ }
+
+ public function expr( $expression = null ) {
+ $this->checkType( 'mw.ext.ParserFunctions.expr', 1, $expression, 'string' );
+ try {
+ return [ ExtParserFunctions::getExprParser()->doExpression( $expression ) ];
+ } catch ( ExprError $e ) {
+ throw new Scribunto_LuaError( $e->getMessage() );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/ParserFunctions/includes/mw.ext.ParserFunctions.lua b/www/wiki/extensions/ParserFunctions/includes/mw.ext.ParserFunctions.lua
new file mode 100644
index 00000000..ccec046d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/includes/mw.ext.ParserFunctions.lua
@@ -0,0 +1,22 @@
+local ParserFunctions = {}
+local php
+
+function ParserFunctions.expr( expression )
+ return php.expr( expression )
+end
+
+function ParserFunctions.setupInterface( options )
+ -- Boilerplate
+ ParserFunctions.setupInterface = nil
+ php = mw_interface
+ mw_interface = nil
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.ext = mw.ext or {}
+ mw.ext.ParserFunctions = ParserFunctions
+
+ package.loaded['mw.ext.ParserFunctions'] = ParserFunctions
+end
+
+return ParserFunctions
diff --git a/www/wiki/extensions/ParserFunctions/mw.ext.ParserFunctions.lua b/www/wiki/extensions/ParserFunctions/mw.ext.ParserFunctions.lua
new file mode 100644
index 00000000..ccec046d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/mw.ext.ParserFunctions.lua
@@ -0,0 +1,22 @@
+local ParserFunctions = {}
+local php
+
+function ParserFunctions.expr( expression )
+ return php.expr( expression )
+end
+
+function ParserFunctions.setupInterface( options )
+ -- Boilerplate
+ ParserFunctions.setupInterface = nil
+ php = mw_interface
+ mw_interface = nil
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.ext = mw.ext or {}
+ mw.ext.ParserFunctions = ParserFunctions
+
+ package.loaded['mw.ext.ParserFunctions'] = ParserFunctions
+end
+
+return ParserFunctions
diff --git a/www/wiki/extensions/ParserFunctions/phpcs.xml b/www/wiki/extensions/ParserFunctions/phpcs.xml
new file mode 100644
index 00000000..403afb8d
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/phpcs.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<ruleset>
+ <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
+ <exclude name="Squiz.Classes.ValidClassName.NotCamelCaps" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingParamName" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingParamTag" />
+ <exclude name="MediaWiki.Files.ClassMatchesFilename.NotMatch" />
+ <exclude name="MediaWiki.Files.OneClassPerFile.MultipleFound" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPublic" />
+ <exclude name="MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment" />
+ </rule>
+ <file>.</file>
+ <arg name="extensions" value="php,php5,inc" />
+ <arg name="encoding" value="UTF-8" />
+ <exclude-pattern>vendor</exclude-pattern>
+ <exclude-pattern>node_modules</exclude-pattern>
+</ruleset>
diff --git a/www/wiki/extensions/ParserFunctions/stringFunctionTests.txt b/www/wiki/extensions/ParserFunctions/stringFunctionTests.txt
new file mode 100644
index 00000000..064decef
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/stringFunctionTests.txt
@@ -0,0 +1,32 @@
+# @todo expand
+!! functionhooks
+len
+!! endfunctionhooks
+
+!! test
+#len
+!! input
+{{#len:}}
+{{#len:0}}
+{{#len:test}}
+!!result
+<p>0
+1
+4
+</p>
+!! end
+
+!! test
+#urldecode
+!! input
+{{#urldecode:}}
+{{#urldecode:foo%20bar}}
+{{#urldecode:%D0%9C%D0%B5%D0%B4%D0%B8%D0%B0%D0%92%D0%B8%D0%BA%D0%B8}}
+{{#urldecode: some unescaped string}}
+!! result
+<p>foo bar
+МедиаВики
+some unescaped string
+</p>
+!! end
+
diff --git a/www/wiki/extensions/ParserFunctions/tests/ExpressionTest.php b/www/wiki/extensions/ParserFunctions/tests/ExpressionTest.php
new file mode 100644
index 00000000..169a9cb4
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/tests/ExpressionTest.php
@@ -0,0 +1,76 @@
+<?php
+class ExpressionTest extends MediaWikiTestCase {
+
+ /**
+ * @var ExprParser
+ */
+ protected $parser;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->parser = new ExprParser();
+ }
+
+ /**
+ * @dataProvider provideExpressions
+ */
+ function testExpression( $input, $expected ) {
+ $this->assertEquals(
+ $expected,
+ $this->parser->doExpression( $input )
+ );
+ }
+
+ function provideExpressions() {
+ return array(
+ array( '1 or 0', '1' ),
+ array( 'not (1 and 0)', '1' ),
+ array( 'not 0', '1' ),
+ array( '4 < 5', '1' ),
+ array( '-5 < 2', '1' ),
+ array( '-2 <= -2', '1' ),
+ array( '4 > 3', '1' ),
+ array( '4 > -3', '1' ),
+ array( '5 >= 2', '1' ),
+ array( '2 >= 2', '1' ),
+ array( '1 != 2', '1' ),
+ array( '-4 * -4 = 4 * 4', '1' ),
+ array( 'not (1 != 1)', '1' ),
+ array( '1 + 1', '2' ),
+ array( '-1 + 1', '0' ),
+ array( '+1 + 1', '2' ),
+ array( '4 * 4', '16' ),
+ array( '(1/3) * 3', '1' ),
+ array( '3 / 1.5', '2' ),
+ array( '3 / 0.2', '15' ),
+ array( '3 / ( 2.0 * 0.1 )', '15' ),
+ array( '3 / ( 2.0 / 10 )', '15' ),
+ array( '3 / (- 0.2 )', '-15' ),
+ array( '3 / abs( 0.2 )', '15' ),
+ array( '3 mod 2', '1' ),
+ array( '1e4', '10000' ),
+ array( '1e-2', '0.01' ),
+ array( '4.0 round 0', '4' ),
+ array( 'ceil 4', '4' ),
+ array( 'floor 4', '4' ),
+ array( '4.5 round 0', '5' ),
+ array( '4.2 round 0', '4' ),
+ array( '-4.2 round 0', '-4' ),
+ array( '-4.5 round 0', '-5' ),
+ array( '-2.0 round 0', '-2' ),
+ array( 'ceil -3', '-3' ),
+ array( 'floor -6.0', '-6' ),
+ array( 'ceil 4.2', '5' ),
+ array( 'ceil -4.5', '-4' ),
+ array( 'floor -4.5', '-5' ),
+ array( 'abs(-2)', '2' ),
+ array( 'ln(exp(1))', '1' ),
+ array( 'trunc(4.5)', '4' ),
+ array( 'trunc(-4.5)', '-4' ),
+ array( '123 fmod (2^64-1)', '123' ),
+ array( '5.7 mod 1.3', '0' ),
+ array( '5.7 fmod 1.3', '0.5' ),
+ );
+ }
+}
+
diff --git a/www/wiki/extensions/ParserFunctions/tests/parser/funcsParserTests.txt b/www/wiki/extensions/ParserFunctions/tests/parser/funcsParserTests.txt
new file mode 100644
index 00000000..b66b6b4a
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/tests/parser/funcsParserTests.txt
@@ -0,0 +1,343 @@
+# Force the test runner to ensure the extension is loaded
+# fixme... this doesn't seem to work :D
+#!! functionhooks
+#time
+#!! endfunctionhooks
+
+# fixme: #time seems to be accepting input as local time, which strikes me as wrong
+
+!! article
+ParserFunctions page
+!! text
+A sample page so we can test ifexist.
+
+This used to be a Main Page, but that caused duplicate article
+warnings when running the normal tests at the same time.
+!! endarticle
+
+!! article
+File:Dionysos-Brunnen am Kölner Dom.jpg
+!! text
+blah blah
+!! endarticle
+
+!! article
+File:Redirect_to_Foobar.jpg
+!! text
+#REDIRECT[[File:Foobar.jpg]]
+!! endarticle
+
+!! article
+File:Redirect_to_nowhere.jpg
+!! text
+#REDIRECT[[File:Missing target file.jpg]]
+!! endarticle
+
+!! test
+Input times are UTC, not local time
+!! input
+{{#time:c|15 January 2001}}
+!!result
+<p>2001-01-15T00:00:00+00:00
+</p>
+!! end
+
+!! test
+Time test in traditional range...
+!! input
+{{#time:Y|15 January 2001}}
+!! result
+<p>2001
+</p>
+!! end
+
+!! test
+Time test prior to 1970 Unix creation myth
+!! input
+{{#time:Y|5 April 1967}}
+!! result
+<p>1967
+</p>
+!! end
+
+!! test
+Time test after the 2038 32-bit Apocalype
+!! input
+{{#time:Y|28 July 2061}}
+!! result
+<p>2061
+</p>
+!! end
+
+!! test
+Explicitly specified timezone: UTC
+!! input
+{{#time:Y-m-d H:i| 2011-11-12 23:00 UTC }}
+!! result
+<p>2011-11-12 23:00
+</p>
+!! end
+
+!! test
+Explicitly specified timezone: Europe/Paris (UTC+1)
+!! input
+{{#time:Y-m-d H:i| 2011-11-12 23:00 Europe/Paris }}
+!! result
+<p>2011-11-12 22:00
+</p>
+!! end
+
+!! test
+Explicitly specified timezone: America/New_York (UTC-5)
+!! input
+{{#time:Y-m-d H:i| 2011-11-12 23:00 America/New_York }}
+!! result
+<p>2011-11-13 04:00
+</p>
+!! end
+
+!! test
+Explicitely specified output language (Dutch)
+!! input
+{{#time:d F Y|1988-02-28|nl}}
+!! result
+<p>28 februari 1988
+</p>
+!! end
+
+!! test
+Preserve tags in #switch default value
+!! input
+{{#switch:a|b|<div>c</div>}}
+!! result
+<div>c</div>
+
+!! end
+
+!! test
+Bug 19093: Default values don't fall through in switch
+!! input
+<{{#switch: foo | bar | #default = DEF }}>
+<{{#switch: foo | #default | bar = DEF }}>
+!! result
+<p>&lt;DEF&gt;
+&lt;DEF&gt;
+</p>
+!! end
+
+!! test
+{{#ifexist}}
+!! input
+{{#ifexist:Media:Foobar.jpg|Found|Not found}}
+{{#ifexist:ParserFunctions page|Found|Not found}}
+{{#ifexist:Missing|Found|Not found}}
+!! result
+<p>Found
+Found
+Not found
+</p>
+!! end
+
+!! test
+{{#ifexist:}} media redirect (bug 32031)
+!! input
+{{#ifexist:Media:Redirect_to_Foobar.jpg|Found|Not found}}
+{{#ifexist:Media:Redirect_to_nowhere.jpg|Found|Not found}}
+{{#ifexist:Media:Missing file.jpg|Found|Not found}}
+{{#ifexist:Media:Dionysos-Brunnen am Kölner Dom.jpg|Found|Not found}}
+!!result
+<p>Found
+Not found
+Not found
+Not found
+</p>
+!!end
+
+!! test
+#if
+!! input
+{{#if: | yes | no}}
+{{#if: string | yes | no}}
+{{#if: | yes | no}}
+{{#if:
+
+
+| yes | no}}
+{{#if: 1==2 | yes | no}}
+{{#if: foo | yes }}
+{{#if: | yes }}(empty)
+{{#if: foo | | no}}(empty)
+{{#if: {{{1}}} | yes | no}}
+{{#if: {{{1|}}} | yes | no}}
+!! result
+<p>no
+yes
+no
+no
+yes
+yes
+(empty)
+(empty)
+yes
+no
+</p>
+!! end
+
+!! test
+#ifeq
+!!input
+{{#ifeq: 01 | 1 | yes | no}}
+{{#ifeq: 0 | -0 | yes | no}}
+{{#ifeq: foo | bar | yes | no}}
+{{#ifeq: foo | Foo | yes | no}}
+{{#ifeq: "01" | "1" | yes | no}}
+!! result
+<p>yes
+yes
+no
+no
+no
+</p>
+!! end
+
+!! test
+#ifeq entities
+!!input
+{{#ifeq: {{PAGENAME:*foo&bar}} | *foo&bar | yes | no}}
+{{#ifeq: a'b | a&#39;b | yes | no}}
+{{#ifeq: a'b | a&amp;#39;b | yes | no}}
+{{#ifeq: foo | Foo | *yes | *no}}
+!! result
+<p>yes
+yes
+no
+</p>
+<ul><li>no</li></ul>
+
+!! end
+
+
+!! test
+#iferror
+!!input
+{{#iferror: {{#expr: 1 + 2 }} | error | correct }}
+{{#iferror: {{#expr: 1 + X }} | error | correct }}
+{{#iferror: {{#expr: 1 + 2 }} | error }}
+{{#iferror: {{#expr: 1 + X }} | error }}
+{{#iferror: {{#expr: 1 + 2 }} }}
+{{#iferror: {{#expr: 1 + X }} }}empty
+!! result
+<p>correct
+error
+3
+error
+3
+empty
+</p>
+!! end
+
+
+!! test
+#ifexpr
+!! input
+{{#ifexpr: | yes | no}}
+{{#ifexpr: 1 > 0 | yes }}
+{{#ifexpr: 1 < 0 | yes }}empty
+{{#ifexpr: 1 > 0 | | no}}empty
+{{#ifexpr: 1 < 0 | | no}}
+{{#ifexpr: 1 > 0 }}empty
+!! result
+<p>no
+yes
+empty
+empty
+no
+empty
+</p>
+!! end
+
+!! test
+Bug 22866: #ifexpr should evaluate "-0" as false
+!! input
+{{#ifexpr: (-1)*0 | true | false }}
+!! result
+<p>false
+</p>
+!! end
+
+!! test
+Templates: Parser functions don't strip whitespace from positional parameters
+!! input
+{{#if: {{foo}}
+| no-pre-then
+| no-pre-else
+}}
+!! result
+<p>no-pre-then
+</p>
+!! end
+
+!! test
+#switch
+!! input
+{{#switch:foo&bar|foo&amp;bar=yes|no}}
+{{#switch:foo&bar|fred=1|foo&amp;bar|g=yes|no}}
+{{#switch:foo&bar|fred=1|foo&amp;&#39;bar|g=yes|no}}
+{{#switch:foo|bar|baz=no|*default}}
+{{#switch:none|foo=1|bar=2|#default=no match|baz=3}}
+{{#switch:none|foo=1|bar=2|#default=ignored|baz=3|Second default}}
+{{#switch:|a&amp;#39;b}}
+!! result
+<p>yes
+yes
+no
+</p>
+<ul><li>default</li></ul>
+<p>no match
+Second default
+a&amp;#39;b
+</p>
+!!end
+
+!! test
+#switch #default should match next and not last named parameter
+!! input
+<{{#switch: foo | #default | bar = DEF }}>
+<{{#switch: foo | #default | bar = DEF | baz = GHI }}>
+!! result
+<p>&lt;DEF&gt;
+&lt;DEF&gt;
+</p>
+!! end
+
+!! test
+#switch should not match #default as a prefix
+!! input
+<{{#switch: foo | #defaultWTF? = This is crazy }}>
+<{{#switch: foo | #defaultWTF? | bar = This is crazy }}>
+!! result
+<p>&lt;&gt;
+&lt;&gt;
+</p>
+!! end
+
+!! test
+#switch Test php truthy
+!!input
+{{#switch: 01 | 1 = yes | no}}
+{{#switch: 0 | -0 = yes | no}}
+{{#switch: foo | bar = yes | no}}
+{{#switch: foo | Foo = yes | no}}
+{{#switch: "01" | "1" = yes | no}}
+{{#switch: 1 | 02 | 01 = yes | no}}
+{{#switch: 1 | "01" | "1" = yes | no}}
+!! result
+<p>yes
+yes
+no
+no
+no
+yes
+no
+</p>
+!! end
diff --git a/www/wiki/extensions/ParserFunctions/tests/parser/stringFunctionTests.txt b/www/wiki/extensions/ParserFunctions/tests/parser/stringFunctionTests.txt
new file mode 100644
index 00000000..b1fb9651
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/tests/parser/stringFunctionTests.txt
@@ -0,0 +1,50 @@
+# @todo expand
+!! functionhooks
+len
+!! endfunctionhooks
+
+!! test
+#len
+!! input
+{{#len:}}
+{{#len:0}}
+{{#len:test}}
+!!result
+<p>0
+1
+4
+</p>
+!! end
+
+!! test
+#urldecode
+!! input
+{{#urldecode:}}
+{{#urldecode:foo%20bar}}
+{{#urldecode:%D0%9C%D0%B5%D0%B4%D0%B8%D0%B0%D0%92%D0%B8%D0%BA%D0%B8}}
+{{#urldecode: some unescaped string}}
+!! result
+<p>foo bar
+МедиаВики
+some unescaped string
+</p>
+!! end
+
+!! test
+#pos
+!! input
+{{#pos:Žmržlina|žlina}}
+{{#pos:stringstring|str|4}}
+!! result
+<p>3
+6
+</p>
+!! end
+
+!! test
+#pos with too large offset (T209600)
+!! input
+{{#pos:FooBar|Foo|32}}
+!! result
+
+!! end
diff --git a/www/wiki/extensions/ParserFunctions/tests/phan/config.php b/www/wiki/extensions/ParserFunctions/tests/phan/config.php
new file mode 100644
index 00000000..83214eee
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/tests/phan/config.php
@@ -0,0 +1,19 @@
+<?php
+
+$cfg = require __DIR__ . '/../../vendor/mediawiki/mediawiki-phan-config/src/config.php';
+
+$cfg['directory_list'] = array_merge(
+ $cfg['directory_list'],
+ [
+ './../../extensions/Scribunto',
+ ]
+);
+
+$cfg['exclude_analysis_directory_list'] = array_merge(
+ $cfg['exclude_analysis_directory_list'],
+ [
+ './../../extensions/Scribunto',
+ ]
+);
+
+return $cfg;
diff --git a/www/wiki/extensions/ParserFunctions/tests/phpunit/ExpressionTest.php b/www/wiki/extensions/ParserFunctions/tests/phpunit/ExpressionTest.php
new file mode 100644
index 00000000..06d571e3
--- /dev/null
+++ b/www/wiki/extensions/ParserFunctions/tests/phpunit/ExpressionTest.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @covers ExprParser
+ */
+class ExpressionTest extends MediaWikiTestCase {
+
+ /**
+ * @var ExprParser
+ */
+ protected $parser;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->parser = new ExprParser();
+ }
+
+ /**
+ * @dataProvider provideExpressions
+ */
+ function testExpression( $input, $expected ) {
+ $this->assertEquals(
+ $expected,
+ $this->parser->doExpression( $input )
+ );
+ }
+
+ function provideExpressions() {
+ return [
+ [ '1 or 0', '1' ],
+ [ 'not (1 and 0)', '1' ],
+ [ 'not 0', '1' ],
+ [ '4 < 5', '1' ],
+ [ '-5 < 2', '1' ],
+ [ '-2 <= -2', '1' ],
+ [ '4 > 3', '1' ],
+ [ '4 > -3', '1' ],
+ [ '5 >= 2', '1' ],
+ [ '2 >= 2', '1' ],
+ [ '1 != 2', '1' ],
+ [ '-4 * -4 = 4 * 4', '1' ],
+ [ 'not (1 != 1)', '1' ],
+ [ '1 + 1', '2' ],
+ [ '-1 + 1', '0' ],
+ [ '+1 + 1', '2' ],
+ [ '4 * 4', '16' ],
+ [ '(1/3) * 3', '1' ],
+ [ '3 / 1.5', '2' ],
+ [ '3 / 0.2', '15' ],
+ [ '3 / ( 2.0 * 0.1 )', '15' ],
+ [ '3 / ( 2.0 / 10 )', '15' ],
+ [ '3 / (- 0.2 )', '-15' ],
+ [ '3 / abs( 0.2 )', '15' ],
+ [ '3 mod 2', '1' ],
+ [ '1e4', '10000' ],
+ [ '1e-2', '0.01' ],
+ [ '4.0 round 0', '4' ],
+ [ 'ceil 4', '4' ],
+ [ 'floor 4', '4' ],
+ [ '4.5 round 0', '5' ],
+ [ '4.2 round 0', '4' ],
+ [ '-4.2 round 0', '-4' ],
+ [ '-4.5 round 0', '-5' ],
+ [ '-2.0 round 0', '-2' ],
+ [ 'ceil -3', '-3' ],
+ [ 'floor -6.0', '-6' ],
+ [ 'ceil 4.2', '5' ],
+ [ 'ceil -4.5', '-4' ],
+ [ 'floor -4.5', '-5' ],
+ [ 'abs(-2)', '2' ],
+ [ 'ln(exp(1))', '1' ],
+ [ 'trunc(4.5)', '4' ],
+ [ 'trunc(-4.5)', '-4' ],
+ [ '123 fmod (2^64-1)', '123' ],
+ [ '5.7 mod 1.3', '0' ],
+ [ '5.7 fmod 1.3', '0.5' ],
+ ];
+ }
+}