Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5965739
jquery.i18n.parser.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
jquery.i18n.parser.js
View Options
/*!
* jQuery Internationalization library
*
* Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar
*
* jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
* anything special to choose one license or the other and you don't have to
* notify anyone which license you are using. You are free to use
* UniversalLanguageSelector in commercial projects as long as the copyright
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
*
* @licence GNU General Public Licence 2.0 or later
* @licence MIT License
*/
(
function
(
$
)
{
'use strict'
;
var
MessageParser
=
function
(
options
)
{
this
.
options
=
$
.
extend
(
{},
$
.
i18n
.
parser
.
defaults
,
options
);
this
.
language
=
$
.
i18n
.
languages
[
String
.
locale
]
||
$
.
i18n
.
languages
[
'default'
];
this
.
emitter
=
$
.
i18n
.
parser
.
emitter
;
};
MessageParser
.
prototype
=
{
constructor
:
MessageParser
,
simpleParse
:
function
(
message
,
parameters
)
{
return
message
.
replace
(
/\$(\d+)/g
,
function
(
str
,
match
)
{
var
index
=
parseInt
(
match
,
10
)
-
1
;
return
parameters
[
index
]
!==
undefined
?
parameters
[
index
]
:
'$'
+
match
;
}
);
},
parse
:
function
(
message
,
replacements
)
{
if
(
message
.
indexOf
(
'{{'
)
<
0
)
{
return
this
.
simpleParse
(
message
,
replacements
);
}
this
.
emitter
.
language
=
$
.
i18n
.
languages
[
$
.
i18n
().
locale
]
||
$
.
i18n
.
languages
[
'default'
];
return
this
.
emitter
.
emit
(
this
.
ast
(
message
),
replacements
);
},
ast
:
function
(
message
)
{
var
pipe
,
colon
,
backslash
,
anyCharacter
,
dollar
,
digits
,
regularLiteral
,
regularLiteralWithoutBar
,
regularLiteralWithoutSpace
,
escapedOrLiteralWithoutBar
,
escapedOrRegularLiteral
,
templateContents
,
templateName
,
openTemplate
,
closeTemplate
,
expression
,
paramExpression
,
result
,
pos
=
0
;
// Try parsers until one works, if none work return null
function
choice
(
parserSyntax
)
{
return
function
()
{
var
i
,
result
;
for
(
i
=
0
;
i
<
parserSyntax
.
length
;
i
++
)
{
result
=
parserSyntax
[
i
]();
if
(
result
!==
null
)
{
return
result
;
}
}
return
null
;
};
}
// Try several parserSyntax-es in a row.
// All must succeed; otherwise, return null.
// This is the only eager one.
function
sequence
(
parserSyntax
)
{
var
i
,
res
,
originalPos
=
pos
,
result
=
[];
for
(
i
=
0
;
i
<
parserSyntax
.
length
;
i
++
)
{
res
=
parserSyntax
[
i
]();
if
(
res
===
null
)
{
pos
=
originalPos
;
return
null
;
}
result
.
push
(
res
);
}
return
result
;
}
// Run the same parser over and over until it fails.
// Must succeed a minimum of n times; otherwise, return null.
function
nOrMore
(
n
,
p
)
{
return
function
()
{
var
originalPos
=
pos
,
result
=
[],
parsed
=
p
();
while
(
parsed
!==
null
)
{
result
.
push
(
parsed
);
parsed
=
p
();
}
if
(
result
.
length
<
n
)
{
pos
=
originalPos
;
return
null
;
}
return
result
;
};
}
// Helpers -- just make parserSyntax out of simpler JS builtin types
function
makeStringParser
(
s
)
{
var
len
=
s
.
length
;
return
function
()
{
var
result
=
null
;
if
(
message
.
slice
(
pos
,
pos
+
len
)
===
s
)
{
result
=
s
;
pos
+=
len
;
}
return
result
;
};
}
function
makeRegexParser
(
regex
)
{
return
function
()
{
var
matches
=
message
.
slice
(
pos
).
match
(
regex
);
if
(
matches
===
null
)
{
return
null
;
}
pos
+=
matches
[
0
].
length
;
return
matches
[
0
];
};
}
pipe
=
makeStringParser
(
'|'
);
colon
=
makeStringParser
(
':'
);
backslash
=
makeStringParser
(
'\\'
);
anyCharacter
=
makeRegexParser
(
/^./
);
dollar
=
makeStringParser
(
'$'
);
digits
=
makeRegexParser
(
/^\d+/
);
regularLiteral
=
makeRegexParser
(
/^[^{}[\]$\\]/
);
regularLiteralWithoutBar
=
makeRegexParser
(
/^[^{}[\]$\\|]/
);
regularLiteralWithoutSpace
=
makeRegexParser
(
/^[^{}[\]$\s]/
);
// There is a general pattern:
// parse a thing;
// if it worked, apply transform,
// otherwise return null.
// But using this as a combinator seems to cause problems
// when combined with nOrMore().
// May be some scoping issue.
function
transform
(
p
,
fn
)
{
return
function
()
{
var
result
=
p
();
return
result
===
null
?
null
:
fn
(
result
);
};
}
// Used to define "literals" within template parameters. The pipe
// character is the parameter delimeter, so by default
// it is not a literal in the parameter
function
literalWithoutBar
()
{
var
result
=
nOrMore
(
1
,
escapedOrLiteralWithoutBar
)();
return
result
===
null
?
null
:
result
.
join
(
''
);
}
function
literal
()
{
var
result
=
nOrMore
(
1
,
escapedOrRegularLiteral
)();
return
result
===
null
?
null
:
result
.
join
(
''
);
}
function
escapedLiteral
()
{
var
result
=
sequence
(
[
backslash
,
anyCharacter
]
);
return
result
===
null
?
null
:
result
[
1
];
}
choice
(
[
escapedLiteral
,
regularLiteralWithoutSpace
]
);
escapedOrLiteralWithoutBar
=
choice
(
[
escapedLiteral
,
regularLiteralWithoutBar
]
);
escapedOrRegularLiteral
=
choice
(
[
escapedLiteral
,
regularLiteral
]
);
function
replacement
()
{
var
result
=
sequence
(
[
dollar
,
digits
]
);
if
(
result
===
null
)
{
return
null
;
}
return
[
'REPLACE'
,
parseInt
(
result
[
1
],
10
)
-
1
];
}
templateName
=
transform
(
// see $wgLegalTitleChars
// not allowing : due to the need to catch "PLURAL:$1"
makeRegexParser
(
/^[ !"$&'()*,./0-9;=?@A-Z^_`a-z~\x80-\xFF+-]+/
),
function
(
result
)
{
return
result
.
toString
();
}
);
function
templateParam
()
{
var
expr
,
result
=
sequence
(
[
pipe
,
nOrMore
(
0
,
paramExpression
)
]
);
if
(
result
===
null
)
{
return
null
;
}
expr
=
result
[
1
];
// use a "CONCAT" operator if there are multiple nodes,
// otherwise return the first node, raw.
return
expr
.
length
>
1
?
[
'CONCAT'
].
concat
(
expr
)
:
expr
[
0
];
}
function
templateWithReplacement
()
{
var
result
=
sequence
(
[
templateName
,
colon
,
replacement
]
);
return
result
===
null
?
null
:
[
result
[
0
],
result
[
2
]
];
}
function
templateWithOutReplacement
()
{
var
result
=
sequence
(
[
templateName
,
colon
,
paramExpression
]
);
return
result
===
null
?
null
:
[
result
[
0
],
result
[
2
]
];
}
templateContents
=
choice
(
[
function
()
{
var
res
=
sequence
(
[
// templates can have placeholders for dynamic
// replacement eg: {{PLURAL:$1|one car|$1 cars}}
// or no placeholders eg:
// {{GRAMMAR:genitive|{{SITENAME}}}
choice
(
[
templateWithReplacement
,
templateWithOutReplacement
]
),
nOrMore
(
0
,
templateParam
)
]
);
return
res
===
null
?
null
:
res
[
0
].
concat
(
res
[
1
]
);
},
function
()
{
var
res
=
sequence
(
[
templateName
,
nOrMore
(
0
,
templateParam
)
]
);
if
(
res
===
null
)
{
return
null
;
}
return
[
res
[
0
]
].
concat
(
res
[
1
]
);
}
]
);
openTemplate
=
makeStringParser
(
'{{'
);
closeTemplate
=
makeStringParser
(
'}}'
);
function
template
()
{
var
result
=
sequence
(
[
openTemplate
,
templateContents
,
closeTemplate
]
);
return
result
===
null
?
null
:
result
[
1
];
}
expression
=
choice
(
[
template
,
replacement
,
literal
]
);
paramExpression
=
choice
(
[
template
,
replacement
,
literalWithoutBar
]
);
function
start
()
{
var
result
=
nOrMore
(
0
,
expression
)();
if
(
result
===
null
)
{
return
null
;
}
return
[
'CONCAT'
].
concat
(
result
);
}
result
=
start
();
/*
* For success, the pos must have gotten to the end of the input
* and returned a non-null.
* n.b. This is part of language infrastructure, so we do not throw an
* internationalizable message.
*/
if
(
result
===
null
||
pos
!==
message
.
length
)
{
throw
new
Error
(
'Parse error at position '
+
pos
.
toString
()
+
' in input: '
+
message
);
}
return
result
;
}
};
$
.
extend
(
$
.
i18n
.
parser
,
new
MessageParser
()
);
}(
jQuery
)
);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 3, 11:10 (6 d, 2 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
8a/e1/419334395a0a08111e7bbfc4db06
Default Alt Text
jquery.i18n.parser.js (7 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment