summaryrefslogtreecommitdiffabout
path: root/wikitrans
authorSergey Poznyakoff <gray@gnu.org>2018-08-16 12:45:00 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2018-08-17 10:17:11 (GMT)
commit7186dbab7f1c1227e9229866e086bc417e3e4e52 (patch) (unidiff)
treef29114e9ff7a7b023dd3d611a9bc8808f5cf5bbd /wikitrans
parentd9e26129527ce84f626eb44ff95e4ecfbc5bc92a (diff)
downloadwikitrans-7186dbab7f1c1227e9229866e086bc417e3e4e52.tar.gz
wikitrans-7186dbab7f1c1227e9229866e086bc417e3e4e52.tar.bz2
Fix PEP 8 issues.
Diffstat (limited to 'wikitrans') (more/less context) (ignore whitespace changes)
-rw-r--r--wikitrans/__init__.py26
-rw-r--r--wikitrans/wiki2html.py320
-rw-r--r--wikitrans/wiki2texi.py410
-rw-r--r--wikitrans/wiki2text.py348
-rw-r--r--wikitrans/wikidump.py77
-rw-r--r--wikitrans/wikimarkup.py1285
-rw-r--r--wikitrans/wikins.py3040
-rw-r--r--wikitrans/wikitoken.py318
8 files changed, 5824 insertions, 0 deletions
diff --git a/wikitrans/__init__.py b/wikitrans/__init__.py
new file mode 100644
index 0000000..5832e38
--- a/dev/null
+++ b/wikitrans/__init__.py
@@ -0,0 +1,26 @@
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2008-2018 Sergey Poznyakoff
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3, or (at your option)
8# any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18__all__ = [
19 "wikitoken",
20 "wikimarkup",
21 "wikidump",
22 "wiki2html",
23 "wiki2text",
24 "wiki2texi",
25 "wikins"
26]
diff --git a/wikitrans/wiki2html.py b/wikitrans/wiki2html.py
new file mode 100644
index 0000000..ce65bae
--- a/dev/null
+++ b/wikitrans/wiki2html.py
@@ -0,0 +1,320 @@
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2008-2018 Sergey Poznyakoff
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3, or (at your option)
8# any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18"""
19Wiki markup to HTML translator.
20
21Classes:
22
23HtmlWikiMarkup -- Converts Wiki material to HTML.
24HtmlWiktionaryMarkup -- Reserved for future use. Currently does the same as
25 HtmlWikiMarkup.
26
27"""
28
29from __future__ import print_function
30from wikitrans.wikimarkup import *
31from wikitrans.wikitoken import *
32from wikitrans.wikins import wiki_ns_re, wiki_ns
33import re
34try:
35 from urllib import quote as url_quote
36except ImportError:
37 from urllib.parse import quote as url_quote
38
39try:
40 from html import escape as html_escape
41except ImportError:
42 from cgi import escape as html_escape
43
44__all__ = [ "HtmlWikiMarkup", "HtmlWiktionaryMarkup" ]
45
46class HtmlSeqNode(WikiSeqNode):
47 def format(self):
48 s = ''
49 for x in self.content:
50 s += x.format()
51 return s
52
53class HtmlLinkNode(HtmlSeqNode):
54 def format(self):
55 arg = self.content[0].format()
56 text = None
57 if len(self.content) > 1:
58 s = [x for x in map(lambda x: x.format(), self.content)]
59 if s[0] == 'disambigR' or s[0] == 'wikiquote':
60 return ""
61 elif len(s) > 1 and s[1] == 'thumb':
62 return ""
63 text = '<span class="template">' + s[1] + '</span>'
64 if self.type == 'TMPL':
65 if re.match("t[+-]$", s[0]):
66 if len(s) > 2:
67 text = s[2]
68 elif s[0] == "term":
69 text = self.parser.tmpl_term(s)
70 elif s[0] == "proto":
71 text = self.parser.tmpl_proto(s)
72 return text
73
74 (qual,sep,tgt) = arg.partition(':')
75 if tgt != '':
76 ns = self.parser.wiki_ns_name(qual)
77 if ns:
78 if ns == 'NS_IMAGE':
79 return ''
80 elif ns == 'NS_MEDIA':
81 tgt = self.parser.media_base + '/' + tgt
82 else:
83 tgt = self.parser.mktgt(tgt)
84 elif self.type == 'LINK' and qual in self.parser.langtab:
85 tgt = self.parser.mktgt(tgt, qual)
86 if not text or text == '':
87 text = self.parser.langtab[qual]
88 else:
89 tgt = self.parser.mktgt(tgt)
90 else:
91 tgt = self.parser.mktgt(arg)
92 return "<a href=\"%s\">%s</a>" % (tgt,
93 text if (text and text != '') else arg)
94
95class HtmlRefNode(WikiRefNode):
96 def format(self):
97 target = self.ref
98 text = self.content.format()
99 return "<a href=\"%s\">%s</a>" % (
100 target,
101 text if (text and text != '') else target
102 )
103
104class HtmlFontNode(HtmlSeqNode):
105 def format(self):
106 comm = { 'IT': 'i',
107 'BOLD': 'b' }
108 s = '<%s>' % comm[self.type]
109 for x in self.content:
110 s += x.format()
111 s += '</%s>' % comm[self.type]
112 return s
113
114class HtmlTextNode(HtmlSeqNode):
115 def format(self):
116 if isinstance(self.content,list):
117 s = ''.join(self.content)
118 else:
119 s = html_escape(self.content, quote=False)
120 return s
121
122class HtmlHdrNode(WikiHdrNode):
123 def format(self):
124 level = self.level
125 if level > 6:
126 level = 6
127 return "<h%s>%s</h%s>\n\n" % (level, self.content.format(), level)
128
129class HtmlBarNode(WikiNode):
130 def format(self):
131 return "<hr/>\n"
132
133class HtmlEnvNode(WikiEnvNode):
134 def format(self):
135 type = self.envtype
136 lev = self.level
137 if lev > 4:
138 lev = 2
139 string = ""
140 for s in self.content:
141 n = s.subtype;
142 string += "<%s>%s</%s>" % (self.parser.envt[type]["elt"][n],
143 s.content.format(),
144 self.parser.envt[type]["elt"][n])
145 return "<%s>%s</%s>" % (self.parser.envt[type]["hdr"],
146 string,
147 self.parser.envt[type]["hdr"])
148 return string
149
150class HtmlTagNode(WikiTagNode):
151 def format(self):
152 if self.tag == 'code':
153 self.parser.nested += 1
154 s = self.content.format()
155 self.parser.nested -= 1
156 return '<pre><code>' + s + '</code></pre>' #FIXME
157 elif self.tag == 'ref':
158 n = self.idx+1
159 return '<sup id="cite_ref-%d" class="reference"><a name="cite_ref-%d" href=#cite_note-%d">%d</a></sup>' % (n,n,n,n)
160 elif self.tag == 'references':
161 s = '<div class="references">\n'
162 s += '<ol class="references">\n'
163 n = 0
164 for ref in self.parser.references:
165 n += 1
166 s += ('<li id="cite_note-%d">'
167 + '<span class="mw-cite-backlink">'
168 + '<b><a href="#cite_ref-%d">^</a></b>'
169 + '</span>'
170 + '<span class="reference-text">'
171 + ref.content.format()
172 + '</span>'
173 + '</li>\n') % (n,n)
174 s += '</ol>\n</div>\n'
175 return s
176 else:
177 s = '<' + self.tag
178 if self.args:
179 s += ' ' + str(self.args)
180 s += '>'
181 s += self.content.format()
182 return s + '</' + self.tag + '>'
183
184class HtmlParaNode(HtmlSeqNode):
185 def format(self):
186 return "<p>" + super(HtmlParaNode, self).format() + "</p>\n"
187
188class HtmlPreNode(HtmlSeqNode):
189 def format(self):
190 s = super(HtmlPreNode, self).format()
191 if self.parser.nested:
192 return s
193 else:
194 return '<pre>' + s + '</pre>'
195
196class HtmlIndNode(WikiIndNode):
197 def format(self):
198 return ("<dl><dd>" * self.level) + self.content.format() + "</dd></dl>" * self.level
199
200
201class HtmlWikiMarkup(WikiMarkup):
202 """A Wiki markup to HTML translator class.
203
204 Usage:
205
206 x = HtmlWikiMarkup(file="input.wiki")
207 # Parse the input:
208 x.parse()
209 # Print it as HTML:
210 print(str(x))
211
212 Known bugs:
213 * [[official position]]s
214 Final 's' gets after closing </a> tag. Should be before.
215 """
216
217 nested = 0
218 references = []
219 def __init__(self, *args, **kwargs):
220 """Create a HtmlWikiMarkup object.
221
222 Arguments:
223
224 filename=FILE
225 Read Wiki material from the file named FILE.
226 file=FD
227 Read Wiki material from file object FD.
228 text=STRING
229 Read Wiki material from STRING.
230 lang=CODE
231 Specifies source language. Default is 'en'. This variable can be
232 referred to as '%(lang)s' in the keyword arguments below.
233 html_base=URL
234 Base URL for cross-references. Default is
235 'http://%(lang)s.wiktionary.org/wiki/'
236 image_base=URL
237 Base URL for images. Default is
238 'http://upload.wikimedia.org/wikipedia/commons/thumb/a/bf'
239 media_base=URL
240 Base URL for media files. Default is
241 'http://www.mediawiki.org/xml/export-0.3'
242 """
243
244 super(HtmlWikiMarkup, self).__init__(*args, **kwargs)
245 self.token_class['LINK'] = HtmlLinkNode
246 self.token_class['TMPL'] = HtmlLinkNode
247 self.token_class['REF'] = HtmlRefNode
248 self.token_class['IT'] = HtmlFontNode
249 self.token_class['BOLD'] = HtmlFontNode
250 self.token_class['HDR'] = HtmlHdrNode
251 self.token_class['BAR'] = HtmlBarNode
252 self.token_class['ENV'] = HtmlEnvNode
253 self.token_class['TAG'] = HtmlTagNode
254 self.token_class['PARA'] = HtmlParaNode
255 self.token_class['PRE'] = HtmlPreNode
256 self.token_class['IND'] = HtmlIndNode
257 self.token_class['TEXT'] = HtmlTextNode
258 self.token_class['SEQ'] = HtmlSeqNode
259
260 def wiki_ns_name(self, str):
261 if str in wiki_ns[self.lang]:
262 return wiki_ns[self.lang][str]
263 elif str in wiki_ns_re[self.lang]:
264 for elt in wiki_ns_re[self.lang][str]:
265 if str.beginswith(elt[0]) and str.endswith(elt[1]):
266 return elt[2]
267 return None
268
269 envt = { "unnumbered": { "hdr": "ul",
270 "elt": ["li"] },
271 "numbered": { "hdr": "ol",
272 "elt": ["li"] },
273 "defn": { "hdr": "dl",
274 "elt": ["dt","dd"] } }
275
276 def mktgt(self, tgt, lang = None):
277 if not lang:
278 lang = self.lang
279 return self.html_base % { 'lang' : lang } + url_quote(tgt)
280
281 def tmpl_term(self, s):
282 if len(s) == 2:
283 return s[1]
284 text = None
285 trans = None
286 for x in s[1:]:
287 m = re.match('(\w+)=', x)
288 if m:
289 if m.group(1) == "tr":
290 trans = x[m.end(1)+1:]
291 elif not text:
292 text = x
293 if text:
294 if trans:
295 text += ' <span class="trans">[' + trans + ']</span>'
296 return text
297
298 def tmpl_proto(self, s):
299 text = '<span class="proto-lang">Proto-' + s[1] + '</span>'
300 if len(s) >= 4:
301 n = 0
302 for x in s[2:-2]:
303 if n > 0:
304 text += ','
305 n += 1
306 text += ' <span class="proto">' + x + '</span>'
307 text += ' <span class="meaning">(' + s[-2] + ')</span>'
308 return text
309
310 def __str__(self):
311 str = ""
312 for elt in self.tree:
313 str += elt.format()
314 return str
315
316class HtmlWiktionaryMarkup(HtmlWikiMarkup):
317 """A class for translating Wiktionary articles into HTML.
318
319 Reserved for future use. Currently does the same as HtmlWikiMarkup.
320 """
diff --git a/wikitrans/wiki2texi.py b/wikitrans/wiki2texi.py
new file mode 100644
index 0000000..d9e5f52
--- a/dev/null
+++ b/wikitrans/wiki2texi.py
@@ -0,0 +1,410 @@
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2015-2018 Sergey Poznyakoff
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3, or (at your option)
8# any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18"""
19Wiki markup to Texinfo translator.
20
21Classes:
22
23TexiWikiMarkup -- Converts Wiki material to Texinfo.
24
25"""
26
27from wikitrans.wikimarkup import *
28from wikitrans.wikitoken import *
29from wikitrans.wikins import wiki_ns_re, wiki_ns
30import re
31import urllib
32
33class Acc(list):
34 def prepend(self,x):
35 self.insert(0,x)
36
37 def is_empty(self):
38 return len(self) == 0
39
40 def clear(self):
41 self = []
42
43 def tail(self, n = 1):
44 s = Acc()
45 i = len(self)
46 while i > 0 and n > 0:
47 elt = self[i-1]
48 l = len(elt)
49 if l == 0:
50 continue
51 elif l > n:
52 l = n
53 s.prepend(elt[-n:])
54 n -= l
55 i -= 1
56 return str(s)
57
58 def trim(self, n):
59 while len(self) and n > 0:
60 elt = self.pop()
61 l = len(elt)
62 if l == 0:
63 continue
64 elif l > n:
65 self += elt[0:-n]
66 break
67 n -= l
68
69 def trimnl(self):
70 if self.endswith('\n'):
71 self.trim(1)
72
73 def trimpara(self):
74 if self.endswith('\n\n'):
75 self.trim(2)
76
77 def endswith(self, x):
78 return self.tail(len(x)) == x
79
80 def in_new_para(self):
81 return self.is_empty() or self.endswith('\n\n')
82
83 def __str__(self):
84 return ''.join(self)
85
86class TexiTextNode(WikiTextNode):
87 def format(self):
88 parser = self.parser
89 if isinstance(self.content,list):
90 for s in self.content:
91 parser._print(s)
92 else:
93 parser._print(self.content)
94
95class TexiTagNode(WikiTagNode):
96 def format(self):
97 parser = self.parser
98 if self.tag in ['code', 'tt']:
99 save = parser._begin_print()
100 parser.nested += 1
101 self.content.format()
102 parser.nested -= 1
103 s = parser._end_print(save)
104 if self.isblock:
105 parser._print('@example', nl=True, escape=False)
106 parser._print(s, escape=False)
107 parser._print('@end example\n', nl=True, escape=False)
108 else:
109 parser._print('@code{%s}' % s, escape=False)
110 elif self.tag == 'div':
111 if self.args and 'id' in self.args:
112 parser._print("@anchor{%s}\n" % self.args['id'],
113 nl=True, escape=False)
114 self.content.format()
115 elif self.tag == 'ref':
116 parser._print('@footnote{', escape=False);
117 self.content.format();
118 parser._print('}', escape=False)
119 elif self.tag == 'references':
120 pass
121 else:
122 parser._print('<' + self.tag)
123 if self.args:
124 parser._print(' ' + self.args)
125 parser._print('>');
126 self.content.format()
127 parser._print('</' + self.tag + '>')
128
129class TexiParaNode(WikiSeqNode):
130 def format(self):
131 parser = self.parser
132 if not parser.acc.in_new_para():
133 parser._print('\n', nl=True)
134 for x in self.content:
135 x.format()
136 if not parser.acc.in_new_para():
137 parser._print('\n', nl=True)
138
139class TexiPreNode(WikiSeqNode):
140 def format(self):
141 parser = self.parser
142 if not parser.nested:
143 parser._print('@example\n', nl=True, escape=False)
144 for x in self.content:
145 x.format()
146 if not parser.nested:
147 parser._print('@end example\n', nl=True, escape=False)
148
149class TexiFontNode(WikiSeqNode):
150 def format(self):
151 parser = self.parser
152 comm = { 'IT': 'i',
153 'BOLD': 'b' }
154 parser._print('@%s{' % comm[self.type], escape=False)
155 for x in self.content:
156 x.format()
157 parser._print('}', escape=False)
158
159class TexiHdrNode(WikiHdrNode):
160 def format(self):
161 parser = self.parser
162 level = self.level
163 # FIXME
164 if level > len(parser.sectcomm[parser.sectioning_model]) - 1 - parser.sectioning_start:
165 parser._print("@* ", nl=True, escape=False)
166 self.content.format()
167 else:
168 parser._print(parser.sectcomm[parser.sectioning_model][level - parser.sectioning_start] + " ", nl=True, escape=False)
169 self.content.format()
170 parser._print(None, nl=True)
171 if parser.sectcomm[parser.sectioning_model][0] == '@top':
172 parser._print('@node ', nl=True, escape=False)
173 self.content.format()
174 parser._print('\n')
175 parser._print(None, nl=True)
176
177class TexiBarNode(WikiNode):
178 def format(self):
179 self.parser._print("\n-----\n")
180
181class TexiIndNode(WikiIndNode):
182 def format(self):
183 parser = self.parser
184 parser._print("@w{ }" * self.level, nl=True, escape=False)
185 self.content.format()
186 parser._print(None, nl=True)
187
188class TexiEnvNode(WikiEnvNode):
189 def format(self):
190 parser = self.parser
191 if self.envtype == 'unnumbered':
192 parser._print('@itemize @bullet\n', nl=True, escape=False)
193 for s in self.content:
194 parser._print('@item ', nl=True, escape=False)
195 s.content.format()
196 parser._print(None, nl=True)
197 parser._print('\n')
198 parser._print('@end itemize\n', nl=True, escape=False)
199 elif self.envtype == 'numbered':
200 parser._print('@enumerate\n', nl=True, escape=False)
201 for s in self.content:
202 parser._print('@item ', nl=True, escape=False)
203 s.content.format()
204 parser._print(None, nl=True)
205 parser._print('\n')
206 parser._print('@end enumerate\n', nl=True, escape=False)
207 elif self.envtype == 'defn':
208 parser._print('@table @asis\n', nl=True, escape=False)
209 for s in self.content:
210 if s.subtype == 0:
211 parser._print('@item ', nl=True, escape=False)
212 s.content.format()
213 parser._print(None, nl=True)
214 else:
215 s.content.format()
216 parser._print(None, nl=True)
217 parser._print('\n')
218 parser._print('@end table\n', nl=True, escape=False)
219
220class TexiLinkNode(WikiSeqNode):
221 def format(self):
222 parser = self.parser
223 save = parser._begin_print()
224 self.content[0].format()
225 arg = parser._end_print()
226 if len(self.content) > 1:
227 s = []
228 for x in self.content[0:2]:
229 parser._begin_print()
230 x.format()
231 s.append(parser._end_print())
232 text = s[1]
233 else:
234 s = None
235 text = None
236
237 parser._end_print(save)
238
239 if s:
240 if s[0] == 'disambigR' or s[0] == 'wikiquote':
241 return
242 if len(s) > 1 and s[1] == 'thumb':
243 return
244
245 (qual,sep,tgt) = arg.partition(':')
246 if text:
247 parser._print("@ref{%s,%s}" % (qual, text), escape=False)
248 else:
249 parser._print("@ref{%s}" % qual, escape=False)
250
251class TexiRefNode(WikiRefNode):
252 def format(self):
253 parser = self.parser
254 target = self.ref
255 save = parser._begin_print()
256 self.content.format()
257 text = parser._end_print(save)
258 if text and text != '':
259 parser._print("@uref{%s,%s}" % (target, text), escape=False)
260 else:
261 parser._print("@uref{%s}" % target, escape=False)
262
263class TexiWikiMarkup(WikiMarkup):
264 """Wiki markup to Texinfo translator class.
265
266 Usage:
267
268 x = TexiWikiMarkup(file="input.wiki")
269 # Parse the input:
270 x.parse()
271 # Print it as Texi:
272 print(str(x))
273
274 """
275
276 nested = 0
277 sectcomm = {
278 'numbered': [
279 '@top',
280 '@chapter',
281 '@section',
282 '@subsection',
283 '@subsubsection'
284 ],
285 'unnumbered': [
286 '@top',
287 '@unnumbered',
288 '@unnumberedsec',
289 '@unnumberedsubsec',
290 '@unnumberedsubsubsec'
291 ],
292 'appendix': [
293 '@top',
294 '@appendix',
295 '@appendixsec',
296 '@appendixsubsec',
297 '@appendixsubsubsec'
298 ],
299 'heading': [
300 '@majorheading'
301 '@chapheading',
302 '@heading',
303 '@subheading',
304 '@subsubheading'
305 ]
306 }
307
308 sectioning_model = 'numbered'
309 sectioning_start = 0
310
311 def __init__(self, *args, **keywords):
312 """Create a TexiWikiMarkup object.
313
314 Arguments:
315
316 filename=FILE
317 Read Wiki material from the file named FILE.
318 file=FD
319 Read Wiki material from file object FD.
320 text=STRING
321 Read Wiki material from STRING.
322
323 sectioning_model=MODEL
324 Select the Texinfo sectioning model for the output document. Possible
325 values are:
326
327 'numbered'
328 Top of document is marked with "@top". Headings ("=", "==",
329 "===", etc) produce "@chapter", "@section", "@subsection", etc.
330 'unnumbered'
331 Unnumbered sectioning: "@top", "@unnumbered", "@unnumberedsec",
332 "@unnumberedsubsec".
333 'appendix'
334 Sectioning suitable for appendix entries: "@top", "@appendix",
335 "@appendixsec", "@appendixsubsec", etc.
336 'heading'
337 Use heading directives to reflect sectioning: "@majorheading",
338 "@chapheading", "@heading", "@subheading", etc.
339 sectioning_start=N
340 Shift resulting heading level by N positions. For example, supposing
341 "sectioning_model='numbered'", "== A ==" normally produces
342 "@section A" on output. Now, if given "sectioning_start=1", this
343 directive will produce "@subsection A" instead.
344 """
345
346 super(TexiWikiMarkup, self).__init__(*args, **keywords)
347
348 self.token_class['TEXT'] = TexiTextNode
349 self.token_class['TAG'] = TexiTagNode
350 self.token_class['PARA'] = TexiParaNode
351 self.token_class['PRE'] = TexiPreNode
352 self.token_class['IT'] = TexiFontNode
353 self.token_class['BOLD'] = TexiFontNode
354 self.token_class['HDR'] = TexiHdrNode
355 self.token_class['BAR'] = TexiBarNode
356 self.token_class['IND'] = TexiIndNode
357 self.token_class['ENV'] = TexiEnvNode
358 self.token_class['LINK'] = TexiLinkNode
359 self.token_class['REF'] = TexiRefNode
360
361 if "sectioning_model" in keywords:
362 val = keywords["sectioning_model"]
363 if val in self.sectcomm:
364 self.sectioning_model = val
365 else:
366 raise ValueError("Invalid value for sectioning model: %s" % val)
367 if "sectioning_start" in keywords:
368 val = keywords["sectioning_start"]
369 if val < 0 or val > 4:
370 raise ValueError("Invalid value for sectioning start: %s" % val)
371 else:
372 self.sectioning_start = val
373
374 replchars = re.compile(r'([@{}])')
375 acc = Acc()
376
377 def _print(self, text, **kw):
378 nl = kw.pop('nl', False)
379 escape = kw.pop('escape', True)
380 if nl and not self.acc.endswith('\n'):
381 self.acc += '\n'
382 if text:
383 if escape:
384 self.acc += self.replchars.sub(r'@\1', text)
385 else:
386 self.acc += text
387
388 def _begin_print(self):
389 s = self.acc
390 self.acc = Acc()
391 return s
392
393 def _end_print(self, val = None):
394 s = self.acc
395 self.acc = val
396 return str(s)
397
398 def __str__(self):
399 self._begin_print()
400 for elt in self.tree:
401 elt.format()
402 self.acc.trimpara()
403 return self._end_print()
404
405
406
407
408
409
410
diff --git a/wikitrans/wiki2text.py b/wikitrans/wiki2text.py
new file mode 100644
index 0000000..1fbc61b
--- a/dev/null
+++ b/wikitrans/wiki2text.py
@@ -0,0 +1,348 @@
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2008-2018 Sergey Poznyakoff
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3, or (at your option)
8# any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18"""
19Wiki markup to plain text translator.
20
21Classes:
22
23TextWikiMarkup -- Converts Wiki material to plain text.
24TextWiktionaryMarkup -- Reserved for future use. Currently does the same as
25 TextWikiMarkup.
26
27"""
28
29from wikitrans.wikitoken import *
30from wikitrans.wikimarkup import *
31from wikitrans.wikins import wiki_ns_re, wiki_ns
32import re
33try:
34 from urllib import quote as url_quote
35except ImportError:
36 from urllib.parse import quote as url_quote
37
38class TextSeqNode(WikiSeqNode):
39 def format(self):
40 string = ""
41 for x in self.content:
42 if len(string) > 1 and not string[-1].isspace():
43 string += ' '
44 string += x.format()
45 return string
46
47class TextTextNode(WikiTextNode):
48 def format(self):
49 if isinstance(self.content,list):
50 string = ""
51 for s in self.content:
52 if string:
53 if string.endswith("."):
54 string += " "
55 else:
56 string += " "
57 string += s
58 else:
59 string = self.content
60 return string
61
62class TextPreNode(WikiSeqNode):
63 def format(self):
64 string = ""
65 for x in self.content:
66 string += x.format()
67 string += '\n'
68 return string
69
70class TextParaNode(WikiSeqNode):
71 def format(self):
72 string = ""
73 for x in self.content:
74 string += x.format()
75 string = self.parser.fmtpara(string) + '\n\n'
76 return string
77
78class TextItNode(WikiSeqNode):
79 def format(self):
80 string = ""
81 for x in self.content:
82 s = x.format()
83 if s:
84 string += " " + s
85 return "_" + string.lstrip(" ") + "_"
86
87class TextBoldNode(WikiSeqNode):
88 def format(self):
89 string = ""
90 for x in self.content:
91 if string.endswith("."):
92 string += " "
93 else:
94 string += " "
95 string += x.format()
96 return string.upper()
97
98class TextLinkNode(WikiSeqNode):
99 def format(self):
100 arg = self.content[0].format()
101 if len(self.content) > 1:
102 s = [x for x in map(lambda x: x.format(), self.content)]
103 text = s[1]
104 else:
105 s = None
106 text = None
107
108 if s:
109 if s[0] == 'disambigR' or s[0] == 'wikiquote':
110 return ""
111 if len(s) > 1 and s[1] == 'thumb':
112 return ""
113 (qual,sep,tgt) = arg.partition(':')
114 if tgt != '':
115 ns = self.parser.wiki_ns_name(qual)
116 if ns:
117 if ns == 'NS_IMAGE':
118 if not self.parser.show_urls:
119 return ""
120 text = "[%s: %s]" % (qual, text if text else arg)
121 tgt = "%s/%s/250px-%s" % (self.image_base,
122 url_quote(tgt),
123 url_quote(tgt))
124 elif ns == 'NS_MEDIA':
125 text = "[%s]" % (qual)
126 else:
127 tgt = self.parser.mktgt(tgt)
128 elif self.type == 'LINK' and qual in self.parser.langtab:
129 text = self.parser.langtab[qual] + ": " + tgt
130 tgt = self.parser.mktgt(tgt, qual)
131 else:
132 tgt = self.parser.mktgt(tgt)
133 else:
134 tgt = self.parser.mktgt(arg)
135 if self.parser.show_urls:
136 return "%s (see %s) " % (text, tgt)
137 elif not text or text == '':
138 return arg
139 else:
140 return text
141
142class TextTmplNode(TextLinkNode):
143 def format(self):
144 return '[' + super(TextTmplNode, self).format() + ']'
145
146class TextBarNode(WikiNode):
147 def format(self):
148 w = self.parser.width
149 if w < 5:
150 w = 5
151 return "\n" + ("-" * (w - 5)).center(w - 1) + "\n"
152
153class TextHdrNode(WikiHdrNode):
154 def format(self):
155 return ("\n"
156 + ("*" * self.level)
157 + " "
158 + self.content.format().lstrip(" ")
159 + "\n\n")
160
161class TextRefNode(WikiRefNode):
162 def format(self):
163 text = self.content.format()
164 if text:
165 return "%s (see %s) " % (text, self.ref)
166 else:
167 return "see " + self.ref
168
169class TextEnvNode(WikiEnvNode):
170 def format(self):
171 type = self.envtype
172 lev = self.level
173 if lev > self.parser.width - 4:
174 lev = 1
175 string = ""
176 n = 1
177 for s in self.content:
178 if not string.endswith("\n"):
179 string += "\n"
180 x = s.content.format()
181 if type == "unnumbered":
182 string += self.parser.indent(lev, "- " + x.lstrip(" "))
183 elif type == "numbered":
184 string += self.parser.indent(lev, "%d. %s" % (n, x))
185 n += 1
186 elif type == "defn":
187 if s.subtype == 0:
188 string += self.parser.indent(lev-1, x)
189 else:
190 string += self.parser.indent(lev+3, x)
191
192 if not string.endswith("\n"):
193 string += "\n"
194
195 return string
196
197class TextIndNode(WikiIndNode):
198 def format(self):
199 return (" " * self.level) + self.content.format() + '\n'
200
201class TextTagNode(WikiTagNode):
202 def format(self):
203 if self.tag == 'code':
204 self.parser.nested += 1
205 s = self.content.format()
206 self.parser.nested -= 1
207 elif self.tag == 'ref':
208 s = '[%d]' % (self.idx+1)
209 elif self.tag == 'references':
210 s = '\nReferences:\n'
211 for ref in self.parser.references:
212 s += ('[%d]. ' % (ref.idx+1)) + ref.content.format() + '\n'
213 else:
214 s = '<' + self.tag
215 if self.args:
216 s += ' ' + str(self.args)
217 s += '>' + self.content.format() + '</' + self.tag + '>'
218 return s
219
220
221class TextWikiMarkup(WikiMarkup):
222 """A Wiki markup to plain text translator.
223
224 Usage:
225
226 x = TextWikiMarkup(file="input.wiki")
227 # Parse the input:
228 x.parse()
229 # Print it as plain text:
230 print(str(x))
231
232 """
233
234 # Output width
235 width = 78
236 # Do not show references.
237 show_urls = False
238 # Provide a minimum markup
239 markup = True
240
241 # Number of current element in the environment
242 num = 0
243
244 # Array of footnote references
245 references = []
246
247 def __init__(self, *args, **keywords):
248 """Create a TextWikiMarkup object.
249
250 Arguments:
251
252 filename=FILE
253 Read Wiki material from the file named FILE.
254 file=FD
255 Read Wiki material from file object FD.
256 text=STRING
257 Read Wiki material from STRING.
258
259 width=N
260 Limit output width to N columns. Default is 78.
261 show_urls=False
262 By default, the link URLs are displayed in parentheses next to the
263 link text. If this argument is given, only the link text will be
264 displayed.
265 """
266
267 super(TextWikiMarkup,self).__init__(*args, **keywords)
268 if 'width' in keywords:
269 self.width = keywords['width']
270 if 'show_urls' in keywords:
271 self.show_urls = keywords['show_urls']
272 self.token_class['SEQ'] = TextSeqNode
273 self.token_class['TEXT'] = TextTextNode
274 self.token_class['PRE'] = TextPreNode
275 self.token_class['PARA'] = TextParaNode
276 self.token_class['SEQ'] = TextSeqNode
277 self.token_class['IT'] = TextItNode
278 self.token_class['BOLD'] = TextBoldNode
279 self.token_class['LINK'] = TextLinkNode
280 self.token_class['TMPL'] = TextTmplNode
281 self.token_class['BAR'] = TextBarNode
282 self.token_class['HDR'] = TextHdrNode
283 self.token_class['REF'] = TextRefNode
284 self.token_class['ENV'] = TextEnvNode
285 self.token_class['IND'] = TextIndNode
286 self.token_class['TAG'] = TextTagNode
287
288 def wiki_ns_name(self, str):
289 if str in wiki_ns[self.lang]:
290 return wiki_ns[self.lang][str]
291 elif str in wiki_ns_re[self.lang]:
292 for elt in wiki_ns_re[self.lang][str]:
293 if str.beginswith(elt[0]) and str.endswith(elt[1]):
294 return elt[2]
295 return None
296
297 def mktgt(self, tgt, lang = None):
298 if not lang:
299 lang = self.lang
300 return self.html_base % { 'lang' : lang } + url_quote(tgt)
301
302 def indent(self, lev, text):
303 if text.find('\n') == -1:
304 s = (" " * lev) + text
305 else:
306 s = ""
307 for elt in text.split('\n'):
308 if elt:
309 s += (" " * lev) + elt + '\n'
310 if not text.endswith('\n'):
311 s = s.rstrip('\n')
312 return s
313
314 def fmtpara(self, input):
315 output = ""
316 linebuf = ""
317 length = 0
318 for s in input.split():
319 wlen = len(s)
320 if len(linebuf) == 0:
321 wsc = 0
322 elif linebuf.endswith("."):
323 wsc = 2
324 else:
325 wsc = 1
326 if length + wsc + wlen > self.width:
327 # FIXME: fill out linebuf
328 output += linebuf + '\n'
329 wsc = 0
330 length = 0
331 linebuf = ""
332 linebuf += " " * wsc + s
333 length += wsc + wlen
334 return output + linebuf
335
336 def __str__(self):
337 str = ""
338 for elt in self.tree:
339 str += elt.format()
340 return str
341
342class TextWiktionaryMarkup(TextWikiMarkup):
343 """A class for translating Wiktionary articles into plain text.
344
345 Reserved for future use. Currently does the same as TextWikiMarkup.
346 """
347
348
diff --git a/wikitrans/wikidump.py b/wikitrans/wikidump.py
new file mode 100644
index 0000000..d5f651c
--- a/dev/null
+++ b/wikitrans/wikidump.py
@@ -0,0 +1,77 @@
1# Wiki "dump" format. -*- coding: utf-8 -*-
2# Copyright (C) 2015-2018 Sergey Poznyakoff
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 3, or (at your option)
7# any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17"""
18Print Wiki parse tree as JSON.
19
20Classes:
21
22DumpWikiMarkup
23
24"""
25
26from __future__ import print_function
27from wikitrans.wikitoken import *
28import json
29from wikitrans.wikimarkup import WikiMarkup
30
31class DumpReferences(object):
32 idx = 0
33 def __len__(self):
34 return self.idx + 1
35 def append(self, obj):
36 self.idx += 1
37
38class DumpWikiMarkup(WikiMarkup):
39 """Produce a JSON dump of the Wiki markup parse tree.
40
41 Usage:
42
43 x = DumpWikiMarkup(file="input.wiki")
44 # Parse the input:
45 x.parse()
46 # Print a JSON dump of the parse tree
47 print(str(x))
48
49 """
50
51 indent = None
52 references = DumpReferences()
53 def __init__(self, **kwarg):
54 """Create a DumpWikiMarkup object.
55
56 Arguments:
57
58 filename=FILE
59 Read Wiki material from the file named FILE.
60 file=FD
61 Read Wiki material from file object FD.
62 text=STRING
63 Read Wiki material from STRING.
64 indent=N
65 Basic indent offset for JSON objects.
66 """
67
68 n = kwarg.pop('indent', None)
69 if n != None:
70 self.indent = int(n)
71 super(DumpWikiMarkup,self).__init__(self, **kwarg)
72 def __str__(self):
73 return json.dumps(self.tree,
74 cls=WikiNodeEncoder,
75 indent=self.indent,
76 separators=(',',': '),
77 sort_keys=True)
diff --git a/wikitrans/wikimarkup.py b/wikitrans/wikimarkup.py
new file mode 100644
index 0000000..77c3b30
--- a/dev/null
+++ b/wikitrans/wikimarkup.py
@@ -0,0 +1,1285 @@
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2008-2018 Sergey Poznyakoff
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3, or (at your option)
8# any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18"""
19Wiki markup parser.
20
21This module provides two class:
22
23WikiMarkupParser:
24 An abstract parser class, which serves as a base class for all markup
25 classes in this package.
26
27WikiMarkup
28 A subclass of the above, providing basic input method.
29
30"""
31
32from __future__ import print_function
33import sys
34import re
35from types import *
36from wikitrans.wikitoken import *
37
38__all__ = [ "WikiMarkupParser", "WikiMarkup",
39 "TagAttributes", "TagAttributeSyntaxError" ]
40
41class UnexpectedTokenError(Exception):
42 def __init__(self, value):
43 self.value = value
44
45class TagAttributeSyntaxError(Exception):
46 def __init__(self, value):
47 self.value = value
48 def __str__(self):
49 return repr(self.value)
50
51class TagAttributes(object):
52 """A dictionary-like collection of tag attributes.
53
54 Example:
55
56 attr = TagAttributes('href="foo" length=2')
57 if 'href' in attr:
58 print(x['href']) # returns "foo"
59 for a in attr:
60 ...
61 """
62
63 attrstart = re.compile("^(?P<attr>[a-zA-Z0-9_-]+)(?P<eq>=\")?")
64 valseg = re.compile("^[^\\\"]+")
65 tab = {}
66 printable = None
67 def __init__(self, string):
68 if not string:
69 self.printable = ''
70 return
71 self.printable = string
72 s = string
73 self.tab = {}
74 while s != '':
75 s = s.strip()
76 m = self.attrstart.match(s)
77 if m:
78 name = m.group('attr')
79 val = ''
80 s = s[m.end(0):]
81 if m.group('eq'):
82 while 1:
83 m = self.valseg.match(s)
84 val += m.group(0)
85 s = s[m.end(0):]
86 if s[0] == '\\':
87 val += s[1]
88 s += 2
89 elif s[0] == '"':
90 s = s[1:]
91 break
92 else:
93 val = 1
94 self.tab[name] = val
95 else:
96 raise TagAttributeSyntaxError(s)
97 def __len__(self):
98 return len(self.tab)
99 def __getitem__(self, key):
100 return self.tab[key]
101 def __contains__(self, key):
102 return key in self.tab
103 def __iter__(self):
104 for key in self.tab:
105 yield(key)
106 def has_key(self, key):
107 return self.__contains__(key)
108 def __setitem__(self, key, value):
109 self.tab[key] = value
110 def __delitem__(self, key):
111 del self.tab[key]
112 def __str__(self):
113 return self.printable
114 def __repr__(self):
115 return self.printable
116
117class WikiMarkupParser(object):
118 """Parser for Wiki markup language.
119
120 Given input in Wiki markup language creates an abstract parse tree for it.
121 This is a base class for actual parsers. The subclasses must provide the
122 input method.
123
124 Public methods:
125
126 parse() -- parse the input.
127
128 Abstract methods (must be overridden by the subclass):
129
130 input() -- returns next physical line from the input material.
131
132 Public attributes:
133
134 tree -- constructed parse tree (a subclass of WikiNode)
135
136 """
137
138 delim = re.compile("^==+[ \t]*|[ \t]*==+[ \t]*$|(^----$)|^\\*+|^#+|^[;:]+|(\\[\\[)|\\[|(\\{\\{)|(\\]\\])|\\]|(\\}\\})|\\||(\\'\\'\\'?)|<")
139 otag = re.compile("<(?P<tag>[a-zA-Z0-9_]+)(?:\s+(?P<args>[^/][^>]+))?\s*(?P<closed>/)?>")
140 ctag = re.compile("</(?P<tag>[a-zA-Z0-9_]+)\s*>")
141 refstart = re.compile("^https?://")
142
143 close_delim = {
144 '[': ']',
145 '[[': ']]',
146 '{{': '}}'
147 }
148
149 # Environment types:
150 envtypes = { "*": [ "unnumbered", 0 ],
151 "#": [ "numbered", 0 ],
152 ";": [ "defn", 0 ],
153 ":": [ "defn", 1 ]
154 }
155
156 toklist = None
157 tokind = 0
158 newline = 0
159 tree = None
160
161 tags = [ 'code', 'nowiki', 'tt', 'div', 'ref', 'references' ]
162
163 debug_level = 0
164
165 def dprint(self, lev, fmt, *argv):
166 """If current debug level is greater than or equal to lev, print *argv
167 according to format.
168 """
169 if self.debug_level >= lev:
170 for l in (fmt % argv).split('\n'):
171 print("[DEBUG] %s" % l)
172
173 inline_delims = [ "''", "'''", "[", "]", "[[", "]]", "{{", "}}", "|" ]
174
175 token_class = {
176 'NIL': WikiNode,
177 'NL': WikiNode,
178 'OTAG': WikiTagNode,
179 'CTAG': WikiTagNode,
180 'TAG': WikiTagNode,
181 'DELIM': WikiDelimNode,
182 'TEXT': WikiTextNode,
183 'PRE': WikiContentNode,
184 'PARA': WikiSeqNode,
185 'BAR': WikiNode,
186 'SEQ': WikiSeqNode,
187 'IND': WikiIndNode,
188 'REF': WikiRefNode,
189 'TMPL': WikiSeqNode,
190 'IT': WikiSeqNode,
191 'BOLD': WikiSeqNode,
192 'ELT': WikiEltNode,
193 'ENV': WikiEnvNode,
194 'LINK': WikiSeqNode,
195 'HDR': WikiHdrNode
196 }
197
198 def _new_node(self,**kwarg):
199 return self.token_class[kwarg['type']](self, **kwarg)
200
201 def tokread(self):
202 """Read next token from the input. Return it as a subclass of WikiNode."""
203 line = None
204 pos = 0
205 while 1:
206 if (not line or pos == len(line)):
207 try:
208 line = self.input()
209 pos = 0
210 except StopIteration:
211 line = u''
212
213 if not line or line == "":
214 yield(self._new_node(type='NIL'))
215 break
216
217 if line == '\n':
218 yield(self._new_node(type='NL'))
219 line = None
220 continue
221
222 self.dprint(100, "LINE: %s", line[pos:])
223 m = self.delim.search(line, pos)
224
225 if m:
226 if (pos < m.start(0)):
227 yield(self._new_node(type='TEXT',
228 content=line[pos:m.start(0)]))
229 pos = m.start(0)
230 t = None
231
232 if line[m.start(0)] == '<':
233 m = self.otag.match(line, pos)
234 if m:
235 pos = m.end(0)
236 if m.group('tag') == 'nowiki':
237 if not m.group('closed'):
238 while 1:
239 try:
240 m = self.ctag.search(line, pos)
241 if m and m.group('tag') == 'nowiki':
242 yield(self._new_node(type='TEXT',
243 content=line[pos:m.start(0)] ))
244 pos = m.end(0)
245 break
246
247 yield(self._new_node(type='TEXT',
248 content=line[pos:]))
249
250 line = self.input()
251 pos = 0
252 except StopIteration:
253 break
254 continue
255 elif m.group('tag') in self.tags:
256 try:
257 yield(self._new_node(type='OTAG',
258 tag=m.group('tag'),
259 isblock=(line[pos] == '\n'),
260 args=TagAttributes(m.group('args'))))
261 if m.group('closed'):
262 yield(self._new_node(type='CTAG',
263 tag=m.group('tag')))
264 except TagAttributeSyntaxError:
265 yield(self._new_node(type='TEXT',
266 content=m.group(0)))
267 continue
268 else:
269 yield(self._new_node(type='TEXT',content=m.group(0)))
270 continue
271 else:
272 m = self.ctag.match(line, pos)
273 if m:
274 if m.group('tag') in self.tags:
275 yield(self._new_node(type='CTAG',
276 tag=m.group('tag')))
277 pos = m.end(0)
278 continue
279 else:
280 yield(self._new_node(type='TEXT',
281 content=line[pos:pos+1]))
282 pos += 1
283 continue
284 else:
285 pos = m.end(0)
286 content = m.group(0)
287 if content[0] in self.envtypes:
288 node = self._new_node(type='DELIM',
289 content=content,
290 isblock=True,
291 continuation=pos < len(line) and line[pos] == ":")
292 if node.continuation:
293 node.content += node.content[0]
294 pos += 1
295
296 yield(node)
297
298 while pos < len(line) and line[pos] in [' ', '\t']:
299 pos += 1
300 else:
301 yield(self._new_node(type='DELIM',
302 isblock=(content.strip() not in self.inline_delims),
303 content=content.strip()))
304 continue
305
306 if line:
307 if line[-1] == '\n':
308 if line[pos:-1] != '':
309 yield(self._new_node(type='TEXT',content=line[pos:-1]))
310 yield(self._new_node(type='NL'))
311 else:
312 yield(self._new_node(type='TEXT',content=line[pos:]))
313 line = None
314
315
316 def input(self):
317 """Return next physical line from the input.
318
319 This method must be overridden by the subclass.
320 """
321 return None
322
323 def swaptkn(self, i, j):
324 """Swap tokens at indices i and j in toklist."""
325 self.dprint(80, "SWAPPING %s <-> %s", i, j)
326 x = self.toklist[i]
327 self.toklist[i] = self.toklist[j]
328 self.toklist[j] = x
329
330 def tokenize(self):
331 """Tokenize the input.
332
333 Read tokens from the input (supplied by the input() method). Place the
334 obtained tokens in the toklist array.
335 """
336 self.toklist = []
337 for tok in self.tokread():
338 self.dprint(100, "TOK: %s", tok)
339 self.toklist.append(tok)
340 # Determine and fix up the ordering of bold and italic markers
341 # There are three possible cases:
342 #
343 # 1a. '''a b ''c'' d'''
344 # 1b. ''a b '''c''' d''
345 #
346 # 2a. '''''a b'' c d'''
347 # 2b. '''''a b''' c d''
348 #
349 # 3a. '''a b ''c d'''''
350 # 3b. ''a b '''c d'''''
351 stack = []
352 for i in range(0,len(self.toklist)):
353 if (self.toklist[i].type == 'DELIM'
354 and (self.toklist[i].content == "''"
355 or self.toklist[i].content == "'''")):
356 if len(stack) > 0:
357 if self.toklist[stack[-1]].content == self.toklist[i].content:
358 # Case 1: just pop the matching delimiter off the stack
359 stack.pop()
360 elif len(stack) == 2 and stack[-2] + 1 == stack[-1]:
361 # Case 2: swap delimiters saved on stack ...
362 self.swaptkn(stack[-2], stack[-1])
363 # and pop off the matching one
364 stack.pop()
365 elif (i < len(self.toklist)
366 and self.toklist[i+1].type == 'DELIM'
367 and self.toklist[stack[-1]].content
368 == self.toklist[i+1].content):
369 # Case 3: swap current and next tokens
370 self.swaptkn(i, i+1)
371 # and pop off the matching one
372 stack.pop()
373 else:
374 # Push the token on stack
375 stack.append(i)
376 else:
377 # Push the token on stack
378 stack.append(i)
379 # Redefine all non-matched tokens as TEXT
380 for i in stack:
381 self.toklist[i].type = 'TEXT' # FIXME
382
383 mark = []
384
385 def push_mark(self):
386 """Save the current token index on stack."""
387 self.mark.append(self.tokind)
388
389 def pop_mark(self):
390 """Restore the token index from top of stack."""
391 self.tokind = self.mark.pop()
392
393 def clear_mark(self):
394 """Forget the last mark."""
395 self.mark.pop()
396
397 def lookahead(self, off=0):
398 """Peek a token at index (tokind+off)."""
399 tok = self.toklist[self.tokind+off]
400 self.dprint(20, "lookahead(%s): %s", off, tok)
401 return tok
402
403 def setkn(self,val):
404 """Store token val at the current token index."""
405 self.toklist[self.tokind] = val
406
407 def getkn(self):
408 """Get next token from the toklist. Advance tokind."""
409 self.newline = self.tokind == 0 or self.toklist[self.tokind-1].type == 'NL'
410 if self.tokind == len(self.toklist):
411 return self._new_node(type='NIL')
412 tok = self.toklist[self.tokind]
413 self.tokind = self.tokind + 1
414 self.dprint(20, "getkn: %s", tok)
415 return tok
416
417 def ungetkn(self, tok=None):
418 """Unget the last read token.
419
420 Decrease the tokind by one, so the last read token will be read again.
421 If optional argument is supplied and is not None, store it in the toklist
422 in place of the current token.
423 """
424 self.tokind = self.tokind - 1
425 self.newline = self.tokind == 0 or self.toklist[self.tokind-1].type == 'NL'
426 if tok:
427 self.toklist[self.tokind] = tok
428 self.dprint(20, "ungetkn: %s", tok)
429 return self.toklist[self.tokind]
430
431 def fixuptkn(self, tok):
432 """Replace the recently read token by tok."""
433 if self.tokind == 0:
434 raise IndexError('WikiMarkupParser.fixuptkn called at start of input')
435 self.toklist[self.tokind-1] = tok
436 return tok
437
438 def dump(self, tree, file=sys.stdout):
439 """Dump the tree to file, node by node."""
440 for node in tree:
441 file.write(str(node))
442 file.write('\n')
443
444 def is_block_end(self, tok):
445 """Return True if tok ends a block environment."""
446 if tok.type == 'NIL':
447 return True
448 elif tok.type == 'NL':
449 if self.lookahead().type == 'NIL':
450 return True
451 elif self.lookahead().type == 'NL':
452 self.getkn()
453 return True
454 elif tok.type in ['DELIM', 'CTAG', 'TAG']:
455 if tok.isblock:
456 self.ungetkn(tok)
457 return True
458 return False
459
460 def parse_para(self, tok):
461 """Read paragraph starting at tok."""
462 self.dprint(80, "ENTER parse_para: %s", tok)
463
464 acc = { 'seq': [],
465 'textlist': [] }
466
467 def flush():
468 if acc['textlist']:
469 acc['seq'].append(self._new_node(type='TEXT',
470 content=''.join(acc['textlist'])))
471 acc['textlist'] = []
472
473 if (isinstance(tok, WikiContentNode)
474 and isinstance(tok.content,str)
475 and re.match("^[ \t]", tok.content)):
476 type = 'PRE'
477 rx = re.compile("^\S")
478 else:
479 type = 'PARA'
480 rx = re.compile("^[ \t]")
481
482 while not self.is_block_end(tok):
483 if tok.type == 'TEXT':
484 if rx and self.newline and rx.match(tok.content):
485 self.ungetkn()
486 break
487 acc['textlist'].append(tok.content)
488 elif tok.type == 'NL':
489 acc['textlist'].append('\n')
490 elif tok.type == 'OTAG':
491 flush()
492 acc['seq'].append(self.parse_tag(tok))
493 elif tok.type == 'DELIM':
494 flush()
495 acc['seq'].append(self.parse_inline_delim(tok))
496 else:
497 raise UnexpectedTokenError(tok)
498 tok = self.getkn()
499 flush()
500 if acc['seq']:
501 tok = self._new_node(type=type, content=acc['seq'])
502 else:
503 tok = None
504 self.dprint(80, "LEAVE parse_para=%s", tok)
505 return tok
506
507 def parse_block_delim(self, tok):
508 """Parse block environment starting at tok."""
509 self.dprint(80, "ENTER parse_block_delim")
510 assert(tok.type == 'DELIM')
511 if tok.content == "----":
512 node = self._new_node(type = 'BAR')
513 elif tok.content[0:2] == "==":
514 node = self.parse_header(tok)
515 if not node:
516 tok = self.ungetkn(self._new_node(type='TEXT',
517 content=tok.content))
518 elif tok.content[0] in self.envtypes:
519 node = None
520 if tok.content[0] == ':':
521 t = self.lookahead(-2)
522 if not (t.type == 'DELIM' and t.content == ';'):
523 node = self.parse_indent(tok)
524 if not node:
525 node = self.parse_env(tok)
526 else:
527 self.ungetkn(tok)
528 node = None
529 self.dprint(80, "LEAVE parse_block_delim=%s", node)
530 return node
531
532 def parse_line(self):
533 """Parse the input line."""
534 self.dprint(80, "ENTER parse_line")
535 list = []
536 while True:
537 tok = self.getkn()
538 if tok.type == 'NL' or tok.type == 'NIL':
539 break
540 elif tok.type == 'TEXT':
541 list.append(tok)
542 elif tok.type == 'DELIM':
543 if tok.isblock:
544 tok = self._new_node(type = 'TEXT', content = tok.content)
545 self.fixuptkn(tok)
546 list.append(tok)
547 elif tok.content[0] == ":":
548 # FIXME
549 list.append(self.parse_indent(tok))
550 break
551 else:
552 x = self.parse_inline_delim(tok)
553 if x:
554 list.append(x)
555 else:
556 list.append(self.fixuptkn(self._new_node(type = 'TEXT',
557 content = tok.content)))
558 elif tok.type == 'OTAG':
559 if tok.isblock:
560 self.ungetkn()
561 break
562 list.append(self.parse_tag(tok))
563 else:
564 list.append(tok)
565 ret = self._new_node(type='SEQ', content=list)
566 self.dprint(80, "LEAVE parse_line=%s", ret)
567 return ret
568
569 def parse_indent(self, tok):
570 """Parse indented block starting at tok."""
571 lev = len(tok.content)
572 self.dprint(80, "ENTER parse_indent(%s)", lev)
573 x = self._new_node(type='IND', level=lev, content=self.parse_line())
574 self.dprint(80, "LEAVE parse_indent=%s", x)
575 return x
576
577 def parse_fontmod(self,delim,what):
578 """Parse font modification directive (bold or italics).
579
580 Arguments:
581
582 delim -- starting delimiter ("''" or "'''")
583 what -- 'IT' or 'BOLD'
584 """
585 self.dprint(80, "ENTER parse_fontmod(%s,%s), tok %s",
586 delim, what, self.lookahead())
587 seq = []
588 text = ''
589 while True:
590 tok = self.getkn()
591 if tok.type == 'TEXT':
592 text += tok.content
593 elif self.is_block_end(tok):
594 self.dprint(80, "LEAVE parse_fontmod=%s", "None")
595 return None
596 elif tok.type == 'DELIM':
597# self.dprint(80, "got %s, want %s", tok.content, delim)
598 if tok.content == delim:
599 break
600 else:
601 if text:
602 seq.append(self._new_node(type='TEXT', content=text))
603 text = ''
604 x = self.parse_inline_delim(tok)
605 if x:
606 seq.append(x)
607 else:
608 self.dprint(80, "LEAVE parse_fontmod=%s", "None")
609 return None
610 elif tok.type == 'NL':
611 seq.append(self._new_node(type='TEXT', content='\n'))
612 else:
613 self.dprint(80, "LEAVE parse_fontmod=None")
614 return None
615 if text:
616 seq.append(self._new_node(type='TEXT', content=text))
617 res = self._new_node(type=what, content=seq)
618 self.dprint(80, "LEAVE parse_fontmod=%s", res)
619 return res
620
621 def parse_ref(self):
622 """Parse a reference block ([...])"""
623 self.dprint(80, "ENTER parse_ref")
624 tok = self.getkn()
625 if not (tok.type == 'TEXT' and self.refstart.match(tok.content)):
626 self.dprint(80, "LEAVE parse_ref=None")
627 return None
628
629 seq = []
630 (ref,sep,text) = tok.content.partition(' ')
631 if text:
632 seq.insert(0, self._new_node(type='TEXT', content=text))
633
634 while True:
635 tok = self.getkn()
636 if tok.type == 'NIL':
637 self.dprint(80, "LEAVE parse_ref=None")
638 return None
639 elif self.is_block_end(tok):
640 self.dprint(80, "LEAVE parse_ref=None")
641 return None
642 elif tok.type == 'DELIM':
643 if tok.content == ']':
644 break
645 else:
646 tok = self.parse_inline_delim(tok)
647 if tok:
648 seq.append(tok)
649 else:
650 self.dprint(80, "LEAVE parse_ref=None")
651 return None
652 elif tok.type == 'OTAG':
653 list.append(self.parse_tag(tok))
654 else:
655 seq.append(tok)
656
657 ret = self._new_node(type='REF', ref=ref,
658 content=self._new_node(type='SEQ', content=seq))
659 self.dprint(80, "LEAVE parse_ref= %s", ret)
660 return ret
661
662 def parse_link(self, type, delim):
663 """Parse an external link ([[...]]).
664
665 In this implementation, it is also used to parse template
666 references ({{...}}).
667
668 Arguments:
669
670 type -- 'LINK' or 'TMPL'
671 delim -- expected closing delimiter.
672 """
673 self.dprint(80, "ENTER parse_link(%s,%s)", type, delim)
674 subtree = []
675 list = []
676 while True:
677 tok = self.getkn()
678 if tok.type == 'NIL':
679 self.dprint(80, "LEAVE parse_link=None [EOF]")
680 return None
681 if tok.type == 'DELIM':
682 if tok.content == delim:
683 if list:
684 subtree.append(self._new_node(type='SEQ',
685 content=list))
686 break
687 elif tok.content == "|":
688 if len(list) > 1:
689 subtree.append(self._new_node(type='SEQ',
690 content=list))
691 elif list:
692 subtree.append(list[0])
693 list = []
694 else:
695 x = self.parse_inline_delim(tok)
696 if x:
697 list.append(x)
698 else:
699 self.dprint(80, "LEAVE parse_link=None [bad inline]")
700 return None
701 elif tok.type == 'TEXT':
702 list.append(tok)
703 else:
704 self.dprint(80, "LEAVE parse_link=None [unexpected token]")
705 return None
706 ret = self._new_node(type=type, content=subtree)
707 self.dprint(80, "LEAVE parse_link=%s", ret)
708 return ret
709
710 def parse_inline_delim(self, tok):
711 """Parse an inline block."""
712 self.dprint(80, "ENTER parse_inline_delim")
713 assert(tok.type == 'DELIM')
714 self.push_mark()
715 if tok.content == "''":
716 x = self.parse_fontmod(tok.content, 'IT')
717 elif tok.content == "'''":
718 x = self.parse_fontmod(tok.content, 'BOLD')
719 elif tok.content == "[":
720 x = self.parse_ref()
721 elif tok.content == "[[":
722 x = self.parse_link('LINK', "]]")
723 elif tok.content == "{{":
724 x = self.parse_link('TMPL', "}}")
725 else:
726 x = None
727
728 if x:
729 self.clear_mark()
730 else:
731 self.dprint(80, "BEGIN DELIMITER RECOVERY: %s", tok)
732 self.pop_mark()
733 x = self.fixuptkn(self._new_node(type='TEXT', content=tok.content))
734 od = tok.content
735 if od in self.close_delim:
736 cd = self.close_delim[od]
737 lev = 0
738 for i,tok in enumerate(self.toklist[self.tokind+1:]):
739 if tok.type == 'NIL':
740 break
741 elif tok.type == 'DELIM':
742 if tok.content == od:
743 lev += 1
744 elif tok.content == cd:
745 if lev == 0:
746 tok = self._new_node(type='TEXT',
747 content=tok.content)
748 self.toklist[self.tokind+1+i] = tok
749 lev -= 1
750 break
751 self.dprint(80, "END DELIMITER RECOVERY: %s", tok)
752
753 self.dprint(80, "LEAVE parse_inline_delim=%s", x)
754 return x
755
756 def parse_tag(self, tag):
757 """Parse an xml-like tag (such as, e.g. "<tt>...</tt>")."""
758 self.dprint(80, "ENTER parse_tag")
759 list = []
760 self.push_mark()
761 while True:
762 tok = self.getkn()
763 if tok.type == 'NIL':
764 self.pop_mark()
765 s = '<' + tag.tag
766 if tag.args:
767 s += ' ' + str(tag.args)
768 s += '>'
769 node = self._new_node(type='TEXT',content=s)
770 if tag.content:
771 self.tree[self.tokind:self.tokind] = tag.content
772 self.dprint(80, "LEAVE parse_tag = %s (tree modified)", node)
773 return node
774 elif tok.type == 'DELIM':
775 if tok.isblock:
776 tok = self.parse_block_delim(tok)
777 else:
778 tok = self.parse_inline_delim(tok)
779 if not tok:
780 tok = self.getkn()
781 elif tok.type == 'CTAG':
782 if tag.tag == tok.tag:
783 break
784 s = '</' + tag.tag + '>'
785 tok = self.fixuptkn(self._new_node(type='TEXT', content=s))
786 elif tok.type == 'NL':
787 tok = self._new_node(type = 'TEXT', content = '\n')
788 list.append(tok)
789
790 self.clear_mark()
791 ret = self._new_node(type = 'TAG',
792 tag = tag.tag,
793 args = tag.args,
794 isblock = tag.isblock,
795 content = self._new_node(type = 'SEQ', content = list))
796 self.dprint(80, "LEAVE parse_tag = %s", ret)
797 return ret
798
799 def parse_env(self, tok):
800 """Parse a block environment (numbered, unnumbered, or definition list)."""
801 type = self.envtypes[tok.content[0]][0]
802 lev = len(tok.content)
803 self.dprint(80, "ENTER parse_env(%s,%s)",type,lev)
804 list = []
805 while True:
806 if (tok.type == 'DELIM'
807 and tok.content[0] in self.envtypes
808 and type == self.envtypes[tok.content[0]][0]):
809 if len(tok.content) < lev:
810 self.ungetkn()
811 break
812 elif len(tok.content) > lev:
813 elt = self.parse_env(tok)
814 else:
815 elt = self.parse_line()
816 if not tok.continuation:
817 list.append(self._new_node(type='ELT',
818 subtype=self.envtypes[tok.content[0]][1],
819 content=elt))
820 tok = self.getkn()
821 continue
822
823 if list:
824 if list[-1].content.type != 'SEQ':
825 x = list[-1].content.content
826 # FIXME:
827 list[-1].content = self._new_node(type='SEQ', content=[x])
828 list[-1].content.content.append(elt)
829 else:
830 self.ungetkn()
831 break
832
833 tok = self.getkn()
834
835 ret = self._new_node(type='ENV',
836 envtype=type,
837 level=lev,
838 content=list)
839 self.dprint(80, "LEAVE parse_env=%s", ret)
840 return ret
841
842 def parse_header(self, tok):
843 """Parse a Wiki header."""
844 self.dprint(80, "ENTER parse_header")
845 self.push_mark()
846 list = []
847 delim = tok.content
848 while True:
849 tok = self.getkn()
850 if tok.type == 'NL':
851 self.pop_mark()
852 self.dprint(80, "LEAVE parse_header=None")
853 return None
854 elif tok.type == 'TEXT':
855 list.append(tok)
856 elif tok.type == 'DELIM':
857 if tok.content == delim:
858 if self.lookahead().type == 'NL':
859 self.getkn()
860 if self.lookahead().type == 'NL':
861 self.getkn()
862 break
863 else:
864 self.pop_mark()
865 self.dprint(80, "LEAVE parse_header=None")
866 return None
867 elif tok.isblock:
868 self.pop_mark()
869 self.dprint(80, "LEAVE parse_header=None")
870 return None
871 else:
872 list.append(self.parse_inline_delim(tok))
873 elif tok.type == 'OTAG':
874 if tok.isblock:
875 self.pop_mark()
876 self.dprint(80, "LEAVE parse_header=None")
877 return None
878 list.append(self.parse_tag(tok))
879 self.clear_mark()
880 ret = self._new_node(type='HDR',
881 level=len(delim),
882 content=self._new_node(type='SEQ', content=list))
883 self.dprint(80, "LEAVE parse_header=%s", ret)
884 return ret
885
886 def parse_block(self):
887 """Parse next block: newline, delimiter, tag, or paragraph."""
888 tok = self.getkn()
889 while tok.type == 'NL':
890 tok = self.getkn()
891 if tok == None or tok.type == 'NIL':
892 return None
893 elif tok.type == 'DELIM':
894 tok = self.parse_block_delim(tok)
895 if tok:
896 return tok
897 else:
898 tok = self.getkn()
899 elif tok.type == 'OTAG' and tok.isblock:
900 return self.parse_tag(tok)
901
902 return self.parse_para(tok)
903
904 def parse(self):
905 """Parse Wiki material supplied by the input() method.
906
907 Store the resulting abstract parsing tree in the tree attribute.
908 """
909 if not self.toklist:
910 self.tokenize()
911 if self.debug_level >= 90:
912 print("TOKEN DUMP BEGIN")
913 self.dump(self.toklist)
914 print("TOKEN DUMP END")
915 self.tokind = 0
916 self.tree = []
917 while 1:
918 subtree = self.parse_block()
919 if subtree == None:
920 break
921 self.tree.append(subtree)
922 if self.debug_level >= 70:
923 print("TREE DUMP BEGIN")
924 self.dump(self.tree)
925 print("TREE DUMP END")
926
927 def __str__(self):
928 return str(self.tree)
929
930
931class WikiMarkup(WikiMarkupParser):
932 """
933 A derived parser class that supplies a basic input method.
934
935 Three types of inputs are available:
936
937 1. filename=<file>
938 The file <file> is opened and used for input.
939 2. file=<file>
940 The already opened file <file> is used for input.
941 3. text=<string>
942 Input is taken from <string>, line by line.
943
944 Usage:
945
946 obj = WikiMarkup(arg=val)
947 obj.parse
948 ... Do whatever you need with obj.tree ...
949
950 """
951
952 file = None
953 text = None
954 lang = 'en'
955 html_base = 'http://%(lang)s.wiktionary.org/wiki/'
956 image_base = 'http://upload.wikimedia.org/wikipedia/commons/thumb/a/bf'
957 media_base = 'http://www.mediawiki.org/xml/export-0.3'
958
959 def __init__(self, *args, **keywords):
960 for kw in keywords:
961 if kw == 'file':
962 self.file = keywords[kw]
963 elif kw == 'filename':
964 self.file = open(keywords[kw])
965 elif kw == 'text':
966 self.text = keywords[kw].split("\n")
967 elif kw == 'lang':
968 self.lang = keywords[kw]
969 elif kw == 'html_base':
970 self.html_base = keywords[kw]
971 elif kw == 'image_base':
972 self.image_base = keywords[kw]
973 elif kw == 'media_base':
974 self.media_base = keywords[kw]
975
976 def __del__(self):
977 if self.file:
978 self.file.close()
979
980 def input(self):
981 if self.file:
982 return self.file.readline()
983 elif self.text:
984 return self.text.pop(0) + '\n'
985 else:
986 return None
987
988 # ISO 639
989 langtab = {
990 "aa": "Afar", # Afar
991 "ab": "Аҧсуа", # Abkhazian
992 "ae": None, # Avestan
993 "af": "Afrikaans", # Afrikaans
994 "ak": "Akana", # Akan
995 "als": "Alemannisch",
996 "am": "አማርኛ", # Amharic
997 "an": "Aragonés", # Aragonese
998 "ang": "Englisc",
999 "ar": "العربية" , # Arabic
1000 "arc": "ܐܪܡܝܐ",
1001 "as": "অসমীয়া", # Assamese
1002 "ast": "Asturian",
1003 "av": "Авар", # Avaric
1004 "ay": "Aymara", # Aymara
1005 "az": "Azərbaycan" , # Azerbaijani
1006
1007 "ba": "Башҡорт", # Bashkir
1008 "bar": "Boarisch",
1009 "bat-smg": "Žemaitėška",
1010 "bcl": "Bikol",
1011 "be": "Беларуская", # Byelorussian; Belarusian
1012 "be-x-old": "Беларуская (тарашкевіца)",
1013 "bg": "Български", # Bulgarian
1014 "bh": "भोजपुरी", # Bihari
1015 "bi": "Bislama", # Bislama
1016 "bm": "Bamanankan", # Bambara
1017 "bn": "বাংলা" , # Bengali; Bangla
1018 "bo": "བོད་སྐད", # Tibetan
1019 "bpy": "ইমার ঠার/বিষ্ণুপ্রিয়া মণিপুরী" ,
1020 "br": "Brezhoneg" , # Breton
1021 "bs": "Bosanski" , # Bosnian
1022 "bug": "Basa Ugi",
1023 "bxr": "Буряад",
1024
1025 "ca": "Català" , # Catalan
1026 "cbk-zam": "Chavacano de Zamboanga",
1027 "cdo": "Mìng-dĕ̤ng-ngṳ̄",
1028 "cho": "Choctaw",
1029 "ce": "Нохчийн", # Chechen
1030 "ceb": "Sinugboanong Binisaya" , # Cebuano
1031 "ch": "Chamor", # Chamorro
1032 "chr": "ᏣᎳᎩ",
1033 "chy": "Tsetsêhestâhese",
1034 "co": "Cors", # Corsican
1035 "cr": "Nehiyaw", # Cree
1036 "crh": "Qırımtatarca",
1037 "cs": "Česky" , # Czech
1038 "csb": "Kaszëbsczi",
1039 "c": "Словѣньскъ", # Church Slavic
1040 "cv": "Чăваш", # Chuvash
1041 "cy": "Cymraeg" , # Welsh
1042
1043 "da": "Dansk" , # Danish
1044 "de": "Deutsch" , # German
1045 "diq": "Zazaki", # Dimli (Southern Zazaki)
1046 "dsb": "Dolnoserbski",
1047 "dv": "ދިވެހިބަސް", # Divehi
1048 "dz": "ཇོང་ཁ", # Dzongkha; Bhutani
1049
1050 "ee": "Eʋegbe", # Ewe
1051 "el": "Ελληνικά" , # Greek
1052 "eml": "Emiliàn e rumagnòl",
1053 "en": "English" , # English
1054 "eo": "Esperanto" ,
1055 "es": "Español" , # Spanish
1056 "et": "Eesti" , # Estonian
1057 "eu": "Euskara" , # Basque
1058 "ext": "Estremeñ",
1059
1060 "fa": "فارسی" , # Persian
1061 "ff": "Fulfulde", # Fulah
1062 "fi": "Suomi" , # Finnish
1063 "fiu-vro": "Võro",
1064 "fj": "Na Vosa Vakaviti",# Fijian; Fiji
1065 "fo": "Føroyskt" , # Faroese
1066 "fr": "Français" , # French
1067 "frp": "Arpitan",
1068 "fur": "Furlan",
1069 "fy": "Frysk", # Frisian
1070
1071 "ga": "Gaeilge", # Irish
1072 "gan": "贛語 (Gànyŭ)",
1073 "gd": "Gàidhlig", # Scots; Gaelic
1074 "gl": "Gallego" , # Gallegan; Galician
1075 "glk": "گیلکی",
1076 "got": "𐌲𐌿𐍄𐌹𐍃𐌺𐍉𐍂𐌰𐌶𐌳𐌰",
1077 "gn": "Avañe'ẽ", # Guarani
1078 "g": "ગુજરાતી", # Gujarati
1079 "gv": "Gaelg", # Manx
1080
1081 "ha": "هَوُسَ", # Hausa
1082 "hak": "Hak-kâ-fa / 客家話",
1083 "haw": "Hawai`i",
1084 "he": "עברית" , # Hebrew (formerly iw)
1085 "hi": "हिन्दी" , # Hindi
1086 "hif": "Fiji Hindi",
1087 "ho": "Hiri Mot", # Hiri Motu
1088 "hr": "Hrvatski" , # Croatian
1089 "hsb": "Hornjoserbsce",
1090 "ht": "Krèyol ayisyen" , # Haitian; Haitian Creole
1091 "hu": "Magyar" , # Hungarian
1092 "hy": "Հայերեն", # Armenian
1093 "hz": "Otsiherero", # Herero
1094
1095 "ia": "Interlingua",
1096 "ie": "Interlingue",
1097 "id": "Bahasa Indonesia",# Indonesian (formerly in)
1098 "ig": "Igbo", # Igbo
1099 "ii": "ꆇꉙ ", # Sichuan Yi
1100 "ik": "Iñupiak", # Inupiak
1101 "ilo": "Ilokano",
1102 "io": "Ido" ,
1103 "is": "Íslenska" , # Icelandic
1104 "it": "Italiano" , # Italian
1105 "i": "ᐃᓄᒃᑎᑐᑦ", # Inuktitut
1106
1107 "ja": "日本語", # Japanese
1108 "jbo": "Lojban",
1109 "jv": "Basa Jawa", # Javanese
1110
1111 "ka": "ქართული" , # Georgian
1112 "kaa": "Qaraqalpaqsha",
1113 "kab": "Taqbaylit",
1114 "kg": "KiKongo", # Kongo
1115 "ki": "Gĩkũyũ", # Kikuyu
1116 "kj": "Kuanyama", # Kuanyama
1117 "kk": "Қазақша", # Kazakh
1118 "kl": "Kalaallisut", # Kalaallisut; Greenlandic
1119 "km": "ភាសាខ្មែរ", # Khmer; Cambodian
1120 "kn": "ಕನ್ನಡ", # Kannada
1121 "ko": "한국어" , # Korean
1122 "kr": "Kanuri", # Kanuri
1123 "ks": "कश्मीरी / كشميري", # Kashmiri
1124 "ksh": "Ripoarisch",
1125 "ku": "Kurdî / كوردی", # Kurdish
1126 "kv": "Коми", # Komi
1127 "kw": "Kernewek/Karnuack", # Cornish
1128 "ky": "Кыргызча", # Kirghiz
1129
1130 "la": "Latina" , # Latin
1131 "lad": "Dzhudezmo",
1132 "lb": "Lëtzebuergesch" , # Letzeburgesch
1133 "lbe": "Лакку",
1134 "lg": "Luganda", # Ganda
1135 "li": "Limburgs", # Limburgish; Limburger; Limburgan
1136 "lij": "Lígur",
1137 "ln": "Lingala", # Lingala
1138 "lmo": "Lumbaart",
1139 "lo": "ລາວ", # Lao; Laotian
1140 "lt": "Lietuvių" , # Lithuanian
1141 "lua": "Luba", # Luba
1142 "lv": "Latvieš" , # Latvian; Lettish
1143
1144 "map-bms": "Basa Banyumasan",
1145 "mdf": "Мокшень (Mokshanj Kälj)",
1146 "mg": "Malagasy", # Malagasy
1147 "mh": "Ebon", # Marshall
1148 "mi": "Māori", # Maori
1149 "mk": "Македонски" , # Macedonian
1150 "ml": None, # Malayalam
1151 "mn": "Монгол", # Mongolian
1152 "mo": "Молдовеняскэ", # Moldavian
1153 "mr": "मराठी" , # Marathi
1154 "ms": "Bahasa Melay" , # Malay
1155 "mt": "Malti", # Maltese
1156 "mus": "Muskogee",
1157 "my": "မ္ရန္‌မာစာ", # Burmese
1158 "myv": "Эрзянь (Erzjanj Kelj)",
1159 "mzn": "مَزِروني",
1160
1161 "na": "dorerin Naoero", # Nauru
1162 "nah": "Nāhuatl",
1163 "nap": "Nnapulitano",
1164 "nb": "Norsk (Bokmål)", # Norwegian Bokm@aa{}l
1165 "nd": None, # Ndebele, North
1166 "nds": "Plattdüütsch",
1167 "nds-nl": "Nedersaksisch",
1168 "ne": "नेपाली", # Nepali
1169 "new": "नेपाल भाषा" , # Nepal Bhasa
1170 "ng": "Oshiwambo", # Ndonga
1171 "nl": "Nederlands" , # Dutch
1172 "nn": "Nynorsk", # Norwegian Nynorsk
1173 "no": "Norsk (Bokmål)" , # Norwegian
1174 "nov": "Novial",
1175 "nr": None, # Ndebele, South
1176 "nrm": "Nouormand/Normaund",
1177 "nv": "Diné bizaad", # Navajo
1178 "ny": "Chi-Chewa", # Chichewa; Nyanja
1179
1180 "oc": "Occitan", # Occitan; Proven@,{c}al
1181 "oj": None, # Ojibwa
1182 "om": "Oromoo", # (Afan) Oromo
1183 "or": "ଓଡ଼ିଆ", # Oriya
1184 "os": "Иронау", # Ossetian; Ossetic
1185
1186 "pa": "ਪੰਜਾਬੀ" , # Panjabi; Punjabi
1187 "pag": "Pangasinan",
1188 "pam": "Kapampangan",
1189 "pap": "Papiament",
1190 "pdc": "Deitsch",
1191 "pi": "पाऴि", # Pali
1192 "pih": "Norfuk",
1193 "pl": "Polski" , # Polish
1194 "pms": "Piemontèis" ,
1195 "ps": "پښتو", # Pashto, Pushto
1196 "pt": "Português" , # Portuguese
1197
1198 "q": "Runa Simi" , # Quechua
1199
1200 "rm": "Rumantsch", # Rhaeto-Romance
1201 "rmy": "romani - रोमानी",
1202 "rn": "Kirundi", # Rundi; Kirundi
1203 "ro": "Română" , # Romanian
1204 "roa-rup": "Armãneashce",
1205 "roa-tara": "Tarandíne",
1206 "ru": "Русский" , # Russian
1207 "rw": "Ikinyarwanda", # Kinyarwanda
1208
1209 "sa": "संस्कृतम्", # Sanskrit
1210 "sah": "Саха тыла (Saxa Tyla)",
1211 "sc": "Sardu", # Sardinian
1212 "scn": "Sicilian",
1213 "sco": "Scots",
1214 "sd": "سنڌي، سندھی ، सिन्ध", # Sindhi
1215 "se": "Sámegiella", # Northern Sami
1216 "sg": "Sängö", # Sango; Sangro
1217 "sh": "Srpskohrvatski / Српскохрватски" ,
1218 "si": "සිංහල",
1219 "simple": "Simple English" ,
1220 "sk": "Slovenčina" , # Slovak
1221 "sl": "Slovenščina" , # Slovenian
1222 "sm": "Gagana Samoa", # Samoan
1223 "sn": "chiShona", # Shona
1224 "so": "Soomaaliga", # Somali
1225 "sr": "Српски / Srpski", # Serbian
1226 "srn": "Sranantongo",
1227 "ss": "SiSwati", # Swati; Siswati
1228 "st": "Sesotho", # Sesotho; Sotho, Southern
1229 "stk": "Seeltersk",
1230 "s": "Basa Sunda", # Sundanese
1231 "sq": "Shqip" , # Albanian
1232 "szl": "Ślůnski",
1233 "sv": "Svenska" , # Swedish
1234 "sw": "Kiswahili", # Swahili
1235
1236 "ta": "தமிழ்" , # Tamil
1237 "te": "తెలుగు" , # Telugu
1238 "tet": "Tetun",
1239 "tg": "Тоҷикӣ", # Tajik
1240 "th": "ไทย" , # Thai
1241 "ti": "ትግርኛ", # Tigrinya
1242 "tk": "تركمن / Туркмен", # Turkmen
1243 "tl": "Tagalog" , # Tagalog
1244 "tn": "Setswana", # Tswana; Setswana
1245 "to": "faka Tonga", # Tonga (?) # Also ZW ; MW
1246 "tokipona": "Tokipona",
1247 "tpi": "Tok Pisin",
1248 "tr": "Türkçe" , # Turkish
1249 "ts": "Xitsonga", # Tsonga
1250 "tt": "Tatarça / Татарча", # Tatar
1251 "tum": "chiTumbuka",
1252 "tw": "Twi", # Twi
1253 "ty": "Reo Mā`ohi", # Tahitian
1254
1255 "udm": "Удмурт кыл",
1256 "ug": "Oyghurque", # Uighur
1257 "uk": "Українська" , # Ukrainian
1258 "ur": "اردو", # Urdu
1259 "uz": "O‘zbek", # Uzbek
1260
1261 "ve": "Tshivenda", # Venda
1262 "vec": "Vèneto",
1263 "vi": "Tiếng Việt" , # Vietnamese
1264 "vls": "West-Vlams",
1265 "vo": "Volapük" ,
1266
1267 "wa": "Walon", # Walloon
1268 "war": "Winaray",
1269 "wo": "Wolof", # Wolof
1270 "w": "吴语",
1271
1272 "xal": "Хальмг",
1273 "xh": "isiXhosa", # Xhosa
1274
1275 "yi": "ייִדיש", # Yiddish
1276 "yo": "Yorùbá", # Yoruba
1277
1278 "za": "Cuengh", # Zhuang
1279 "zea": "Zeêuws",
1280 "zh": "中文" , # Chinese
1281 "zh-classical": "古文 / 文言文",
1282 "zm-min-nan": "Bân-lâm-gú",
1283 "zh-yue": "粵語",
1284 "zu": "isiZulu" # Zulu
1285 }
diff --git a/wikitrans/wikins.py b/wikitrans/wikins.py
new file mode 100644
index 0000000..4fb5315
--- a/dev/null
+++ b/wikitrans/wikins.py
@@ -0,0 +1,3040 @@
1# This file is generated automatically. Do not edit.
2# -*- coding: utf-8 -*-
3wiki_ns_io = {
4 "Media": "NS_MEDIA",
5 "Specala": "NS_SPECIAL",
6 "Debato": "NS_TALK",
7 "Uzanto": "NS_USER",
8 "Uzanto_Debato": "NS_USER_TALK",
9 "Imajo": "NS_IMAGE",
10 "Imajo_Debato": "NS_IMAGE_TALK",
11 "MediaWiki": "NS_MEDIAWIKI",
12 "MediaWiki_Debato": "NS_MEDIAWIKI_TALK",
13 "Shablono": "NS_TEMPLATE",
14 "Shablono_Debato": "NS_TEMPLATE_TALK",
15 "Helpo": "NS_HELP",
16 "Helpo_Debato": "NS_HELP_TALK",
17 "Kategorio": "NS_CATEGORY",
18 "Kategorio_Debato": "NS_CATEGORY_TALK",
19}
20wiki_ns_re_io = [
21 ("", "_Debato", "NS_PROJECT_TALK"),
22]
23wiki_ns_et = {
24 "Meedia": "NS_MEDIA",
25 "Eri": "NS_SPECIAL",
26 "Arutelu": "NS_TALK",
27 "Kasutaja": "NS_USER",
28 "Kasutaja_arutelu": "NS_USER_TALK",
29 "Pilt": "NS_IMAGE",
30 "Pildi_arutelu": "NS_IMAGE_TALK",
31 "MediaWiki": "NS_MEDIAWIKI",
32 "MediaWiki_arutelu": "NS_MEDIAWIKI_TALK",
33 "Mall": "NS_TEMPLATE",
34 "Malli_arutelu": "NS_TEMPLATE_TALK",
35 "Juhend": "NS_HELP",
36 "Juhendi_arutelu": "NS_HELP_TALK",
37 "Kategooria": "NS_CATEGORY",
38 "Kategooria_arutelu": "NS_CATEGORY_TALK",
39}
40wiki_ns_re_et = [
41 ("", "_arutelu", "NS_PROJECT_TALK"),
42]
43wiki_ns_is = {
44 "Miðill": "NS_MEDIA",
45 "Kerfissíða": "NS_SPECIAL",
46 "Spjall": "NS_TALK",
47 "Notandi": "NS_USER",
48 "Notandaspjall": "NS_USER_TALK",
49 "Mynd": "NS_IMAGE",
50 "Myndaspjall": "NS_IMAGE_TALK",
51 "Melding": "NS_MEDIAWIKI",
52 "Meldingarspjall": "NS_MEDIAWIKI_TALK",
53 "Snið": "NS_TEMPLATE",
54 "Sniðaspjall": "NS_TEMPLATE_TALK",
55 "Hjálp": "NS_HELP",
56 "Hjálparspjall": "NS_HELP_TALK",
57 "Flokkur": "NS_CATEGORY",
58 "Flokkaspjall": "NS_CATEGORY_TALK",
59}
60wiki_ns_re_is = [
61 ("", "spjall", "NS_PROJECT_TALK"),
62]
63wiki_ns_mr = {
64 "मिडिया": "NS_MEDIA",
65 "विशेष": "NS_SPECIAL",
66 "चर्चा": "NS_TALK",
67 "सदस्य": "NS_USER",
68 "सदस्य_चर्चा": "NS_USER_TALK",
69 "चित्र": "NS_IMAGE",
70 "चित्र_चर्चा": "NS_IMAGE_TALK",
71 "मिडियाविकी": "NS_MEDIAWIKI",
72 "मिडियाविकी_चर्चा": "NS_MEDIAWIKI_TALK",
73 "साचा": "NS_TEMPLATE",
74 "साचा_चर्चा": "NS_TEMPLATE_TALK",
75 "साहाय्य": "NS_HELP",
76 "साहाय्य_चर्चा": "NS_HELP_TALK",
77 "वर्ग": "NS_CATEGORY",
78 "वर्ग_चर्चा": "NS_CATEGORY_TALK",
79}
80wiki_ns_re_mr = [
81 ("", "_चर्चा", "NS_PROJECT_TALK"),
82]
83wiki_ns_tyv = {
84 "Медиа": "NS_MEDIA",
85 "Тускай": "NS_SPECIAL",
86 "Чугаа": "NS_TALK",
87 "Aжыглакчы": "NS_USER",
88 "Aжыглакчы_чугаа": "NS_USER_TALK",
89 "Чурук": "NS_IMAGE",
90 "Чурук_чугаа": "NS_IMAGE_TALK",
91 "МедиаВики": "NS_MEDIAWIKI",
92 "МедиаВики_чугаа": "NS_MEDIAWIKI_TALK",
93 "Хээ": "NS_TEMPLATE",
94 "Хээ_чугаа": "NS_TEMPLATE_TALK",
95 "Дуза": "NS_HELP",
96 "Дуза_чугаа": "NS_HELP_TALK",
97 "Бөлүк": "NS_CATEGORY",
98 "Бөлүк_чугаа": "NS_CATEGORY_TALK",
99}
100wiki_ns_re_tyv = [
101 ("", "_чугаа", "NS_PROJECT_TALK"),
102]
103wiki_ns_qu = {
104 "Midya": "NS_MEDIA",
105 "Sapaq": "NS_SPECIAL",
106 "Rimanakuy": "NS_TALK",
107 "Ruraq": "NS_USER",
108 "Ruraq_rimanakuy": "NS_USER_TALK",
109 "Rikcha": "NS_IMAGE",
110 "Rikcha_rimanakuy": "NS_IMAGE_TALK",
111 "MediaWiki": "NS_MEDIAWIKI",
112 "MediaWiki_rimanakuy": "NS_MEDIAWIKI_TALK",
113 "Plantilla": "NS_TEMPLATE",
114 "Plantilla_rimanakuy": "NS_TEMPLATE_TALK",
115 "Yanapa": "NS_HELP",
116 "Yanapa_rimanakuy": "NS_HELP_TALK",
117 "Katiguriya": "NS_CATEGORY",
118 "Katiguriya_rimanakuy": "NS_CATEGORY_TALK",
119}
120wiki_ns_re_qu = [
121 ("", "_rimanakuy", "NS_PROJECT_TALK"),
122]
123wiki_ns_frp = {
124 "Mèdia": "NS_MEDIA",
125 "Spèciâl": "NS_SPECIAL",
126 "Discutar": "NS_TALK",
127 "Utilisator": "NS_USER",
128 "Discussion_Utilisator": "NS_USER_TALK",
129 "Émâge": "NS_IMAGE",
130 "Discussion_Émâge": "NS_IMAGE_TALK",
131 "MediaWiki": "NS_MEDIAWIKI",
132 "Discussion_MediaWiki": "NS_MEDIAWIKI_TALK",
133 "Modèlo": "NS_TEMPLATE",
134 "Discussion_Modèlo": "NS_TEMPLATE_TALK",
135 "Éde": "NS_HELP",
136 "Discussion_Éde": "NS_HELP_TALK",
137 "Catègorie": "NS_CATEGORY",
138 "Discussion_Catègorie": "NS_CATEGORY_TALK",
139}
140wiki_ns_re_frp = [
141 ("Discussion_", "", "NS_PROJECT_TALK"),
142]
143wiki_ns_kab = {
144 "Media": "NS_MEDIA",
145 "Uslig": "NS_SPECIAL",
146 "Mmeslay": "NS_TALK",
147 "Amseqdac": "NS_USER",
148 "Amyannan_umsqedac": "NS_USER_TALK",
149 "Tugna": "NS_IMAGE",
150 "Amyannan_n_tugna": "NS_IMAGE_TALK",
151 "MediaWiki": "NS_MEDIAWIKI",
152 "Amyannan_n_MediaWiki": "NS_MEDIAWIKI_TALK",
153 "Talɣa": "NS_TEMPLATE",
154 "Amyannan_n_talɣa": "NS_TEMPLATE_TALK",
155 "Tallat": "NS_HELP",
156 "Amyannan_n_tallat": "NS_HELP_TALK",
157 "Taggayt": "NS_CATEGORY",
158 "Amyannan_n_taggayt": "NS_CATEGORY_TALK",
159}
160wiki_ns_re_kab = [
161 ("Amyannan_n_", "", "NS_PROJECT_TALK"),
162]
163wiki_ns_fo = {
164 "Miðil": "NS_MEDIA",
165 "Serstakur": "NS_SPECIAL",
166 "Kjak": "NS_TALK",
167 "Brúkari": "NS_USER",
168 "Brúkari_kjak": "NS_USER_TALK",
169 "Mynd": "NS_IMAGE",
170 "Mynd_kjak": "NS_IMAGE_TALK",
171 "MidiaWiki": "NS_MEDIAWIKI",
172 "MidiaWiki_kjak": "NS_MEDIAWIKI_TALK",
173 "Fyrimynd": "NS_TEMPLATE",
174 "Fyrimynd_kjak": "NS_TEMPLATE_TALK",
175 "Hjálp": "NS_HELP",
176 "Hjálp kjak": "NS_HELP_TALK",
177 "Bólkur": "NS_CATEGORY",
178 "Bólkur_kjak": "NS_CATEGORY_TALK",
179}
180wiki_ns_re_fo = [
181 ("", "_kjak", "NS_PROJECT_TALK"),
182]
183wiki_ns_pt_br = {
184 "Media": "NS_MEDIA",
185 "Especial": "NS_SPECIAL",
186 "Discussão": "NS_TALK",
187 "Usuário": "NS_USER",
188 "Usuário_Discussão": "NS_USER_TALK",
189 "Imagem": "NS_IMAGE",
190 "Imagem_Discussão": "NS_IMAGE_TALK",
191 "MediaWiki": "NS_MEDIAWIKI",
192 "MediaWiki_Discussão": "NS_MEDIAWIKI_TALK",
193 "Predefinição": "NS_TEMPLATE",
194 "Predefinição_Discussão": "NS_TEMPLATE_TALK",
195 "Ajuda": "NS_HELP",
196 "Ajuda_Discussão": "NS_HELP_TALK",
197 "Categoria": "NS_CATEGORY",
198 "Categoria_Discussão": "NS_CATEGORY_TALK",
199}
200wiki_ns_re_pt_br = [
201 ("", "_Discussão", "NS_PROJECT_TALK"),
202]
203wiki_ns_dsb = {
204 "Medija": "NS_MEDIA",
205 "Specialne": "NS_SPECIAL",
206 "Diskusija": "NS_TALK",
207 "Wužywaŕ": "NS_USER",
208 "Diskusija_wužywarja": "NS_USER_TALK",
209 "Wobraz": "NS_IMAGE",
210 "Diskusija_wó_wobrazu": "NS_IMAGE_TALK",
211 "MediaWiki": "NS_MEDIAWIKI",
212 "MediaWiki_diskusija": "NS_MEDIAWIKI_TALK",
213 "Pśedłoga": "NS_TEMPLATE",
214 "Diskusija_wó_pśedłoze": "NS_TEMPLATE_TALK",
215 "Pomoc": "NS_HELP",
216 "Diskusija_wó_pomocy": "NS_HELP_TALK",
217 "Kategorija": "NS_CATEGORY",
218 "Diskusija_wó_kategoriji": "NS_CATEGORY_TALK",
219}
220wiki_ns_re_dsb = [
221 ("", "_diskusija", "NS_PROJECT_TALK"),
222]
223wiki_ns_jv = {
224 "Media": "NS_MEDIA",
225 "Astamiwa": "NS_SPECIAL",
226 "Dhiskusi": "NS_TALK",
227 "Panganggo": "NS_USER",
228 "Dhiskusi_Panganggo": "NS_USER_TALK",
229 "Gambar": "NS_IMAGE",
230 "Dhiskusi_Gambar": "NS_IMAGE_TALK",
231 "MediaWiki": "NS_MEDIAWIKI",
232 "Dhiskusi_MediaWiki": "NS_MEDIAWIKI_TALK",
233 "Cithakan": "NS_TEMPLATE",
234 "Dhiskusi_Cithakan": "NS_TEMPLATE_TALK",
235 "Pitulung": "NS_HELP",
236 "Dhiskusi_Pitulung": "NS_HELP_TALK",
237 "Kategori": "NS_CATEGORY",
238 "Dhiskusi_Kategori": "NS_CATEGORY_TALK",
239}
240wiki_ns_re_jv = [
241 ("Dhiskusi_", "", "NS_PROJECT_TALK"),
242]
243wiki_ns_vo = {
244 "Nünamakanäd": "NS_MEDIA",
245 "Patikos": "NS_SPECIAL",
246 "Bespik": "NS_TALK",
247 "Geban": "NS_USER",
248 "Gebanibespik": "NS_USER_TALK",
249 "Magod": "NS_IMAGE",
250 "Magodibespik": "NS_IMAGE_TALK",
251 "Sitanuns": "NS_MEDIAWIKI",
252 "Bespik_dö_sitanuns": "NS_MEDIAWIKI_TALK",
253 "Samafomot": "NS_TEMPLATE",
254 "Samafomotibespik": "NS_TEMPLATE_TALK",
255 "Yuf": "NS_HELP",
256 "Yufibespik": "NS_HELP_TALK",
257 "Klad": "NS_CATEGORY",
258 "Kladibespik": "NS_CATEGORY_TALK",
259}
260wiki_ns_re_vo = [
261 ("Bespik_dö_", "", "NS_PROJECT_TALK"),
262]
263wiki_ns_ka = {
264 "მედია": "NS_MEDIA",
265 "სპეციალური": "NS_SPECIAL",
266 "განხილვა": "NS_TALK",
267 "მომხმარებელი": "NS_USER",
268 "მომხმარებელი_განხილვა": "NS_USER_TALK",
269 "სურათი": "NS_IMAGE",
270 "სურათი_განხილვა": "NS_IMAGE_TALK",
271 "მედიავიკი": "NS_MEDIAWIKI",
272 "მედიავიკი_განხილვა": "NS_MEDIAWIKI_TALK",
273 "თარგი": "NS_TEMPLATE",
274 "თარგი_განხილვა": "NS_TEMPLATE_TALK",
275 "დახმარება": "NS_HELP",
276 "დახმარება_განხილვა": "NS_HELP_TALK",
277 "კატეგორია": "NS_CATEGORY",
278 "კატეგორია_განხილვა": "NS_CATEGORY_TALK",
279}
280wiki_ns_re_ka = [
281 ("", "_განხილვა", "NS_PROJECT_TALK"),
282]
283wiki_ns_gn = {
284 "Mba'echĩchĩ": "NS_SPECIAL",
285 "Myangekõi": "NS_TALK",
286 "Puruhára": "NS_USER",
287 "Puruhára_myangekõi": "NS_USER_TALK",
288 "Ta'ãnga": "NS_IMAGE",
289 "Ta'ãnga_myangekõi": "NS_IMAGE_TALK",
290 "MediaWiki": "NS_MEDIAWIKI",
291 "MediaWiki_myangekõi": "NS_MEDIAWIKI_TALK",
292 "Tembiecharã": "NS_TEMPLATE",
293 "Tembiecharã_myangekõi": "NS_TEMPLATE_TALK",
294 "Pytyvõ": "NS_HELP",
295 "Pytyvõ_myangekõi": "NS_HELP_TALK",
296 "Ñemohenda": "NS_CATEGORY",
297 "Ñemohenda_myangekõi": "NS_CATEGORY_TALK",
298}
299wiki_ns_re_gn = [
300 ("", "_myangekõi", "NS_PROJECT_TALK"),
301]
302wiki_ns_sr_el = {
303 "Medija": "NS_MEDIA",
304 "Posebno": "NS_SPECIAL",
305 "Razgovor": "NS_TALK",
306 "Korisnik": "NS_USER",
307 "Razgovor_sa_korisnikom": "NS_USER_TALK",
308 "Slika": "NS_IMAGE",
309 "Razgovor_o_slici": "NS_IMAGE_TALK",
310 "MedijaViki": "NS_MEDIAWIKI",
311 "Razgovor_o_MedijaVikiju": "NS_MEDIAWIKI_TALK",
312 "Šablon": "NS_TEMPLATE",
313 "Razgovor_o_šablonu": "NS_TEMPLATE_TALK",
314 "Pomoć": "NS_HELP",
315 "Razgovor_o_pomoći": "NS_HELP_TALK",
316 "Kategorija": "NS_CATEGORY",
317 "Razgovor_o_kategoriji": "NS_CATEGORY_TALK",
318}
319wiki_ns_re_sr_el = [
320 ("Razgovor_o_", "", "NS_PROJECT_TALK"),
321]
322wiki_ns_cs = {
323 "Média": "NS_MEDIA",
324 "Speciální": "NS_SPECIAL",
325 "Diskuse": "NS_TALK",
326 "Uživatel": "NS_USER",
327 "Uživatel_diskuse": "NS_USER_TALK",
328 "Soubor": "NS_IMAGE",
329 "Soubor_diskuse": "NS_IMAGE_TALK",
330 "MediaWiki": "NS_MEDIAWIKI",
331 "MediaWiki_diskuse": "NS_MEDIAWIKI_TALK",
332 "Šablona": "NS_TEMPLATE",
333 "Šablona_diskuse": "NS_TEMPLATE_TALK",
334 "Nápověda": "NS_HELP",
335 "Nápověda_diskuse": "NS_HELP_TALK",
336 "Kategorie": "NS_CATEGORY",
337 "Kategorie_diskuse": "NS_CATEGORY_TALK",
338}
339wiki_ns_re_cs = [
340 ("", "_diskuse", "NS_PROJECT_TALK"),
341]
342wiki_ns_sc = {
343 "Speciale": "NS_SPECIAL",
344 "Contièndha": "NS_TALK",
345 "Utente": "NS_USER",
346 "Utente_discussioni": "NS_USER_TALK",
347 "Immàgini": "NS_IMAGE",
348 "Immàgini_contièndha": "NS_IMAGE_TALK",
349}
350wiki_ns_re_sc = [
351 ("", "_discussioni", "NS_PROJECT_TALK"),
352]
353wiki_ns_km = {
354 "មេឌា": "NS_MEDIA",
355 "ពិសេស": "NS_SPECIAL",
356 "ការពិភាក្សា": "NS_TALK",
357 "អ្នកប្រើប្រាស់": "NS_USER",
358 "ការពិភាក្សារបស់អ្នកប្រើប្រាស់": "NS_USER_TALK",
359 "រូបភាព": "NS_IMAGE",
360 "ការពិភាក្សាអំពីរូបភាព": "NS_IMAGE_TALK",
361 "មេឌាវិគី": "NS_MEDIAWIKI",
362 "ការពិភាក្សាអំពីមេឌាវិគី": "NS_MEDIAWIKI_TALK",
363 "ទំព័រគំរូ": "NS_TEMPLATE",
364 "ការពិភាក្សាអំពីទំព័រគំរូ": "NS_TEMPLATE_TALK",
365 "ជំនួយ": "NS_HELP",
366 "ការពិភាក្សាអំពីជំនួយ": "NS_HELP_TALK",
367 "ចំណាត់ថ្នាក់ក្រុម": "NS_CATEGORY",
368 "ការពិភាក្សាអំពីចំណាត់ថ្នាក់ក្រុម": "NS_CATEGORY_TALK",
369}
370wiki_ns_re_km = [
371 ("ការពិភាក្សាអំពី", "", "NS_PROJECT_TALK"),
372]
373wiki_ns_sk = {
374 "Médiá": "NS_MEDIA",
375 "Špeciálne": "NS_SPECIAL",
376 "Diskusia": "NS_TALK",
377 "Redaktor": "NS_USER",
378 "Diskusia_s_redaktorom": "NS_USER_TALK",
379 "Obrázok": "NS_IMAGE",
380 "Diskusia_k_obrázku": "NS_IMAGE_TALK",
381 "MediaWiki": "NS_MEDIAWIKI",
382 "Diskusia_k_MediaWiki": "NS_MEDIAWIKI_TALK",
383 "Šablóna": "NS_TEMPLATE",
384 "Diskusia_k_šablóne": "NS_TEMPLATE_TALK",
385 "Pomoc": "NS_HELP",
386 "Diskusia_k_pomoci": "NS_HELP_TALK",
387 "Kategória": "NS_CATEGORY",
388 "Diskusia_ku_kategórii": "NS_CATEGORY_TALK",
389}
390wiki_ns_re_sk = [
391 ("Diskusia_k_{{grammar:datív|", "}}", "NS_PROJECT_TALK"),
392]
393wiki_ns_bpy = {
394 "মিডিয়া": "NS_MEDIA",
395 "বিশেষ": "NS_SPECIAL",
396 "য়্যারী": "NS_TALK",
397 "আতাকুরা": "NS_USER",
398 "আতাকুরার_য়্যারী": "NS_USER_TALK",
399 "ছবি": "NS_IMAGE",
400 "ছবি_য়্যারী": "NS_IMAGE_TALK",
401 "মিডিয়াউইকি": "NS_MEDIAWIKI",
402 "মিডিয়াউইকির_য়্যারী": "NS_MEDIAWIKI_TALK",
403 "মডেল": "NS_TEMPLATE",
404 "মডেলর_য়্যারী": "NS_TEMPLATE_TALK",
405 "পাংলাক": "NS_HELP",
406 "পাংলাকর_য়্যারী": "NS_HELP_TALK",
407 "থাক": "NS_CATEGORY",
408 "থাকর_য়্যারী": "NS_CATEGORY_TALK",
409}
410wiki_ns_re_bpy = [
411 ("", "_য়্যারী", "NS_PROJECT_TALK"),
412]
413wiki_ns_he = {
414 "מדיה": "NS_MEDIA",
415 "מיוחד": "NS_SPECIAL",
416 "שיחה": "NS_TALK",
417 "משתמש": "NS_USER",
418 "שיחת_משתמש": "NS_USER_TALK",
419 "תמונה": "NS_IMAGE",
420 "שיחת_תמונה": "NS_IMAGE_TALK",
421 "מדיה_ויקי": "NS_MEDIAWIKI",
422 "שיחת_מדיה_ויקי": "NS_MEDIAWIKI_TALK",
423 "תבנית": "NS_TEMPLATE",
424 "שיחת_תבנית": "NS_TEMPLATE_TALK",
425 "עזרה": "NS_HELP",
426 "שיחת_עזרה": "NS_HELP_TALK",
427 "קטגוריה": "NS_CATEGORY",
428 "שיחת_קטגוריה": "NS_CATEGORY_TALK",
429}
430wiki_ns_re_he = [
431 ("שיחת_", "", "NS_PROJECT_TALK"),
432]
433wiki_ns_hi = {
434 "Media": "NS_MEDIA",
435 "विशेष": "NS_SPECIAL",
436 "वार्ता": "NS_TALK",
437 "सदस्य": "NS_USER",
438 "सदस्य_वार्ता": "NS_USER_TALK",
439 "चित्र": "NS_IMAGE",
440 "चित्र_वार्ता": "NS_IMAGE_TALK",
441 "MediaWiki": "NS_MEDIAWIKI",
442 "MediaWiki_talk": "NS_MEDIAWIKI_TALK",
443 "साँचा": "NS_TEMPLATE",
444 "साँचा_वार्ता": "NS_TEMPLATE_TALK",
445 "श्रेणी": "NS_CATEGORY",
446 "श्रेणी_वार्ता": "NS_CATEGORY_TALK",
447}
448wiki_ns_re_hi = [
449 ("", "_वार्ता", "NS_PROJECT_TALK"),
450]
451wiki_ns_hu = {
452 "Média": "NS_MEDIA",
453 "Speciális": "NS_SPECIAL",
454 "Vita": "NS_TALK",
455 "Szerkesztő": "NS_USER",
456 "Szerkesztővita": "NS_USER_TALK",
457 "Kép": "NS_IMAGE",
458 "Képvita": "NS_IMAGE_TALK",
459 "MediaWiki": "NS_MEDIAWIKI",
460 "MediaWiki-vita": "NS_MEDIAWIKI_TALK",
461 "Sablon": "NS_TEMPLATE",
462 "Sablonvita": "NS_TEMPLATE_TALK",
463 "Segítség": "NS_HELP",
464 "Segítségvita": "NS_HELP_TALK",
465 "Kategória": "NS_CATEGORY",
466 "Kategóriavita": "NS_CATEGORY_TALK",
467}
468wiki_ns_re_hu = [
469 ("", "-vita", "NS_PROJECT_TALK"),
470]
471wiki_ns_lt = {
472 "Medija": "NS_MEDIA",
473 "Specialus": "NS_SPECIAL",
474 "Aptarimas": "NS_TALK",
475 "Naudotojas": "NS_USER",
476 "Naudotojo_aptarimas": "NS_USER_TALK",
477 "Vaizdas": "NS_IMAGE",
478 "Vaizdo_aptarimas": "NS_IMAGE_TALK",
479 "MediaWiki": "NS_MEDIAWIKI",
480 "MediaWiki_aptarimas": "NS_MEDIAWIKI_TALK",
481 "Šablonas": "NS_TEMPLATE",
482 "Šablono_aptarimas": "NS_TEMPLATE_TALK",
483 "Pagalba": "NS_HELP",
484 "Pagalbos_aptarimas": "NS_HELP_TALK",
485 "Kategorija": "NS_CATEGORY",
486 "Kategorijos_aptarimas": "NS_CATEGORY_TALK",
487}
488wiki_ns_re_lt = [
489 ("", "_aptarimas", "NS_PROJECT_TALK"),
490]
491wiki_ns_hy = {
492 "Մեդիա": "NS_MEDIA",
493 "Սպասարկող": "NS_SPECIAL",
494 "Քննարկում": "NS_TALK",
495 "Մասնակից": "NS_USER",
496 "Մասնակցի_քննարկում": "NS_USER_TALK",
497 "Պատկեր": "NS_IMAGE",
498 "Պատկերի_քննարկում": "NS_IMAGE_TALK",
499 "MediaWiki": "NS_MEDIAWIKI",
500 "MediaWiki_քննարկում": "NS_MEDIAWIKI_TALK",
501 "Կաղապար": "NS_TEMPLATE",
502 "Կաղապարի_քննարկում": "NS_TEMPLATE_TALK",
503 "Օգնություն": "NS_HELP",
504 "Օգնության_քննարկում": "NS_HELP_TALK",
505 "Կատեգորիա": "NS_CATEGORY",
506 "Կատեգորիայի_քննարկում": "NS_CATEGORY_TALK",
507}
508wiki_ns_re_hy = [
509 ("{{GRAMMAR:genitive|", "}}_քննարկում", "NS_PROJECT_TALK"),
510]
511wiki_ns_ps = {
512 "رسنۍ": "NS_MEDIA",
513 "ځانګړی": "NS_SPECIAL",
514 "خبرې_اترې": "NS_TALK",
515 "کارونکی": "NS_USER",
516 "د_کارونکي_خبرې_اترې": "NS_USER_TALK",
517 "انځور": "NS_IMAGE",
518 "د_انځور_خبرې_اترې": "NS_IMAGE_TALK",
519 "ميډياويکي": "NS_MEDIAWIKI",
520 "د_ميډياويکي_خبرې_اترې": "NS_MEDIAWIKI_TALK",
521 "کينډۍ": "NS_TEMPLATE",
522 "د_کينډۍ_خبرې_اترې": "NS_TEMPLATE_TALK",
523 "لارښود": "NS_HELP",
524 "د_لارښود_خبرې_اترې": "NS_HELP_TALK",
525 "وېشنيزه": "NS_CATEGORY",
526 "د_وېشنيزې_خبرې_اترې": "NS_CATEGORY_TALK",
527}
528wiki_ns_re_ps = [
529 ("د_", "_خبرې_اترې", "NS_PROJECT_TALK"),
530]
531wiki_ns_ksh = {
532 "Medie": "NS_MEDIA",
533 "Spezial": "NS_SPECIAL",
534 "Klaaf": "NS_TALK",
535 "Metmaacher": "NS_USER",
536 "Metmaacher_Klaaf": "NS_USER_TALK",
537 "Beld": "NS_IMAGE",
538 "Belder_Klaaf": "NS_IMAGE_TALK",
539 "MediaWiki": "NS_MEDIAWIKI",
540 "MediaWiki_Klaaf": "NS_MEDIAWIKI_TALK",
541 "Schablon": "NS_TEMPLATE",
542 "Schablone_Klaaf": "NS_TEMPLATE_TALK",
543 "Hölp": "NS_HELP",
544 "Hölp_Klaaf": "NS_HELP_TALK",
545 "Saachjrupp": "NS_CATEGORY",
546 "Saachjrupp_Klaaf": "NS_CATEGORY_TALK",
547}
548wiki_ns_re_ksh = [
549 ("", "_Klaaf", "NS_PROJECT_TALK"),
550]
551wiki_ns_tr = {
552 "Media": "NS_MEDIA",
553 "Özel": "NS_SPECIAL",
554 "Tartışma": "NS_TALK",
555 "Kullanıcı": "NS_USER",
556 "Kullanıcı_mesaj": "NS_USER_TALK",
557 "Resim": "NS_IMAGE",
558 "Resim_tartışma": "NS_IMAGE_TALK",
559 "MedyaViki": "NS_MEDIAWIKI",
560 "MedyaViki_tartışma": "NS_MEDIAWIKI_TALK",
561 "Şablon": "NS_TEMPLATE",
562 "Şablon_tartışma": "NS_TEMPLATE_TALK",
563 "Yardım": "NS_HELP",
564 "Yardım_tartışma": "NS_HELP_TALK",
565 "Kategori": "NS_CATEGORY",
566 "Kategori_tartışma": "NS_CATEGORY_TALK",
567}
568wiki_ns_re_tr = [
569 ("", "_tartışma", "NS_PROJECT_TALK"),
570]
571wiki_ns_af = {
572 "Media": "NS_MEDIA",
573 "Spesiaal": "NS_SPECIAL",
574 "Bespreking": "NS_TALK",
575 "Gebruiker": "NS_USER",
576 "Gebruikerbespreking": "NS_USER_TALK",
577 "Beeld": "NS_IMAGE",
578 "Beeldbespreking": "NS_IMAGE_TALK",
579 "MediaWiki": "NS_MEDIAWIKI",
580 "MediaWikibespreking": "NS_MEDIAWIKI_TALK",
581 "Sjabloon": "NS_TEMPLATE",
582 "Sjabloonbespreking": "NS_TEMPLATE_TALK",
583 "Hulp": "NS_HELP",
584 "Hulpbespreking": "NS_HELP_TALK",
585 "Kategorie": "NS_CATEGORY",
586 "Kategoriebespreking": "NS_CATEGORY_TALK",
587}
588wiki_ns_re_af = [
589 ("", "bespreking", "NS_PROJECT_TALK"),
590]
591wiki_ns_zh_hans = {
592 "Media": "NS_MEDIA",
593 "Special": "NS_SPECIAL",
594 "Talk": "NS_TALK",
595 "User": "NS_USER",
596 "User_talk": "NS_USER_TALK",
597 "Image": "NS_IMAGE",
598 "Image_talk": "NS_IMAGE_TALK",
599 "MediaWiki": "NS_MEDIAWIKI",
600 "MediaWiki_talk": "NS_MEDIAWIKI_TALK",
601 "Template": "NS_TEMPLATE",
602 "Template_talk": "NS_TEMPLATE_TALK",
603 "Help": "NS_HELP",
604 "Help_talk": "NS_HELP_TALK",
605 "Category": "NS_CATEGORY",
606 "Category_talk": "NS_CATEGORY_TALK",
607}
608wiki_ns_re_zh_hans = [
609 ("", "_talk", "NS_PROJECT_TALK"),
610]
611wiki_ns_id = {
612 "Media": "NS_MEDIA",
613 "Istimewa": "NS_SPECIAL",
614 "Pembicaraan": "NS_TALK",
615 "Pengguna": "NS_USER",
616 "Pembicaraan_Pengguna": "NS_USER_TALK",
617 "Berkas": "NS_IMAGE",
618 "Pembicaraan_Berkas": "NS_IMAGE_TALK",
619 "MediaWiki": "NS_MEDIAWIKI",
620 "Pembicaraan_MediaWiki": "NS_MEDIAWIKI_TALK",
621 "Templat": "NS_TEMPLATE",
622 "Pembicaraan_Templat": "NS_TEMPLATE_TALK",
623 "Bantuan": "NS_HELP",
624 "Pembicaraan_Bantuan": "NS_HELP_TALK",
625 "Kategori": "NS_CATEGORY",
626 "Pembicaraan_Kategori": "NS_CATEGORY_TALK",
627}
628wiki_ns_re_id = [
629 ("Pembicaraan_", "", "NS_PROJECT_TALK"),
630]
631wiki_ns_tet = {
632 "Media": "NS_MEDIA",
633 "Espesiál": "NS_SPECIAL",
634 "Diskusaun": "NS_TALK",
635 "Uza-na'in": "NS_USER",
636 "Diskusaun_Uza-na'in": "NS_USER_TALK",
637 "Imajen": "NS_IMAGE",
638 "Diskusaun_Imajen": "NS_IMAGE_TALK",
639 "MediaWiki": "NS_MEDIAWIKI",
640 "Diskusaun_MediaWiki": "NS_MEDIAWIKI_TALK",
641 "Template": "NS_TEMPLATE",
642 "Diskusaun_Template": "NS_TEMPLATE_TALK",
643 "Ajuda": "NS_HELP",
644 "Diskusaun_Ajuda": "NS_HELP_TALK",
645 "Kategoria": "NS_CATEGORY",
646 "Diskusaun_Kategoria": "NS_CATEGORY_TALK",
647}
648wiki_ns_re_tet = [
649 ("Diskusaun_", "", "NS_PROJECT_TALK"),
650]
651wiki_ns_an = {
652 "Media": "NS_MEDIA",
653 "Espezial": "NS_SPECIAL",
654 "Descusión": "NS_TALK",
655 "Usuario": "NS_USER",
656 "Descusión_usuario": "NS_USER_TALK",
657 "Imachen": "NS_IMAGE",
658 "Descusión_imachen": "NS_IMAGE_TALK",
659 "MediaWiki": "NS_MEDIAWIKI",
660 "Descusión_MediaWiki": "NS_MEDIAWIKI_TALK",
661 "Plantilla": "NS_TEMPLATE",
662 "Descusión_plantilla": "NS_TEMPLATE_TALK",
663 "Aduya": "NS_HELP",
664 "Descusión_aduya": "NS_HELP_TALK",
665 "Categoría": "NS_CATEGORY",
666 "Descusión_categoría": "NS_CATEGORY_TALK",
667}
668wiki_ns_re_an = [
669 ("Descusión_", "", "NS_PROJECT_TALK"),
670]
671wiki_ns_ar = {
672 "ميديا": "NS_MEDIA",
673 "خاص": "NS_SPECIAL",
674 "نقاش": "NS_TALK",
675 "مستخدم": "NS_USER",
676 "نقاش_المستخدم": "NS_USER_TALK",
677 "صورة": "NS_IMAGE",
678 "نقاش_الصورة": "NS_IMAGE_TALK",
679 "ميدياويكي": "NS_MEDIAWIKI",
680 "نقاش_ميدياويكي": "NS_MEDIAWIKI_TALK",
681 "قالب": "NS_TEMPLATE",
682 "نقاش_القالب": "NS_TEMPLATE_TALK",
683 "مساعدة": "NS_HELP",
684 "نقاش_المساعدة": "NS_HELP_TALK",
685 "تصنيف": "NS_CATEGORY",
686 "نقاش_التصنيف": "NS_CATEGORY_TALK",
687}
688wiki_ns_re_ar = [
689 ("نقاش_", "", "NS_PROJECT_TALK"),
690]
691wiki_ns_tg_cyrl = {
692 "Медиа": "NS_MEDIA",
693 "Вижа": "NS_SPECIAL",
694 "Баҳс": "NS_TALK",
695 "Корбар": "NS_USER",
696 "Баҳси_корбар": "NS_USER_TALK",
697 "Акс": "NS_IMAGE",
698 "Баҳси_акс": "NS_IMAGE_TALK",
699 "Медиавики": "NS_MEDIAWIKI",
700 "Баҳси_медиавики": "NS_MEDIAWIKI_TALK",
701 "Шаблон": "NS_TEMPLATE",
702 "Баҳси_шаблон": "NS_TEMPLATE_TALK",
703 "Роҳнамо": "NS_HELP",
704 "Баҳси_роҳнамо": "NS_HELP_TALK",
705 "Гурӯҳ": "NS_CATEGORY",
706 "Баҳси_гурӯҳ": "NS_CATEGORY_TALK",
707}
708wiki_ns_re_tg_cyrl = [
709 ("Баҳси_", "", "NS_PROJECT_TALK"),
710]
711wiki_ns_rmy = {
712 "Mediya": "NS_MEDIA",
713 "Uzalutno": "NS_SPECIAL",
714 "Vakyarimata": "NS_TALK",
715 "Jeno": "NS_USER",
716 "Jeno_vakyarimata": "NS_USER_TALK",
717 "Chitro": "NS_IMAGE",
718 "Chitro_vakyarimata": "NS_IMAGE_TALK",
719 "MediyaViki": "NS_MEDIAWIKI",
720 "MediyaViki_vakyarimata": "NS_MEDIAWIKI_TALK",
721 "Sikavno": "NS_TEMPLATE",
722 "Sikavno_vakyarimata": "NS_TEMPLATE_TALK",
723 "Zhutipen": "NS_HELP",
724 "Zhutipen_vakyarimata": "NS_HELP_TALK",
725 "Shopni": "NS_CATEGORY",
726 "Shopni_vakyarimata": "NS_CATEGORY_TALK",
727}
728wiki_ns_re_rmy = [
729 ("{{grammar:genitive-pl|", "}}_vakyarimata", "NS_PROJECT_TALK"),
730]
731wiki_ns_mk = {
732 "Медија": "NS_MEDIA",
733 "Специјални": "NS_SPECIAL",
734 "Разговор": "NS_TALK",
735 "Корисник": "NS_USER",
736 "Разговор_со_корисник": "NS_USER_TALK",
737 "Слика": "NS_IMAGE",
738 "Разговор_за_слика": "NS_IMAGE_TALK",
739 "МедијаВики": "NS_MEDIAWIKI",
740 "Разговор_за_МедијаВики": "NS_MEDIAWIKI_TALK",
741 "Шаблон": "NS_TEMPLATE",
742 "Разговор_за_шаблон": "NS_TEMPLATE_TALK",
743 "Помош": "NS_HELP",
744 "Разговор_за_помош": "NS_HELP_TALK",
745 "Категорија": "NS_CATEGORY",
746 "Разговор_за_категорија": "NS_CATEGORY_TALK",
747}
748wiki_ns_re_mk = [
749 ("Разговор_за_", "", "NS_PROJECT_TALK"),
750]
751wiki_ns_eu = {
752 "Media": "NS_MEDIA",
753 "Aparteko": "NS_SPECIAL",
754 "Eztabaida": "NS_TALK",
755 "Lankide": "NS_USER",
756 "Lankide_eztabaida": "NS_USER_TALK",
757 "Irudi": "NS_IMAGE",
758 "Irudi_eztabaida": "NS_IMAGE_TALK",
759 "MediaWiki": "NS_MEDIAWIKI",
760 "MediaWiki_eztabaida": "NS_MEDIAWIKI_TALK",
761 "Txantiloi": "NS_TEMPLATE",
762 "Txantiloi_eztabaida": "NS_TEMPLATE_TALK",
763 "Laguntza": "NS_HELP",
764 "Laguntza_eztabaida": "NS_HELP_TALK",
765 "Kategoria": "NS_CATEGORY",
766 "Kategoria_eztabaida": "NS_CATEGORY_TALK",
767}
768wiki_ns_re_eu = [
769 ("", "_eztabaida", "NS_PROJECT_TALK"),
770]
771wiki_ns_az = {
772 "Mediya": "NS_MEDIA",
773 "Xüsusi": "NS_SPECIAL",
774 "Müzakirə": "NS_TALK",
775 "İstifadəçi": "NS_USER",
776 "İstifadəçi_müzakirəsi": "NS_USER_TALK",
777 "Şəkil": "NS_IMAGE",
778 "Şəkil_müzakirəsi": "NS_IMAGE_TALK",
779 "MediyaViki": "NS_MEDIAWIKI",
780 "MediyaViki_müzakirəsi": "NS_MEDIAWIKI_TALK",
781 "Şablon": "NS_TEMPLATE",
782 "Şablon_müzakirəsi": "NS_TEMPLATE_TALK",
783 "Kömək": "NS_HELP",
784 "Kömək_müzakirəsi": "NS_HELP_TALK",
785 "Kateqoriya": "NS_CATEGORY",
786 "Kateqoriya_müzakirəsi": "NS_CATEGORY_TALK",
787}
788wiki_ns_re_az = [
789 ("", "_müzakirəsi", "NS_PROJECT_TALK"),
790]
791wiki_ns_bat_smg = {
792 "Specēlos": "NS_SPECIAL",
793 "Aptarėms": "NS_TALK",
794 "Nauduotuos": "NS_USER",
795 "Nauduotuojė_aptarėms": "NS_USER_TALK",
796 "Abruozdielis": "NS_IMAGE",
797 "Abruozdielė_aptarėms": "NS_IMAGE_TALK",
798 "MediaWiki": "NS_MEDIAWIKI",
799 "MediaWiki_aptarėms": "NS_MEDIAWIKI_TALK",
800 "Šabluons": "NS_TEMPLATE",
801 "Šabluona_aptarėms": "NS_TEMPLATE_TALK",
802 "Pagelba": "NS_HELP",
803 "Pagelbas_aptarėms": "NS_HELP_TALK",
804 "Kateguorėjė": "NS_CATEGORY",
805 "Kateguorėjės_aptarėms": "NS_CATEGORY_TALK",
806}
807wiki_ns_re_bat_smg = [
808 ("", "_aptarėms", "NS_PROJECT_TALK"),
809]
810wiki_ns_it = {
811 "Media": "NS_MEDIA",
812 "Speciale": "NS_SPECIAL",
813 "Discussione": "NS_TALK",
814 "Utente": "NS_USER",
815 "Discussioni_utente": "NS_USER_TALK",
816 "Immagine": "NS_IMAGE",
817 "Discussioni_immagine": "NS_IMAGE_TALK",
818 "MediaWiki": "NS_MEDIAWIKI",
819 "Discussioni_MediaWiki": "NS_MEDIAWIKI_TALK",
820 "Template": "NS_TEMPLATE",
821 "Discussioni_template": "NS_TEMPLATE_TALK",
822 "Aiuto": "NS_HELP",
823 "Discussioni_aiuto": "NS_HELP_TALK",
824 "Categoria": "NS_CATEGORY",
825 "Discussioni_categoria": "NS_CATEGORY_TALK",
826}
827wiki_ns_re_it = [
828 ("Discussioni_", "", "NS_PROJECT_TALK"),
829]
830wiki_ns_ms = {
831 "Media": "NS_MEDIA",
832 "Khas": "NS_SPECIAL",
833 "Perbincangan": "NS_TALK",
834 "Pengguna": "NS_USER",
835 "Perbincangan_Pengguna": "NS_USER_TALK",
836 "Imej": "NS_IMAGE",
837 "Perbincangan_Imej": "NS_IMAGE_TALK",
838 "MediaWiki": "NS_MEDIAWIKI",
839 "Perbincangan_MediaWiki": "NS_MEDIAWIKI_TALK",
840 "Templat": "NS_TEMPLATE",
841 "Perbincangan_Templat": "NS_TEMPLATE_TALK",
842 "Bantuan": "NS_HELP",
843 "Perbincangan_Bantuan": "NS_HELP_TALK",
844 "Kategori": "NS_CATEGORY",
845 "Perbincangan_Kategori": "NS_CATEGORY_TALK",
846}
847wiki_ns_re_ms = [
848 ("Perbincangan_", "", "NS_PROJECT_TALK"),
849]
850wiki_ns_ba = {
851 "Медиа": "NS_MEDIA",
852 "Ярҙамсы": "NS_SPECIAL",
853 "Фекер_алышыу": "NS_TALK",
854 "Ҡатнашыусы": "NS_USER",
855 "Ҡатнашыусы_м-н_фекер_алышыу": "NS_USER_TALK",
856 "Рәсем": "NS_IMAGE",
857 "Рәсем_б-са_фекер_алышыу": "NS_IMAGE_TALK",
858 "MediaWiki": "NS_MEDIAWIKI",
859 "MediaWiki_б-са_фекер_алышыу": "NS_MEDIAWIKI_TALK",
860 "Ҡалып": "NS_TEMPLATE",
861 "Ҡалып_б-са_фекер_алышыу": "NS_TEMPLATE_TALK",
862 "Белешмә": "NS_HELP",
863 "Белешмә_б-са_фекер_алышыу": "NS_HELP_TALK",
864 "Категория": "NS_CATEGORY",
865 "Категория_б-са_фекер_алышыу": "NS_CATEGORY_TALK",
866}
867wiki_ns_re_ba = [
868 ("", "_б-са_фекер_алышыу", "NS_PROJECT_TALK"),
869]
870wiki_ns_be = {
871 "Мультымедыя": "NS_MEDIA",
872 "Адмысловае": "NS_SPECIAL",
873 "Размовы": "NS_TALK",
874 "Удзельнік": "NS_USER",
875 "Размовы_з_удзельнікам": "NS_USER_TALK",
876 "Выява": "NS_IMAGE",
877 "Размовы_пра_выяву": "NS_IMAGE_TALK",
878 "MediaWiki": "NS_MEDIAWIKI",
879 "Размовы_пра_MediaWiki": "NS_MEDIAWIKI_TALK",
880 "Шаблон": "NS_TEMPLATE",
881 "Размовы_пра_шаблон": "NS_TEMPLATE_TALK",
882 "Даведка": "NS_HELP",
883 "Размовы_пра_даведку": "NS_HELP_TALK",
884 "Катэгорыя": "NS_CATEGORY",
885 "Размовы_пра_катэгорыю": "NS_CATEGORY_TALK",
886}
887wiki_ns_re_be = [
888 ("", "_размовы", "NS_PROJECT_TALK"),
889]
890wiki_ns_crh_cyrl = {
891 "Медиа": "NS_MEDIA",
892 "Махсус": "NS_SPECIAL",
893 "Музакере": "NS_TALK",
894 "Къулланыджы": "NS_USER",
895 "Къулланыджы_музакереси": "NS_USER_TALK",
896 "Ресим": "NS_IMAGE",
897 "Ресим_музакереси": "NS_IMAGE_TALK",
898 "МедиаВики": "NS_MEDIAWIKI",
899 "МедиаВики_музакереси": "NS_MEDIAWIKI_TALK",
900 "Шаблон": "NS_TEMPLATE",
901 "Шаблон_музакереси": "NS_TEMPLATE_TALK",
902 "Ярдым": "NS_HELP",
903 "Ярдым_музакереси": "NS_HELP_TALK",
904 "Категория": "NS_CATEGORY",
905 "Категория_музакереси": "NS_CATEGORY_TALK",
906}
907wiki_ns_re_crh_cyrl = [
908 ("", "_музакереси", "NS_PROJECT_TALK"),
909]
910wiki_ns_nn = {
911 "Filpeikar": "NS_MEDIA",
912 "Spesial": "NS_SPECIAL",
913 "Diskusjon": "NS_TALK",
914 "Brukar": "NS_USER",
915 "Brukardiskusjon": "NS_USER_TALK",
916 "Fil": "NS_IMAGE",
917 "Fildiskusjon": "NS_IMAGE_TALK",
918 "MediaWiki": "NS_MEDIAWIKI",
919 "MediaWiki-diskusjon": "NS_MEDIAWIKI_TALK",
920 "Mal": "NS_TEMPLATE",
921 "Maldiskusjon": "NS_TEMPLATE_TALK",
922 "Hjelp": "NS_HELP",
923 "Hjelpdiskusjon": "NS_HELP_TALK",
924 "Kategori": "NS_CATEGORY",
925 "Kategoridiskusjon": "NS_CATEGORY_TALK",
926}
927wiki_ns_re_nn = [
928 ("", "-diskusjon", "NS_PROJECT_TALK"),
929]
930wiki_ns_nv = {
931 "Media": "NS_MEDIA",
932 "Special": "NS_SPECIAL",
933 "Naaltsoos_baa_yinísht'į́": "NS_TALK",
934 "Choinish'įįhí": "NS_USER",
935 "Choinish'įįhí_baa_yinísht'į́": "NS_USER_TALK",
936 "E'elyaaígíí": "NS_IMAGE",
937 "E'elyaaígíí_baa_yinísht'į́": "NS_IMAGE_TALK",
938 "MediaWiki": "NS_MEDIAWIKI",
939 "MediaWiki_baa_yinísht'į́": "NS_MEDIAWIKI_TALK",
940 "Template": "NS_TEMPLATE",
941 "Template_talk": "NS_TEMPLATE_TALK",
942 "Aná'álwo'": "NS_HELP",
943 "Aná'álwo'_baa_yinísht'į́": "NS_HELP_TALK",
944 "T'ááłáhági_át'éego": "NS_CATEGORY",
945 "T'ááłáhági_át'éego_baa_yinísht'į́": "NS_CATEGORY_TALK",
946}
947wiki_ns_re_nv = [
948 ("", "_baa_yinísht'į́", "NS_PROJECT_TALK"),
949]
950wiki_ns_ru = {
951 "Медиа": "NS_MEDIA",
952 "Служебная": "NS_SPECIAL",
953 "Обсуждение": "NS_TALK",
954 "Участник": "NS_USER",
955 "Обсуждение_участника": "NS_USER_TALK",
956 "Изображение": "NS_IMAGE",
957 "Обсуждение_изображения": "NS_IMAGE_TALK",
958 "MediaWiki": "NS_MEDIAWIKI",
959 "Обсуждение_MediaWiki": "NS_MEDIAWIKI_TALK",
960 "Шаблон": "NS_TEMPLATE",
961 "Обсуждение_шаблона": "NS_TEMPLATE_TALK",
962 "Справка": "NS_HELP",
963 "Обсуждение_справки": "NS_HELP_TALK",
964 "Категория": "NS_CATEGORY",
965 "Обсуждение_категории": "NS_CATEGORY_TALK",
966}
967wiki_ns_re_ru = [
968 ("Обсуждение_{{grammar:genitive|", "}}", "NS_PROJECT_TALK"),
969]
970wiki_ns_crh_latn = {
971 "Media": "NS_MEDIA",
972 "Mahsus": "NS_SPECIAL",
973 "Muzakere": "NS_TALK",
974 "Qullanıcı": "NS_USER",
975 "Qullanıcı_muzakeresi": "NS_USER_TALK",
976 "Resim": "NS_IMAGE",
977 "Resim_muzakeresi": "NS_IMAGE_TALK",
978 "MediaViki": "NS_MEDIAWIKI",
979 "MediaViki_muzakeresi": "NS_MEDIAWIKI_TALK",
980 "Şablon": "NS_TEMPLATE",
981 "Şablon_muzakeresi": "NS_TEMPLATE_TALK",
982 "Yardım": "NS_HELP",
983 "Yardım_muzakeresi": "NS_HELP_TALK",
984 "Kategoriya": "NS_CATEGORY",
985 "Kategoriya_muzakeresi": "NS_CATEGORY_TALK",
986}
987wiki_ns_re_crh_latn = [
988 ("", "_muzakeresi", "NS_PROJECT_TALK"),
989]
990wiki_ns_be_tarask = {
991 "Мэдыя": "NS_MEDIA",
992 "Спэцыяльныя": "NS_SPECIAL",
993 "Абмеркаваньне": "NS_TALK",
994 "Удзельнік": "NS_USER",
995 "Гутаркі_ўдзельніка": "NS_USER_TALK",
996 "Выява": "NS_IMAGE",
997 "Абмеркаваньне_выявы": "NS_IMAGE_TALK",
998 "MediaWiki": "NS_MEDIAWIKI",
999 "Абмеркаваньне_MediaWiki": "NS_MEDIAWIKI_TALK",
1000 "Шаблён": "NS_TEMPLATE",
1001 "Абмеркаваньне_шаблёну": "NS_TEMPLATE_TALK",
1002 "Дапамога": "NS_HELP",
1003 "Абмеркаваньне_дапамогі": "NS_HELP_TALK",
1004 "Катэгорыя": "NS_CATEGORY",
1005 "Абмеркаваньне_катэгорыі": "NS_CATEGORY_TALK",
1006}
1007wiki_ns_re_be_tarask = [
1008 ("Абмеркаваньне_", "", "NS_PROJECT_TALK"),
1009]
1010wiki_ns_yue = {
1011 "Media": "NS_MEDIA",
1012 "Special": "NS_SPECIAL",
1013 "Talk": "NS_TALK",
1014 "User": "NS_USER",
1015 "User_talk": "NS_USER_TALK",
1016 "Image": "NS_IMAGE",
1017 "Image_talk": "NS_IMAGE_TALK",
1018 "MediaWiki": "NS_MEDIAWIKI",
1019 "MediaWiki_talk": "NS_MEDIAWIKI_TALK",
1020 "Template": "NS_TEMPLATE",
1021 "Template_talk": "NS_TEMPLATE_TALK",
1022 "Help": "NS_HELP",
1023 "Help_talk": "NS_HELP_TALK",
1024 "Category": "NS_CATEGORY",
1025 "Category_talk": "NS_CATEGORY_TALK",
1026}
1027wiki_ns_re_yue = [
1028 ("", "_talk", "NS_PROJECT_TALK"),
1029]
1030wiki_ns_kn = {
1031 "ಮೀಡಿಯ": "NS_MEDIA",
1032 "ವಿಶೇಷ": "NS_SPECIAL",
1033 "ಚರ್ಚೆಪುಟ": "NS_TALK",
1034 "ಸದಸ್ಯ": "NS_USER",
1035 "ಸದಸ್ಯರ_ಚರ್ಚೆಪುಟ": "NS_USER_TALK",
1036 "ಚಿತ್ರ": "NS_IMAGE",
1037 "ಚಿತ್ರ_ಚರ್ಚೆಪುಟ": "NS_IMAGE_TALK",
1038 "ಮೀಡಿಯವಿಕಿ": "NS_MEDIAWIKI",
1039 "ಮೀಡೀಯವಿಕಿ_ಚರ್ಚೆ": "NS_MEDIAWIKI_TALK",
1040 "ಟೆಂಪ್ಲೇಟು": "NS_TEMPLATE",
1041 "ಟೆಂಪ್ಲೇಟು_ಚರ್ಚೆ": "NS_TEMPLATE_TALK",
1042 "ಸಹಾಯ": "NS_HELP",
1043 "ಸಹಾಯ_ಚರ್ಚೆ": "NS_HELP_TALK",
1044 "ವರ್ಗ": "NS_CATEGORY",
1045 "ವರ್ಗ_ಚರ್ಚೆ": "NS_CATEGORY_TALK",
1046}
1047wiki_ns_re_kn = [
1048 ("", "_ಚರ್ಚೆ", "NS_PROJECT_TALK"),
1049]
1050wiki_ns_sl = {
1051 "Media": "NS_MEDIA",
1052 "Posebno": "NS_SPECIAL",
1053 "Pogovor": "NS_TALK",
1054 "Uporabnik": "NS_USER",
1055 "Uporabniški_pogovor": "NS_USER_TALK",
1056 "Slika": "NS_IMAGE",
1057 "Pogovor_o_sliki": "NS_IMAGE_TALK",
1058 "MediaWiki": "NS_MEDIAWIKI",
1059 "Pogovor_o_MediaWiki": "NS_MEDIAWIKI_TALK",
1060 "Predloga": "NS_TEMPLATE",
1061 "Pogovor_o_predlogi": "NS_TEMPLATE_TALK",
1062 "Pomoč": "NS_HELP",
1063 "Pogovor_o_pomoči": "NS_HELP_TALK",
1064 "Kategorija": "NS_CATEGORY",
1065 "Pogovor_o_kategoriji": "NS_CATEGORY_TALK",
1066}
1067wiki_ns_re_sl = [
1068 ("Pogovor_{{grammar:mestnik|", "}}", "NS_PROJECT_TALK"),
1069]
1070wiki_ns_nds = {
1071 "Media": "NS_MEDIA",
1072 "Spezial": "NS_SPECIAL",
1073 "Diskuschoon": "NS_TALK",
1074 "Bruker": "NS_USER",
1075 "Bruker_Diskuschoon": "NS_USER_TALK",
1076 "Bild": "NS_IMAGE",
1077 "Bild_Diskuschoon": "NS_IMAGE_TALK",
1078 "MediaWiki": "NS_MEDIAWIKI",
1079 "MediaWiki_Diskuschoon": "NS_MEDIAWIKI_TALK",
1080 "Vörlaag": "NS_TEMPLATE",
1081 "Vörlaag_Diskuschoon": "NS_TEMPLATE_TALK",
1082 "Hülp": "NS_HELP",
1083 "Hülp_Diskuschoon": "NS_HELP_TALK",
1084 "Kategorie": "NS_CATEGORY",
1085 "Kategorie_Diskuschoon": "NS_CATEGORY_TALK",
1086}
1087wiki_ns_re_nds = [
1088 ("", "_Diskuschoon", "NS_PROJECT_TALK"),
1089]
1090wiki_ns_tlh = {
1091 "Doch": "NS_MEDIA",
1092 "le'": "NS_SPECIAL",
1093 "ja'chuq": "NS_TALK",
1094 "lo'wI'": "NS_USER",
1095 "lo'wI'_ja'chuq": "NS_USER_TALK",
1096 "nagh_beQ": "NS_IMAGE",
1097 "nagh_beQ_ja'chuq": "NS_IMAGE_TALK",
1098 "MediaWiki": "NS_MEDIAWIKI",
1099 "MediaWiki_ja'chuq": "NS_MEDIAWIKI_TALK",
1100 "chen'ay'": "NS_TEMPLATE",
1101 "chen'ay'_ja'chuq": "NS_TEMPLATE_TALK",
1102 "QaH": "NS_HELP",
1103 "QaH_ja'chuq": "NS_HELP_TALK",
1104 "Segh": "NS_CATEGORY",
1105 "Segh_ja'chuq": "NS_CATEGORY_TALK",
1106}
1107wiki_ns_re_tlh = [
1108 ("", "_ja'chuq", "NS_PROJECT_TALK"),
1109]
1110wiki_ns_la = {
1111 "Specialis": "NS_SPECIAL",
1112 "Disputatio": "NS_TALK",
1113 "Usor": "NS_USER",
1114 "Disputatio_Usoris": "NS_USER_TALK",
1115 "Imago": "NS_IMAGE",
1116 "Disputatio_Imaginis": "NS_IMAGE_TALK",
1117 "MediaWiki": "NS_MEDIAWIKI",
1118 "Disputatio_MediaWiki": "NS_MEDIAWIKI_TALK",
1119 "Formula": "NS_TEMPLATE",
1120 "Disputatio_Formulae": "NS_TEMPLATE_TALK",
1121 "Auxilium": "NS_HELP",
1122 "Disputatio_Auxilii": "NS_HELP_TALK",
1123 "Categoria": "NS_CATEGORY",
1124 "Disputatio_Categoriae": "NS_CATEGORY_TALK",
1125}
1126wiki_ns_re_la = [
1127 ("Disputatio_{{grammar:genitive|", "}}", "NS_PROJECT_TALK"),
1128]
1129wiki_ns_li = {
1130 "Media": "NS_MEDIA",
1131 "Speciaal": "NS_SPECIAL",
1132 "Euverlèk": "NS_TALK",
1133 "Gebroeker": "NS_USER",
1134 "Euverlèk_gebroeker": "NS_USER_TALK",
1135 "Plaetje": "NS_IMAGE",
1136 "Euverlèk_plaetje": "NS_IMAGE_TALK",
1137 "MediaWiki": "NS_MEDIAWIKI",
1138 "Euverlèk_MediaWiki": "NS_MEDIAWIKI_TALK",
1139 "Sjabloon": "NS_TEMPLATE",
1140 "Euverlèk_sjabloon": "NS_TEMPLATE_TALK",
1141 "Help": "NS_HELP",
1142 "Euverlèk_help": "NS_HELP_TALK",
1143 "Categorie": "NS_CATEGORY",
1144 "Euverlèk_categorie": "NS_CATEGORY_TALK",
1145}
1146wiki_ns_re_li = [
1147 ("Euverlèk_", "", "NS_PROJECT_TALK"),
1148]
1149wiki_ns_hr = {
1150 "Mediji": "NS_MEDIA",
1151 "Posebno": "NS_SPECIAL",
1152 "Razgovor": "NS_TALK",
1153 "Suradnik": "NS_USER",
1154 "Razgovor_sa_suradnikom": "NS_USER_TALK",
1155 "Slika": "NS_IMAGE",
1156 "Razgovor_o_slici": "NS_IMAGE_TALK",
1157 "MediaWiki": "NS_MEDIAWIKI",
1158 "MediaWiki_razgovor": "NS_MEDIAWIKI_TALK",
1159 "Predložak": "NS_TEMPLATE",
1160 "Razgovor_o_predlošku": "NS_TEMPLATE_TALK",
1161 "Pomoć": "NS_HELP",
1162 "Razgovor_o_pomoći": "NS_HELP_TALK",
1163 "Kategorija": "NS_CATEGORY",
1164 "Razgovor_o_kategoriji": "NS_CATEGORY_TALK",
1165}
1166wiki_ns_re_hr = [
1167 ("Razgovor_", "", "NS_PROJECT_TALK"),
1168]
1169wiki_ns_pl = {
1170 "Media": "NS_MEDIA",
1171 "Specjalna": "NS_SPECIAL",
1172 "Dyskusja": "NS_TALK",
1173 "Użytkownik": "NS_USER",
1174 "Dyskusja_użytkownika": "NS_USER_TALK",
1175 "Grafika": "NS_IMAGE",
1176 "Dyskusja_grafiki": "NS_IMAGE_TALK",
1177 "MediaWiki": "NS_MEDIAWIKI",
1178 "Dyskusja_MediaWiki": "NS_MEDIAWIKI_TALK",
1179 "Szablon": "NS_TEMPLATE",
1180 "Dyskusja_szablonu": "NS_TEMPLATE_TALK",
1181 "Pomoc": "NS_HELP",
1182 "Dyskusja_pomocy": "NS_HELP_TALK",
1183 "Kategoria": "NS_CATEGORY",
1184 "Dyskusja_kategorii": "NS_CATEGORY_TALK",
1185}
1186wiki_ns_re_pl = [
1187 ("Dyskusja_", "", "NS_PROJECT_TALK"),
1188]
1189wiki_ns_nds_nl = {
1190 "Media": "NS_MEDIA",
1191 "Speciaal": "NS_SPECIAL",
1192 "Overleg": "NS_TALK",
1193 "Gebruker": "NS_USER",
1194 "Overleg_gebruker": "NS_USER_TALK",
1195 "Ofbeelding": "NS_IMAGE",
1196 "Overleg_ofbeelding": "NS_IMAGE_TALK",
1197 "MediaWiki": "NS_MEDIAWIKI",
1198 "Overleg_MediaWiki": "NS_MEDIAWIKI_TALK",
1199 "Sjabloon": "NS_TEMPLATE",
1200 "Overleg_sjabloon": "NS_TEMPLATE_TALK",
1201 "Hulpe": "NS_HELP",
1202 "Overleg_hulpe": "NS_HELP_TALK",
1203 "Kattegerie": "NS_CATEGORY",
1204 "Overleg_kattegerie": "NS_CATEGORY_TALK",
1205}
1206wiki_ns_re_nds_nl = [
1207 ("Overleg_", "", "NS_PROJECT_TALK"),
1208]
1209wiki_ns_pt = {